痛点:IaC 配置写完就上线,安全漏洞全靠事后补
你用 Terraform 管理云资源、用 YAML 管理 Kubernetes 工作负载,基础设施即代码(IaC)让一切变得可重复、可审计。但有个问题常被忽视:IaC 代码本身的安全性谁来保障?
现实中这些场景屡见不鲜:
- Terraform 里 S3 Bucket 开了 Public Access,上线后数据泄露
- Kubernetes Deployment 用了
privileged: true,容器逃逸风险直接暴露 - Security Group 放通了
0.0.0.0/0:22,SSH 暴露公网被暴力破解 - Dockerfile 用 root 用户运行,镜像里还藏着硬编码密钥
这些不是理论风险——根据 Gartner 的预测,到 2025 年超过 99% 的云安全事件源自用户配置错误。IaC 代码 Review 靠人眼根本看不过来,你需要一个自动化的安全扫描工具在代码提交阶段就拦住这些问题。
Checkov 就是干这个的。
方案:Checkov — 开源 IaC 静态安全分析利器
Checkov 是 Bridgecrew(现属 Palo Alto Networks)开源的 IaC 静态分析工具,核心能力:
| 特性 | 说明 |
|---|---|
| 多框架支持 | Terraform、CloudFormation、Kubernetes、Helm、Dockerfile、ARM、Bicep、Serverless 等 |
| 内置策略丰富 | 1000+ 条内置检查规则,覆盖 CIS Benchmark、PCI-DSS、HIPAA、SOC2 等合规框架 |
| 自定义策略 | 支持 Python 和 YAML 两种方式编写自定义规则 |
| 依赖图分析 | 基于 Terraform Plan 和资源间关系做深度安全分析,不只是正则匹配 |
| CI/CD 友好 | 原生支持 GitHub Actions、GitLab CI、Jenkins,输出 SARIF/JSON/JUnit 格式 |
与 Trivy(侧重镜像 CVE 扫描)、Semgrep(侧重应用代码 SAST)定位不同,Checkov 专注于 基础设施配置层面的安全策略检查,三者互补构成完整的供应链安全防线。
实操步骤
第 1 步:安装 Checkov 并扫描本地 Terraform 代码
# 推荐用 pip 安装(需要 Python 3.8+)
pip install checkov
# 验证安装
checkov --version
假设你有一个典型的 Terraform 项目:
# main.tf — 一个存在安全问题的 S3 Bucket
resource "aws_s3_bucket" "data" {
bucket = "my-app-data-bucket"
}
resource "aws_s3_bucket_public_access_block" "data" {
bucket = aws_s3_bucket.data.id
# 注意:缺少了关键的 block 配置
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
resource "aws_security_group" "web" {
name = "web-sg"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # SSH 对全网开放
}
}
执行扫描:
# 扫描当前目录下所有 Terraform 文件
checkov -d . --framework terraform
# 只看 FAILED 的检查项
checkov -d . --framework terraform --compact
输出示例(关键部分):
Check: CKV_AWS_145: "Ensure that S3 Buckets are encrypted with KMS"
FAILED for resource: aws_s3_bucket.data
File: /main.tf:2-4
Check: CKV_AWS_24: "Ensure no security groups allow ingress from 0.0.0.0/0 to port 22"
FAILED for resource: aws_security_group.web
File: /main.tf:14-23
Check: CKV_AWS_53: "Ensure S3 bucket has block public ACLS enabled"
FAILED for resource: aws_s3_bucket_public_access_block.data
File: /main.tf:6-13
每条输出包含:规则 ID、描述、失败资源、文件位置,一目了然。
第 2 步:扫描 Kubernetes YAML 和 Dockerfile
Checkov 对 Kubernetes 和 Dockerfile 的检查同样强大:
# deploy.yaml — 一个高风险的 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: app
image: myapp:latest # 用了 latest tag
securityContext:
privileged: true # 特权容器
runAsUser: 0 # root 用户运行
ports:
- containerPort: 8080
# 扫描 Kubernetes YAML
checkov -f deploy.yaml --framework kubernetes
# 扫描 Dockerfile
checkov -f Dockerfile --framework dockerfile
# 一次性扫描目录下所有支持的文件类型
checkov -d . --skip-framework secrets
Kubernetes 常见检测项:
| 规则 ID | 检查内容 |
|---|---|
| CKV_K8S_1 | 不允许使用特权容器 |
| CKV_K8S_6 | 必须配置 CPU/Memory Limits |
| CKV_K8S_14 | 镜像 tag 不能用 latest |
| CKV_K8S_20 | 不允许以 root 用户运行 |
| CKV_K8S_22 | 必须设置只读根文件系统 |
| CKV_K8S_28 | 容器不允许提权(allowPrivilegeEscalation) |
第 3 步:集成到 GitHub Actions CI/CD 流水线
在 PR 阶段自动运行 Checkov,发现问题直接阻断合并:
# .github/workflows/iac-security-scan.yml
name: IaC Security Scan
on:
pull_request:
paths:
- 'terraform/**'
- 'k8s/**'
- 'Dockerfile'
jobs:
checkov:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Checkov (Terraform)
uses: bridgecrewio/checkov-action@v12
with:
directory: terraform/
framework: terraform
output_format: sarif
output_file_path: results-tf.sarif
soft_fail: false # 发现 HIGH/CRITICAL 直接失败
skip_check: CKV_AWS_145 # 按需跳过特定规则
quiet: true
- name: Run Checkov (Kubernetes)
uses: bridgecrewio/checkov-action@v12
with:
directory: k8s/
framework: kubernetes
output_format: sarif
output_file_path: results-k8s.sarif
soft_fail: false
- name: Upload SARIF to GitHub Security
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results-tf.sarif
上传 SARIF 后,扫描结果会直接出现在 GitHub 的 Security 面板和 PR 的 Code Scanning 告警中,开发者在 PR 页面就能看到具体问题。
避坑指南
坑 1:初次接入满屏 FAILED,团队直接放弃
刚接入时老项目可能有上百个 FAILED,不要一步到位。正确做法:
# 先生成 baseline,记录存量问题
checkov -d . --create-baseline
# 后续扫描只报增量问题(.checkov.baseline 文件自动加载)
checkov -d . --baseline .checkov.baseline
存量问题建立专项治理计划逐步消化,增量代码立即强制通过。
坑 2:自定义规则写成了"通用检查",误报率飙升
Checkov 支持用 YAML 写自定义规则,但规则范围要精确:
# custom_checks/require_encryption_tag.yaml
metadata:
id: "CUSTOM_001"
name: "Ensure all S3 buckets have encryption tag"
severity: "HIGH"
definition:
cond_type: "attribute"
resource_types:
- "aws_s3_bucket" # 精确指定资源类型
attribute: "tags.encryption"
operator: "exists"
# 加载自定义规则目录
checkov -d . --external-checks-dir custom_checks/
建议:自定义规则先在 soft_fail 模式运行一周观察误报率,稳定后再切为强制阻断。
坑 3:Terraform Plan 扫描与静态扫描结果不一致
Checkov 默认扫描 .tf 源码(静态分析),但有些安全问题只有在 Plan 阶段才能暴露(如变量计算后的值):
# 先生成 plan 文件
terraform init && terraform plan -out=tfplan
terraform show -json tfplan > tfplan.json
# 基于 Plan JSON 做深度扫描
checkov -f tfplan.json --framework terraform_plan
Plan 扫描能检测到动态值、模块嵌套引用等静态分析无法覆盖的场景,建议 CI 中同时运行静态扫描和 Plan 扫描。
总结
| 维度 | 建议 |
|---|---|
| 工具定位 | Checkov 专注 IaC 配置安全,与 Trivy(镜像 CVE)、Semgrep(代码 SAST)互补 |
| 接入策略 | 先 baseline 存量 → 增量强制 → 逐步治理历史债务 |
| 扫描范围 | Terraform 源码 + Plan JSON + Kubernetes YAML + Dockerfile 全覆盖 |
| CI/CD 集成 | PR 阶段阻断高危问题,SARIF 上报 GitHub Security 面板 |
| 自定义规则 | YAML 定义简单规则,Python 处理复杂逻辑,先 soft_fail 观察再强制 |
一句话:安全左移不是口号,把 Checkov 塞进 CI 流水线,IaC 配置漏洞在合并前就被拦住,比上线后擦屁股高效 10 倍。