3. 创建客户管理型 CMK:三种姿势,一种信任
咱们直接进入正题。客户管理型 CMK,说白了就是你自己全权掌控的密钥。AWS 提供三种创建方式:Console 点点点、CLI 敲命令、CloudFormation 写模板。我三种都用过,今天把心得和坑都抖出来。
先给个全景图——下面是三种创建方式的逻辑对比,你看完心里就有谱了。
3.1 AWS Console 操作:从零到一,5 分钟搞定
Console 是最直观的方式。我记得刚接手项目时,同事给了我一张截图让我照着配,结果因为没选对密钥类型,S3 加密一直报错。嗯,这里我重点提醒:默认的「Symmetric」就是加密最常用的,不要手滑选成 asymmetric。
操作步骤
- 登录 AWS Console,进入 KMS 服务。
- 左侧点击「客户管理型密钥」→「创建密钥」。
- 密钥类型:选择对称(Symmetric),一般场景用这个就够了。如果你需要在外部加密、AWS 内部解密(比如 S3 SSE-KMS),必须选对称。
- 密钥材料来源:
- KMS(默认):AWS 帮你生成并托管密钥材料。
- 外部(导入密钥材料):你自己在本地生成密钥材料,然后导入。这个场景我遇到过——合规要求密钥材料必须由安全团队生成,不能交给云厂商。但注意,一旦选择外部导入,后续轮换策略要手动实现,KMS 自动轮换不支持导入的密钥。
- 别名(Alias):建议遵循公司命名规范,比如
alias/myapp/prod、alias/s3-ssekms。别名可以随时改,但创建时最好一次到位,否则后面改起来还要排查引用。 - 描述(Description):简单说明用途,比如「用于 prod 环境 S3 存储桶加密」。
- 密钥策略:这是最重要的部分。Console 默认提供「Allow root user + 当前 IAM 用户」的简化策略,但生产环境建议你直接用「切换到策略视图」自定义。我曾经见过团队一路点默认,结果后来加授权时发现策略冲突,折腾了半天。
- 标签(Tags):按项目、环境、团队打标签,方便按标签做权限隔离。
- 预览并创建。
kms:DeleteKey(除非特定条件),防止误删。另外,记得设置 kms:EnableKeyRotation 权限给管理员组,后面做自动轮换要用。
3.2 AWS CLI 创建:摆脱鼠标,效率翻倍
如果你管理几十个账号,Console 点来点去会疯掉。CLI 命令一次执行,又快又准。我当年做大规模密钥迁移时,写了个 shell 脚本批量创建了 200 多个 CMK,全程没出过岔子——当然,前提是参数要对。
基本命令
# 创建对称 CMK,使用 AWS 托管的密钥材料(默认)
aws kms create-key \
--key-usage ENCRYPT_DECRYPT \
--key-spec SYMMETRIC_DEFAULT \
--description "用于 S3 SSE-KMS 的 CMK" \
--tags TagKey=Environment,TagValue=Prod \
--policy file://key-policy.json
解密一下参数:
--key-usage:ENCRYPT_DECRYPT是最常见的,要是用于签名验签用SIGN_VERIFY。--key-spec:对称密钥固定SYMMETRIC_DEFAULT。异步用RSA_2048等等。--policy:推荐从文件加载策略,比 inline 长串好维护。--tags:不能少,特别是做成本分配时。
创建完密钥,你会得到一个 KeyId(UUID)。通常我们还要绑定别名,方便使用:
aws kms create-alias \
--alias-name alias/myapp-prod-key \
--target-key-id <YourKeyId>
另外,如果你要创建带有外部密钥材料的 CMK,需要多一步:
# 先创建没有密钥材料的 CMK
aws kms create-key \
--key-usage ENCRYPT_DECRYPT \
--key-spec SYMMETRIC_DEFAULT \
--origin EXTERNAL \
--policy file://key-policy.json
# 然后通过 GetParametersForImport 获取包装公钥,再导入密钥材料(后续章节细讲)
3.3 CloudFormation 创建:基础设施即代码的优雅解法
我最喜欢用 CloudFormation 创建 CMK,因为它把整个生命周期都纳入了模板。想想看,一个 aws kms create-key 你跑完还要单独配别名、标签,而 CloudFormation 一个 YAML 全部搞定,还自动处理依赖和回滚。
下面是一个标准模板,你可以直接拿去用:
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyCMK:
Type: AWS::KMS::Key
Properties:
KeyUsage: ENCRYPT_DECRYPT
KeySpec: SYMMETRIC_DEFAULT
Description: "CloudFormation 创建的 CMK"
Enabled: true
EnableKeyRotation: true # 自动轮换!每年一次
KeyPolicy:
Version: "2012-10-17"
Statement:
- Sid: "Enable IAM User Permissions"
Effect: Allow
Principal:
AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root"
Action: "kms:*"
Resource: "*"
- Sid: "Allow S3 Service to Use Key"
Effect: Allow
Principal:
Service: s3.amazonaws.com
Action:
- "kms:Encrypt"
- "kms:Decrypt"
- "kms:ReEncrypt*"
- "kms:GenerateDataKey"
- "kms:DescribeKey"
Resource: "*"
Tags:
- Key: Environment
Value: Production
MyKeyAlias:
Type: AWS::KMS::Alias
Properties:
AliasName: "alias/myapp-prod-key"
TargetKeyId: !Ref MyCMK
关键点解读
| 参数/属性 | 说明 | 注意事项 |
|---|---|---|
EnableKeyRotation: true | 开启自动轮换(每年一次) | 仅对 AWS 托管密钥材料有效;外部导入的密钥不支持此属性 |
KeyPolicy | 必须至少包含 root 用户的完全权限,否则后续你无法管理 | 写错策略会导致整个密钥不可用,部署后修改策略需要额外操作 |
TargetKeyId: !Ref MyCMK | 引用 CMK 资源,自动建立依赖 | 别名是独立资源,不能直接在 CMK 内部设置 Alias |
📌 实战建议:我建议把所有 CMK 和相关资源(别名、策略、权限)放在一个嵌套堆栈中,统一版本管理。每次改动都通过 CloudFormation ChangeSet 审查效果,避免直接修改策略导致权限错乱。
部署命令简单:
aws cloudformation deploy \
--template-file cmk-template.yaml \
--stack-name my-cmk-stack \
--capabilities CAPABILITY_IAM
注意要加 CAPABILITY_IAM,因为密钥策略里定义了 IAM 权限,CloudFormation 需要你确认这是有意为之。
AWS::Include 或直接 Fn::Sub 引用参数。但我个人更倾向把策略直接写在模板里,这样模板自己就是完整的,别人 review 也方便。
三种方式对比,选哪个?
我把常见场景列了个表,你参考一下:
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 首次学习、快速测试 | Console | 零门槛,随时调整 |
| 自动化部署、CI/CD | CLI | 简单命令,可集成脚本 |
| 多账号、多环境、基础设施即代码 | CloudFormation | 声明式、可版本控制、可审计 |
| 需要外部密钥材料 | CLI 或 Console | CloudFormation 目前不直接支持导入密钥材料的过程 |
最后唠叨一句:不管用哪种方式,密钥策略千万不能出错。我建议创建一个 CMK 后,先用 aws kms describe-key 和 aws kms get-key-policy 验证策略是否如预期。别嫌麻烦,出过一次生产事故就知道它的价值了。