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" # [OK] 安全
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 を必須とする
- apply の前に plan:提案された変更をレビューする
- 環境の分離:Dev/Staging/Prod を分離する
- タグ付け戦略:ガバナンスとコスト配分のためのタグ
- 最小権限:CI/CD 専用の IAM ロール
- 自動テスト:検証のための Terratest
最終的な推奨事項
IaC セキュリティは自動化し、最初から CI/CD に統合すべきです。完全なカバレッジのために 複数のスキャンツール(tfsec、Checkov)を使用してください。OPA または Sentinel で policy as code を実装しましょう。シークレットは決してコミットせず、シークレットマネージャーを使用してください。 ドリフトを継続的に監視しましょう。IaC の設定ミスは、クラウド侵害の最も一般的な原因の一つです。
