審計 Terraform 基礎設施以確保安全性
使用時機
- 將安全掃描整合至 Terraform 部署的 CI/CD 管線時
- 在套用 Terraform 計畫和模組前,審查其安全最佳實務時
- 建置雲端基礎設施佈建的「政策即程式碼」護欄時
- 審計現有 Terraform 狀態檔案,以識別已部署的配置錯誤時
- 在多個 Terraform 專案間強制執行組織安全標準時
請勿用於:執行期安全監控(請使用 CSPM 工具)、應用程式安全測試(請使用 SAST/DAST 工具)或雲端配置漂移偵測(部署後請使用 AWS Config 或 Azure Policy)。
先決條件
- 已安裝 Checkov(
pip install checkov) - 已安裝 tfsec(
brew install tfsec或從 GitHub 下載二進位檔) - 已安裝 Terrascan(
brew install terrascan) - 用於產生計畫檔的 Terraform v1.0+
- 用於自訂政策強制執行的 OPA(Open Policy Agent)
- 包含待審計 Terraform 程式碼的 Git 儲存庫
工作流程
步驟 1:使用 Checkov 掃描 Terraform 程式碼
執行 Checkov 以進行全面的 IaC 安全掃描,包含內建與自訂政策。
# 掃描 Terraform 目錄
checkov -d ./terraform/ --framework terraform
# 掃描特定檢查類別
checkov -d ./terraform/ --check CKV_AWS_18,CKV_AWS_19,CKV_AWS_20,CKV_AWS_21
# 掃描並以 JSON 格式輸出結果
checkov -d ./terraform/ --output json > checkov-results.json
# 掃描 Terraform 計畫檔案以進行更精確的分析
terraform init && terraform plan -out=tfplan
terraform show -json tfplan > tfplan.json
checkov -f tfplan.json --framework terraform_plan
# 跳過特定檢查並附上理由
checkov -d ./terraform/ --skip-check CKV_AWS_145 \
--bc-api-key $BRIDGECREW_API_KEY
# 掃描 Terraform 模組
checkov -d ./modules/ --framework terraform --compact
# 列出所有可用的檢查項目
checkov --list --framework terraform | grep CKV_AWS
步驟 2:使用 tfsec 掃描 Terraform 特定問題
使用 tfsec 進行 Terraform 原生的安全分析,並提供詳細的補救指引。
# 掃描 Terraform 目錄
tfsec ./terraform/
# 以最低嚴重性門檻掃描
tfsec ./terraform/ --minimum-severity HIGH
# 以 JSON 格式輸出,便於 CI/CD 處理
tfsec ./terraform/ --format json > tfsec-results.json
# 使用自訂檢查掃描
tfsec ./terraform/ --custom-check-dir ./custom-checks/
# 排除特定規則
tfsec ./terraform/ --exclude-downloaded-modules \
--exclude aws-s3-enable-bucket-logging
# 掃描並於達到特定嚴重性時失敗
tfsec ./terraform/ --minimum-severity CRITICAL --soft-fail
# 產生 SARIF 輸出給 GitHub 安全性標籤頁
tfsec ./terraform/ --format sarif > tfsec.sarif
步驟 3:執行 Terrascan 進行多框架合規檢查
執行 Terrascan 以檢查是否符合 CIS、NIST 和 SOC 2 框架。
# 針對 CIS AWS 基準掃描 Terraform
terrascan scan -t aws -i terraform -d ./terraform/ \
--policy-type aws --verbose
# 針對特定合規框架掃描
terrascan scan -t aws -i terraform -d ./terraform/ \
--policy-type aws \
--categories "Compliance Validation"
# 以 JSON 格式輸出
terrascan scan -t aws -i terraform -d ./terraform/ \
--output json > terrascan-results.json
# 掃描 Terraform 計畫
terrascan scan -t aws -i terraform \
--iac-file tfplan.json \
--iac-type tfplan
# 列出可用政策
terrascan scan --list-policies -t aws
步驟 4:建立自訂 OPA 政策以符合組織標準
撰寫 Rego 政策以處理特定組織的安全需求。
# policy/aws_s3_encryption.rego
package terraform.aws.s3
deny[msg] {
resource := input.resource.aws_s3_bucket[name]
not resource.server_side_encryption_configuration
msg := sprintf("S3 儲存貯體 '%s' 必須啟用伺服器端加密", [name])
}
# policy/aws_iam_no_wildcards.rego
package terraform.aws.iam
deny[msg] {
resource := input.resource.aws_iam_policy[name]
statement := resource.policy.Statement[_]
statement.Action == "*"
statement.Effect == "Allow"
msg := sprintf("IAM 政策 '%s' 不得使用萬用字元 (*) 動作", [name])
}
deny[msg] {
resource := input.resource.aws_iam_policy[name]
statement := resource.policy.Statement[_]
statement.Resource == "*"
statement.Effect == "Allow"
contains(statement.Action[_], "*")
msg := sprintf("IAM 政策 '%s' 在萬用字元資源上具有過度寬鬆的動作", [name])
}
# policy/aws_no_public_ingress.rego
package terraform.aws.security_group
deny[msg] {
resource := input.resource.aws_security_group_rule[name]
resource.type == "ingress"
resource.cidr_blocks[_] == "0.0.0.0/0"
resource.from_port <= 22
resource.to_port >= 22
msg := sprintf("安全群組規則 '%s' 允許來自 0.0.0.0/0 的 SSH 連線", [name])
}
# 針對 OPA 政策評估 Terraform 計畫
terraform show -json tfplan | opa eval \
--data ./policy/ \
--input /dev/stdin \
"data.terraform.aws" \
--format pretty
# 使用 Conftest 進行更簡便的 OPA 政策測試
conftest test tfplan.json --policy ./policy/ --output json
步驟 5:將安全掃描整合至 CI/CD 管線
將 IaC 安全掃描設為強制性的 CI/CD 閘門。
# GitHub Actions:Terraform 安全管線
name: Terraform 安全掃描
on:
pull_request:
paths: ['terraform/**']
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 設定 Terraform
uses: hashicorp/setup-terraform@v3
- name: Terraform 初始化並產生計畫
run: |
cd terraform/
terraform init
terraform plan -out=tfplan
terraform show -json tfplan > tfplan.json
- name: Checkov 掃描
uses: bridgecrewio/checkov-action@master
with:
directory: terraform/
framework: terraform
output_format: sarif
output_file_path: checkov.sarif
soft_fail: false
- name: tfsec 掃描
uses: aquasecurity/[email protected]
with:
working_directory: terraform/
soft_fail: false
- name: 上傳 SARIF
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: checkov.sarif
- name: OPA 政策檢查
run: |
conftest test terraform/tfplan.json \
--policy ./policy/ \
--output json
步驟 6:掃描 Terraform 狀態以找出已部署的配置錯誤
審計目前的 Terraform 狀態,以識別已部署的安全問題。
# 將當前狀態匯出為 JSON
terraform show -json > terraform-state.json
# 使用 Checkov 掃描狀態
checkov -f terraform-state.json --framework terraform_plan
# 查詢狀態中的特定安全問題
terraform state list | while read resource; do
terraform state show "$resource" 2>/dev/null | grep -i "public\|0.0.0.0\|encrypt.*false\|password"
done
# 尋找缺少必要標籤的資源
terraform state list | grep aws_instance | while read resource; do
tags=$(terraform state show "$resource" | grep -A20 "tags")
if ! echo "$tags" | grep -q "Environment"; then
echo "缺少標籤:$resource 缺少 'Environment' 標籤"
fi
done
關鍵概念
| 術語 | 定義 |
|---|---|
| 基礎設施即程式碼 | 透過宣告式設定檔(Terraform、CloudFormation)而非手動主控台操作來管理雲端基礎設施的作法 |
| 政策即程式碼 | 將安全性與合規政策表述為可執行程式碼(Rego、Python),以便自動針對基礎設施定義進行評估 |
| 左移安全 | 在部署前掃描 IaC,將安全檢查移至開發生命週期更早的階段,而非在佈建後才進行審計 |
| Terraform 計畫 | Terraform 將執行之變更的預覽,可在套用變更前匯出為 JSON 以供安全掃描 |
| Checkov | 開源 IaC 靜態分析工具,支援 Terraform、CloudFormation、Kubernetes 及 Docker,內建 1000 多條政策 |
| OPA/Rego | Open Policy Agent 及其政策語言 Rego,用於定義能針對結構化資料輸入進行評估的自訂安全規則 |
工具與系統
- Checkov:全面的 IaC 掃描器,為 Terraform、CloudFormation、Kubernetes、ARM 及 Dockerfile 提供 1000 多條政策
- tfsec:Terraform 專用的靜態分析工具,提供詳細的補救指引與 SARIF 輸出
- Terrascan:多 IaC 掃描器,支援合規框架(CIS、NIST、SOC 2)並搭載政策即程式碼
- OPA/Conftest:自訂政策引擎,用於使用 Rego 語言定義組織特定的安全規則
- Bridgecrew:以 Checkov 為基礎的商業平台,提供漂移偵測與供應鏈安全功能
常見情境
情境:為現有 Terraform CI/CD 管線加入安全閘門
背景:某 DevOps 團隊透過 GitHub Actions 中的 Terraform 部署基礎設施,但未進行安全掃描。最近的審計結果顯示多個 S3 儲存貯體未加密,且安全群組允許來自網際網路的 SSH 連線。
方法:
- 將 Checkov 作為第一個安全閘門加入 GitHub Actions 工作流程
- 執行
checkov -d ./terraform/以建立當前發現項目的基準 - 分類既有發現項目:修復 CRITICAL(關鍵)問題、為 HIGH(高)問題建立工單、抑制已接受的風險
- 加入 tfsec 作為第二個掃描器,進行 Terraform 專屬檢查
- 為組織標準(必要標籤、命名慣例)撰寫自訂 OPA 政策
- 設定管線在遇到 CRITICAL 或 HIGH 發現項目時封鎖 PR
- 產生 SARIF 報告以整合至 GitHub 安全性標籤頁
陷阱:為現有專案加入安全掃描初期會產生數百個發現項目。應逐步實施:先僅封鎖 CRITICAL 層級,再逐步擴展至 HIGH。使用行內抑制註解(#checkov:skip=CKV_AWS_18:用於靜態網站的公開儲存貯體)來處理有明確文件記錄的例外情況。
輸出格式
Terraform 安全審計報告
==================================
儲存庫:acme-corp/infrastructure
分支:main
掃描日期:2026-02-23
工具:Checkov 3.x, tfsec 1.x, OPA 自訂政策
掃描結果:
Checkov 檢查通過: 187
Checkov 檢查失敗: 34
tfsec 檢查通過: 156
tfsec 檢查失敗: 28
OPA 自訂政策: 12 通過,3 失敗
關鍵發現項目:
[TF-001] S3 儲存貯體未加密
檔案:modules/storage/main.tf:24
資源:aws_s3_bucket.data_lake
檢查:CKV_AWS_19
修復:加入 server_side_encryption_configuration 區塊
[TF-002] 安全群組允許來自 0.0.0.0/0 的 SSH 連線
檔案:modules/network/security.tf:45
資源:aws_security_group_rule.ssh_access
檢查:CKV_AWS_24
修復:將 cidr_blocks 限制為堡壘子網路
[TF-003] 具有萬用字元動作的 IAM 政策
檔案:modules/iam/policies.tf:12
資源:aws_iam_policy.developer_policy
檢查:CKV_AWS_1
修復:將動作範圍限定至所需的特定服務
依嚴重性摘要:
Critical(關鍵): 6 項發現
High(高): 14 項發現
Medium(中): 28 項發現
Low(低): 18 項發現
Info(資訊): 12 項發現