使用 IAM 设置 RDS (MySQL) 数据库访问以生成访问令牌

Setting up RDS (MySQL) database access using IAM to generate access tokens

我已按照说明设置 AWS 和 MySQL,这样我应该能够使用 mysql-client 和一个用户(名为 aws_iam) 没有密码,但有 awscli 生成的令牌,角色附加到我的 EC2 实例。

说明are here

所以我有:

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-转义,就是 "authentication token"...你只需要将它括起来在命令行的 ' 单引号中。

我是这样得出结论的:

我尝试解决这个问题的第一步是检查 RDS API 参考。没有 GetDbAuthToken 动作。好奇。

然后,我注意到 aws rds generate-db-auth-token 不需要区域。怎么可能?

除非...

从字里行间看,这里的操作术语似乎是 generate... 不是 get 的同义词(通过 API请求)。

这看起来像是一个完全本地的操作,这意味着可以成功地 "generate" 一个完全无效的身份验证令牌...与生成预签名 URL 的方式完全相同语法上有效但访问仍然被拒绝,因为请求签名者缺少必要的权限。

if your EC2 role doesn't have the policy for "rds-db" you can still generate a token. This likely means the token generation doesn't prove that your policy works.

在这里,我将此称为对我的断言的进一步证明。鉴于我所看到的,我想说成功的令牌生成根本不能证明什么。

你只是在生成他们所谓的"token"——也就是说,在形式上,与AWS4-HMAC-SHA256("Signature Version 4") 签名 URL... 使用您的凭据签名。

RDS 获取整条线,并使用与面向外部的服务 APIs 使用基本相同的机制将其传递给 IAM,以验证它。这也解释了为什么令牌只能使用 15 分钟……这就是大多数查询 API 的工作方式。签名请求仅适用于 +/- 15 分钟。它还解释了为什么他们建议每秒不超过 20 个新连接——您的 RDS 实例正在发出内部 API 请求以在您尝试使用它登录时实际验证令牌。

我会回顾所有 setup steps 但在测试时使用 IAM 用户而不是实例角色,只是为了消除一点复杂性。

RDS 实例的错误日志可能包含更多信息。您可能需要在参数组中将 log_warnings 设置为 2 或更高,无论如何这可能是个好主意。

原来我的角色没有正确的权限。不幸的是,那些 错误的 权限及时丢失了,但我似乎记得 "Resource" 密钥是错误的。

这是您需要替换以下变量的政策:

  • AWS_ROLE_NAME: 您分配给实例的角色名称
  • AWS_ACCOUNT_ID:您的整体账户 ID(从账户或账单页面查看)
  • RDS_REGION:您的实例所在的区域,例如"us-east-1"(单AZ不需要指定AZ)
  • RDS_RESOURCE_ID:您希望访问的实例在 RDS Web 控制台中标题 "Resource 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 给出了正确的答案,因为他们用有用的信息更快地回答了很多问题,但这项政策应该可以帮助一些人。