2. 密钥策略基础:策略结构拆解

好,咱们开始啃最核心的部分——密钥策略的结构。你想想看,不管你在阿里云还是AWS上写策略,骨架都是一样的。

我刚开始接触KMS的时候,觉得这东西不就是个JSON嘛,有什么难的?直到有一次把Principal写错,整个生产环境的密钥访问全断了……嗯,那次教训挺深刻的。

密钥策略结构图 策略根对象 Version 2012-10-17 (必填) Statement 数组,至少1条语句 Effect Allow / Deny Principal 谁可以访问 Action 允许的操作 Resource 资源范围 Condition 附加条件 (可选) Condition 是合规场景的核心武器 限VPC、限来源IP、限指定角色……全靠它

2.1 Version:别小看这个字段

Version只有一种写法:2012-10-17。为什么是2012年?这是AWS定义的策略语言版本。

我个人习惯是:永远写死这个值,不要花样。曾经有人写了个2011或2020,结果策略解析失败。

"Version": "2012-10-17"  // 就这一种写法
小提示:在任何云平台上,Version都直接复制粘贴。手写容易出格式错误。

2.2 Statement:策略的真正核心

Statement是个数组。换句话说,你可以写多条策略规则。每条Statement里,又包含Effect、Principal、Action、Resource、Condition这5个元素。

说白了,一条Statement就是一句权限断语:“谁可以/不可以对什么资源做什么操作,在什么条件下”。

2.2.1 Effect:Allow还是Deny?

只有两种值:Allow和Deny。Deny的优先级高于Allow。

Effect值 含义 命中后结果
Allow 显式允许 允许访问(除非有Deny覆盖)
Deny 显式拒绝 直接拒绝,无视任何Allow
避坑指南:我曾经见过一个团队,写了一大堆Allow,结果忘了检查是否存在隐含的Deny。最后某个运维人员访问被拒,排查了整整两天才发现是默认拒绝策略在生效。记住:Deny为王。

2.2.2 Principal:谁可以访问?

Principal就是“主体”。你可以指定某个用户、角色、服务账号甚至阿里云账号。

这里有个常见误区:很多人以为Principal只能写一个,其实它可以写数组。

"Principal": {
    "RAM": [
        "acs:ram::1234567890:user/Alice",
        "acs:ram::1234567890:role/AdminRole"
    ]
}

如果你想让所有人都能用这个密钥——嗯,这在合规场景下非常危险。但我还是教你写法:

"Principal": "*"
我的经验:在生产环境,永远不要用 "Principal": "*"。合规审计看到这个直接标红。应该用小范围的Principal + Condition双重限制。

2.2.3 Action:允许干哪些事?

Action就是操作列表。常见的有:

  • kms:Encrypt —— 加密
  • kms:Decrypt —— 解密
  • kms:GenerateDataKey —— 生成数据密钥
  • kms:CreateKey —— 创建密钥(这是管理操作,一般不开给普通用户)

Action支持通配符 *。但我建议:能写具体的就不要写通配符。

"Action": [
    "kms:Encrypt",
    "kms:Decrypt",
    "kms:GenerateDataKey"
]

2.2.4 Resource:作用在什么资源上?

对于KMS,Resource就是你想要保护的密钥的ARN。格式大致是:

"Resource": "acs:kms:cn-hangzhou:1234567890:key/abc-def-123"

注意:Resource支持通配符,但我在项目里踩过坑——用通配符匹配密钥时,把不该放开的密钥也放开了。那次差点导致数据泄露。

我现在的习惯是:每个密钥的策略里,Resource只写它自己的ARN。不偷懒,不出错。

2.2.5 Condition:合规场景的杀手锏

Condition是整篇文章的精华。没有Condition,你只能做粗粒度的控制。有了它,你才能实现真正精细化的合规策略。

核心理念:Condition限定“在什么环境下/用什么方式”才能访问密钥。

常见的Condition场景:

  • 限制来源IP:只能从公司内网访问密钥
  • 限制VPC:密钥只能被特定VPC内的服务调用
  • 限制请求时间:只能在业务时间段内使用(比如9:00-18:00)
  • 限制TLS版本:必须使用1.2及以上版本
  • 限制调用者身份:必须是某个指定角色才能解密

举个例子,限制来源IP:

"Condition": {
    "IpAddress": {
        "acs:SourceIp": "10.0.0.0/8"
    }
}
Condition键 说明 常见值示例
acs:SourceIp 限制来源IP地址 10.0.0.0/8, 192.168.1.0/24
acs:SourceVpc 限制来源VPC vpc-abcdef123
acs:CurrentTime 限制访问时间 2024-01-01T00:00:00Z
acs:SecureTransport 是否要求HTTPS "true"
避坑指南:我有一个真实教训:曾经写了一个Condition,把IP段写成了10.0.0.0/8,但公司实际用的是10.0.0.0/16。结果一大批正常请求被拒绝。所以条件里的IP段一定要确认网络规划,别抄网上的示例。

2.3 把一切组合起来——完整示例

好,我们看看一个符合合规要求的完整策略长什么样:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "RAM": "acs:ram::1234567890:role/ProductionAppRole"
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:GenerateDataKey"
            ],
            "Resource": "acs:kms:cn-hangzhou:1234567890:key/abc-def-123",
            "Condition": {
                "IpAddress": {
                    "acs:SourceIp": "10.0.0.0/8"
                },
                "Bool": {
                    "acs:SecureTransport": "true"
                }
            }
        }
    ]
}

什么意思?看几遍你就懂了:

  • 只有ProductionAppRole这个角色能用这个密钥
  • 只能做加密、解密、生成数据密钥这三个操作
  • 只在10.0.0.0/8网段内才能访问
  • 必须走HTTPS(加密传输)

这就是合规策略。每一行都不是摆设。

小技巧:写策略的时候,从最小的权限开始。先写一个只Allow自己需要的操作,跑起来之后,再一点点放开。别一开始就写个宽泛的Allow *。

嗯,到这里,策略的骨架你应该清楚了。记住:Version别写错,Statement里Effect、Principal、Action、Resource、Condition要配合使用。其中Condition,是你在合规审计里最大的底气。