terraform-security-audit について
terraform-security-audit は、Terraform のコードベースを IAM、ネットワーク、暗号化など 6 つの領域で監査するスキルです。領域ごとの合否を報告し、不合格項目には修正コードを提示します。
主な機能
- 016 つのセキュリティ領域を確認
- 02すべての .tf ファイルをスキャン
- 03重大度順に問題を提示
- 04不合格項目の修正コードを提示
- 05領域別の監査レポートを生成
活用シーン
- 01本番デプロイ前のインフラ確認
- 02インフラの定期的な監査
- 03新サービス設定の検証
- 04インシデント後のセキュリティ強化
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ c0x12c/ ai-toolkit --skill terraform-security-auditインストール後、Claude Code で/terraform-security-auditを入力して読み込まれたか確認します。
詳細
Terraform セキュリティ監査
Terraform のコードベースに対して、6 領域のセキュリティ監査を実行します。各領域の合格/不合格レポートを生成します。
使用するタイミング
- 本番環境へのデプロイ前のセキュリティレビュー
- 定期的なインフラストラクチャのセキュリティ監査
- 新しいサービスのセットアップ検証
- インシデント後のセキュリティ強化チェック
プロセス
1. IAM — アイデンティティとアクセス管理
- CI/CD で OIDC を使用している(長期間有効なアクセスキーを使用していない)
- EKS ワークロードに IRSA を使用している(ノードレベルの IAM を使用していない)
- ECS タスクロールがサービスごとに適切に制限されている(共有ロールを使用していない)
- IAM ポリシーが最小権限の原則に従っている
-
*リソースに対する*アクションがない - インラインポリシーを使用していない(マネージドポリシーまたはカスタマーポリシーを使用する)
- Assume role の条件に
ExternalIdまたはsts:SourceIdentityが含まれている
# INSECURE — overly broad permissions
resource "aws_iam_policy" "bad" {
policy = jsonencode({
Statement = [{
Effect = "Allow"
Action = "*"
Resource = "*"
}]
})
}
# SECURE — scoped to specific actions and resources
resource "aws_iam_policy" "good" {
policy = jsonencode({
Statement = [{
Effect = "Allow"
Action = ["s3:GetObject", "s3:PutObject"]
Resource = "${aws_s3_bucket.assets.arn}/*"
}]
})
}
# SECURE — IRSA for EKS pods
module "irsa" {
source = "git::https://github.com/{project}/terraform-modules.git//irsa?ref=v1.0.0"
name = "${local.name_prefix}-irsa"
oidc_provider_arn = var.oidc_provider_arn
namespace = var.service
service_account = var.service
policy_arns = [aws_iam_policy.service.arn]
}
2. ネットワーク — VPC とセキュリティグループ
- データベースがプライベートサブネットのみに配置されている
- ALB の 443 番ポートを除き、
0.0.0.0/0からのインバウンド通信がない - セキュリティグループで CIDR ではなく
source_security_group_idを使用している - 可能な範囲でエグレスが制限されている
- VPC フローログが有効になっている
- 踏み台インスタンス以外にパブリック IP が割り当てられていない
# INSECURE — database accessible from anywhere
resource "aws_security_group_rule" "rds_bad" {
type = "ingress"
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.rds.id
}
# SECURE — database only from app security group
resource "aws_security_group_rule" "rds_good" {
type = "ingress"
from_port = 5432
to_port = 5432
protocol = "tcp"
source_security_group_id = aws_security_group.app.id
security_group_id = aws_security_group.rds.id
description = "PostgreSQL access from application"
}
3. 暗号化 — 保存データと転送中のデータ
- S3:SSE が有効になっている(KMS または AES-256)
- RDS:
storage_encrypted = trueに設定されている - RDS:パラメータグループで
ssl_enforcementを設定している - Redis:
transit_encryption_enabled = trueに設定されている - Redis:
at_rest_encryption_enabled = trueに設定されている - EBS ボリュームが暗号化されている
- Terraform のステートバケットが SSE-KMS で暗号化されている
- ALB が TLS 1.2 以降のみを使用している
# INSECURE — no encryption
resource "aws_db_instance" "bad" {
storage_encrypted = false # default
}
# SECURE — encryption enabled
resource "aws_db_instance" "good" {
storage_encrypted = true
kms_key_id = var.rds_kms_key_arn
}
# SECURE — Redis encryption
module "redis" {
source = "git::https://github.com/{project}/terraform-modules.git//elasticache?ref=v1.0.0"
transit_encryption = true
at_rest_encryption = true
auth_token = var.redis_auth_token
}
4. シークレット — シークレット管理
-
.tfファイルやコミット済みの.tfvarsにシークレットが含まれていない -
secrets.tfvarsが.gitignoreに含まれている - 機密変数に
sensitive = trueが指定されている - CI/CD の環境変数を介してシークレットが注入されている
- ステートに平文のパスワードがない(
sensitive出力を使用する) - git-secret-protector または pre-commit フックで、誤ったコミットを防いでいる
# INSECURE — password in code
resource "aws_db_instance" "bad" {
password = "SuperSecret123!"
}
# SECURE — from variable, marked sensitive
variable "db_password" {
description = "Database master password"
type = string
sensitive = true
}
resource "aws_db_instance" "good" {
password = var.db_password
}
# SECURE — sensitive output
output "connection_string" {
value = "postgresql://${var.db_user}:${var.db_password}@${aws_db_instance.main.endpoint}/${var.db_name}"
sensitive = true
}
5. アクセス — クラスターとコンソールへのアクセス
- EKS の
aws-authConfigMap で、必要なロールのみにアクセスを制限している - コンソールへのアクセスに SSO を使用している(パスワードを持つ IAM ユーザーを使用していない)
- Session Manager を使用するプライベートサブネット内の踏み台ホストがある(SSH キーを使用していない)
- API 監査ログ用に CloudTrail が有効になっている
- 人間のアカウントで MFA が強制されている
# EKS access control
resource "kubernetes_config_map" "aws_auth" {
metadata {
name = "aws-auth"
namespace = "kube-system"
}
data = {
mapRoles = yamlencode([
{
rolearn = var.admin_role_arn
username = "admin"
groups = ["system:masters"]
},
{
rolearn = var.node_role_arn
username = "system:node:{{EC2PrivateDNSName}}"
groups = ["system:bootstrappers", "system:nodes"]
}
])
}
}
6. コンプライアンス — タグ、命名、バックアップ
- すべてのリソースに Project、Service、Environment、ManagedBy のタグが付いている
-
{project}-{service}-{env}の規則に従って命名している - RDS の自動バックアップが有効になっている(保持期間は 7 日以上、本番環境では 30 日)
- データバケットで S3 のバージョニングが有効になっている
- DynamoDB のポイントインタイムリカバリが有効になっている
- 重要なメトリクスに CloudWatch アラームが設定されている
- コスト配分タグが設定されている
# CORRECT — default tags at provider level
provider "aws" {
default_tags {
tags = {
Project = var.project
Service = var.service
Environment = var.env
ManagedBy = "terraform"
}
}
}
# CORRECT — backup retention
resource "aws_db_instance" "main" {
backup_retention_period = var.env == "prod" ? 30 : 7
backup_window = "03:00-04:00"
}
対話スタイル
- コードベース内のすべての
.tfファイルをスキャンします - すべての領域を確認し、セクションを省略しません
- 重大な指摘事項(IAM のワイルドカード、パブリックアクセス、暗号化の欠如)を最初に強調します
- 不合格となった各チェックについて、修正用のコードを提示します
ルール
- 重大:IAM の
*/*、データベースへのパブリックアクセス、ストレージの暗号化なし、コード内のシークレット - 警告:タグの欠如、バックアップ保持期間の不足、フローログの未設定
- 情報:説明の欠如、任意のセキュリティ強化が未適用
出力
セキュリティ監査レポートを生成します:
## Terraform Security Audit: {service}
### Overall: Pass | Fail
| Area | Status | Critical | Warnings | Info |
|------------|----------|----------|----------|------|
| IAM | Pass | 0 | 0 | 1 |
| Network | Fail | 1 | 0 | 0 |
| Encryption | Pass | 0 | 1 | 0 |
| Secrets | Pass | 0 | 0 | 0 |
| Access | Pass | 0 | 0 | 1 |
| Compliance | Warning | 0 | 2 | 0 |
### Critical Findings
- **[Network]** Security group `rds_main` allows ingress from 0.0.0.0/0 on port 5432
- File: `modules/{service}/sg.tf:15`
- Fix: Replace `cidr_blocks` with `source_security_group_id`
### Warnings
- **[Encryption]** Redis `at_rest_encryption` not enabled
- File: `modules/{service}/redis.tf:8`
- Fix: Add `at_rest_encryption = true`
### Remediation Priority
1. Fix critical findings before any deployment
2. Address warnings before production promotion
3. Info items for next sprint
コメント
Markdown 対応