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 错误配置是云端数据泄露最常见的原因之一。
