AWS Secrets Manager:完整指南与最佳实践
AWS Secrets Manager是亚马逊的原生密钥管理服务,用于安全存储、检索、轮换和审计数据库凭证、API密钥等敏感信息。

AWS Secrets Manager 是亚马逊原生的密钥管理解决方案。对于任何在亚马逊基础设施上构建的公司来说,这看起来都是一个显而易见的选择:它直接与 AWS IAM、RDS、Redshift 以及许多其他服务集成。
选择正确的安全基础设施非常重要,因为迁移安全基础设施是一件痛苦的事,所以深入了解你的密钥管理器是值得的。如果你的基础设施运行在 AWS 上,那么在采用 AWS Secrets Manager 之前,值得深入了解它的功能、架构、优点和缺点。
AWS Secrets Manager 是什么
AWS Secrets Manager 是一项托管服务,用于存储、检索、轮换和审计密钥:数据库凭据、API 密钥、OAuth Token 以及任何其他密钥。相比于 .env 文件或任何其他形式的手动密钥管理,这是一个巨大的升级。你的应用程序不再将凭据硬编码在可能意外泄露的地方,而是从一个中央密钥存储中检索,并在运行时注入。这消除了密钥蔓延,从而提高了安全性,避免了停机或工程效率下降。
AWS Secrets Manager 的核心架构与其他密钥管理工具类似:它将密钥存储在数据库中,并进行静态加密。然后,通过经过身份验证的 API 调用,在运行时将其提供给应用程序。
AWS Secrets Manager 与两个听起来相似、经常引起混淆的 AWS 服务不同。
AWS Systems Manager 参数存储 vs. AWS Secrets Manager
AWS Systems Manager 参数存储存储配置值,并且可以保存密钥。它还具有一些便利功能,例如通过 AWS IAM 进行访问控制以及与 AWS 其他组件的原生集成。但是,将凭据存储在参数存储中而不是 Secrets Manager 中,就像在 EC2 上运行 Postgres 而不是在 RDS 上运行一样。
这是可行的,但你会缺少那些让你更轻松的核心功能。例如,参数存储缺乏内置的密钥轮换(定期更改密钥值以限制泄露的爆炸半径)。Secrets Manager 是为密钥管理而专门构建的。用它来进行密钥管理意味着更多的手动工作,且效果更差。
AWS Secrets Manager vs. AWS Key Management Service (KMS)
AWS Key Management Service (KMS) 管理加密密钥,这些密钥也是机密。但 Secrets Manager 在底层使用 KMS,而不是取代它。
KMS 并非为密钥管理而构建,除非你正在为数据构建自定义加密工作流程,否则你可能只会通过它来与 Secrets Manager 交互。只有在你构建自己的密钥管理器时,你才会直接使用它。
AWS Secrets Manager 如何工作
Secrets Manager 的架构包括三个核心工作流程:加密、访问控制和版本控制。
使用 KMS 进行加密
每个密钥值都使用来自 AWS KMS 的密钥进行静态加密。当你创建密钥时,通常会使用 AWS 托管密钥 aws/secretsmanager,该密钥是免费的,并且是大多数工作负载的默认选择。Secrets Manager 为每个密钥版本生成一个唯一的数据密钥,并使用该密钥对值进行加密。数据密钥本身受你的 KMS 密钥保护。当为构建检索密钥时,值会被解密,通过 TLS 返回并注入到构建中。
你也可以使用客户管理密钥 (CMK) 进行加密。这对于高级工作流程非常理想,例如跨 AWS 账户共享密钥、应用自定义密钥策略或独立审计加密操作。在 CMK 密钥策略中,你可以通过将 kms:ViaService 条件设置为 secretsmanager.<region>.amazonaws.com 将密钥范围限定为仅 Secrets Manager,这样密钥就不能用于其他任何用途。
使用 AWS IAM 进行访问控制
对密钥的访问由两层控制:第一层是附加到用户和角色的基于身份的 IAM 策略。例如,一个 staging backend service 角色获得对特定路径下密钥的读取权限。
另一种类型的策略是基于资源的策略。这些是直接附加到密钥的密钥策略,意味着一个数据库凭据可以有自己的策略,规定哪些身份拥有什么访问权限。
关于访问控制,最重要的实践是最小权限原则。这意味着每个身份应该拥有最小的必要权限,以限制任何出错时的后果。这与之前的密钥管理实践(如 .env 文件)形成对比,后者倾向于根据方便捆绑的密钥来授予访问权限。
一个应用程序角色应该能够在其所需的具体密钥上调用 secretsmanager:GetSecretValue,而不能做其他任何事情。AWS 通过为每个密钥分配一个 Amazon 资源编号 (ARN)(一个唯一的标识符)来实现这一点。
一个严格限定的身份策略如下所示:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:us-east-1:111122223333:secret:prod/db/credentials-??????"
}
]
}
尾部的问号匹配 AWS 附加到每个密钥 ARN 的六字符随机后缀,因此该策略在密钥重新创建后仍然有效,而不会授予访问共享名称前缀的其他密钥的权限。
版本控制与暂存标签
Secrets Manager 中的密钥不是单个值,而是一系列版本,每个版本都有暂存标签进行跟踪。标签 AWSCURRENT 指向应用程序默认检索的版本。在轮换期间,会创建一个新版本并标记为 AWSPENDING,进行测试,然后才提升为 AWSCURRENT。
上一个版本被重新标记为 AWSPREVIOUS,如果轮换出现问题,这为你提供了一步回滚的路径。理解这些标签是理解轮换的关键,本指南后面会讲到。
在控制台上快速入门
创建第一个密钥最快的方法是使用控制台。打开 Secrets Manager,选择 Store a new secret,然后选择一种密钥类型。对于 Amazon RDS、Aurora、Redshift 或 DocumentDB 凭据,专用类型会为你连接数据库引用。对于其他所有情况,选择 Other type of secret 并输入键值对或原始 JSON。
选择你的加密密钥(除非你有理由不选择,否则使用 aws/secretsmanager),给密钥起一个反映清晰层次结构的名称,例如 prod/payments/db-credentials,然后存储它。命名约定比看起来更重要:密钥名称在账户和区域内是唯一的,一致的路径式方案会使 IAM 策略、搜索和审计在后续变得容易得多。
控制台适用于创建第一个密钥和偶尔检查。对于任何可重复的操作,请迁移到 CLI 或 Terraform。
使用 AWS CLI
CLI 是日常密钥管理发生的地方。创建一个密钥只需要一个命令:
aws secretsmanager create-secret \
--name prod/payments/db-credentials \
--description "Payments service database credentials" \
--secret-string '{"username":"payments_app","password":"REPLACE_ME"}'
检索它同样直接:
aws secretsmanager get-secret-value \
--secret-id prod/payments/db-credentials \
--query SecretString \
--output text
更新密钥值会创建一个新版本,并自动将 AWSCURRENT 移动到该版本:
aws secretsmanager put-secret-value \
--secret-id prod/payments/db-credentials \
--secret-string '{"username":"payments_app","password":"NEW_VALUE"}'
一个值得牢记的注意事项:在命令行上传入的任何密钥值都可能出现在你的 shell 历史记录中,并且在某些配置下,还可能出现在进程列表或 CloudTrail 中。对于敏感值,请使用 --secret-string file://creds.json 从文件读取,而不是内联输入值,之后清除该文件。AWS 直接指出这是一种需要缓解的 CLI 风险。
列出和检查密钥是基础知识:
aws secretsmanager list-secrets --query "SecretList[].Name"
aws secretsmanager describe-secret --secret-id prod/payments/db-credentials
describe-secret 返回元数据、轮换配置和版本标签,而不会暴露密钥值,这使得它在自动化和仪表板中使用是安全的。
使用 Terraform 在 AWS Secrets Manager 中管理密钥
Terraform 密钥管理 有点不同。但如果你运行基础设施即代码,Secrets Manager 可以很好地融入 Terraform。aws_secretsmanager_secret 资源定义了密钥容器,aws_secretsmanager_secret_version 保存值:
resource "aws_secretsmanager_secret" "db_credentials" {
name = "prod/payments/db-credentials"
description = "Payments service database credentials"
kms_key_id = aws_kms_key.secrets.id
}
resource "aws_secretsmanager_secret_version" "db_credentials" {
secret_id = aws_secretsmanager_secret.db_credentials.id
secret_string = jsonencode({
username = "payments_app"
password = var.db_password
})
}
这里有一个每个团队最终都会遇到的真实陷阱:Terraform 管理的任何内容都会进入 Terraform 状态,而状态以纯文本形式存储值。
如果你在配置中放入字面密码,它会存在于状态和任何计划输出中。避免这种情况的常见模式是:从标记为 sensitive = true 的变量中获取值;让数据库资源生成密码并通过引用传递;或者使用 Terraform 创建空密钥,然后通过单独的进程写入实际值,这样它就不会进入状态。将你的状态后端(通常是带有锁定的加密 S3 存储桶)本身视为一个密钥存储。
要在配置的其他地方使用现有密钥,aws_secretsmanager_secret_version 数据源会在计划时读取当前值:
data "aws_secretsmanager_secret_version" "db" {
secret_id = "prod/payments/db-credentials"
}
同样的状态中纯文本注意事项也适用于数据源,因此要谨慎地引用它们。
轮换密钥
轮换是区分 Secrets Manager 与简单加密存储的功能,也是最值得正确理解的功能。密钥轮换是自动的、定期的密钥更改。这是一种最佳实践,用于使任何可能意外泄露或将来可能泄露的凭据失效。
Secrets Manager 的轮换运行在一个 AWS Lambda 函数上。当触发轮换时,Secrets Manager 会调用该函数四次,每个步骤一次:
createSecret → 生成一个新凭据,存储为 AWSPENDING
setSecret → 将新凭据应用到数据库或服务
testSecret → 验证 AWSPENDING 凭据是否真正有效
finishSecret → 将 AWSCURRENT 标签移动到新版本
只有在 finishSecret 完成后,应用程序才会开始接收新值,因为它们默认检索 AWSCURRENT。如果任何步骤失败,旧凭据将继续服务于流量,你可以在不中断服务的情况下进行调查。
有两种轮换策略,选择会带来真正的操作后果:
单用户轮换 在原地更新一个数据库用户的密码。设置起来更简单,但会在轮换期间创建一个短暂的窗口期,在此期间使用旧密码进行中的连接可能会失败。它适用于能够容忍短暂波动或能够干净重新连接的工作负载。
交替用户轮换 维护两个用户并在它们之间切换。当一个用户的凭据是活动的并为流量服务时,另一个用户在后台被轮换,然后 AWSCURRENT 标签切换到它。这实际上实现了零停机轮换,是高可用性服务的更好选择。它需要一个具有管理轮换用户权限的第二个管理员(超级用户)密钥。
对于 Amazon RDS、Aurora、Redshift 和 DocumentDB,AWS 提供了现成的轮换函数模板,因此你无需自己编写 Lambda。对于其他数据库或自定义服务,AWS 发布了一个你可以根据自己的系统定制的通用轮换模板。Secrets Manager 支持每四个小时轮换一次,除了底层的 Lambda 调用外,无需额外费用。
从 CLI 启用轮换如下所示:
aws secretsmanager rotate-secret \
--secret-id prod/payments/db-credentials \
--rotation-lambda-arn arn:aws:lambda:us-east-1:111122223333:function:rotate-payments-db \
--rotation-rules '{"ScheduleExpression":"rate(30 days)"}'
所有这些功能都通过原生集成与其他 AWS 资源和服务关联。这正是许多使用 AWS 的团队首先评估它的原因。但与其他所有工具一样,AWS Secrets Manager 也有优点和缺点,并且并非适用于所有用例(即使你严重依赖 AWS)。
AWS Secrets Manager 的优缺点
优点
- 直接与 IAM 集成。无需单独的身份验证层,你的基础设施已经使用的相同角色和策略即可管理密钥访问。
- 为 RDS、Aurora、Redshift 和 DocumentDB 内置了轮换功能,覆盖了大多数团队最重要的凭据。
- 完全托管:无需运行服务器、无需配置存储、无需手动编排密钥轮换。
- 对于已经处于 AWS 生态系统内(并且没有计划扩展出去)的团队来说,留在该生态系统内可能很方便。
缺点
- 对于 AWS 外部的工作负载没有原生解决方案。多云团队最终会管理并行的存储或构建它们之间的桥梁。
- 按每个密钥每个区域定价的模式,在小规模时可以忽略不计,但当密钥跨环境和区域复制时,成本会变得显著。
- 没有内置的访问生产凭据的审批流程、没有变更管理、也没有跨团队的统一审计视图。
- 轮换功能对 AWS 管理的数据库支持良好,但对于其他任何数据库,则需要自定义 Lambda 函数。
成本及如何控制
Secrets Manager 的定价很简单,但很容易被低估。标价是每个密钥每月 0.40 美元,加上每 10,000 次 API 调用 0.05 美元。该定价在所有 36 个 AWS 区域中相同,这在 AWS 服务中是一个罕见的例外,这意味着你可以根据延迟和合规性而不是成本来选择区域。
对于一个只有几十个密钥的小团队来说,账单通常只有几美元一个月,这是一个可以忽略不计的项目。但随着组织的壮大,团队经常在几个方面计算错误,导致 AWS Secrets Manager 账单高昂:
环境和区域倍增 一百个生产密钥,一旦你将其复制到生产、预发布、QA 和开发环境中,就变成了四百个。现在,再乘以每个区域,任何快速增长的公司的 Secrets Manager 成本都会迅速增加。
API 调用量 许多团队低估了密钥被获取的频率。如果一个数据库凭据在自动扩缩容的容器群中的每个请求上都被获取,它可能会产生数百万次调用。
AWS Secrets Manager 定价政策的一个问题是,它不利于良好的安全态势。像动态密钥(即时创建的短期凭据)和频繁轮换这样的最佳实践,比长期、静态凭据更重要。
AWS Secrets Manager 最佳实践
使 Secrets Manager 安全且可维护的大部分因素归结为少数几个纪律:
将密钥集中到 Secrets Manager 中。 对于密钥管理,将所有内容放在一个地方很重要。所有密钥都应在 Secrets Manager 中管理,以使 DevOps 或平台团队有确定性并能够完全审计。这可以使事件响应更容易,并限制任何潜在泄露的爆炸半径。
使用 IAM 角色进行 AWS 到 AWS 的身份验证,这样一开始就无需管理引导密钥。为了捕捉漏网之鱼,将 Secrets Manager 与仓库中的密钥扫描配对,以便在泄露的凭据成为事件之前就被检测到。
通过 IAM 严格限定访问范围。 授予对特定密钥 ARN 的 GetSecretValue 权限,而不是使用通配符。使用基于资源的策略添加第二层控制,并通过在 PutResourcePolicy 调用上设置 BlockPublicPolicy 来阻止广泛访问。
在底层系统支持的地方开启轮换。 轮换后的凭据是有时间限制的凭据。对于无法容忍连接波动的场景,选择交替用户轮换。
使用 CloudTrail 审计所有操作。 每次 Secrets Manager API 调用都会被记录。CloudTrail 为你提供了谁在何时检索了哪个密钥的记录,这既是操作工具,也是 SOC 2 和 PCI DSS 等框架下的合规要求。
缓存读取并适当调整 Secrets Manager 中存储的内容。 缓存可以保护你的延迟和账单。将静态配置排除在 Secrets Manager 之外,可以使服务专注于真正的密钥。
使用清晰的命名层次结构。 像 <env>/<service>/<purpose> 这样的方案可以使策略、搜索和访问推理随着密钥数量增长而伸缩,而不是与之对抗。
当 AWS Secrets Manager 不够用时
当你的世界是一个 AWS 账户时,AWS Secrets Manager 是一个出色的默认选择。它深度集成、托管,并且对 AWS 原生工作负载效果良好。许多团队直接使用它并继续前进。
但 AWS Secrets Manager 很快就会遇到限制。作为 AWS 专有产品,它不支持多云和混合基础设施。一旦你还在 Azure、GCP、本地以及跨 SaaS 平台上运行工作负载,你就需要使用单独的解决方案。这抵消了每个环境中中心化的好处,并要求你的组织构建脆弱的变通方案来弥合并行密钥基础设施之间的差距。一旦工作负载超出 AWS 范围,许多团队开始评估AWS Secrets Manager 的替代方案。
第二个是工作流程深度。Secrets Manager 可以很好地存储和轮换密钥,但在人工流程方面提供的很少:访问凭据的审批工作流、细粒度的变更管理、跨团队的统一审计视图,或按需生成的动态短期密钥。团队通常需要自己构建这些功能,这会产生依赖关系,并成为一个需要维护的内部工具。
第三个是规模化时的成本行为。当团队规模很小的时候看似微不足道的成本,一旦密钥数量增长到数千,且基础设施需要数百万次 API 调用时,就会成为一个值得质疑的条目。
为什么有些团队使用 Infisical 而不是 AWS Secrets Manager
这就是专用的身份和密钥平台发挥作用的地方,它与其说是 AWS 的替代品,不如说是一个将所有东西统一起来的层。Infisical 提供了一个与任何类型的基础设施配合使用的密钥管理平台,并提供了许多 AWS Secrets Manager 所缺少的工作流程和开发者体验升级。它构建在 Postgres 而不是专有基础设施之上,可以在云中运行或完全自托管,并为开发人员提供开箱即用的可用仪表板、审批工作流和动态密钥。
采用它并不意味着破坏性迁移。Infisical 的 AWS Secrets Manager 同步 直接连接到你的现有设置:你可以导入已有的密钥,保持同步,并采用中心化工作流,而无需拆除任何东西。这正是 Infisical 客户 Teamworks 所做的:AWS Secrets Manager 仍然是他们工作流程的核心部分,但在他们超越单一云基础设施后,Infisical 成为了统一管理密钥的层。有关更广泛的选择调查,我们的最佳密钥管理工具汇总提供了并排比较。
- 原文链接: infisical.com/blog/aws-s...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~