IaC安全左移:从Terraform扫描到黄金镜像
文章目录
一、Terraform HCL安全加固
1.1 Go绑定深度检测
AST解析引擎:
import (
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/zclconf/go-cty/cty"
)
func AnalyzeTerraform(content []byte) []Issue {
// 解析HCL
file, diags := hclsyntax.ParseConfig(content, "main.tf", hcl.Pos{
Line: 1, Column: 1})
if diags.HasErrors() {
return nil
}
var issues []Issue
hclsyntax.VisitAll(file.Body.(*hclsyntax.Body), func(node hclsyntax.Node) bool {
switch n := node.(type) {
case *hclsyntax.Block:
// 安全规则1:检查未加密的存储
if n.Type == "resource" && len(n.Labels) > 0 && n.Labels[0] == "aws_s3_bucket" {
if attr := n.Body.GetAttribute("server_side_encryption_configuration"); attr == nil {
issues = append(issues, Issue{
Pos: n.TypeRange,
Message: "S3存储桶未启用加密",
})
}
}
// 安全规则2:检查开放安全组
if n.Type == "resource" && len(n.Labels) > 0 && n.Labels[0] == "aws_security_group" {
for _, ruleBlock := range n.Body.Blocks {
if ruleBlock.Type == "ingress" {
if attr := ruleBlock.Body.GetAttribute("cidr_blocks"); attr != nil {
val, _ := attr.Expr.Value(nil)
if val.AsValueSlice()[0].AsString() == "0.0.0.0/0" {
issues = append(issues, Issue{
Pos: ruleBlock.TypeRange,
Message: "安全组允许任意IP访问",
})
}
}
}
}
}
}
return true
})
return issues
}
1.2 敏感数据防护
tfvars加密方案:
func EncryptTfvars(inputFile, outputFile string, key []byte) error {
// 读取原始文件
data, err := os.ReadFile(inputFile)
if err != nil {
return err
}
// 加密内容
block, _ := aes.NewCipher(key)
gcm, _ := cipher.NewGCM(block)
nonce := make([]byte, gcm.NonceSize())
rand.Read(nonce)
encrypted := gcm.Seal(nonce, nonce, data, nil)
// 写入加密文件
return os.WriteFile(outputFile, encrypted, 0600)
}
// CI/CD解密示例
func init() {
key := os.Getenv("TFVARS_KEY")
DecryptTfvars("secrets.enc.tfvars", "terraform.tfvars", key)
}
1.3 策略即代码集成
Rego Terraform策略:
# terraform_policy.rego
package terraform
deny[msg] {
# 规则1: 禁止公开存储桶
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
resource.change.after.public_access_block_configuration == null
msg := "S3存储桶必须配置公共访问块"
}
deny[msg] {
# 规则2: 强制开启数据库加密
resource := input.resource_changes[_]
resource.type == "aws_db_instance"
resource.change.after.storage_encrypted != true
msg := "RDS实例必须启用存储加密"
}
执行扫描:
terraform plan -out=tfplan
terraform show -json tfplan | conftest test -