4. 密钥的访问控制:IAM策略与权限管理归纳总结

密钥的访问控制,说白了就是「谁能在什么条件下、对哪把密钥做什么操作」。我过去在帮一家金融客户做KMS迁移时,就因为权限策略没写清楚,导致一个测试账号能删生产密钥……那一次真是惊出一身冷汗。所以这一章我打算把IAM策略和KMS权限管理的核心要点掰开揉碎了讲清楚。

4.1 IAM策略的基本模型

IAM策略分两类:身份策略(贴给用户/角色/组)和资源策略(直接贴到密钥上)。KMS同时支持这两类,但实际项目中我更推荐优先用资源策略——因为密钥的权限边界更清晰。

一个完整的策略文档包含四个要素:

  • 主体(Principal):谁可以访问?用ARN指定用户/角色。
  • 操作(Action):能做什么?kms:Encrypt、kms:Decrypt、kms:CreateKey 等。
  • 资源(Resource):作用于哪些密钥?通常写 "arn:aws:kms:region:account:key/*" 或精确到某个Key ID。
  • 条件(Condition):额外的限制,比如来源VPC、加密上下文、请求时间等。

下面这个表格能帮你快速区分两类策略的适用场景:

策略类型挂载位置典型使用场景权限范围
身份策略IAM用户/角色/组给开发人员分配通用加密权限跨多个密钥
资源策略CMK(客户主密钥)限制特定密钥只能由特定服务或账号使用只作用于该密钥

我个人习惯:平时用资源策略管密钥,只有需要跨密钥批量授权时才用身份策略。这样每个密钥的权限一目了然,审计日志对起来也快。

4.2 细粒度权限设计原则

这里有三条铁律,是我踩过坑后总结出来的:

  1. 最小权限:给操作员只开放他用得到的那几个API。比如只做加密的人,别给他kms:Decrypt。
  2. 职责分离:密钥管理员(能创建/删除/轮换密钥)和密钥使用者(只能加解密)必须分开。我曾经把这两个角色混到一个组里,结果有人误删了密钥,所有加密数据全部作废……心疼那几天的恢复工作。
  3. 条件约束:尽量加上 Condition 限定。比如只允许来自特定VPC的请求,或者只允许带有特定加密上下文的调用。
⚠️ 避坑指南
我曾经遇到一个场景:给Lambda角色赋予了 kms:* 权限。结果Lambda函数被注入恶意代码后,攻击者直接用这个角色删除了所有密钥。教训就是——永远别用通配符 * 在KMS上。就算你图省事,也要用 kms:Encrypt,kms:Decrypt 这样的显式列表。

嗯,这里再补充一个细节:条件里的 kms:ViaService 非常实用。比如你希望某个密钥只给ECS服务用,写在资源策略里:"Condition": { "StringEquals": { "kms:ViaService": "ecs.amazonaws.com" } }。这样就算有人拿着管理员权限发请求,只要不是来自ECS,照样被拒绝。

4.3 常见权限配置模式

讲几个我在生产环境反复用过的模式:

模式一:加密解密权限分离

开发团队用加密权限(Encrypt/GenerateDataKey),运维团队用解密权限(Decrypt)。这样就算开发人员的账号被盗,攻击者也解不了生产数据。

模式二:密钥管理员 vs 密钥使用者

创建一个管理员角色,可以管理密钥生命周期(CreateKey/EnableKeyRotation/ScheduleKeyDeletion);再创建一个使用者角色,只能进行密码运算。两者用不同IAM路径隔离。

模式三:限制加密上下文

在资源策略里强制要求加密上下文匹配某个固定值。例如:"Condition": { "StringEquals": { "kms:EncryptionContext:department": "finance" } }。这样就算有人拿到了密钥,也得知道上下文才能解密——多了一层防护。

下面这张表汇总了三种模式的策略片段:

模式关键操作典型条件适用角色
读/写分离开发者:Encrypt, GenerateDataKey
运维:Decrypt
无或按IP限制开发/运维组
管理/使用分离管理员:CreateKey, EnableKeyRotation
使用者:Encrypt, Decrypt
管理员可附加kms:ViaService条件安全团队/业务团队
上下文绑定额同上kms:EncryptionContext:appId = "order-service"微服务场景
💡 小技巧
写策略时可以先在AWS IAM Policy Simulator里测试,或者用aws kms encrypt --dry-run参数模拟执行。我每次改策略都先跑一遍模拟,确认不会意外拒绝正常业务。

4.4 权限审计与监控

策略写好了,不代表万事大吉。你想想看,业务在变,人员流动也在变。权限会慢慢变宽。我建议你做三件事:

  • 激活CloudTrail审计日志:记录每次KMS API调用,至少保留90天。
  • 定期用IAM Access Analyzer:它会自动检测哪些策略有「越权」风险。比如某个资源策略允许了匿名主体访问,它会直接报告警。
  • 每季度做一次权限Review:把策略文档拉出来,逐个密钥过一遍。问问自己:「这把密钥真的还需要对那个旧角色开放吗?」

我记得有一次Review,发现一个三年前试用的临时角色仍然拥有某个核心密钥的 kms:Decrypt 权限。幸好发现得早,没出事故。从那以后我就把权限Review写进了SOP。

4.5 最佳实践总结

好了,把这一章的核心要点串起来——

  • 优先使用资源策略绑定到密钥,权限边界清晰。
  • 坚持最小权限:明确列出需要的操作,别用 *。
  • 利用Condition强化约束:kms:ViaService、加密上下文、来源IP。
  • 分离管理员与使用者角色。
  • 定期审计并清理僵尸权限。
一句话总结:
密钥的访问控制不是「写一次就完事」,而是需要持续治理的活。但只要你把策略模型吃透、条件用对、审计跟上,就能把风险降到最低。

下面这张图帮你直观理解整个IAM策略与KMS密钥的访问控制关系:

IAM策略与KMS密钥访问控制关系图 IAM 主体 用户 / 角色 / 组 IAM 策略 Effect: Allow/Deny Action: kms:Encrypt Resource: key/* KMS 操作 Encrypt / Decrypt GenerateDataKey / CreateKey Condition kms:ViaService EncryptionContext CMK (客户主密钥) arn:aws:kms:region:... 访问控制流程 IAM主体携带策略 → 策略匹配操作和条件 → 最终决定是否允许对指定密钥执行动作

从图里能清楚看到:主体通过策略绑定到操作,而操作最终作用于具体的CMK,而且中间还可以插一层条件来做精细控制。这就是整个KMS访问控制的骨架。记住它,你写策略时就不会乱。