饮墨

子安饮墨馀三斗,留与卿儿作赋来

3 步集成 Checkov 到 CI/CD:Terraform 和 Kubernetes 配置安全扫描实战

11 views

痛点: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 倍。

分享:

相关文章