Infrastructure as Code Security

Infrastructure as Code 带来了版本控制和自动化的好处,但如果错误配置被自动传播, 则会引入风险。安全工作应针对 IaC 做到 shift-left(左移)。

IaC 中的常见漏洞

  • 硬编码密钥:版本化代码中的凭据
  • 过度宽松的规则:安全组 0.0.0.0/0
  • 未加密的资源:未加密的 S3 存储桶、RDS
  • 公开访问:不必要地暴露的资源
  • 缺失日志记录:禁用的 CloudTrail、流日志
  • 弱身份验证:未强制启用 MFA

扫描工具

Terraform - tfsec、Checkov、Terrascan

      # 漏洞示例 - 公开的 S3 存储桶
      resource "aws_s3_bucket" "bad_bucket" {
      bucket = "my-public-bucket"
      acl    = "public-read"  # [错误] 存在漏洞
      }
      # 修复
      resource "aws_s3_bucket" "good_bucket" {
      bucket = "my-private-bucket"
      acl    = "private"  # [正确] 安全
      server_side_encryption_configuration {
      rule {
      apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
      }
      }
      }
      versioning {
      enabled = true
      }
      }
      resource "aws_s3_bucket_public_access_block" "good_bucket" {
      bucket = aws_s3_bucket.good_bucket.id
      block_public_acls       = true
      block_public_policy     = true
      ignore_public_acls      = true
      restrict_public_buckets = true
      }
      

tfsec - 扫描 Terraform

      # 安装
      brew install tfsec
      # 扫描 Terraform 文件
      tfsec .
      # 指定输出格式
      tfsec --format json --out results.json .
      # CI/CD 集成
      tfsec --soft-fail . || exit 1
      

Checkov - 多云 IaC 扫描器

      # 安装
      pip install checkov
      # 扫描 Terraform
      checkov -d ./terraform
      # 扫描 CloudFormation
      checkov -f template.yaml
      # 扫描 Kubernetes 清单
      checkov -d ./k8s
      # 跳过特定检查
      checkov -d . --skip-check CKV_AWS_20
      # 自定义策略
      checkov -d . --external-checks-dir ./custom-policies
      

Policy as Code(策略即代码)

Open Policy Agent (OPA)

OPA 允许使用 Rego 语言编写策略,以强制执行合规要求:

      # deny_public_s3.rego
      package terraform.aws.s3
      deny[msg] {
      resource := input.resource_changes[_]
      resource.type == "aws_s3_bucket"
      resource.change.after.acl == "public-read"
      msg := sprintf("S3 bucket %s cannot be public", [resource.address])
      }
      deny[msg] {
      resource := input.resource_changes[_]
      resource.type == "aws_s3_bucket"
      not resource.change.after.server_side_encryption_configuration
      msg := sprintf("S3 bucket %s must have encryption enabled", [resource.address])
      }
      

Sentinel (HashiCorp)

与 Terraform Cloud/Enterprise 集成的策略框架:

      # enforce-mandatory-tags.sentinel
      import "tfplan/v2" as tfplan
      mandatory_tags = ["Environment", "Owner", "Project"]
      all_resources = filter tfplan.resource_changes as _, rc {
      rc.mode is "managed"
      }
      deny_resources_without_tags = rule {
      all all_resources as _, resource {
      all mandatory_tags as tag {
      resource.change.after.tags contains tag
      }
      }
      }
      

IaC 中的密钥管理

Terraform - 使用 AWS Secrets Manager

      # 在 Secrets Manager 中创建 secret
      resource "aws_secretsmanager_secret" "db_password" {
      name = "production/db/password"
      recovery_window_in_days = 30
      }
      resource "aws_secretsmanager_secret_version" "db_password" {
      secret_id     = aws_secretsmanager_secret.db_password.id
      secret_string = random_password.db_password.result
      }
      # 引用 secret(不暴露其值)
      data "aws_secretsmanager_secret_version" "db_password" {
      secret_id = aws_secretsmanager_secret.db_password.id
      }
      # 在 RDS 中使用(引用,而非硬编码值)
      resource "aws_db_instance" "main" {
      # ... 其他配置
      password = data.aws_secretsmanager_secret_version.db_password.secret_string
      }
      

git-secrets - 防止提交密钥

      # 安装 git-secrets
      brew install git-secrets
      # 为代码仓库设置钩子
      git secrets --install
      git secrets --register-aws
      # 扫描提交历史
      git secrets --scan-history
      # 防止提交包含密钥的内容
      # 通过 pre-commit 钩子自动执行
      

State 文件安全

  • 远程 state:S3 + DynamoDB 锁,切勿提交本地 state
  • 加密:S3 上的服务器端加密
  • 访问控制:针对 state 存储桶的限制性 IAM 策略
  • 版本控制:启用版本控制以便恢复
  • State 锁定:使用 DynamoDB 防止并发修改

安全的 Terraform 远程后端

      terraform {
      backend "s3" {
      bucket         = "terraform-state-prod"
      key            = "global/s3/terraform.tfstate"
      region         = "us-east-1"
      encrypt        = true
      dynamodb_table = "terraform-state-lock"
      # MFA 删除保护
      versioning {
      enabled = true
      mfa_delete = true
      }
      }
      }
      

CI/CD 集成

GitHub Actions - 安全的 Terraform 工作流

      name: 'Terraform Security Scan'
      on:
      pull_request:
      branches: [ main ]
      jobs:
      terraform-security:
      runs-on: ubuntu-latest
      steps:
      - uses: actions/checkout@v3
      - name: Run tfsec
      uses: aquasecurity/[email protected]
      with:
      soft_fail: false
      - name: Run Checkov
      uses: bridgecrewio/checkov-action@master
      with:
      directory: .
      framework: terraform
      output_format: sarif
      output_file_path: checkov.sarif
      - name: Upload results to GitHub Security
      uses: github/codeql-action/upload-sarif@v2
      with:
      sarif_file: checkov.sarif
      

Drift Detection(漂移检测)

检测在 IaC 之外进行的、会造成安全缺口的手动变更:

  • Terraform Cloud:自动健康检查
  • driftctl:开源漂移检测
  • CloudFormation Drift Detection:AWS 原生服务
  • 计划扫描:定期的 CI/CD 作业

合规框架

  • CIS Benchmarks:用于合规的 Terraform 模块
  • NIST 800-53:用于控制项的策略包
  • PCI-DSS:用于支付卡处理的策略
  • HIPAA:医疗健康合规策略
  • SOC 2:安全组织策略

安全的 Terraform 模块

  • 使用经过验证的 Terraform Registry 模块
  • 锁定模块版本(不要使用 latest)
  • 对内部模块进行代码审查
  • 为自定义模块使用私有 registry
  • 记录安全注意事项

最佳实践

  • 同行评审:生产环境变更必须提交 PR
  • 先 plan 再 apply:审查拟议的变更
  • 环境隔离:隔离 Dev/Staging/Prod
  • 标签策略:用于治理和成本分摊的标签
  • 最小权限:为 CI/CD 设置专用的 IAM 角色
  • 自动化测试:使用 Terratest 进行验证

最终建议

IaC 安全应当自动化,并从一开始就集成到 CI/CD 中。使用多种扫描工具 (tfsec、Checkov)以获得全面覆盖。借助 OPA 或 Sentinel 实施 policy as code。 切勿提交密钥,应使用密钥管理器。持续监控漂移。IaC 错误配置是云端数据泄露最常见的原因之一。