3. IaC安全编码规范设计
当团队从“个人写脚本”走向“组织级基础设施交付”时,IaC 代码就不再只是工程师的个人资产,而是承载生产环境安全基线的组织资产。此时如果没有统一的安全编码标准,同一个 Terraform 模块可能由不同人写出完全不同的安全姿态:有人默认开启存储加密,有人忘记关闭公网访问,有人把密钥硬编码进变量文件。IaC 安全编码规范要解决的,正是这种“同一类资源、不同安全结果”的离散化问题。
本节的核心任务是:把命名、加密、网络、IAM、日志、标签等关键规则,从零散经验沉淀为一份可检查、可评审、可自动化的组织级规范文档。规范不是安全愿望清单,而是能被代码审查、策略引擎和 CI 流水线直接消费的约束集合。
一、规范文档的结构设计
一份可落地的 IaC 安全编码规范,建议采用“规则域—规则条目—检查方式—违规示例—修复示例”五层结构。规则域对应命名、加密、网络、IAM、日志、标签等主题;每条规则条目必须包含唯一编号(如 IAC-ENC-001)、适用资源类型、约束描述、严重级别(阻断/警告/提示)、检查方式(人工评审/静态扫描/策略即代码)以及正反示例。缺少“检查方式”的规则,本质上只是建议,无法进入自动化门禁。
严重级别的划分直接影响流水线行为:阻断级规则在 CI 阶段直接失败,禁止合并;警告级规则允许合并但必须记录豁免理由;提示级规则仅输出报告。这样既保证关键安全底线不可绕过,又避免规范过于刚性导致团队抵触。
二、六大关键规则域的具体约束
命名规则要求资源名称可追溯、可分组。推荐格式为 {org}-{env}-{region}-{service}-{resource},例如 acme-prod-cn-north-payment-sg。命名规则的价值在于:安全事件响应时能快速定位资源归属,策略扫描时能按环境批量匹配。命名规则通常设为警告级,因为改名成本高,但新资源必须遵守。
加密规则是阻断级重点。对象存储必须启用服务端加密(SSE),数据库必须启用静态加密与传输加密,密钥必须使用 KMS 托管而非本地生成。以 Terraform 为例,S3 存储桶应显式声明加密配置,而不是依赖默认值:
resource "aws_s3_bucket_server_side_encryption_configuration" "example" {
bucket = aws_s3_bucket.example.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.example.arn
}
bucket_key_enabled = true
}
}
网络规则要求默认拒绝、显式放行。安全组不得出现 0.0.0.0/0 开放 22/3389 等高危端口;数据库与缓存必须部署在私有子网;负载均衡到后端只允许必要端口。网络规则适合用策略即代码检查,例如 OPA/Rego 或 Checkov 自定义规则,对 CIDR 与端口组合做匹配。
IAM 规则要求最小权限与禁止通配。策略中不得出现 "Action": "*" 与 "Resource": "*" 同时存在;角色信任策略必须限定具体主体;长期访问密钥应禁止创建,优先使用角色与临时凭证。IAM 规则通常设为阻断级,因为权限扩散的后果最严重。
日志规则要求关键资源开启审计日志。云审计、VPC 流日志、对象存储访问日志、数据库审计日志必须启用并投递到集中日志账户。日志规则需要检查“是否启用”和“投递目标是否存在”两个条件,避免只声明资源却未真正生效。
标签规则要求所有资源携带 owner、env、cost-center、data-classification 四类标签。标签不仅是成本管理手段,更是安全分级依据:data-classification=confidential 的资源应自动触发更严格的加密与网络规则。
三、从规范到可检查文档的落地方法
规范文档如果只停留在 Wiki 页面,很快会与代码脱节。推荐把规范拆成两层:一层是面向人的说明文档,解释每条规则的背景、风险和修复方式;另一层是面向机器的规则文件,例如 Checkov 自定义策略、OPA Rego 策略或 Sentinel 策略。两层通过规则编号一一对应,保证“文档里写的”和“流水线查的”是同一件事。
以标签规则为例,Rego 策略可以这样表达:遍历 plan 中所有资源,检查 tags 是否包含 owner、env、cost-center、data-classification 四个键,缺失任一键则返回违规。策略输出中带上资源地址和缺失标签名,开发者在 PR 评论中就能直接看到问题位置,而不是只收到一句“标签不合规”。
规范还需要版本化维护。规则变更应走与代码相同的评审流程:提出变更、说明影响范围、更新正反示例、同步更新策略文件、在测试仓库验证后再发布。建议为规范文档打上语义化版本号,并在流水线中记录本次检查使用的规范版本,便于事后追溯“当时为什么允许这次变更”。
四、规范文档示例片段
下面给出一条可直接参考的规则条目写法,展示“规则—检查—示例”如何组织:
| 规则编号 | 规则域 | 约束描述 | 严重级别 | 检查方式 |
|---|---|---|---|---|
| IAC-ENC-001 | 加密 | 对象存储必须启用 SSE-KMS 服务端加密,禁止使用明文或仅 SSE-S3 | 阻断 | Checkov 自定义策略 + plan 校验 |
| IAC-NET-003 | 网络 | 安全组不得对 0.0.0.0/0 开放 22、3389、3306、6379 端口 | 阻断 | OPA/Rego 策略 |
| IAC-IAM-002 | IAM | 策略语句中 Action 与 Resource 不得同时为通配符 | 阻断 | tfsec + 人工评审 |
| IAC-TAG-001 | 标签 | 所有可打标签资源必须包含 owner、env、cost-center、data-classification | 警告 | Rego 策略 + 合规报告 |
这份表格本身就是规范文档的核心骨架。每条规则都能被策略引擎消费,也能被人工评审引用。当规则数量增长到几十条时,建议按规则域拆分为多个策略文件,并在 CI 中并行执行,避免单次检查时间过长影响开发体验。
最后需要强调:IaC 安全编码规范的目标不是追求“零违规”的数字,而是让安全约束成为基础设施交付流程中默认存在的一部分。规范写清楚、检查自动化、豁免有记录、整改有闭环,组织才能在保持交付速度的同时,把安全基线稳定地固化到每一行 IaC 代码里。