我已经按照说明设置了AWS和MySQL,这样我应该能够使用mysql-client
和用户(名为aws_iam
(登录mysql,而无需密码,但使用awscli
生成的令牌,该令牌具有附加到我的EC2实例的角色。
说明在这里
所以我拥有的是:
- 具有允许我生成 RDS 凭证的角色的 EC2 实例
- 运行 MySQL 的 RDS 实例,用户
aws_iam
由AWSAuthenticationPlugin
标识 - 通过 SSH 登录 EC2 实例时,我可以运行
mysql -h mydb.randomstring.region.rds.amazonaws.com -u root -p
并从 RDS 设置中输入主密码以获取 mysql shell。 - 此外,当通过 SSH 登录到 EC2 实例时,我可以运行
aws rds generate-db-auth-token --hostname mydb.randomstring.region.rds.amazonaws.com --port 3306 --username aws_iam
运行此实例时,我会得到一个如下所示的令牌:
mydb.randomstring.region.rds.amazon.aws.com:port-number/?Action=connect&DBUser=aws_iam&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=900&X-Amz-Date=current_time&X-Amz-SignedHeaders=host&X-Amz-Security-Token=really-long-url-encoded-string&X-Amz-Credential=string/region/rds-db/aws4_request&X-Amz-Signature=long-hash
然后我运行一个连接命令:
mysql -h mydb.randomstring.region.rds.amazonaws.com --ssl-ca=rds-ca-2015-eu-west-1.pem --ssl-mode=VERIFY_IDENTITY -u aws_iam --enable-cleartext-plugin --password=TOKEN
但后来我只是得到
ERROR 1045 (28000): Access denied for user 'aws_iam'@IP (using password: YES)
我注意到的几件事:
- "令牌"最初是URL编码的;但是解码也不起作用 令牌
- 具有许多URL格式的参数;这些参数中可能只有一个是实际的令牌,但文档中未提及。
- 如果您的 EC2 角色没有"RDS-db"策略,您仍然可以生成令牌。这可能意味着令牌生成不能证明你的策略有效;但是除此之外没有办法调试它
那么有没有人启用此功能,我错过了什么吗?
文档看起来确实很少。
乍一看似乎很荒谬,但看起来整个事情,连同它的 url 转义,都是"身份验证令牌"......您只需要在命令行上将其括在'
单引号中即可。
以下是我得出这个结论的方式:
我尝试解决这个问题的第一步是检查 RDS API 参考。 没有GetDbAuthToken
行动。 好奇。
然后,我注意到aws rds generate-db-auth-token
不需要区域。 这怎么可能?
除非。。。
从字里行间看,看起来这里的操作术语是生成的......不是get的同义词(通过 API 请求(。
这看起来像一个完全本地的操作,这意味着可以成功"生成"一个完全无效的身份验证令牌......与生成语法有效但访问仍被拒绝的预签名 URL 的方式完全相同,因为请求签名者缺少必要的权限。
如果您的 EC2 角色没有"RDS-db"策略,您仍然可以生成令牌。这可能意味着令牌生成无法证明策略有效。
我在这里称之为我的断言的进一步证明。 根据我所看到的,我会说成功的代币生成根本证明不了什么。
您只是在生成他们所谓的"令牌"——也就是说,在形式上,与AWS4-HMAC-SHA256
("签名版本 4"(签名 URL 没有什么不同......使用您的凭据签名。
RDS 采用整条线路,并使用与面向外部的服务 API 基本相同的机制将其传递给 IAM,以对其进行验证。 这也解释了为什么令牌只能使用 15 分钟......这就是大多数查询 API 的工作方式。 已签名的请求仅在 +/- 15 分钟内有效。 这也解释了为什么他们建议每秒不超过 20 个新连接 - 您的 RDS 实例正在发出内部 API 请求,以便在您尝试使用它登录时实际验证令牌。
我会回顾所有设置步骤,但在测试时使用 IAM 用户而不是实例角色,只是为了消除一点复杂性。
RDS 实例的错误日志可能包含更多信息。 您可能需要在参数组中将log_warnings
设置为 2 或更高,无论如何这可能是一个好主意。
事实证明,我的角色没有正确的权限。不幸的是,那些错误的权限已经及时丢失了,但我似乎记得"资源"键是错误的。
下面是需要替换以下变量的策略:
- AWS_ROLE_NAME:分配给实例的角色名称
- AWS_ACCOUNT_ID:您的整体帐号 ID(请参阅帐号或结算页面(
- RDS_REGION:您的实例所在的区域,例如"us-east-1"(不需要为单个可用区指定可用区(
- RDS_RESOURCE_ID:RDS Web 控制台中标题为"资源 ID"的代码,用于要访问的实例(格式应为
db-([A-Z0-9]+)
(
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"rds-db:connect"
],
"Resource": [
"arn:aws:rds-db:RDS_REGION:AWS_ACCOUNT_ID:dbuser:RDS_RESOURCE_ID/AWS_ROLE_NAME"
]
}
]
}
我已经给出了 sqlbot 的正确答案,因为他们用有用的信息回答得更快,但这个政策应该可以帮助一些人。