• Projects
  • Service
  • About
  • branding.bz
  • Podcast
  • Tips
  • FAQ
  • Recruit
  • Download
  • Contact
  • branding.bz(ブランド構築SaaS)
  • DESIGN NOW(デザインメディア)
  • X
  • LinkedIn
  • Spotify
  • Facebook

213-0011 神奈川県川崎市高津区久本3-6-7-303

© 2026 ID INC. All rights reserved

claude-skills/スキル
SKILLOfficialdevelopment

tf-best-practices

プラグイン
aws-startup-advisor
ソース
GitHub で見る ↗
説明

**AWS Terraform のベストプラクティス確認とポリシーチェック** 移行スキル(クラウド環境を別のシステムに移す際に使うツール)で生成された AWS Terraform コード向けの、ベストプラクティス作成ガイダンスと読み取り専用のポリシーゲート(承認判定)です。 terraform/ ディレクトリへの書き込みが行われるあらゆる段階で読み込まれます。まず「何を出力するか」というルール + セキュリティの基本仕様として機能し、その後の書き込み完了後には、確定的なポリシー判定を行います。 読み取り専用であるため、生成された Terraform が基準に適合しているかを報告するのみです。.tf ファイルの編集、.phase-status.json の変更、フェーズ完了の判定は一切行いません。terraform fmt/init/validate といった既存のツールを補完するもので、それらに置き換わるものではありません。 **使用場面:** AWS への移行時に Terraform コードの品質とセキュリティが基準を満たしているか確認したい場合

原文を表示

Best-practice authoring guidance AND a read-only policy gate for AWS Terraform generated by a migration skill. Load during any phase that writes a terraform/ directory — first as the "what to emit" posture rules + security-baseline spec, then after writing as the deterministic policy verdict. Read-only: it reports whether the generated Terraform passes; it never edits .tf files, never touches .phase-status.json, and never decides phase completion. Complements (does not replace) terraform fmt/init/validate.

ユースケース
  • AWS移行時にTerraformコードの品質を確認するとき
  • セキュリティ基本仕様への適合性を判定するとき
  • terraform/ディレクトリへの書き込み時にポリシーをチェックするとき
本文(日本語訳)

tf-best-practices — 生成されたインフラストラクチャコード(IaC)のセキュリティ方針ルール + 読み取り専用ポリシーチェック

共有された作成ガイドと判定結果の提供者で、ワークフローではありません。AWS Terraformを生成するフェーズのために、2つの質問に答えます:

  1. 作成前 — 「生成された terraform/ はどのセキュリティ方針に従う必要があるか?」 (方針ルール + baseline.tf アカウント堅牢化仕様)
  2. 作成後 — 「生成された terraform/ はポリシー要件をクリアしているか?」 (決定的な読み取り専用の判定 + 機械判読可能なレポート)

ルーティング — あなたの状況に合った部分を読む

このスキルは呼び出し元の生成フローの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 の Caller-context signals セクションを参照してください。

境界(最初に読んでください)

この単位は判定結果の生成者であり、決して修正者ではありません。書き込み表面全体は、出力するよう求められるJSON判定のみです。具体的には以下をしてはいけません:

  • .tf ファイルを編集、フォーマット、書き直さない(修正は呼び出し元が所有)
  • .phase-status.json やランタイム状態ファイルを読み書きしない(インタプリタ所有)
  • フェーズの完了を決定したり、ユーザーにプロンプト表示したりしない(呼び出し元ポリシー)

呼び出し元(マイグレーションスキルの生成フェーズ)が所有するもの:生成した .tf を編集する修正・リトライループ、terraform fmt 自動適用、リトライ/スキップ/中止プロンプト、フェーズ完了ゲート、すべての .phase-status.json 書き込み。判定がこれらの決定にどう反映されるかは、使用側スキルの生成フェーズのドキュメントを参照してください。

使用者: gcp-to-aws(散文形式の生成)と heroku-to-aws(DSL形式の生成)。契約はソース非依存です。各呼び出し元は2つのタッチポイントを自身の生成イディオムで結線します — gcp-to-awsは散文ステップとして、heroku-to-awsはフラグメントステップとインタプリタが強制する fail-closed 型の _postconditions アサートとして。

Part 1 — 作成時のセキュリティ方針(terraform/ 作成前に読む)

references/security-posture-rules.md の方針を満たす生成Terraformを出力します。

これらは「良いAWS Terraformとは何か」というルールです。これらに従うことで、Part 2のゲートは構造上パスします。このユニットは呼び出し元のアーティファクトを読まず、呼び出し元が渡す呼び出し元コンテキスト信号のみを消費します。

対象範囲。 security-posture-rules.md は3つの層でカバーしています:

  • ゲート強制(Part 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)

Part 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 実行、修正・リトライループ、レポート書き込みを所有します。このユニットは読み取り専用ポリシー段階 + 判定形状のみを提供します。

終了コード → 呼び出し元のアクション

コード 標準出力 意味 呼び出し元の対応
0 POLICY_OK 方針を満たしている 進む
1 POLICY_FAIL 違反がある violations[] を読み、該当 .tf 部分を編集し、再実行(呼び出し元のリトライ予算内)
2 (使用法エラー) 不正なパス / IO エラー ユーザーに表示。パスと見なさない

判定結果の形状(--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": "人間が読める違反説明",
      "fix_hint": "呼び出し元が適用できる具体的な修正方法"
    }
  ]
}

各 violations[] エントリは実行可能な証拠です。file + line + fix_hint は呼び出し元に何を編集すべきか正確に伝えます。呼び出し元が編集を適用します。このユニットはレポートのみです。

現在強制されているポリシールール

すべてのルールは曖昧さについてはフェイルオープンです — 明確で、ブロック内の文字通りの証拠でのみ発火するため、有効なスタックがブロックされることはありません(POLICY_FAIL は呼び出し元の hard completion gate(硬い完了門)なので、偽陽性は本当のマイグレーションをブロックします)。

インターネット公開ALB のTLS方針(ALBがインターネット公開の場合:internal が存在しない、false、または変数駆動 — fail-safe):

  • alb_https_listener — 443 上のHTTPSリスナーが certificate_arn と forward アクションを持つ必要がある
  • alb_http_redirect — HTTP :80 リスナーは HTTPS にリダイレクト(redirect)する必要があり、決してターゲットにフォワード(forward)しない。内部ALB(internal = true)は対象外

Elastic Beanstalk ALBはこれらのルールに見えません。 ALBルールはスタンドアロン aws_lb_listener ブロックを検査します。EB LoadBalanced 環境はALBを aws_elastic_beanstalk_environment の setting ブロックからプロビジョニングし、静的チェッカーはこれを読みません — つまり純粋な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 を設定してはいけない(存在しない/変数 → fail-open)
  • rds_encryption_at_rest — storage_encrypted = true を設定する必要があります。存在しないか文字通り false なら発火(RDSは暗号化されていないのがデフォルト)。変数駆動は fail-open。S3は検査されません(2023年1月以来デフォルトSSE-S3)

ElastiCache暗号化 (aws_elasticache_replication_group, Redis aws_elasticache_cluster):

  • elasticache_encryption_at_rest — レプリケーション グループは at_rest_encryption_enabled = true を設定する必要があります。存在しないか文字通り false なら発火。変数駆動は fail-open
  • elasticache_cluster_encryption — Redis エンジンの aws_elasticache_cluster(単一ノード:engine = "redis"、replication_group_id なし)は at_rest_encryption_enabled = true と transit_encryption_enabled = true の両方を設定する必要があります。どちらかが存在しないか文字通り false なら発火。変数駆動は fail-open。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_ci
原文(English)を表示

tf-best-practices — Generated-IaC posture rules + read-only policy gate

A shared authoring guide and verdict producer, not a workflow. It answers two questions for a phase that generates AWS Terraform:

  1. Before writing — "what security posture must the generated terraform/ follow?" (the posture rules + the baseline.tf account-hardening spec)
  2. After writing — "does the generated terraform/ pass policy?" (a deterministic, read-only verdict + a machine-readable report)

Routing — load the part that matches your context

This skill is entered at two touchpoints in the caller's Generate flow, with the caller's own terraform-authoring work in between. The caller states which touchpoint it is at when it loads this skill, and reads the corresponding part:

Caller context Load Why
About to author terraform/ (before writing) Part 1 → references/security-posture-rules.md The "what to emit" AWS authoring rules (gate-enforced + authoring-only + compliance-conditional).
terraform/ written, ready to validate (after writing) Part 2 → references/terraform-validation.md + run the gate script The fmt → init → validate → policy protocol and the read-only verdict.

Everything this skill states is source-cloud-agnostic (pure AWS Terraform). Any GCP/Heroku detection or artifact reading is the caller's job; where a rule needs a caller-known fact (e.g. declared compliance frameworks), the caller passes it as a caller-context signal — see references/security-posture-rules.md § Caller-context signals.

Boundary (read this first)

This unit is a verdict producer, never a mutator. Its entire write surface is the JSON verdict it is asked to emit. Specifically it MUST NOT:

  • edit, format, or rewrite any .tf file (the caller owns remediation),
  • read or write .phase-status.json or any run-state file (interpreter-owned),
  • decide whether a phase may complete, or prompt the user (caller policy).

The caller (a migration skill's Generate phase) owns: the fix-and-retry loop that edits the .tf it generated, terraform fmt auto-apply, the retry/skip/abort prompt, the Phase Completion gate, and every .phase-status.json write. See the consuming skill's generate phase for how the verdict feeds those decisions.

Consumers: gcp-to-aws (prose Generate) and heroku-to-aws (DSL Generate). The contract is source-agnostic; each caller wires the two touchpoints in its own Generate idiom — gcp-to-aws as prose steps, heroku-to-aws as a fragment step plus a fail-closed _postconditions assert enforced by the interpreter.

Part 1 — Authoring posture (load before writing terraform/)

Emit generated Terraform that satisfies the posture in references/security-posture-rules.md.

These are the "what good AWS Terraform looks like" rules. Following them makes the Part 2 gate pass by construction. This unit does not read the caller's artifacts — it consumes only caller-context signals the caller passes in.

Scope. security-posture-rules.md covers, in three tiers:

  • Gate-enforced (Part 2 verifies statically): ALB TLS, no-public-database, RDS + ElastiCache encryption-at-rest, no-public-DB-port ingress, no-public admin/datastore-port ingress, no-wildcard-IAM.
  • Authoring-only (not gate-checkable, still required): deletion_protection, master-password-via-Secrets-Manager, S3 hardening, Fargate/EKS/ECR settings, private-subnet placement, backups, baseline monitoring.
  • Compliance-conditional (emitted when the caller declares soc2/pci/hipaa/fedramp): VPC flow logs, S3 access logging, secret rotation, customer-managed KMS.

Still the caller's own generation concern (candidates to migrate here later): the account-hardening baseline.tf layer (CloudTrail, GuardDuty, Config, Security Hub).

Part 2 — Policy gate (run after writing terraform/)

Run the read-only checker against the generated directory. Resolve the script path relative to the plugin root ($PLUGIN_ROOT/skills/tf-best-practices/scripts/...), the same convention the plugin uses for its other scripts:

python3 "$PLUGIN_ROOT/skills/tf-best-practices/scripts/validate-terraform-policy.py" "$TERRAFORM_DIR" --json "$VERDICT_PATH"
  • $TERRAFORM_DIR — required, caller-supplied: the generated terraform/ directory (e.g. $MIGRATION_DIR/terraform). This skill never defaults or discovers it — the caller always passes the path it wrote Terraform to.
  • --json $VERDICT_PATH — optional; writes a machine-readable verdict the caller can merge into its own validation-report.json.

The policy check is one stage of a larger validation flow (fmt → init → validate → policy). The full protocol — including offline-fallback behavior and how the policy verdict maps into a validation-report.json — is documented in references/terraform-validation.md. That protocol is descriptive: the caller owns the fmt/init/validate execution, the fix-and-retry loop, and the report write; this unit contributes only the read-only policy stage + verdict shape.

Exit codes → caller action

Exit stdout Meaning Caller does
0 POLICY_OK posture satisfied proceed
1 POLICY_FAIL violations present read violations[], edit the named .tf sites, re-run (caller's retry budget)
2 (usage error) bad path / IO surface to user; do not treat as pass

Verdict shape (--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"
    }
  ]
}

Each violations[] entry is actionable evidence — file + line + fix_hint tell the caller exactly what to edit. The caller applies the edit; this unit only reports.

Policy rules enforced today

Every rule is fail-open on ambiguity — it fires only on unambiguous, in-block literal evidence, so a valid stack is never falsely blocked (a POLICY_FAIL is a hard completion gate for the caller, so a false positive would block a real migration).

Internet-facing ALB TLS posture (an ALB is internet-facing when internal is absent, false, or variable-driven — fail-safe):

  • alb_https_listener — must have an HTTPS listener on 443 with certificate_arn and a forward action.
  • alb_http_redirect — an HTTP :80 listener must redirect to HTTPS, never forward to targets. Internal ALBs (internal = true) are exempt.

Elastic Beanstalk ALBs are invisible to these rules. The ALB rules inspect standalone aws_lb_listener blocks. An EB LoadBalanced environment provisions its ALB from aws_elastic_beanstalk_environment setting blocks, which the static checker does not read — so a pure-EB design passes the ALB rules vacuously (no listener to inspect). EB listener/TLS posture is therefore authoring-only, not gate-enforced. (Fixtures good-heroku-eb-only and good-heroku-eb-singleinstance document this; good-heroku-eb-loadbalanced carries a standalone ALB so the listener rules are exercised on real blocks.)

Managed database exposure & encryption (aws_db_instance, aws_rds_cluster):

  • rds_not_public — must not set publicly_accessible = true (absent/variable → fail-open).
  • rds_encryption_at_rest — must set storage_encrypted = true; missing or literal false fires (RDS defaults to unencrypted), variable-driven fails open. S3 is not checked (default SSE-S3 since Jan 2023).

ElastiCache encryption (aws_elasticache_replication_group, Redis aws_elasticache_cluster):

  • elasticache_encryption_at_rest — a replication group must set at_rest_encryption_enabled = true; missing or literal false fires, variable-driven fails open.
  • elasticache_cluster_encryption — a Redis-engine aws_elasticache_cluster (single-node: engine = "redis", no replication_group_id) must set BOTH at_rest_encryption_enabled = true and transit_encryption_enabled = true; missing or literal false on either fires, variable-driven fails open. engine = "memcached" clusters (and variable-driven/absent engine) are exempt — Memcached does not support these attributes.

Security group ingress:

  • db_sg_no_public_ingress — an inline aws_security_group ingress covering 5432/3306 must not allow 0.0.0.0/0 or ::/0.
  • sg_no_public_admin_ingress — an inline ingress must not open a curated never-public admin/datastore port (22, 3389, 6379, 11211, 27017, 9200/9300, 5601) to 0.0.0.0/0 or ::/0. Web (80/443) and app/game ports are not flagged; DB ports are handled by the rule above. Both check cidr_blocks and ipv6_cidr_blocks independently, so a benign IPv4 list does not mask an open IPv6 one. Both: separate aws_security_group_rule / aws_vpc_security_group_ingress_rule resources fail open (not correlated).

IAM least-privilege (aws_iam_policy, aws_iam_role_policy, aws_iam_group_policy, aws_iam_user_policy):

  • no_wildcard_iam — an Allow statement must not use Action/Resource "*". The one narrow exception is an isolated elasticbeanstalk:CreateStorageLocation statement with Resource = "*" because AWS does not support resource-level permissions for that action. aws_iam_policy_document data sources and assume-role trust policies fail open.

The checker is a zero-dependency static HCL reader (no terraform init, no provider download) — it runs even when the registry is unreachable. It uses brace-depth matching for nested blocks, so a valid HTTPS listener written with a nested forward { ... } block is not a false failure.

Fixtures (also the checker's regression suite)

fixtures/terraform-policy/ holds intentionally-shaped Terraform used by scripts/test_validate_terraform_policy.py:

  • bad-http-forward/ — internet-facing ALB that forwards plaintext HTTP → MUST POLICY_FAIL.
  • internal-alb-only/ — internal ALB on HTTP → MUST POLICY_OK (HTTP allowed internally).
  • good-https-redirect/ — the correct pattern → POLICY_OK.

These are deliberately non-compliant test data (never deployed). They are excluded from the repo-wide checkov scan via .checkov.yaml skip-path; do not "harden" them — doing so breaks the tests that assert the failure paths.

Verification

# from skills/tf-best-practices/
uv run --python 3.12 --with pytest python -m pytest scripts/test_validate_terraform_policy.py -q

原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。