tf-best-practices について
移行ワークフローで生成する AWS Terraform 向けの共有ガイド兼読み取り専用ポリシーチェッカーです。作成時のセキュリティルールと機械可読な判定を提供し、Terraform ファイルやワークフロー状態は変更しません。
主な機能
- 01AWS Terraform のセキュリティルール
- 02読み取り専用のポリシー検証
- 03機械可読な判定レポート
- 04修正に役立つ違反の詳細
- 05依存関係不要の静的 HCL チェック
活用シーン
- 01Terraform 生成の指針
- 02生成した Terraform のセキュリティ確認
- 03完了前のポリシー違反の特定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ aws/ agent-toolkit-for-aws --skill tf-best-practicesインストール後、Claude Code で/tf-best-practicesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.gitignorefixtures/terraform-policy/bad-db-sg-public-quoted-port/vpc.tffixtures/terraform-policy/bad-db-sg-public/vpc.tffixtures/terraform-policy/bad-elasticache-cluster-redis-unencrypted/cache.tffixtures/terraform-policy/bad-elasticache-unencrypted/cache.tffixtures/terraform-policy/bad-heroku-eb-elasticache/cache.tffixtures/terraform-policy/bad-http-forward/compute.tffixtures/terraform-policy/bad-rds-public-brace-in-comment/main.tffixtures/terraform-policy/bad-rds-public-closing-brace/main.tffixtures/terraform-policy/bad-rds-public-interpolated-brace/rds.tffixtures/terraform-policy/bad-rds-public-unencrypted/database.tffixtures/terraform-policy/bad-sg-public-ipv6/vpc.tffixtures/terraform-policy/bad-sg-public-ssh/vpc.tffixtures/terraform-policy/bad-wildcard-iam-listform/security.tffixtures/terraform-policy/bad-wildcard-iam/security.tffixtures/terraform-policy/good-db-sg-scoped/vpc.tffixtures/terraform-policy/good-elasticache-cluster-memcached/cache.tffixtures/terraform-policy/good-elasticache-cluster-redis-encrypted/cache.tffixtures/terraform-policy/good-elasticache-encrypted/cache.tffixtures/terraform-policy/good-heroku-eb-codepipeline/pipeline.tffixtures/terraform-policy/good-heroku-eb-loadbalanced/compute.tfdatabase.tfsecurity.tffixtures/terraform-policy/good-heroku-eb-only/compute.tffixtures/terraform-policy/good-heroku-eb-singleinstance/compute.tffixtures/terraform-policy/good-https-redirect/compute.tffixtures/terraform-policy/good-iam-scoped-list/security.tffixtures/terraform-policy/good-internet-nlb/compute.tffixtures/terraform-policy/good-quoted-port-https/compute.tffixtures/terraform-policy/good-rds-private-encrypted/database.tf詳細
tf-best-practices — 生成された IaC のセキュリティポスチャルール + 読み取り専用ポリシーゲート
共有の作成ガイド兼判定結果の生成ツールであり、ワークフローではありません。AWS Terraform を生成するフェーズに、次の 2 つの問いに答えます。
- 作成前 — 生成する
terraform/が従うべきセキュリティポスチャとは何か? (セキュリティポスチャルール +baseline.tfのアカウント強化仕様) - 作成後 — 生成した
terraform/はポリシーに合格するか?(決定論的な読み取り専用の判定結果 + 機械可読なレポート)
ルーティング — コンテキストに合った部分を読み込む
このスキルは、呼び出し元の Generate フローにある 2 つのタイミングで実行され、その間に呼び出し元が Terraform の作成作業を行います。このスキルを読み込む際に、呼び出し元がどちらのタイミングであるかを指定し、該当する部分を読み込みます。
| 呼び出し元のコンテキスト | 読み込む内容 | 理由 |
|---|---|---|
terraform/ を作成する直前(作成前) | Part 1 → references/security-posture-rules.md | 出力すべき AWS の作成ルール(ゲートで強制されるルール + 作成時のみのルール + コンプライアンス条件付きルール)。 |
terraform/ の作成後、検証の準備完了(作成後) | Part 2 → references/terraform-validation.md + ゲートスクリプトを実行 | fmt → init → validate → policy の手順と読み取り専用の判定結果。 |
このスキルで述べる内容はすべてソースクラウドに依存しません(AWS Terraform のみ)。GCP/Heroku の検出やアーティファクトの読み取りは呼び出し元の役割です。ルールに呼び出し元が把握している事実(宣言されたコンプライアンスフレームワークなど)が必要な場合、呼び出し元はそれを呼び出し元コンテキストシグナルとして渡します。詳しくは references/security-posture-rules.md § 呼び出し元コンテキストシグナル を参照してください。
境界(最初にお読みください)
このユニットは判定結果を生成するものであり、変更を加えることはありません。書き込み対象は、出力を求められた JSON 判定結果のみです。具体的には、次の操作をしてはなりません。
.tfファイルを編集、フォーマット、または書き換える(修正は呼び出し元の担当です)。.phase-status.jsonや実行状態ファイルを読み書きする(インタープリターの管理対象です)。- フェーズを完了できるか判断したり、ユーザーにプロンプトを表示したりする(呼び出し元のポリシーです)。
生成した .tf の修正を伴う再試行ループ、terraform fmt の自動適用、再試行/スキップ/中止のプロンプト、Phase Completion ゲート、およびすべての .phase-status.json の書き込みは、呼び出し元(移行スキルの Generate フェーズ)が担当します。判定結果をこれらの判断にどう反映するかについては、利用するスキルの Generate フェーズを参照してください。
利用者:
gcp-to-aws(文章形式の Generate)およびheroku-to-aws(DSL 形式の Generate)。この契約はソースに依存しません。各呼び出し元は、それぞれの Generate の記述形式に応じて 2 つのタイミングを組み込みます。gcp-to-aws は文章形式の手順、heroku-to-aws はフラグメント手順に加え、インタープリターが強制するフェイルクローズの_postconditionsアサーションを使用します。
パート 1 — 作成時の指針(terraform/ の作成前に読み込む)
references/security-posture-rules.md に記載された指針を満たす Terraform を生成します。
これは「適切な AWS Terraform の要件」です。これに従うことで、パート 2 のゲートを最初から通過できます。このユニットは呼び出し元の成果物を読み取りません。呼び出し元が渡すコンテキスト情報のみを使用します。
範囲。
security-posture-rules.mdでは、次の 3 つの段階に分けて説明しています。
- ゲートで強制される項目(パート 2 で静的に検証):ALB の TLS、パブリックデータベースの禁止、RDS と ElastiCache の保存時暗号化、パブリック DB ポートからのイングレスの禁止、パブリック管理/データストアポートからのイングレスの禁止、ワイルドカード IAM の禁止。
- 作成時のみの項目(ゲートではチェックできませんが、必須):
deletion_protection、Secrets Manager 経由のマスターパスワード、S3 の強化、Fargate/EKS/ECR の設定、プライベートサブネットへの配置、バックアップ、基本的なモニタリング。- コンプライアンス条件付きの項目(呼び出し元が
soc2/pci/hipaa/fedrampを宣言した場合に生成):VPC フローログ、S3 アクセスログ、シークレットのローテーション、カスタマー管理の KMS。アカウント強化の
baseline.tfレイヤー(CloudTrail、GuardDuty、Config、Security Hub)は、引き続き呼び出し元自身が生成を検討する項目です(今後、ここに移行する候補)。
パート 2 — ポリシーゲート(terraform/ の作成後に実行)
生成したディレクトリに対して、読み取り専用のチェッカーを実行します。スクリプトのパスはプラグインルートを基準に解決します($PLUGIN_ROOT/skills/tf-best-practices/scripts/...)。これは、プラグイン内の他のスクリプトと同じ規約です。
python3 "$PLUGIN_ROOT/skills/tf-best-practices/scripts/validate-terraform-policy.py" "$TERRAFORM_DIR" --json "$VERDICT_PATH"
$TERRAFORM_DIR— 必須、呼び出し元が指定:生成したterraform/ディレクトリ(例:$MIGRATION_DIR/terraform)。このスキルはデフォルト値の設定やパスの検索を行いません。呼び出し元は、Terraform を書き込んだパスを必ず渡します。--json $VERDICT_PATH— 任意。呼び出し元が自身のvalidation-report.jsonに統合できる、機械可読な判定結果を書き込みます。
ポリシーチェックは、より大きな検証フロー(fmt → init → validate → policy)の 1 段階です。オフライン時のフォールバック動作や、ポリシー判定結果を validation-report.json に反映する方法を含むプロトコル全体については、references/terraform-validation.md を参照してください。このプロトコルは説明を目的とするものです。fmt/init/validate の実行、修正と再試行のループ、およびレポートの書き込みは呼び出し元が担当します。このユニットが担うのは、読み取り専用のポリシー段階と判定結果の形式のみです。
終了コード → 呼び出し元の対応
| 終了コード | stdout | 意味 | 呼び出し元の対応 |
|---|---|---|---|
0 | POLICY_OK | 指針を満たしています | 続行 |
1 | POLICY_FAIL | 違反があります | violations[] を読み、指定された .tf の箇所を編集し、再実行する(呼び出し元の再試行上限に従う) |
2 | (使用エラー) | パス不正/入出力エラー | ユーザーに伝え、合格として扱わない |
判定結果の形式(--json)
{
"check": "policy",
"policy_status": "POLICY_OK | POLICY_FAIL",
"violations": [
{
"check": "policy",
"rule": "alb_https_listener | alb_http_redirect | no_tf_files",
"file": "compute.tf",
"line": 7,
"severity": "error",
"summary": "human-readable violation",
"fix_hint": "concrete remediation the caller can apply"
}
]
}
各 violations[] エントリは、対応可能な根拠情報です。file、line、fix_hint により、呼び出し元は編集すべき箇所を正確に把握できます。編集は呼び出し元が行い、このユニットは報告のみを行います。
現在適用されているポリシールール
すべてのルールは、曖昧な場合はフェイルオープンです。明確なブロック内のリテラルな証拠がある場合にのみ発動するため、有効な構成が誤ってブロックされることはありません(POLICY_FAILは呼び出し元にとって完了を妨げるハードゲートなので、誤検知があると実際の移行がブロックされます)。
インターネット向けALBのTLS設定(internalがない、false、または変数駆動の場合、ALBはインターネット向けとみなされます。フェイルセーフ):
alb_https_listener—certificate_arnとforwardアクションを指定したHTTPSリスナーを443に設定する必要があります。alb_http_redirect— HTTPの:80リスナーはHTTPSにredirectする必要があります。ターゲットへのforwardは許可されません。内部ALB(internal = true)は対象外です。
Elastic BeanstalkのALBは、これらのルールでは検出されません。 ALBルールはスタンドアロンの
aws_lb_listenerブロックを検査します。EBのLoadBalanced環境は、aws_elastic_beanstalk_environmentのsettingブロックからALBをプロビジョニングしますが、静的チェッカーはこれを読み取りません。そのため、純粋なEB構成は、検査対象のリスナーがないため、ALBルールを実質的に通過します。したがって、EBのリスナー/TLS設定は作成時にのみ確認され、ゲートによる強制はありません。(フィクスチャgood-heroku-eb-onlyとgood-heroku-eb-singleinstanceがこれを示しています。good-heroku-eb-loadbalancedにはスタンドアロンALBが含まれているため、実際のブロックに対してリスナールールが適用されます。)
マネージドデータベースの公開設定と暗号化(aws_db_instance、aws_rds_cluster):
rds_not_public—publicly_accessible = trueを設定してはいけません(未指定/変数の場合はフェイルオープン)。rds_encryption_at_rest—storage_encrypted = trueを設定する必要があります。未指定またはリテラルのfalseの場合は発動します(RDSのデフォルトは暗号化なしです)。変数駆動の場合はフェイルオープンです。S3は検査対象外です(2023年1月以降、デフォルトでSSE-S3が適用されます)。
ElastiCacheの暗号化(aws_elasticache_replication_group、Redisのaws_elasticache_cluster):
elasticache_encryption_at_rest— レプリケーショングループにはat_rest_encryption_enabled = trueを設定する必要があります。未指定またはリテラルのfalseの場合は発動し、変数駆動の場合はフェイルオープンです。elasticache_cluster_encryption— Redisエンジンのaws_elasticache_cluster(単一ノード:engine = "redis"、replication_group_idなし)には、at_rest_encryption_enabled = trueとtransit_encryption_enabled = trueの両方を設定する必要があります。いずれかが未指定またはリテラルのfalseの場合は発動し、変数駆動の場合はフェイルオープンです。engine = "memcached"のクラスター(およびエンジンが変数駆動または未指定の場合)は対象外です。Memcachedはこれらの属性をサポートしていません。
セキュリティグループのインバウンドルール:
db_sg_no_public_ingress—5432/3306を対象とするインラインのaws_security_groupインバウンドルールで、0.0.0.0/0または::/0を許可してはいけません。sg_no_public_admin_ingress— インラインのインバウンドルールで、一般公開を決して許可しない管理/データストア用ポート(22、3389、6379、11211、27017、9200/9300、5601)を0.0.0.0/0または::/0に開放してはいけません。Web(80/443)およびアプリ/ゲーム用ポートは検出対象外です。DBポートは上記のルールで扱われます。どちらのルールもcidr_blocksとipv6_cidr_blocksを個別に確認するため、問題のないIPv4リストによって、開放されたIPv6ルールが見逃されることはありません。どちらも、個別のaws_security_group_rule/aws_vpc_security_group_ingress_ruleリソースはフェイルオープンです(関連付けて検査されません)。
IAMの最小権限(aws_iam_policy、aws_iam_role_policy、aws_iam_group_policy、aws_iam_user_policy):
no_wildcard_iam—AllowステートメントでAction/Resourceに"*"を使用してはいけません。唯一の限定的な例外は、独立したelasticbeanstalk:CreateStorageLocationステートメントでResource = "*"を指定する場合です。このアクションでは、AWSがリソースレベルの権限をサポートしていないためです。aws_iam_policy_documentデータソースとロール引き受けの信頼ポリシーはフェイルオープンです。
チェッカーは依存関係ゼロの静的HCLリーダーです(
terraform initやプロバイダーのダウンロードは不要です)。レジストリに接続できない場合でも実行されます。ネストされたブロックには波括弧の深さによる照合を使用するため、ネストしたforward { ... }ブロックを含む有効なHTTPSリスナーが誤って失敗することはありません。
フィクスチャ(チェッカーの回帰テストスイートでもあります)
scripts/test_validate_terraform_policy.py で使用する、意図的に形を調整した Terraform が fixtures/terraform-policy/ に格納されています。
bad-http-forward/— インターネットに公開された ALB が暗号化されていない HTTP を転送します →POLICY_FAILでなければなりません。internal-alb-only/— HTTP を使用する内部 ALB です →POLICY_OKでなければなりません(内部では HTTP が許可されています)。good-https-redirect/— 正しいパターンです →POLICY_OK。
これらは意図的に準拠していないテストデータであり、デプロイされることはありません。.checkov.yaml の skip-path によって、リポジトリ全体に対する checkov スキャンから除外されています。これらを「強化」しないでください。失敗パスを検証するテストが壊れます。
検証
# from skills/tf-best-practices/
uv run --python 3.12 --with pytest python -m pytest scripts/test_validate_terraform_policy.py -q