密钥边界设计原则:最小权限、职责分离、防御深度
密钥边界的设计,说白了就是回答三个问题:谁能用?怎么分权?扛得住几层攻击?
我这些年看过不少密钥泄露事故,绝大多数都不是算法被攻破,而是边界没划好。今天我们就来拆解这三个原则,每个都是我亲手踩过坑、补过洞的。
1. 最小权限:给钥匙就给人进一间屋
最小权限原则听起来简单——只给主体完成任务所需的最小权限集合。但现实里经常变成“先给满,再回收”,结果回收的时候发现权限早已走远了。
我习惯把密钥的权限拆成三级:生成、使用、轮换/删除。生成和删除是管理员级,使用是调用方级。这两者必须隔开。
举个例子,在AWS KMS里,你可以创建一个Key Policy,只允许某个IAM Role解密,不允许它加密。这就把“使用”的权利进一步拆分。我曾经见过一个项目组,把同一个密钥的加密和解密权限都给了同一个微服务,结果日志泄露后攻击者直接用密钥加密勒索数据……
怎么做才对?我推荐用政策边界(Policy Boundary) 和条件键(Condition Key)。比如在IAM Policy里加上:
{
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": "arn:aws:kms:us-east-1:123456789012:key/xxxxx",
"Condition": {
"StringEquals": {
"kms:EncryptionContext:service": "payments"
}
}
}
这样一来,即使有解密权限,也只能解带指定加密上下文的密文。这就是最小权限的落地姿势。
2. 职责分离:不能让厨师自己试菜
职责分离,简单说就是管密钥的人不能同时用密钥,管存储的人不能同时管密钥。我把它叫做“互相监督的三角关系”。
| 角色 | 职责 | 不能做的 |
|---|---|---|
| 密钥管理员 | 创建、轮换、删除密钥 | 不能执行加解密操作 |
| 密钥使用者 | 调用加解密API | 不能修改密钥策略 |
| 审计员 | 查看日志、审查操作 | 不能执行任何写操作 |
你看,三个人各司其职。审计员虽然没有操作权限,但能看到所有操作记录——这就形成了威慑。
我在一个金融项目里遇到过反面案例:运维团队同时是密钥管理员,他们为了方便,把所有密钥的删除权限都给了同一个内部服务。结果某次上线脚本出错,直接删了生产密钥。虽然备份还在,但那一整天的交易记录都没法解密了。嗯,从那以后,我坚持把“删除”操作单独拎出来,必须双人审批才能执行。
具体实施时,我建议用IAM Conditions + MFA 来强制临时提升权限。比如删除密钥必须额外通过MFA认证,且时间窗口只有15分钟。这样即使管理员账号泄露,攻击者也很难在短时间内完成MFA劫持。
3. 防御深度:洋葱一样一层一层剥
防御深度的意思是:别指望单点防御能挡住所有攻击。你要设计多层屏障,每一层都是独立的,攻破一层还有下一层等着。
我观察到一个常见的错误:团队只做了网络隔离,密钥存HSM里就以为万事大吉。结果内部人员通过API直接请求KMS密钥,因为没有应用层的鉴权,照样能拿到明文。
真正的防御深度,应该覆盖四个层面:
- 网络层: 密钥服务只在VPC内可达,禁用公网端点。
- 身份层: 每次调用都要验证IAM、MAC、甚至设备证书。
- 应用层: 密钥的使用必须带上加密上下文(Encryption Context),用条件键做细粒度控制。
- 存储层: 密钥本身在HSM或KMS里加密存储,即使存储介质被盗也读不出明文。
我参与过一个医疗系统审计,他们只做了网络隔离,结果一个开发环境的临时密钥不小心配置成了“允许所有VPC Endpoint”访问。攻击者通过一个未打补丁的EC2实例,直接跨区域调用了KMS API。这就是典型的“只建了一层墙”。
三者如何协同?
三个原则不是孤立存在的,它们互相支撑。我把它们画成了一张结构图——你看完就明白了。
你看这张图,最小权限在最底层,它决定了密钥可被谁用、怎么用。职责分离在中间层,把权力拆开,防止任何一个人拥有完整链条。防御深度在最外层,用多层防线兜底。三者叠加,才能形成真正的密钥边界。
最后给个自查清单,你可以拿去对照:
- 您的密钥策略是否只包含了最小必要的Action和Resource?
- 加密、解密、删除的权限是否分别由不同角色承担?
- 密钥的备份是否也遵循了相同的边界控制?
- 有没有条件键(Encryption Context)限制密钥的用法?
- 网络层是否只允许VPC内访问,且启用了加密传输?
- 审计日志是否实时投递到独立的、不可修改的存储?
如果有一项没做到,嗯,您最好停下来想想。我用自己的教训担保——这些坑,走一遍就够了。不如现在就去检查您的密钥策略吧。