3. 创建和管理客户主密钥(CMK):控制台与CLI操作,密钥策略配置要点

咱们书接上回。上一章我们把 KMS 的基础概念理清了,这一章直接上手操作。创建 CMK 其实不难,但是管好它、用对策略,才是真正体现功力的地方。我见过太多团队,密钥创建了一堆,最后审计的时候发现权限全乱套了。

所以这一章,我带你从控制台点一遍,再从 CLI 敲一遍,最后把密钥策略这个核心要点说透。你想想看,如果密钥策略写错了,那审计日志里要么全是拒绝记录,要么就是谁都能用——这两个极端都挺危险的。

3.1 控制台创建 CMK:一步步来

我第一次创建 CMK 的时候,其实也被那些配置项绕晕过。后来总结了一套流程,走熟了就觉得没什么特别的了。

  1. 登录 KMS 控制台:找到"客户管理密钥",点击"创建密钥"。
  2. 选择密钥类型:对称还是非对称?我个人的习惯是,90% 的场景用对称密钥就够了。你如果只是做 Envelope Encryption(信封加密),对称密钥够用。
  3. 给别名(Alias):这一步别偷懒。直接写个有意义的别名,比如 app-prod-db-encryption-key。我踩过坑——第一次设了个 test-key,结果几个月后谁都不知道这个 key 干嘛用的。
  4. 定义密钥管理员:这里选哪些 IAM 用户/角色可以管理这个密钥(启用/禁用/轮换)。记住,管理员不等于使用者。
  5. 定义密钥使用者:选哪些主体可以用这个密钥做加密/解密操作。
  6. 审核密钥策略:这一步是控制台生成的默认策略,我建议你把 JSON 复制出来看一眼,心里有个数。
控制台默认生成的策略,其实是"启用 IAM 策略控制"的模式。也就是说,它会允许实体的 IAM 策略来赋予权限。我个人更推荐这种方式,比直接把主体写死在策略里更灵活。

3.2 AWS CLI 操作:效率翻倍

说实话,我都习惯用 CLI 了。特别是你要批量创建或者自动化运维的时候,点控制台太慢了。来看几个常用命令。

创建 CMK

# 创建一个对称 CMK,启用自动轮换
aws kms create-key \
    --description "Production database encryption key" \
    --key-usage ENCRYPT_DECRYPT \
    --origin AWS_KMS \
    --tags TagKey=Environment,TagValue=Production

# 输出会返回 KeyId 和 Arn,记得存好

这里有个细节:--origin 参数。如果你选 EXTERNAL,那把密钥材料导入的过程会比较麻烦。我建议刚开始的用户直接用 AWS_KMS,别给自己加戏。

给 CMK 加别名

# 创建别名,关联到上面那个 KeyId
aws kms create-alias \
    --alias-name alias/prod-db-key \
    --target-key-id 1234abcd-12ab-34cd-56ef-1234567890ab
别名创建后不能直接用 update 修改关联的 KeyId。你得先删除旧别名,再创建新的。如果正在用的应用是用别名引用密钥的,操作前一定要确认好影响范围。我曾经在生产环境吃过这个亏——换别名时有一段时间应用找不到密钥,幸好是低峰期。

启用/禁用密钥轮换

# 启用自动轮换
aws kms enable-key-rotation --key-id 1234abcd-12ab-34cd-56ef-1234567890ab

# 查看轮换状态
aws kms get-key-rotation-status --key-id 1234abcd-12ab-34cd-56ef-1234567890ab

轮换这件事,AWS 默认每年一次。我个人觉得这个频率对于大多数场景都够了。但如果你有严格的合规要求,可能需要自己写脚本做更频繁的轮换。

3.3 密钥策略:这里才是大头

密钥策略,说白了就是"谁能用、怎么用、什么时候用"的规则集。我见过很多 DevOps 写了很复杂的策略,最后自己都看不懂了。其实核心就几种模式。

三种主要授权模型

模型 说明 适用场景
启用 IAM 策略控制 密钥策略允许账号内所有 IAM 策略生效 多团队共享同一个密钥
直接指定主体 密钥策略写死 IAM 角色/用户 ARN 严格隔离环境,单应用专用密钥
跨账号授权 允许其他 AWS 账号的 IAM 角色使用 组织级共享密钥,比如日志集中加密
关于选哪种策略,我个人的建议是:只要你没有跨账号需求,就用"启用 IAM 策略控制"模式。它允许你在 IAM 里做更细粒度的控制,而不用每次改密钥策略。但记住,这种模式下,IAM 里的 Deny 是优先于密钥策略的 Allow 的。

举个例子:直接限制只有特定 IAM 角色能用

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:role/Ec2AppRole"
      },
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:GenerateDataKey"
      ],
      "Resource": "*"
    }
  ]
}

嗯,这里要注意一点:Resource: "*" 在密钥策略里是合法的,因为它默认就只对这个密钥生效。别看到星号就害怕。

跨账号配置要点

跨账号的时候,你需要在密钥策略里指定外部账号的根用户或者角色。同时,外部账号的 IAM 也要配上对应的权限。说白了就是两边都得点头才行。

{
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::987654321098:role/SecurityAuditRole"
  },
  "Action": "kms:Decrypt",
  "Resource": "*",
  "Condition": {
    "StringEquals": {
      "kms:ViaService": "s3.us-east-1.amazonaws.com"
    }
  }
}

这段策略还做了进一步约束:只有通过 S3 服务发起的 Decrypt 才允许。这就是为什么我说条件键(Condition Key)是精细控制的神器。我曾经在审计日志排查里发现一例异常调用,就是因为有人没有加 kms:ViaService 限制,导致 EC2 也能用本该只给 S3 用的密钥解密数据。

3.4 本章知识体系速览

下面这张图总结了 CMK 从创建到使用的整体流程,以及密钥策略的核心决策树。你可以把它当作一张脑图来看。

CMK 创建与策略配置核心流程 创建 CMK 选择创建方式 控制台创建 AWS CLI 创建 配置密钥策略 IAM 策略控制 (推荐,灵活性高) 直接指定主体 (单应用专用) 跨账号授权 (需配合条件键) 注意:密钥策略 + IAM 策略共同决定最终权限,Deny 优先级高于 Allow