terraform destroyとは?初心者でもわかる基礎知識
terraform destroyコマンドの基本的な機能と目的
Terraform destroyは、Terraformで作成したインフラストラクチャを完全に削除するためのコマンドです。このコマンドは、terraform applyの逆の動作を行い、管理されているすべてのリソースを安全に解体します。
基本的な使用方法:
# 基本的なdestroyコマンド terraform destroy # 実行計画の確認のみ terraform plan -destroy # 自動承認付きのdestroy terraform destroy -auto-approve
主な特徴:
- べき等性の保証
- 複数回実行しても同じ結果になることを保証
- 既に削除されているリソースは無視される
- 依存関係の自動解決
- リソース間の依存関係を考慮して適切な順序で削除
- 例:ECSクラスタを削除する前に、タスクとサービスを先に削除
- ステート管理との連携
- terraform.tfstateファイルを参照して現在の状態を把握
- 削除完了後、ステートファイルも適切に更新
destroy実行時の内部動作の仕組み
terraform destroyコマンドが実行される際の内部動作を理解することで、より安全な運用が可能になります。
実行フロー:
- 計画フェーズ
graph TB
A[設定ファイル読み込み] --> B[現在の状態確認]
B --> C[削除計画の作成]
C --> D[依存関係グラフの構築]
D --> E[削除順序の決定]
- 実行フェーズ
- リソースの依存関係グラフを逆順に走査
- 各リソースのdestroyメソッドを呼び出し
- 削除結果をステートファイルに反映
重要な内部処理:
| フェーズ | 処理内容 | 目的 |
|---|---|---|
| 前処理 | プロバイダーの初期化 | API接続の準備 |
| 計画作成 | 依存関係の解析 | 安全な削除順序の決定 |
| リソース削除 | APIコール実行 | 実際のリソース削除 |
| 後処理 | ステート更新 | 状態の整合性維持 |
エラーハンドリング機能:
- タイムアウト処理
- リトライメカニズム
- ロールバックのサポート
- エラーメッセージの詳細な記録
destroyコマンドは、これらの機能を組み合わせることで、複雑なインフラストラクチャでも安全な削除を実現します。次のセクションでは、実行前に確認すべき重要なポイントについて詳しく説明します。
terraform destroyを実行する前に必ず確認すべき7つのポイント
実行計画の確認方法とリスク評価の手順
terraform destroyを実行する前の計画確認は、事故を防ぐための最も重要なステップです。以下の手順に従って、慎重に確認を行いましょう。
1. 実行計画の確認手順:
# 削除計画の詳細な確認 terraform plan -destroy -detailed-exitcode # 特定のリソースのみの削除計画確認 terraform plan -destroy -target="aws_instance.example" # 変数値を指定して計画確認 terraform plan -destroy -var="environment=staging"
リスク評価チェックリスト:
- [ ] 対象環境(本番/検証/開発)の確認
- [ ] 削除対象リソースの完全な列挙
- [ ] 依存サービスへの影響調査
- [ ] データ損失のリスク評価
- [ ] 復旧時間の見積もり
依存関係の把握と削除順序の確認方法
リソース間の依存関係を正確に把握することで、予期しない削除の連鎖を防ぐことができます。
依存関係の可視化:
# グラフの生成 terraform graph | dot -Tsvg > dependency.svg # 詳細な依存関係の出力 terraform state list terraform state show aws_vpc.main
重要な確認項目:
| 確認項目 | 確認方法 | 注意点 |
|---|---|---|
| 直接的な依存関係 | terraform graph | 削除順序の確認 |
| 暗黙の依存関係 | リソース設定確認 | クロススタック参照 |
| 外部依存関係 | 手動調査 | 他チームの利用状況 |
| データ依存関係 | バックアップ確認 | 永続データの有無 |
バックアップとロールバック戦略の準備
安全なdestroyの実行には、適切なバックアップとロールバック戦略が不可欠です。
バックアップ手順:
- ステートファイルのバックアップ
# ステートファイルのバックアップ作成 cp terraform.tfstate terraform.tfstate.backup # S3へのバックアップ aws s3 cp terraform.tfstate s3://backup-bucket/$(date +%Y%m%d)/
- 重要データのスナップショット
# EC2スナップショットの作成例
resource "aws_ebs_snapshot" "backup" {
volume_id = aws_ebs_volume.main.id
description = "Pre-destroy backup"
tags = {
Name = "pre-destroy-backup"
Timestamp = timestamp()
}
}
ロールバック戦略:
- 即時ロールバック手順の準備
- terraform.tfstateの復元手順
- 重要リソースの再作成スクリプト
- 依存サービスの復旧手順
- 復旧時間目標(RTO)の設定
- 許容できるダウンタイムの定義
- 必要なリソースの確保
- チーム間の連携体制確認
- 検証環境での予行演習
- 削除とロールバックの実践
- タイムライン記録
- 問題点の洗い出し
これらの確認ポイントを慎重にチェックすることで、terraform destroyの実行リスクを最小限に抑えることができます。次のセクションでは、これらの確認を踏まえた上での具体的な実行手順について説明します。
実践!terraform destroyの安全な実行手順
ステップバイステップで学ぶdestroyコマンドの使い方
terraform destroyを安全に実行するための具体的な手順を、実践的な例を交えて解説します。
1. 事前準備フェーズ
# 最新の状態を取得 terraform init terraform get -update # 現在のステート確認 terraform show # 実行計画の確認 terraform plan -destroy -out=destroy.plan
2. 安全確認フェーズ
# プラン内容の詳細確認 terraform show destroy.plan # 影響範囲の確認 terraform state list # 依存関係の確認 terraform graph | dot -Tsvg > destroy-plan.svg
3. 実行フェーズ
# プランに基づいた実行 terraform apply destroy.plan # または直接実行(非推奨) terraform destroy -auto-approve
各フェーズでの確認項目:
| フェーズ | 確認項目 | 合格基準 |
|---|---|---|
| 事前準備 | 設定ファイルの整合性 | エラーなし |
| 安全確認 | リソース依存関係 | 想定通りの順序 |
| 実行 | 削除進捗 | エラーなし |
| 完了確認 | リソース存在確認 | 全て削除済み |
-targetオプションを使用した部分的な削除の方法
特定のリソースのみを安全に削除する方法について説明します。
基本的な使用方法:
# 特定のリソースの削除 terraform destroy -target="aws_instance.example" # 複数リソースの削除 terraform destroy \ -target="aws_instance.web" \ -target="aws_eip.web_ip"
高度な使用例:
# モジュール内のリソース削除 terraform destroy -target="module.vpc.aws_subnet.public[0]" # タグベースの削除(スクリプト例) #!/bin/bash for resource in $(terraform state list | grep "environment=dev"); do terraform destroy -target="$resource" -auto-approve done
自動化スクリプトでの使用方法とベストプラクティス
CI/CDパイプラインやシェルスクリプトでterraform destroyを使用する際のベストプラクティスを紹介します。
1. 安全な自動化スクリプトの例:
#!/bin/bash
set -e
# 環境変数の検証
if [ -z "$TF_WORKSPACE" ]; then
echo "Error: TF_WORKSPACE is not set"
exit 1
fi
# 事前チェック関数
function pre_destroy_check() {
local workspace=$1
# プロダクション環境の保護
if [[ "$workspace" == "production" ]]; then
echo "Error: Cannot destroy production environment"
exit 1
}
# ステートファイルの存在確認
if [ ! -f "terraform.tfstate" ]; then
echo "Error: State file not found"
exit 1
}
}
# メイン処理
pre_destroy_check "$TF_WORKSPACE"
# バックアップ作成
timestamp=$(date +%Y%m%d_%H%M%S)
terraform state pull > "tfstate_backup_${timestamp}.json"
# 実行計画の作成と確認
terraform plan -destroy -out=destroy.plan
# 承認プロセス(オプション)
read -p "Continue with destroy? (y/n) " -n 1 -r
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
# 実行
terraform apply destroy.plan
ベストプラクティス:
- 環境分離
# 環境別の変数定義
variable "environment" {
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
- リソースタグ付け
# 共通タグの定義
locals {
common_tags = {
Environment = var.environment
ManagedBy = "terraform"
Team = "infrastructure"
}
}
- ロギングと監査
# CloudWatchログの設定
resource "aws_cloudwatch_log_group" "terraform_audit" {
name = "/terraform/destroy-audit"
retention_in_days = 30
tags = local.common_tags
}
これらの手順とベストプラクティスを組み合わせることで、安全かつ効率的なterraform destroyの実行が可能になります。次のセクションでは、実行時に発生する可能性のあるトラブルとその対処方法について説明します。
terraform destroyのトラブルシューティング完全ガイド
よくあるエラーとその解決方法
terraform destroyの実行時に遭遇する可能性のある主要なエラーとその解決方法を解説します。
1. 認証関連のエラー
Error: error configuring Terraform AWS Provider: no valid credential sources found
解決手順:
# AWSクレデンシャルの確認 aws configure list # 環境変数での設定 export AWS_ACCESS_KEY_ID="your_access_key" export AWS_SECRET_ACCESS_KEY="your_secret_key" export AWS_DEFAULT_REGION="ap-northeast-1"
2. 依存関係エラー
Error: error deleting S3 Bucket (example-bucket): BucketNotEmpty: status code: 409
解決手順:
# バケット内のオブジェクト確認 aws s3 ls s3://example-bucket --recursive # 強制削除(注意して使用) aws s3 rm s3://example-bucket --recursive terraform destroy -target="aws_s3_bucket.example"
一般的なエラーと解決策:
| エラータイプ | 主な原因 | 解決アプローチ | 予防策 |
|---|---|---|---|
| 認証エラー | クレデンシャル不正 | 認証情報の再設定 | 定期的な認証確認 |
| 依存関係エラー | リソース順序違反 | 依存関係の手動解決 | グラフ確認の徹底 |
| タイムアウト | API制限/ネットワーク | リトライ/タイムアウト延長 | 十分な時間確保 |
| 権限エラー | IAM権限不足 | 必要権限の付与 | 事前権限確認 |
スタックしたdestroyの対処方法
destroyが途中で停止した場合の対処方法について説明します。
1. プロセス分析
# 実行状態の確認 terraform show # ロックファイルの確認 ls -la .terraform.tfstate.lock.info # ロック強制解除(慎重に使用) terraform force-unlock LOCK_ID
2. 段階的な削除戦略
# 問題のリソースを特定 terraform state list # 個別リソースの削除 terraform destroy -target="問題のリソース" # ステート削除(最終手段) terraform state rm "問題のリソース"
トラブルシューティングフローチャート:
graph TD
A[Destroy失敗] --> B{エラー種別判定}
B -->|認証エラー| C[認証情報確認]
B -->|依存関係エラー| D[依存リソース確認]
B -->|タイムアウト| E[再実行/時間延長]
B -->|権限エラー| F[IAM権限確認]
C --> G[クレデンシャル再設定]
D --> H[手動依存解決]
E --> I[パラメータ調整]
F --> J[権限追加]
削除が失敗した場合のリカバリー手順
削除失敗時の安全なリカバリー手順を説明します。
1. 状態評価
# 現在の状態確認 terraform show # プランの再作成 terraform plan -destroy -refresh-only
2. システマチックな復旧手順
#!/bin/bash
# リカバリースクリプトの例
set -e
function check_state() {
terraform show > current_state.txt
if grep -q "Error" current_state.txt; then
echo "State contains errors"
return 1
fi
return 0
}
function attempt_recovery() {
local resource=$1
echo "Attempting recovery for $resource"
# バックアップ作成
terraform state pull > "state_backup_$(date +%s).tfstate"
# リソース個別削除試行
if terraform destroy -target="$resource" -auto-approve; then
echo "Successfully recovered $resource"
return 0
else
echo "Recovery failed for $resource"
return 1
fi
}
# メイン処理
failed_resources=$(terraform show | grep "Error" | cut -d'"' -f2)
for resource in $failed_resources; do
if ! attempt_recovery "$resource"; then
echo "Manual intervention required for $resource"
fi
done
リカバリーチェックリスト:
- 初期評価
- エラーメッセージの記録
- 影響範囲の特定
- 依存リソースの確認
- バックアップ作成
# ステートファイルバックアップ cp terraform.tfstate terraform.tfstate.$(date +%s).backup # 設定ファイルバックアップ cp -r . ../terraform-backup-$(date +%s)
- 段階的リカバリー
- 問題の少ないリソースから対応
- 依存関係を考慮した順序
- 各ステップでの状態確認
- 検証と文書化
# 状態の検証 terraform validate terraform plan -destroy # 実行ログの保存 terraform destroy -auto-approve 2>&1 | tee destroy_recovery.log
これらのトラブルシューティング手順を理解し、実践することで、ほとんどの問題に対処することが可能になります。次のセクションでは、terraform destroyを活用したコスト最適化戦略について説明します。
terraform destroyを活用したコスト最適化戦略
開発環境の自動シャットダウンの実装方法
開発環境のコスト最適化のため、不要な時間帯のリソースを自動的に削除する方法を解説します。
1. 時間帯別の環境管理システム
# variables.tf
variable "environment" {
type = string
default = "development"
}
variable "working_hours" {
type = object({
start = number
end = number
})
default = {
start = 9 # 9:00
end = 18 # 18:00
}
}
# main.tf
locals {
is_working_hours = (
can(timestamp()) &&
tonumber(formatdate("H", timestamp())) >= var.working_hours.start &&
tonumber(formatdate("H", timestamp())) < var.working_hours.end
)
}
# リソース定義例
resource "aws_instance" "dev_instance" {
count = local.is_working_hours ? 1 : 0
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
tags = {
Name = "dev-instance"
Environment = var.environment
AutoDestroy = "true"
}
}
自動化スクリプトの実装:
#!/bin/bash
# schedule-destroy.sh
# タイムゾーンの設定
export TZ=Asia/Tokyo
# 現在の時刻を取得
current_hour=$(date +%H)
# 稼働時間外の場合、destroyを実行
if [ $current_hour -lt 9 ] || [ $current_hour -ge 18 ]; then
echo "Outside working hours - destroying development environment"
terraform destroy -auto-approve -var="environment=development"
else
echo "Within working hours - environment will be maintained"
fi
cronでの設定例:
# crontab -e 0 18 * * 1-5 /path/to/schedule-destroy.sh >> /var/log/terraform-destroy.log 2>&1 0 9 * * 1-5 /path/to/terraform-apply.sh >> /var/log/terraform-apply.log 2>&1
使用していないリソースの特定と削除の自動化
未使用リソースを特定し、自動的に削除する仕組みの実装方法を説明します。
1. リソース使用状況の監視スクリプト
import boto3
import json
from datetime import datetime, timedelta
def find_unused_resources():
# CloudWatchクライアントの初期化
cloudwatch = boto3.client('cloudwatch')
ec2 = boto3.client('ec2')
# 未使用EC2インスタンスの検出
instances = ec2.describe_instances()
unused_instances = []
for reservation in instances['Reservations']:
for instance in reservation['Instances']:
instance_id = instance['InstanceId']
# CPU使用率の確認
response = cloudwatch.get_metric_statistics(
Namespace='AWS/EC2',
MetricName='CPUUtilization',
Dimensions=[{'Name': 'InstanceId', 'Value': instance_id}],
StartTime=datetime.utcnow() - timedelta(days=7),
EndTime=datetime.utcnow(),
Period=3600,
Statistics=['Average']
)
# 7日間のCPU使用率が10%未満の場合
if not response['Datapoints'] or \
max(point['Average'] for point in response['Datapoints']) < 10:
unused_instances.append(instance_id)
return unused_instances
def generate_terraform_destroy():
unused = find_unused_resources()
# Terraformコマンドの生成
for instance_id in unused:
print(f"terraform destroy -target=aws_instance.{instance_id} -auto-approve")
if __name__ == "__main__":
generate_terraform_destroy()
2. 自動削除のワークフロー実装
# .github/workflows/cleanup.yml
name: Cleanup Unused Resources
on:
schedule:
- cron: '0 0 * * 0' # 毎週日曜日に実行
workflow_dispatch: # 手動実行も可能
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
- name: Setup Terraform
uses: hashicorp/setup-terraform@v1
- name: Find and Destroy Unused Resources
run: |
python3 scripts/find_unused_resources.py > destroy_commands.sh
chmod +x destroy_commands.sh
./destroy_commands.sh
- name: Notify Results
if: always()
uses: actions/github-script@v6
with:
script: |
const script = require('./.github/scripts/notify.js')
await script({github, context})
コスト最適化のベストプラクティス:
| 戦略 | 実装方法 | 期待効果 |
|---|---|---|
| 時間帯制御 | スケジュール実行 | 非稼働時間のコスト削減 |
| 未使用検出 | メトリクス監視 | 無駄なリソースの削除 |
| 自動化 | CI/CDパイプライン | 運用コストの削減 |
| レポート | 定期メール通知 | 可視化とトラッキング |
コスト監視と通知の実装:
# cost_monitoring.tf
resource "aws_budgets_budget" "cost_alert" {
name = "development-cost-alert"
budget_type = "COST"
limit_amount = "1000"
limit_unit = "USD"
time_period_start = "2024-01-01_00:00"
time_unit = "MONTHLY"
notification {
comparison_operator = "GREATER_THAN"
threshold = 80
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_email_addresses = ["team@example.com"]
}
}
これらの戦略を組み合わせることで、効果的なコスト最適化が実現できます。次のセクションでは、実践的なterraform destroy活用事例について説明します。
実践的なterraform destroy活用事例
大規模環境での安全な削除戦略
大規模なインフラストラクチャでterraform destroyを安全に実行するための戦略と実践例を紹介します。
1. 段階的な削除戦略の実装
# environments/production/main.tf
locals {
deletion_stages = {
stage1 = ["aws_lb.front", "aws_autoscaling_group.web"]
stage2 = ["aws_ecs_service.api", "aws_ecs_cluster.main"]
stage3 = ["aws_rds_cluster.main", "aws_elasticache_cluster.cache"]
stage4 = ["aws_vpc.main", "aws_subnet.private", "aws_subnet.public"]
}
}
# 段階的削除の実装
resource "null_resource" "staged_destroy" {
for_each = local.deletion_stages
provisioner "local-exec" {
command = <<-EOF
echo "Starting deletion stage: ${each.key}"
for resource in ${join(" ", each.value)}; do
terraform destroy -target=$resource -auto-approve
if [ $? -ne 0 ]; then
echo "Error in ${each.key} during $resource deletion"
exit 1
fi
done
EOF
}
}
大規模環境での削除チェックリスト:
- 事前評価
# リソース数の確認 terraform state list | wc -l # 推定削除時間の計算 terraform plan -destroy -detailed-exitcode
- 影響範囲の分析
# impact_analysis.tf
data "external" "resource_dependencies" {
program = ["python", "${path.module}/scripts/analyze_dependencies.py"]
}
output "deletion_impact" {
value = data.external.resource_dependencies.result
}
- 段階的な実行計画
graph TD
A[フロントエンド層] --> B[アプリケーション層]
B --> C[データベース層]
C --> D[ネットワーク層]
D --> E[IAMとセキュリティ]
マルチアカウント環境での運用テクニック
複数のAWSアカウントにまたがる環境でのterraform destroy運用方法を解説します。
1. アカウント間の依存関係管理
# provider設定
provider "aws" {
alias = "prod"
region = "ap-northeast-1"
assume_role {
role_arn = "arn:aws:iam::PROD-ACCOUNT-ID:role/TerraformExecutionRole"
}
}
provider "aws" {
alias = "dev"
region = "ap-northeast-1"
assume_role {
role_arn = "arn:aws:iam::DEV-ACCOUNT-ID:role/TerraformExecutionRole"
}
}
# クロスアカウントリソースの管理
module "cross_account_resources" {
source = "./modules/cross-account"
providers = {
aws.prod = aws.prod
aws.dev = aws.dev
}
}
2. マルチアカウント削除の自動化
# multi_account_destroy.py
import boto3
import subprocess
def destroy_resources(account_id, role_name):
# アカウントの認証情報を取得
sts = boto3.client('sts')
assumed_role = sts.assume_role(
RoleArn=f'arn:aws:iam::{account_id}:role/{role_name}',
RoleSessionName='TerraformDestroy'
)
# 環境変数の設定
os.environ['AWS_ACCESS_KEY_ID'] = assumed_role['Credentials']['AccessKeyId']
os.environ['AWS_SECRET_ACCESS_KEY'] = assumed_role['Credentials']['SecretAccessKey']
os.environ['AWS_SESSION_TOKEN'] = assumed_role['Credentials']['SessionToken']
# Terraformの実行
subprocess.run([
'terraform',
'destroy',
'-auto-approve',
f'-var="account_id={account_id}"'
])
# アカウントリストでの実行
accounts = [
{'id': '111111111111', 'role': 'TerraformRole'},
{'id': '222222222222', 'role': 'TerraformRole'}
]
for account in accounts:
destroy_resources(account['id'], account['role'])
マルチアカウント運用のベストプラクティス:
| 項目 | 実装方法 | 重要ポイント |
|---|---|---|
| 認証管理 | IAMロール継承 | 最小権限の原則 |
| 依存関係 | グラフ分析 | アカウント間の順序 |
| ログ管理 | CloudWatch統合 | 集中管理 |
| バックアップ | クロスアカウント | 復旧可能性確保 |
実践的な運用シナリオ:
- 環境のクリーンアップ
# cleanup.sh
#!/bin/bash
# 環境変数の設定
export TF_WORKSPACE="cleanup"
# アカウントごとの処理
for account in $(cat accounts.txt); do
echo "Processing account: $account"
# アカウント別の設定読み込み
source "./config/$account.env"
# terraform実行
terraform init
terraform destroy -auto-approve \
-var="account_id=$account" \
-var="environment=$ENVIRONMENT"
done
- 定期的なメンテナンス
# maintenance-workflow.yml
name: Regular Maintenance
on:
schedule:
- cron: '0 0 * * 0' # 毎週日曜日
jobs:
cleanup:
runs-on: ubuntu-latest
strategy:
matrix:
account: ['dev', 'staging', 'prod']
steps:
- uses: actions/checkout@v2
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/GithubActionsRole
aws-region: ap-northeast-1
- name: Execute Terraform Destroy
run: |
cd environments/${{ matrix.account }}
terraform init
terraform destroy -auto-approve
これらの実践例を参考に、組織の規模と要件に合わせた適切な運用方法を選択することで、安全かつ効率的なリソース管理が可能になります。次のセクションでは、terraform destroyのセキュリティベストプラクティスについて説明します。
terraform destroyのセキュリティベストプラクティス
アクセス制御と監査ログの設定方法
terraform destroyコマンドの実行に関する適切なアクセス制御と監査の実装方法を解説します。
1. IAMポリシーの実装
# terraform_iam.tf
resource "aws_iam_policy" "terraform_destroy" {
name = "terraform-destroy-policy"
description = "Policy for terraform destroy execution"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"terraform:Destroy"
]
Resource = "*"
Condition = {
StringEquals = {
"aws:RequestTag/Environment": ["development", "staging"]
}
StringNotEquals = {
"aws:RequestTag/Environment": "production"
}
}
},
{
Effect = "Deny"
Action = [
"terraform:Destroy"
]
Resource = "*"
Condition = {
StringEquals = {
"aws:RequestTag/Protected": "true"
}
}
}
]
})
}
# 監査ログ設定
resource "aws_cloudwatch_log_group" "terraform_audit" {
name = "/terraform/destroy-audit"
retention_in_days = 365
tags = {
Environment = var.environment
Service = "terraform-audit"
}
}
resource "aws_cloudwatch_metric_alarm" "destroy_alert" {
alarm_name = "terraform-destroy-execution"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = "1"
metric_name = "DestroyExecutionCount"
namespace = "Custom/Terraform"
period = "300"
statistic = "Sum"
threshold = "0"
alarm_description = "This metric monitors terraform destroy executions"
alarm_actions = [aws_sns_topic.security_alerts.arn]
}
2. 監査ログの設定
# audit_logging.sh
#!/bin/bash
# ログ出力関数
log_terraform_action() {
local action=$1
local user=$2
local resources=$3
# CloudWatchへのログ送信
aws logs put-log-events \
--log-group-name "/terraform/destroy-audit" \
--log-stream-name "$(date +%Y-%m-%d)" \
--log-events timestamp=$(date +%s%3N),message="{\"action\":\"$action\",\"user\":\"$user\",\"resources\":\"$resources\"}"
}
# Terraformラッパースクリプト
terraform destroy "$@" 2>&1 | tee >(log_terraform_action "destroy" "${AWS_USER}" "$(terraform show -json | jq -r '.planned_values.root_module.resources[].address')")
CI/CDパイプラインでの安全な実装方法
CI/CDパイプラインでterraform destroyを安全に実装する方法を説明します。
1. GitHubActions実装例
# .github/workflows/terraform-destroy.yml
name: Terraform Destroy
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment to destroy'
required: true
type: choice
options:
- development
- staging
approval_token:
description: 'Approval token'
required: true
permissions:
id-token: write
contents: read
jobs:
security-check:
runs-on: ubuntu-latest
steps:
- name: Verify approval token
run: |
if [[ "${{ github.event.inputs.approval_token }}" != "$(cat .github/approval_tokens/${{ github.event.inputs.environment }})" ]]; then
echo "Invalid approval token"
exit 1
fi
destroy-plan:
needs: security-check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/GithubActionsRole
aws-region: ap-northeast-1
- name: Terraform Plan Destroy
run: |
terraform init
terraform plan -destroy -out=destroy.plan
- name: Upload Plan
uses: actions/upload-artifact@v2
with:
name: destroy-plan
path: destroy.plan
approve-destroy:
needs: destroy-plan
runs-on: ubuntu-latest
environment:
name: ${{ github.event.inputs.environment }}
steps:
- name: Download Plan
uses: actions/download-artifact@v2
with:
name: destroy-plan
- name: Apply Destroy
run: terraform apply destroy.plan
2. セキュリティチェックの実装
# security_checks.py
import boto3
import json
def check_protected_resources():
"""保護されたリソースのチェック"""
client = boto3.client('resourcegroupstaggingapi')
response = client.get_resources(
TagFilters=[
{
'Key': 'Protected',
'Values': ['true']
}
]
)
return [r['ResourceARN'] for r in response['ResourceTagMappingList']]
def validate_destroy_plan(plan_file):
"""destroyプランの検証"""
with open(plan_file, 'r') as f:
plan = json.load(f)
protected_resources = check_protected_resources()
for resource in plan.get('resource_changes', []):
if resource['address'] in protected_resources:
raise Exception(f"Protected resource found: {resource['address']}")
if __name__ == "__main__":
validate_destroy_plan('destroy.plan.json')
セキュリティベストプラクティスまとめ:
| カテゴリ | 実装項目 | 重要ポイント |
|---|---|---|
| アクセス制御 | IAMポリシー | 最小権限の原則 |
| 監査 | CloudWatchログ | 完全な監査証跡 |
| 承認フロー | 多段階承認 | 意図しない実行の防止 |
| 保護機能 | リソースタグ | 重要リソースの保護 |
セキュリティチェックリストの実装:
# security_checks.tf
locals {
security_checks = {
production_protection = {
condition = var.environment == "production"
error_message = "Direct destroy in production is not allowed"
}
backup_verification = {
condition = var.backup_confirmed
error_message = "Backup confirmation required"
}
approval_validation = {
condition = var.approval_token != ""
error_message = "Valid approval token required"
}
}
}
resource "null_resource" "security_validation" {
count = var.enable_security_checks ? 1 : 0
lifecycle {
precondition {
condition = !contains([for check in local.security_checks : check.condition], false)
error_message = join("\n", [for check in local.security_checks : check.error_message if !check.condition])
}
}
}
これらのセキュリティ実装により、terraform destroyの安全な実行が確保されます。適切なアクセス制御、監査ログ、承認フロー、保護機能を組み合わせることで、意図しない削除や不正なアクセスを防ぐことができます。