terraform-patterns について
インフラチーム向けのTerraformワークフロースキルです。モジュール設計の標準化、ステートの保護、本番向けコードレビューを支援します。レビュー・セキュリティ用コマンドに加え、モジュール品質や設定リスクを調べるコマンドライン分析ツールを備えています。
主な機能
- 01Terraformコードレビューコマンド
- 02モジュール設計とリファクタリングの指針
- 03ステートとバックエンドの安全性チェック
- 04モジュール構造のコマンドライン分析ツール
- 05.tfファイル向けセキュリティスキャナー
- 06CI/CDとドリフト検出のパターン
活用シーン
- 01Terraformファイルの構造上の問題をレビュー
- 02入出力が明確な再利用可能モジュールの設計
- 03インフラコード内の露出したシークレットのスキャン
- 04リモートステートとロック設定の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ alirezarezvani/ claude-skills --skill terraform-patternsインストール後、Claude Code で/terraform-patternsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/module-patterns.mdstate-management.mdscripts/tf_module_analyzer.pytf_security_scanner.py詳細
Terraform のパターン
予測可能なインフラストラクチャ。安全なステート。組み合わせられるモジュール。ドリフトなし。
広大な HCL を、適切に構成された安全な本番環境向けインフラストラクチャコードに変える、独自の方針に基づいた Terraform ワークフローです。モジュール設計、ステート管理、プロバイダーパターン、セキュリティ強化、CI/CD 連携を扱います。
Terraform のチュートリアルではありません。午前 3 時に壊れないインフラストラクチャコードを書くための、具体的な方針をまとめています。
スラッシュコマンド
| コマンド | 内容 |
|---|---|
/terraform:review | Terraform コードを分析し、アンチパターン、セキュリティ上の問題、構成上の問題を特定します |
/terraform:module | 適切な入力、出力、構成を備えた Terraform モジュールを設計またはリファクタリングします |
/terraform:security | Terraform コードを監査し、セキュリティの脆弱性、シークレットの漏えい、IAM の設定ミスを特定します |
このスキルが有効になる場面
ユーザーの次のようなパターンを認識します。
- 「この Terraform コードをレビューして」
- 「次のための Terraform モジュールを設計して……」
- 「Terraform のステートが……」
- 「リモートステートバックエンドを設定して」
- 「マルチリージョンの Terraform デプロイ」
- 「Terraform のセキュリティレビュー」
- 「モジュール構成のベストプラクティス」
- 「Terraform の CI/CD パイプライン」
.tfファイル、HCL、Terraform モジュール、ステート管理、プロバイダー設定、Infrastructure as Code に関するあらゆるリクエスト
ユーザーが .tf ファイルを持っている場合、または Terraform でインフラストラクチャをプロビジョニングしようとしている場合、このスキルが適用されます。
ワークフロー
/terraform:review — Terraform コードレビュー
-
現在の状態を分析
- 対象ディレクトリ内のすべての
.tfファイルを読み取ります - モジュール構成(フラットかネストか)を特定します
- リソース、データソース、変数、出力の数を数えます
- 命名規則を確認します
- 対象ディレクトリ内のすべての
-
レビュー用チェックリストを適用
MODULE STRUCTURE ├── Variables have descriptions and type constraints ├── Outputs expose only what consumers need ├── Resources use consistent naming: {provider}_{type}_{purpose} ├── Locals used for computed values and DRY expressions └── No hardcoded values — everything parameterized or in locals STATE & BACKEND ├── Remote backend configured (S3, GCS, Azure Blob, Terraform Cloud) ├── State locking enabled (DynamoDB for S3, native for others) ├── State encryption at rest enabled ├── No secrets stored in state (or state access is restricted) └── Workspaces or directory isolation for environments PROVIDERS ├── Version constraints use pessimistic operator: ~> 5.0 ├── Required providers block in terraform {} block ├── Provider aliases for multi-region or multi-account └── No provider configuration in child modules SECURITY ├── No hardcoded secrets, keys, or passwords ├── IAM follows least-privilege principle ├── Encryption enabled for storage, databases, secrets ├── Security groups are not overly permissive (no 0.0.0.0/0 ingress on sensitive ports) └── Sensitive variables marked with sensitive = true -
レポートを生成
python3 scripts/tf_module_analyzer.py ./terraform -
セキュリティスキャンを実行
python3 scripts/tf_security_scanner.py ./terraform
/terraform:module — モジュール設計
-
モジュールの範囲を特定
- 単一責任:1 つのモジュールにつき 1 つの論理的なグループ
- 入力(変数)、出力、リソースの境界を決定します
- フラットなモジュール(単一ディレクトリ)か、ネストしたモジュール(子モジュールを呼び出す)かを決めます
-
モジュール設計用チェックリストを適用
STRUCTURE ├── main.tf — Primary resources ├── variables.tf — All input variables with descriptions and types ├── outputs.tf — All outputs with descriptions ├── versions.tf — terraform {} block with required_providers ├── locals.tf — Computed values and naming conventions ├── data.tf — Data sources (if any) └── README.md — Usage examples and variable documentation VARIABLES ├── Every variable has: description, type, validation (where applicable) ├── Sensitive values marked: sensitive = true ├── Defaults provided for optional settings ├── Use object types for related settings: variable "config" { type = object({...}) } └── Validate with: validation { condition = ... } OUTPUTS ├── Output IDs, ARNs, endpoints — things consumers need ├── Include description on every output ├── Mark sensitive outputs: sensitive = true └── Don't output entire resources — only specific attributes COMPOSITION ├── Root module calls child modules ├── Child modules never call other child modules ├── Pass values explicitly — no hidden data source lookups in child modules ├── Provider configuration only in root module └── Use module "name" { source = "./modules/name" } -
モジュールのひな形を生成
- ボイラープレートを含むファイル構成を出力します
- 変数の検証ブロックを含めます
- 適切な場合はライフサイクルルールを追加します
/terraform:security — セキュリティ監査
-
コードレベルの監査
確認項目 重大度 修正方法 .tfファイル内のハードコードされたシークレット致命的 sensitive = trueを指定した変数または Vault を使用します*アクションを含む IAM ポリシー致命的 特定のアクションとリソースに範囲を絞ります ポート 22/3389 で 0.0.0.0/0 を許可するセキュリティグループ 致命的 既知の CIDR ブロックに制限するか、SSM/bastion を使用します 暗号化されていない S3 バケット 高 server_side_encryption_configurationブロックを追加しますパブリックアクセスが可能な S3 バケット 高 aws_s3_bucket_public_access_blockを追加します暗号化されていない RDS 高 storage_encrypted = trueを設定しますパブリックアクセスが可能な RDS 高 publicly_accessible = falseを設定しますCloudTrail が有効になっていない 中 aws_cloudtrailリソースを追加しますステートフルリソースに prevent_destroyがない中 lifecycle { prevent_destroy = true }を追加しますシークレット用の変数に sensitive = trueがない中 シークレット用変数に sensitive = trueを追加します -
ステートのセキュリティ監査
確認項目 重大度 修正方法 ローカルのステートファイル 致命的 暗号化されたリモートバックエンドに移行します 暗号化されていないリモートステート 高 バックエンドで暗号化(SSE-S3、KMS)を有効にします ステートロックがない 高 S3 では DynamoDB、TF Cloud ではネイティブのロックを有効にします すべてのチームメンバーがステートにアクセス可能 中 IAM ポリシーまたは TF Cloud のチームを使って制限します -
セキュリティレポートを生成
python3 scripts/tf_security_scanner.py ./terraform python3 scripts/tf_security_scanner.py ./terraform --output json
ツール
scripts/tf_module_analyzer.py
Terraform のディレクトリ構造とモジュールの品質を分析する CLI ユーティリティです。
機能:
- リソースとデータソースのカウント
- 変数と出力の分析(説明、型、検証の不足)
- 命名規則のチェック
- モジュール構成の検出
- ファイル構造の検証
- JSON およびテキスト形式での出力
使用方法:
# Analyze a Terraform directory
python3 scripts/tf_module_analyzer.py ./terraform
# JSON output
python3 scripts/tf_module_analyzer.py ./terraform --output json
# Analyze a specific module
python3 scripts/tf_module_analyzer.py ./modules/vpc
scripts/tf_security_scanner.py
.tf ファイルをスキャンして、よくあるセキュリティ上の問題を検出する CLI ユーティリティです。
機能:
- ハードコードされたシークレットの検出(AWS キー、パスワード、トークン)
- 過度に許容的な IAM ポリシーの検出
- 外部公開されたセキュリティグループの検出(機密性の高いポートでの 0.0.0.0/0)
- 暗号化設定の不足をチェック(S3、RDS、EBS)
- パブリックアクセスの検出(S3、RDS、EC2)
- 機密変数の監査
- JSON およびテキスト形式での出力
使用方法:
# Scan a Terraform directory
python3 scripts/tf_security_scanner.py ./terraform
# JSON output
python3 scripts/tf_security_scanner.py ./terraform --output json
# Strict mode (elevate warnings)
python3 scripts/tf_security_scanner.py ./terraform --strict
モジュール設計パターン
パターン 1: フラットモジュール(小規模/中規模プロジェクト)
infrastructure/
├── main.tf # All resources
├── variables.tf # All inputs
├── outputs.tf # All outputs
├── versions.tf # Provider requirements
├── terraform.tfvars # Environment values (not committed)
└── backend.tf # Remote state configuration
適している用途: 単一のアプリケーション、リソースが 20 未満、すべてを 1 つのチームが所有する場合。
パターン 2: 入れ子のモジュール(中規模/大規模プロジェクト)
infrastructure/
├── environments/
│ ├── dev/
│ │ ├── main.tf # Calls modules with dev params
│ │ ├── backend.tf # Dev state backend
│ │ └── terraform.tfvars
│ ├── staging/
│ │ └── ...
│ └── prod/
│ └── ...
├── modules/
│ ├── networking/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ ├── compute/
│ │ └── ...
│ └── database/
│ └── ...
└── versions.tf
適している用途: 複数の環境、共有インフラストラクチャのパターン、チームでのコラボレーション。
パターン 3: Terragrunt を使用したモノレポ
infrastructure/
├── terragrunt.hcl # Root config
├── modules/ # Reusable modules
│ ├── vpc/
│ ├── eks/
│ └── rds/
├── dev/
│ ├── terragrunt.hcl # Dev overrides
│ ├── vpc/
│ │ └── terragrunt.hcl # Module invocation
│ └── eks/
│ └── terragrunt.hcl
└── prod/
├── terragrunt.hcl
└── ...
適している用途: 大規模、多数の環境、DRY な設定、チーム単位の分離。
プロバイダー設定パターン
バージョンの固定
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0" # Allow 5.x, block 6.0
}
random = {
source = "hashicorp/random"
version = "~> 3.5"
}
}
}
エイリアスを使用したマルチリージョン
provider "aws" {
region = "us-east-1"
}
provider "aws" {
alias = "west"
region = "us-west-2"
}
resource "aws_s3_bucket" "primary" {
bucket = "my-app-primary"
}
resource "aws_s3_bucket" "replica" {
provider = aws.west
bucket = "my-app-replica"
}
Assume Role を使用したマルチアカウント
provider "aws" {
alias = "production"
region = "us-east-1"
assume_role {
role_arn = "arn:aws:iam::PROD_ACCOUNT_ID:role/TerraformRole"
}
}
状態管理の判断ツリー
Single developer, small project?
├── Yes → Local state (but migrate to remote ASAP)
└── No
├── Using Terraform Cloud/Enterprise?
│ └── Yes → TF Cloud native backend (built-in locking, encryption, RBAC)
└── No
├── AWS?
│ └── S3 + DynamoDB (encryption, locking, versioning)
├── GCP?
│ └── GCS bucket (native locking, encryption)
├── Azure?
│ └── Azure Blob Storage (native locking, encryption)
└── Other?
└── Consul or PostgreSQL backend
Environment isolation strategy:
├── Separate state files per environment (recommended)
│ ├── Option A: Separate directories (dev/, staging/, prod/)
│ └── Option B: Terraform workspaces (simpler but less isolation)
└── Single state file for all environments (never do this)
CI/CD 統合パターン
GitHub Actions の Plan/Apply
# .github/workflows/terraform.yml
name: Terraform
on:
pull_request:
paths: ['terraform/**']
push:
branches: [main]
paths: ['terraform/**']
jobs:
plan:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- run: terraform init
- run: terraform validate
- run: terraform plan -out=tfplan
- run: terraform show -json tfplan > plan.json
# Post plan as PR comment
apply:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
environment: production
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- run: terraform init
- run: terraform apply -auto-approve
ドリフト検出
# Run on schedule to detect drift
name: Drift Detection
on:
schedule:
- cron: '0 6 * * 1-5' # Weekdays at 6 AM
jobs:
detect:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- run: terraform init
- run: |
terraform plan -detailed-exitcode -out=drift.tfplan 2>&1 | tee drift.log
EXIT_CODE=$?
if [ $EXIT_CODE -eq 2 ]; then
echo "DRIFT DETECTED — review drift.log"
# Send alert (Slack, PagerDuty, etc.)
fi
先回りして通知する項目
依頼されていなくても、以下の項目を指摘してください。
- リモートバックエンドが設定されていない → ロックと暗号化を設定し、S3/GCS/Azure Blob に移行してください。
- プロバイダーにバージョン制約がない → 破壊的なアップグレードを防ぐため、
version = "~> X.0"を追加してください。 - .tf ファイル内にハードコードされたシークレットがある →
sensitive = trueを設定した変数を使用するか、Vault/SSM と統合してください。 - IAM ポリシーに
"Action": "*"がある → 特定のアクションに範囲を絞ってください。本番環境ではワイルドカードアクションを使用しないでください。 - SSH/RDP で 0.0.0.0/0 に公開されたセキュリティグループがある → バスティオンの CIDR に制限するか、SSM Session Manager を使用してください。
- 状態のロックがない → S3 バックエンドでは DynamoDB テーブルを有効にするか、TF Cloud を使用してください。
- タグのないリソースがある → プロバイダーブロックに default_tags を追加してください。コスト追跡にはタグが必須です。
- データベース/ストレージに
prevent_destroyが設定されていない → 誤削除を防ぐため、lifecycle ブロックを追加してください。
マルチクラウドのプロバイダー設定
単一のルートモジュールで AWS、Azure、GCP にまたがるプロビジョニングが必要な場合に使用します。
プロバイダーのエイリアスパターン
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
provider "google" {
project = var.gcp_project_id
region = var.gcp_region
}
プロバイダー間で共有する変数
variable "environment" {
description = "Environment name used across all providers"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Must be dev, staging, or prod."
}
}
locals {
common_tags = {
environment = var.environment
managed_by = "terraform"
project = var.project_name
}
}
マルチクラウドを使用する場合
- 使用する: 規制要件によりプロバイダー間でのデータレジデンシーが義務付けられている場合、または組織が複数のクラウドですでにワークロードを運用している場合。
- 使用しない: 「ベンダーロックインの回避」だけでは、十分な正当化理由になりません。マルチクラウドは運用の複雑さを倍増させます。具体的なビジネス要件がない限り、単一のクラウドを優先してください。
OpenTofu との互換性
OpenTofu は Terraform のオープンソースフォークで、MPL 2.0 ライセンスのもと Linux Foundation が管理しています。
Terraform から OpenTofu への移行
# 1. Install OpenTofu
brew install opentofu # macOS
snap install --classic tofu # Linux
# 2. Replace the binary — state files are compatible
tofu init # Re-initializes with OpenTofu
tofu plan # Identical plan output
tofu apply # Same apply workflow
ライセンスに関する考慮事項
| Terraform (1.6+) | OpenTofu | |
|---|---|---|
| ライセンス | BSL 1.1(ソース公開型) | MPL 2.0(オープンソース) |
| 商用利用 | 競合製品では制限あり | 制限なし |
| コミュニティガバナンス | HashiCorp | Linux Foundation |
機能の同等性
OpenTofu は Terraform 1.6.x の機能に追随しています。OpenTofu 独自の主な追加機能:
- クライアント側の状態暗号化(
tofu init -encryption) - 変数/locals の早期評価
- プロバイダー定義関数
OpenTofu を選ぶ場合
- サプライチェーンに完全なオープンソースライセンスが必要な場合。
- Terraform Cloud を使わずに、クライアント側で状態を暗号化したい場合。
- それ以外の場合は、どちらのツールでも問題ありません。HCL の構文とプロバイダーのエコシステムは同一です。
Infracost との連携
Infracost は、リソースがプロビジョニングされる前に Terraform コードからクラウドコストを見積もります。
PR ワークフロー
# Show cost breakdown for current code
infracost breakdown --path .
# Compare cost difference between current branch and main
infracost diff --path . --compare-to infracost-base.json
GitHub Actions のコストコメント
# .github/workflows/infracost.yml
name: Infracost
on: [pull_request]
jobs:
cost:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: infracost/actions/setup@v3
with:
api-key: ${{ secrets.INFRACOST_API_KEY }}
- run: infracost breakdown --path ./terraform --format json --out-file /tmp/infracost.json
- run: infracost comment github --path /tmp/infracost.json --repo $GITHUB_REPOSITORY --pull-request ${{ github.event.pull_request.number }} --github-token ${{ secrets.GITHUB_TOKEN }} --behavior update
予算のしきい値とコストポリシー
# infracost.yml — policy file
version: 2.9.0
policies:
- path: "*"
max_monthly_cost: "5000" # Fail PR if estimated cost exceeds $5,000/month
max_cost_increase: "500" # Fail PR if cost increase exceeds $500/month
既存のインフラストラクチャのインポート
手動で作成したリソースを Terraform の管理下に置きます。
terraform import ワークフロー
# 1. Write the resource block first (empty body is fine)
# main.tf:
# resource "aws_s3_bucket" "legacy" {}
# 2. Import the resource into state
terraform import aws_s3_bucket.legacy my-existing-bucket-name
# 3. Run plan to see attribute diff
terraform plan
# 4. Fill in the resource block until plan shows no changes
設定生成を使った一括インポート(Terraform 1.5+)
# Generate HCL for imported resources
terraform plan -generate-config-out=generated.tf
# Review generated.tf, then move resources into proper files
よくある落とし穴
- インポート後のリソースのドリフト:インポートしたリソースには、Terraform が管理していない属性が含まれている場合があります。すぐに
terraform planを実行し、差分をすべて解消してください。 - 状態の操作:名前を変更したり、構成を整理したりするには
terraform state mvを使用します。リソースを破棄せずに削除するにはterraform state rmを使用します。状態を操作する前に必ずバックアップしてください:terraform state pull > backup.tfstate。 - 機密性の高いデフォルト値:インポートしたリソースによって、状態ファイル内のシークレットが露出する場合があります。状態ファイルへのアクセスを制限し、暗号化を有効にしてください。
Terragrunt のパターン
Terragrunt は Terraform の軽量なラッパーで、複数環境のセットアップ向けに DRY な構成を提供します。
ルートの terragrunt.hcl(共有設定)
# terragrunt.hcl (root)
remote_state {
backend = "s3"
generate = {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
}
config = {
bucket = "my-org-terraform-state"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
子の terragrunt.hcl(環境ごとのオーバーライド)
# prod/vpc/terragrunt.hcl
include "root" {
path = find_in_parent_folders()
}
terraform {
source = "../../modules/vpc"
}
inputs = {
environment = "prod"
cidr_block = "10.0.0.0/16"
}
モジュール間の依存関係
# prod/eks/terragrunt.hcl
dependency "vpc" {
config_path = "../vpc"
}
inputs = {
vpc_id = dependency.vpc.outputs.vpc_id
subnet_ids = dependency.vpc.outputs.private_subnet_ids
}
Terragrunt が役立つ場面
- はい:モジュール構造が同一の環境が3つ以上ある場合、バックエンド設定を共有する場合、またはモジュール間の依存関係がある場合。
- いいえ:単一の環境、小規模なチーム、またはディレクトリベースのシンプルな分離ですでに十分な場合。Terragrunt を導入すると、習得の手間が増え、管理するバイナリも1つ増えます。
インストール
1行でインストール(任意のツール)
git clone https://github.com/alirezarezvani/claude-skills.git
cp -r claude-skills/engineering/terraform-patterns ~/.claude/skills/
複数ツールのインストール
./scripts/convert.sh --skill terraform-patterns --tool codex|gemini|cursor|windsurf|openclaw
OpenClaw
clawhub install terraform-patterns
関連スキル
- senior-devops — CI/CD、モニタリング、コンテナ化など、より広範な DevOps 領域を扱います。相互補完的です。IaC 固有の作業には terraform-patterns を、パイプラインとインフラストラクチャの運用には senior-devops を使用してください。
- aws-solution-architect — AWS のアーキテクチャ設計を扱います。相互補完的です。terraform-patterns でインフラストラクチャを実装し、aws-solution-architect で設計します。
- senior-security — アプリケーションセキュリティを扱います。相互補完的です。terraform-patterns はインフラストラクチャのセキュリティ態勢を、senior-security はアプリケーションレベルの脅威を扱います。
- ci-cd-pipeline-builder — パイプラインの構築を扱います。相互補完的です。terraform-patterns でインフラストラクチャを定義し、ci-cd-pipeline-builder でデプロイを自動化します。