Amazon SCS-C02: 加密、KMS 与密钥 — 学习指南
属于 AWS Security Specialty SCS-C02 — 学习指南. 使用经过验证的答案练习: Amazon 考试中心, 或参加限时模拟考试: ExamRoll.io.
AWS KMS 密钥类型、策略和访问控制
AWS KMS 支持三大类密钥,选择正确的类型决定了谁控制密钥材料、密钥材料的存放位置以及如何轮换。AWS 拥有的密钥对您不可见,不产生费用,并由 S3 等服务在您启用 SSE-S3 时使用。AWS 托管的密钥(别名为 aws/<service>)允许服务代表您进行加密,但您无法修改其密钥策略,因此它们不适用于跨账户访问或精细化治理。客户托管密钥 (CMK) 是主力:您可以控制密钥策略、轮换(每年自动或按需)、授权 (grants)、别名和删除窗口期。
两种特殊的变体很重要。当法规或 BYOK(自带密钥)要求强制您在 AWS 外部生成密钥材料并将其导入 KMS 密钥时,会使用导入的密钥材料。导入的材料是配置密钥材料显式过期的唯一方法——AWS 生成的 CMK 永不过期。您不能对导入的密钥启用 AWS 年度自动轮换;您必须自己重新导入材料。多区域密钥通过副本密钥在多个区域间共享相同的密钥 ID 和材料,因此在 us-east-1 中生成的密文可以在 us-west-1 中解密,无需重新加密。每个副本都有自己独立的密钥策略和别名,但加密材料是同步的。
最容易被误解的控制是 KMS 密钥策略。与大多数仅凭 IAM 策略即可授予访问权限的 AWS 资源不同,KMS 密钥使用其密钥策略作为根授权。授予某个密钥 kms:Decrypt 权限的 IAM 策略本身是无效的,除非密钥策略也通过 Principal 为账户根用户加上适当的声明,或直接指定该主体,从而将访问权限委托给 IAM。这就是为什么拥有 AdministratorAccess 权限的工程师在调用某个 CMK 的 Decrypt 操作时,如果该 CMK 的策略不信任其所在账户,仍然会收到 AccessDenied 错误。规范的委托声明如下所示:
{
"Sid": "EnableIAMPermissions",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:root" },
"Action": "kms:*",
"Resource": "*"
}
授权 (Grants) 和 ViaService 条件增加了分层限制——例如,强制要求密钥只能通过特定区域的 S3 使用,条件为 kms:ViaService: s3.us-east-1.amazonaws.com。
服务器端和客户端加密
对于 S3,两种常见的服务器端选项主要在控制和可审计性方面有所不同:
- SSE-S3 (AES-256): S3 完全管理密钥;没有客户可见的密钥策略,没有按密钥记录的 CloudTrail 解密事件,也没有跨账户治理。对于基本的静态加密来说足够了,但当合规性要求证明谁解密了数据时,则显不足。
- SSE-KMS: 使用您控制的 CMK;每次解密调用都会被记录,密钥策略强制执行访问控制,并且您可以按加密上下文进行限制。它的每次请求成本更高,并消耗 KMS TPS 配额,因此应启用存储桶密钥 (
BucketKeyEnabled: true) 以显著减少 KMS 调用。
当数据必须在离开应用程序之前加密,或者存储服务绝不能看到明文时,适合使用 AWS Encryption SDK 进行客户端加密。高吞吐量的工作负载应使用缓存加密材料管理器 (CachingCryptoMaterialsManager) 包装 SDK,该管理器在可配置的字节、消息和 TTL 限制内,跨多个消息重用数据密钥。如果不进行缓存,每次 encrypt 调用都会触发一次 GenerateDataKey 请求,这会迅速耗尽 KMS 请求配额并增加成本。
from aws_encryption_sdk import CachingCryptoMaterialsManager, LocalCryptoMaterialsCache
cache = LocalCryptoMaterialsCache(capacity=100)
ccmm = CachingCryptoMaterialsManager(
master_key_provider=mkp, cache=cache,
max_age=600.0, max_messages_encrypted=10000)
Secrets Manager 和 Parameter Store
Secrets Manager 使用 KMS CMK 加密存储凭证,并通过 Lambda 函数支持自动轮换——AWS 为 RDS、Redshift 和 DocumentDB 提供了模板,而自定义 Lambda 可以处理任何其他情况。轮换运行一个四步状态机(createSecret、setSecret、testSecret、finishSecret),它将新凭证暂存在 AWSPENDING 标签下,然后将其提升为 AWSCURRENT。应用程序应捕获身份验证失败,刷新密钥并重试——这种模式可以消除停机时间,因为之前的凭证会通过 AWSPREVIOUS 短暂保持有效。
当轮换 Lambda 在 VPC 内运行时(通常是为了访问私有 RDS 实例),它需要到 Secrets Manager 服务终端节点的出站网络访问。在没有 NAT 的私有 VPC 中,您必须部署一个接口 VPC 终端节点 (com.amazonaws.<region>.secretsmanager),并允许 Lambda 的安全组访问该终端节点的 443 端口。忘记这一点是一个典型故障:轮换看起来已配置好,但每次调用都会超时。
为了实现跨区域弹性,请使用多区域 KMS 密钥和 Secrets Manager 的副本密钥功能。us-east-1 中的主密钥使用主 CMK 加密;us-west-1 中的副本使用副本 CMK 解密。像 alias/prod-db 这样的别名可以按需指向新的密钥 ID,以便在不更改应用程序代码的情况下快速进行密钥轮换。
当您不需要轮换功能时,Parameter Store 的 SecureString 类型是一个轻量级的替代方案。这两种服务都在 CloudFormation 中提供动态引用 ({{resolve:secretsmanager:MySecret:SecretString:password}}),因此堆栈模板永远不会嵌入明文。
EBS、RDS、Aurora 和快照加密
静态加密在创建卷或实例时按需启用,并且无法原地切换。对于不合规的未加密资源,修复模式是快照复制并加密:
aws ec2 copy-snapshot --source-snapshot-id snap-abc \
--source-region us-east-1 --encrypted \
--kms-key-id alias/prod-ebs
aws ec2 create-volume --snapshot-id snap-newEncrypted ...
对于 RDS 和 Aurora,将加密的快照恢复到一个新实例中,然后进行切换。跨账户恢复需要共享快照并通过密钥策略授予目标账户对 CMK 的 kms:CreateGrant 和 kms:Decrypt 权限——仅共享快照会失败,因为目标账户无法解密数据密钥。应启用账户级别的 EBS 默认加密,以便无论调用者行为如何,新创建的卷始终被加密。
TLS:ACM 与 ALB 策略
当绑定到集成服务(如 ALB、CloudFront、API Gateway)时,ACM 可以免费颁发并自动续订公有证书。这些证书无法被导出,因此,若要在 EC2 上终止 TLS,就需要使用 ACM Private CA(用于导出私有证书)或导入的证书。一个实用的模式是:使用 ACM 证书在 ALB 处终止公有 TLS,如果需要端到端加密,则在 ALB 到 EC2 的跃点上使用自签名证书或私有 CA 证书。通过使用像 ELBSecurityPolicy-TLS13-1-2-2021-06 这样的安全策略,可以强制客户端使用现代密码套件,该策略会禁用 TLS 1.0/1.1 和弱密码套件。
常见陷阱
没有密钥策略的 IAM。 如果在 IAM 策略中授予了 kms:Decrypt 权限,但 CMK 的密钥策略中省略了账户主体,将会导致 AccessDenied 错误。KMS 将密钥策略视为权威;IAM 权限只能在密钥策略允许的范围内进行进一步限制。
没有 VPC 端点的轮换 Lambda。 如果 Lambda 在私有子网中运行,而 VPC 没有 NAT 网关且没有 secretsmanager 接口端点,那么对 secretsmanager.<region>.amazonaws.com 的轮换调用将无法解析或连接。端点上的安全组还必须允许来自 Lambda 安全组的 443 端口流量。
将 SSE-S3 等同于 SSE-KMS。 SSE-S3 使用 AWS 拥有的密钥,该密钥没有客户可编辑的策略,不在 CloudTrail 中提供逐对象的解密日志记录,也不支持跨账户密钥共享。它满足了“静态加密”的基本要求,但无法强制规定哪些主体可以解密特定对象——只有使用 CMK 的 SSE-KMS 才能提供这种治理能力。
实践问题:用例场景
场景: Meridian Financial 公司在一个多账户的 AWS Organization 中运营,其中包括一个安全账户、独立的生产/非生产账户、由 ALB 提供前端的 ECS/EKS 微服务、RDS/Aurora 集群、由 EBS 支持的 EC2 实例以及 S3 数据湖。目前,开发人员和自动化流程混合使用了 AWS 托管密钥、明文 SSM 参数,并且偶尔在账户之间手动共享快照。
挑战: 一名工程师意外地将一个未加密的 RDS 快照共享给了一个第三方账户,并且发现有几个 API 凭证以明文 SecureString 参数的形式存储,这带来了数据泄露和未经授权的恢复访问风险。
推荐方法:
- 在安全账户中创建一个组织范围的、客户管理的 AWS KMS 对称 CMK,其密钥策略通过 aws:PrincipalOrgID 授予成员账户使用权限,并启用自动轮换;对于短期的跨账户操作,使用授权 (grants)。
- 通过复制未加密的 RDS 快照和任何 EBS 快照来修复现有构件,在复制过程中选择新的 CMK 以生成加密副本,然后删除原始的未加密快照;设置账户默认值,以便新创建的 RDS 和 EBS 资源默认就是加密的。
- 将密钥迁移到 AWS Secrets Manager(或 SSM Parameter Store SecureString)中,并使用该 CMK 进行加密,通过 Lambda 为数据库凭证启用 Secrets Manager 自动轮换,并使用基于资源的策略和最小权限 IAM 角色来限制访问。
- 通过配置由 ACM 管理的 TLS 证书并将其附加到 ALB 上,同时采用现代 TLS 策略(TLS 1.2/1.3),来强制执行传输中加密,并配置数据库和客户端要求使用 TLS 连接。
- 通过护栏防止再次发生:应用服务控制策略 (SCP) 来拒绝创建/共享未加密的快照和未加密的 S3 上传操作,为加密资源启用 AWS Config 规则,并通过 CloudTrail 和 CloudWatch Alarms 监控 KMS 和 Secrets Manager 的使用情况。
基本原理: 采用具有组织级别策略的中央 CMK、自动重新加密、使用 Secrets Manager 管理密钥生命周期、强制执行 TLS 以及设置预防性护栏,这些都遵循了 AWS 的最小权限和深度防御最佳实践,旨在消除明文密钥和未经授权的快照访问。
客户托管的 CMK:多区域、导入材料和密钥策略
客户托管的 CMK 是您在 AWS 中自有数据所有加密操作的控制平面。最常决定设计成败或导致服务中断的三个属性是:密钥的区域拓扑、其密钥材料的来源以及附加到它的策略。
多区域密钥是一组位于不同区域的 KMS 密钥,它们共享相同的密钥 ID,并且最关键的是,共享相同的底层密钥材料。它们不会像 DynamoDB 全局表那样自动复制——您需要使用 ReplicateKey 从主密钥显式创建副本。由于副本之间的密钥材料完全相同,因此在 us-east-1 中生成的密文可以在 us-west-1 中解密,而无需进行跨区域的 KMS 调用。这正是在跨区域复制 Secrets Manager 机密时所必需的特性:故障转移区域中的副本机密必须能够在本地解密,这既是为了消除每次 GetSecretValue 调用时的跨区域延迟,也是为了在主区域发生区域性中断时仍能正常工作。单区域 CMK 无法为另一个区域中的 Secrets Manager 副本提供支持,因此正确的模式是使用多区域 CMK 加密主机密,将该密钥复制到目标区域,然后在复制机密时指向副本 CMK。
aws kms create-key --multi-region --region us-east-1
aws kms replicate-key --key-id mrk-abc123 \
--replica-region us-west-1
aws secretsmanager replicate-secret-to-regions \
--secret-id prod/db \
--add-replica-regions Region=us-west-1,KmsKeyId=mrk-abc123
当您在 AWS 外部生成原始 AES-256 材料并将其导入到一个 KMS 密钥“外壳”中时,就存在导入的密钥材料(外部来源,Origin=EXTERNAL)。AWS 绝不会在 HSM 的受保护内存之外拥有该材料的副本,并且没有备份。如果您删除了导入的材料——无论是通过 DeleteImportedKeyMaterial 还是因为其到期日已过——密钥状态将变为 PendingImport,并且在该密钥下生成的所有密文都将无法恢复,除非您重新导入完全相同的字节。例如,当一个 EBS 卷因其加密的数据密钥无法解密而挂载失败时,这就是恢复路径:从您的离线托管中重新导入相同的密钥材料,该卷即可再次使用。没有任何 AWS 端的恢复方法、轮换技巧或支持工单可以恢复已删除的导入材料。应将离线副本视为零层基础设施。
密钥策略是每个 KMS 密钥的信任根。与单独使用 IAM 不同,KMS 要求在密钥策略本身中进行显式允许;一个授予 kms:Decrypt 权限的 IAM 策略是无效的,除非密钥策略将权限委托给 IAM("Principal": {"AWS": "arn:aws:iam::111122223333:root"} 并结合条件语句)。对于跨账户使用,密钥的策略必须明确指定外部账户或主体,然后外部账户必须通过 IAM 为其自己的用户授予权限。忘记配置密钥策略是跨账户 Secrets Manager 失败的最常见原因——Secrets Manager 资源策略允许外部主体调用 GetSecretValue,但底层的 Decrypt 操作会失败,因为 CMK 仍然拒绝该调用者。
Secrets Manager 和 Parameter Store SecureString 模式
Secrets Manager 和 SSM Parameter Store SecureStrings 都将加密委托给 KMS,但它们在成本、轮换语义和跨区域行为方面有所不同。Secrets Manager 支持原生多区域复制、带暂存标签(AWSCURRENT、AWSPENDING)的版本控制以及由 Lambda 支持的轮换。Parameter Store SecureString 成本更低,与分层路径集成,并且非常适用于不经常轮换的配置类机密。
对于跨账户访问,您必须同时更新机密上的资源策略(或 Parameter Store 消费者账户中的 IAM 策略)和用于加密的 CMK 上的密钥策略。认为仅有 Secrets Manager 权限就足够是错误的,因为检索工作流总是会对 CMK 执行隐式的 kms:Decrypt 操作;如果没有密钥策略对外部账户的允许,即使机密自身的策略得到满足,调用者在 Decrypt 步骤也会收到 AccessDeniedException。
- Secrets Manager: 托管轮换,JSON 结构,约 $0.40/机密/月,内置多区域复制功能
- Parameter Store SecureString (Advanced): 对于大量值更便宜,每参数 8 KB,无内置跨区域复制功能
- Parameter Store SecureString (Standard): KMS 加密的参数有免费套餐(最高 4 KB),无轮换框架
信封加密、存储桶密钥和授权令牌
信封加密意味着 KMS 永远不会接触您的批量数据。您可以调用 GenerateDataKey,它会返回一个明文数据密钥(用于在本地使用 AES-GCM 加密您的有效负载)和一个该数据密钥的加密副本(与密文一起存储)。要解密,您需要对包装的数据密钥调用 Decrypt,并在本地重新派生出明文密钥。这种模式至关重要,因为 KMS 有请求配额(按区域、按密钥)和按 API 调用计费的定价。如果您对每条 4 KB 的记录都进行直接的 Encrypt 调用,您将遇到节流和成本悬崖;如果您为每批或每个文件生成一个数据密钥,吞吐量将与您的本地加密库呈线性扩展。
S3 存储桶密钥在 S3 内部为 SSE-KMS 应用了相同的原则。如果没有存储桶密钥,每次对 SSE-KMS 对象的 PUT 和 GET 操作都会产生一个 GenerateDataKey 或 Decrypt 调用。在一个每秒接收数千个对象的存储桶上,这会产生 KMS 节流和一笔惊人的 KMS 账单。启用存储桶密钥会使 S3 在存储桶级别生成一个短期密钥,并为许多对象重用它,从而将 KMS 请求量减少几个数量级:
aws s3api put-bucket-encryption --bucket app-data \
--server-side-encryption-configuration '{
"Rules":[{
"ApplyServerSideEncryptionByDefault":{
"SSEAlgorithm":"aws:kms","KMSMasterKeyID":"alias/app"},
"BucketKeyEnabled":true}]}'
**授权(Grants)**是密钥策略的一种替代方案,用于临时的、细粒度的委托。它们在操作上很重要,因为存在最终一致性:CreateGrant 返回后,该授权不会立即对区域中的每个 KMS 端点可见。如果客户端在几毫秒后尝试 Encrypt,它可能会收到 AccessDeniedException。CreateGrant 的响应正文中包含一个 GrantToken 字符串,当通过 --grant-tokens 参数在后续的 KMS 调用中传递时,它会强制 KMS 立即履行该授权,而不管其传播状态如何。
TOKEN=$(aws kms create-grant --key-id $KEY \
--grantee-principal arn:aws:iam::111122223333:role/worker \
--operations Encrypt Decrypt --query GrantToken --output text)
aws kms encrypt --key-id $KEY --plaintext fileb://payload \
--grant-tokens "$TOKEN"
依赖带退避的重试而不是使用授权令牌是一种有效但较差的缓解措施——它会浪费延迟,并且在负载下仍然会失败。标准的答案永远是:从创建授权的服务返回授权令牌,并要求调用者在他们的第一个操作中出示它。
实践问题:用例场景
场景: Meridian Financial 在一个多账户 AWS 环境中运营,该环境在 S3 中托管客户 PII,在 RDS 中托管事务性数据库,并通过 Lambda 进行无服务器处理。他们使用带有导入密钥材料的客户管理型 CMK 来满足区域性的密钥保管规则,并将密钥复制到第二个区域以进行灾难恢复。
挑战: 最近的一次审计发现了一个配置错误的 KMS 密钥策略,该策略允许跨账户解密,并且一个外部审计员需要临时访问权限来解密 S3 对象的一个子集;Meridian 还需要安全的密钥轮换和对大对象的高效加密,以控制 KMS 请求成本。
推荐方法:
- 轮换 AWS KMS 中配置错误的 CMK 策略,改为一个最小权限策略,该策略明确仅授予所需的 IAM 主体和角色,并使用 KMS 多区域密钥为 DR 创建一个多区域副本 CMK。
- 根据合规窗口重新导入或为导入的密钥材料安排生命周期管理,并使用 AWS Config 和 EventBridge 启用密钥材料自动过期/轮换通知。
- 对于审计员,创建一个具有较短 TTL 的 KMS 授权,并在审计员的代入角色会话中立即使用授权令牌,以允许临时的解密操作,而无需更改密钥策略。
- 将长期凭证移至 AWS Secrets Manager,并使用基于 Lambda 的轮换,该轮换与底层服务(RDS 或 API 密钥)绑定,并将基础设施参数作为 Systems Manager Parameter Store SecureString 存储非轮换项目,强制使用 CMK 加密和严格的基于资源的策略。
- 通过在应用程序代码中或通过 AWS SDK 调用 KMS GenerateDataKey (Encrypt/Decrypt) 来为大型 S3 对象实施信封加密,并启用 S3 存储桶密钥以减少对大型对象进行服务器端加密时的 KMS 请求和成本。
- 启用 CloudTrail 日志记录和 KMS 密钥使用情况日志记录,并创建 CloudWatch Alarms/GuardDuty 规则,以便在发生意外的解密或授权创建时发出警报。
基本原理: 此方法强制实施了密钥的最小权限访问,为导入的材料和多区域连续性保留了合规性,使用临时授权实现安全的第三方访问,通过轮换集中管理密钥,并根据 AWS 最佳实践优化了 KMS 的使用和成本。
← 日志、审计与取证 · 所有领域 · 数据保护与 S3 →
练习这些题目 → · 在 ExamRoll.io 上限时练习 →
Pass the whole exam — not just this question
You found this answer. Get every verified question and explanation in one place, and save hours of prep. Free to start.
通过考试 →