Terraform 인프라 보안 감사은(는) 무엇을 하나요?
사용 시기
- CI/CD 파이프라인에 보안 스캔을 통합하여 Terraform 배포를 검증할 때
- Terraform Plan 및 모듈을 적용하기 전에 보안 모범 사례를 검토할 때
- 클라우드 인프라 프로비저닝을 위한 정책 코드(Policy as Code) 가드레일을 구축할 때
- 기존 Terraform State 파일을 감사하여 배포된 설정 오류를 식별할 때
- 여러 Terraform 프로젝트 전반에 조직 보안 표준을 적용할 때
다음 상황에서는 사용하지 마십시오: 런타임 보안 모니터링(CSPM 도구 사용), 애플리케이션 보안 테스트(SAST/DAST 도구 사용), 클라우드 구성 변동 탐지(배포 후 AWS Config 또는 Azure Policy 사용).
사전 요구 사항
- Checkov 설치 (
pip install checkov) - tfsec 설치 (
brew install tfsec또는 GitHub 바이너리) - Terrascan 설치 (
brew install terrascan) - Terraform v1.0+ (Plan 생성용)
- 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 Plan 파일 스캔
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
# CI/CD 처리를 위해 JSON 출력
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
# GitHub Security 탭 연동을 위한 SARIF 출력 생성
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 Plan 스캔
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 Plan 평가
terraform show -json tfplan | opa eval \
--data ./policy/ \
--input /dev/stdin \
"data.terraform.aws" \
--format pretty
# 더 쉬운 OPA 정책 테스트를 위해 Conftest 실행
conftest test tfplan.json --policy ./policy/ --output json
5단계: CI/CD 파이프라인에 보안 스캔 통합
IaC 보안 스캔을 필수 CI/CD 게이트로 추가합니다.
# GitHub Actions: Terraform 보안 파이프라인
name: Terraform Security Scan
on:
pull_request:
paths: ['terraform/**']
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
- name: Terraform Init & Plan
run: |
cd terraform/
terraform init
terraform plan -out=tfplan
terraform show -json tfplan > tfplan.json
- name: Checkov Scan
uses: bridgecrewio/checkov-action@master
with:
directory: terraform/
framework: terraform
output_format: sarif
output_file_path: checkov.sarif
soft_fail: false
- name: tfsec Scan
uses: aquasecurity/[email protected]
with:
working_directory: terraform/
soft_fail: false
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: checkov.sarif
- name: OPA Policy Check
run: |
conftest test terraform/tfplan.json \
--policy ./policy/ \
--output json
6단계: Terraform State 스캔으로 배포된 설정 오류 확인
현재 Terraform State를 감사하여 이미 배포된 보안 문제를 식별합니다.
# 현재 State를 JSON으로 내보내기
terraform show -json > terraform-state.json
# Checkov로 State 스캔
checkov -f terraform-state.json --framework terraform_plan
# 특정 보안 이슈에 대해 State 쿼리
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
주요 개념
| 용어 | 정의 |
|---|---|
| Infrastructure as Code | 수동 콘솔 작업 대신 선언적 구성 파일(Terraform, CloudFormation)을 통해 클라우드 인프라를 관리하는 방법 |
| Policy as Code | 보안 및 규정 준수 정책을 실행 가능한 코드(Rego, Python)로 표현하여 인프라 정의에 대해 자동으로 평가하는 방식 |
| Shift Left Security | 배포 후 감사 대신 배포 전에 IaC를 스캔하여 개발 수명 주기 초기에 보안 검사를 이동하는 방법 |
| Terraform Plan | Terraform이 수행할 변경 사항 미리보기. 변경 사항 적용 전 보안 스캔을 위해 JSON으로 내보낼 수 있음 |
| Checkov | Terraform, CloudFormation, Kubernetes, Docker를 지원하는 1000개 이상의 내장 정책을 갖춘 오픈소스 IaC 정적 분석 도구 |
| OPA/Rego | 구조화된 데이터 입력에 대해 평가하는 사용자 정의 보안 규칙을 정의하기 위한 Open Policy Agent와 그 정책 언어 Rego |
도구 및 시스템
- Checkov: Terraform, CloudFormation, Kubernetes, ARM, Dockerfile을 위한 1000개 이상의 정책을 갖춘 종합 IaC 스캐너
- tfsec: Terraform 특화 정적 분석 도구로 상세한 수정 가이드와 SARIF 출력 제공
- Terrascan: 규정 준수 프레임워크(CIS, NIST, SOC 2)를 지원하는 다중 IaC 스캐너, 정책 코드 포함
- OPA/Conftest: Rego 언어를 사용하여 조직별 보안 규칙을 정의하기 위한 사용자 정의 정책 엔진
- Bridgecrew: Checkov 기반 상용 플랫폼으로 구성 변동 탐지 및 공급망 보안 제공
일반 시나리오
시나리오: 기존 Terraform CI/CD 파이프라인에 보안 게이트 추가
상황: DevOps 팀이 GitHub Actions에서 Terraform을 통해 인프라를 배포하지만 보안 스캔이 없습니다. 최근 감사 결과 여러 S3 버킷에 암호화가 없고 인터넷에서 SSH를 허용하는 보안 그룹이 발견되었습니다.
접근 방식:
- GitHub Actions 워크플로에 첫 번째 보안 게이트로 Checkov를 추가합니다
checkov -d ./terraform/를 실행하여 현재 발견 사항 기준을 설정합니다- 기존 발견 사항을 분류합니다: CRITICAL 이슈 수정, HIGH 티켓 생성, 승인된 위험은 억제
- Terraform 특화 검사를 위해 tfsec을 보조 스캐너로 추가합니다
- 조직 표준(필수 태그, 명명 규칙)에 대한 사용자 정의 OPA 정책을 작성합니다
- CRITICAL 또는 HIGH 발견 사항이 있는 PR을 차단하도록 파이프라인을 구성합니다
- GitHub Security 탭 통합을 위해 SARIF 보고서를 생성합니다
함정: 기존 프로젝트에 보안 스캔을 추가하면 처음에는 수백 개의 발견 사항이 나타납니다. CRITICAL만 차단하는 것으로 시작하여 점진적으로 HIGH로 확장하십시오. 의도적인 예외는 문서화된 이유와 함께 인라인 억제 주석(#checkov:skip=CKV_AWS_18:정적 웹 사이트용 퍼블릭 버킷)을 사용하십시오.
출력 형식
Terraform Security Audit Report
==================================
Repository: acme-corp/infrastructure
Branch: main
Scan Date: 2026-02-23
Tools: Checkov 3.x, tfsec 1.x, OPA custom policies
SCAN RESULTS:
Checkov checks passed: 187
Checkov checks failed: 34
tfsec checks passed: 156
tfsec checks failed: 28
OPA custom policies: 12 passed, 3 failed
CRITICAL FINDINGS:
[TF-001] S3 Bucket Without Encryption
File: modules/storage/main.tf:24
Resource: aws_s3_bucket.data_lake
Check: CKV_AWS_19
Fix: Add server_side_encryption_configuration block
[TF-002] Security Group Allows SSH from 0.0.0.0/0
File: modules/network/security.tf:45
Resource: aws_security_group_rule.ssh_access
Check: CKV_AWS_24
Fix: Restrict cidr_blocks to bastion subnet
[TF-003] IAM Policy with Wildcard Actions
File: modules/iam/policies.tf:12
Resource: aws_iam_policy.developer_policy
Check: CKV_AWS_1
Fix: Scope actions to specific services required
SUMMARY BY SEVERITY:
Critical: 6 findings
High: 14 findings
Medium: 28 findings
Low: 18 findings
Info: 12 findings