用 AWS Secrets Manager 存储和管理密钥

目前我们在 AWS 上把密钥,API Key  等信息是存储在  AWS Systems Manager 的 Parameter Store 中,它只提供了用 KMS Key 加密存储字符串的功能,最大字符串大小是 4096 个字符,它是免费的。

最近发现 AWS 上有一个新的服务 AWS Secrets Manager(2018 年 4 月发布的),听起来用它来存储密钥信息更高大上些。它同样提供了用 KMS Key 加密存储字符串的功能,字符串最大也是 4096 个字符。从 AWS Web 控制台上看可配置用 Key/Value 的形式,其实本质也是存储为一个 JSON 字符串。

Secrets Manager 与 Parameter Store 更多的功能是能与 RDS 集成 -- 选择数据库收集数据库的配置信息(主机名,端口,实例等), 还有就是可配置定期更新密钥,这对一个安全的系统定期改密码很重要。对于定期更新密钥的未作深入研究,AWS Secrets Manager 本身知道如何轮换 RDS 数据库的密钥,其他的需要一个 Lambda 来支持。

Secrets Manger 相比于 Parameter Store 除了可定期轮换密码,再就是审计功能,其他的话没有太大的差别。对了 Secrets Manager 要钱的,一个密钥一个月 $0.40, 每 10,000 次 API 调用收 $0.05。如果用 Parameter Store, 结合 CloudWatch 和 Lambda 也能实现定期轮换密码。

为了方便 Parameter Store 过度到 Secrets Manager,我们还能用 Parameter Store(SSM) 的 API 来获得  Secrets Manager 中配置的值。支持 GetParameterGetParameters 操作,需要加上特定的 Key 前缀来指明获取的是 Secrets Manager 中的密钥,如 Key: /aws/reference/secretsmanager/<secret_ID_in_Secrets_Manager>

Secret 的创建

创建 Secret 时可以选择某个 RDS 实例,填入用户名,密码,选择一个用于加密的 KMS key,那么 Secrets Manager 生成一个包含类似以下信息的字符串密钥

后台可展示为 Secret key/value 形式,便于查看与编辑。

或者创建时可以手工以 Secret key/value 的形式输入或直接编辑 Plaintext 内容。注意 Plaintext 中编辑时并不要求一定要符合 JSON 格式,可为任意的字符串,只是会造成切换回 Secret key/value 标签后无法显示。这个不要紧,反正后面的 API 获取到的也是一个字符串,必要时自行解析字符串为 JSON 对象。

输入其他的基本信息,Secret name, 描述信息,Tag 等。

获取 Secret

在 AWS 控制台打开每个 Secret 下方要获取密钥的示例代码,包含 Java, Javascript, C#, Python3, Ruby 和 Go 语言的。下面以 Python 3 为例,只保留了关键代码

上面代码得到前面数据库配置的用户名,假设 Secret key 是 qa/postgres/my_db。如果配置的只是一个 Plaintext,那么取到的 get_secrete() 就是我们想要的。

读取 Secret 的 IAM 权限

上面读取 Secret 的用户需要有两个相应的权限才能正确执行

  1. 对 Secret key qa/postgres/my_db 的 secretsmanager:GetSecretValue 权限
  2. 对所用来加密的 KMS key 的 kms:Decrypt 权限

少了第一个权限会得到如下类似错误:

botocore.exceptions.ClientError: An error occurred (AccessDeniedException) when calling the GetSecretValue operation: User: arn:aws:iam::1234567890:user/program_user is not authorized to perform: secretsmanager:GetSecretValue on resource: arn:aws:secretsmanager:us-east-1:1234567890:secret:qa/postgres/my_db-DaFxju

如果没有第二个权限会得到如下类似的错误:

botocore.exceptions.ClientError: An error occurred (AccessDeniedException) when calling the GetSecretValue operation: Access to KMS is not allowed

通过 Parameter Store API 来读取 Secret

这时候的权限要求就会有些奇怪了。需要的也是同上面完全一样的两个  secretsmanager:GetSecretValue 和 kms:Decrypt 。

虽然是在用 ssm 的 getParameter() 方法,实际上是不需要 ssm:GetParameter 权限的,所以底层上对 ssm.get_parameter() 的调用实际上委派给了 secretsmanager.get_secret_value() 操作。如果真要给个 ssm:GetParameter 权限,资源上也无法指定一个 secretesmanager 的资源啊。

链接:

  1. Keeping Secrets with AWS Secrets Manager

类别: AWS. 标签: , . 阅读(14). 订阅评论. TrackBack.

Leave a Reply

avatar