S3バケットのバージョニング有効化設定手順

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、 「どうやって直すのか?」 という具体的な修復手順(コンソール、AWS CLI、Terraformなど)まで、分かりやすく解説します。

この記事では、S3バケットのバージョニング機能を有効化する方法について、リスクと対策を解説します。

ポリシーの説明

S3バージョニングは、同一バケット内でオブジェクトの複数のバリアントを保持する機能です。バージョニングを有効にすると、オブジェクトが上書きや削除された場合でも、以前のバージョンを保持し続けます。各バージョンは完全なオブジェクトとして保存され、固有のバージョンIDが付与されます。

この機能は、誤削除からの復旧、変更履歴の追跡、コンプライアンス要件への対応など、データ保護の基本的な要素として重要な役割を果たします。本番環境など重要な環境において有効化するようにしましょう。

修復方法

コンソールでの修復手順

AWSのコンソールを使用して、S3バケットのバージョニングを有効化します。

  1. AWS Management Console にログインし、S3サービスに移動します。
  2. バケットの選択
    • 「バケット」リストから、バージョニングを有効化したいバケット名をクリックします
  3. プロパティタブへの移動
    • バケットの詳細画面で「プロパティ」タブをクリックします
  4. バージョニング設定の編集
    • 「バケットのバージョニング」セクションを見つけます
    • 「編集」ボタンをクリックします
  5. バージョニングの有効化
    • 「バケットのバージョニング」で「有効化」を選択します
    • 注意事項を確認します(一度有効化すると無効化できず、一時停止のみ可能)
  6. 変更の保存
    • 「変更の保存」ボタンをクリックします
    • 確認メッセージが表示されたら、内容を確認して続行します
  7. 設定の確認
    • プロパティタブに戻り、「バケットのバージョニング」が「有効」と表示されていることを確認します
    • 新しくアップロードされるオブジェクトにバージョンIDが付与されることを確認します

注意事項:

  • バージョニングの変更は完全に反映されるまで最大15分かかる場合があります
  • 既存のオブジェクトには「null」バージョンIDが付与されます
  • バージョニング有効化後は、各バージョンが個別にストレージ料金の対象となります
  • MFA Deleteを有効化する場合は、ルートアカウントまたはMFA認証済みのIAMユーザーが必要です
  • レプリケーション設定を行う場合は、送信元と送信先の両方でバージョニングが必要です

Terraformでの修復手順

S3バケットのバージョニングを有効にするTerraformコードと、主要な修正ポイントを説明します。

# S3バケットの作成
resource "aws_s3_bucket" "versioned_bucket" {
  bucket = "my-versioned-data-bucket"

  tags = {
    Name        = "Versioned Data Bucket"
    Environment = "Production"
    DataProtection = "Versioning-Enabled"
  }
}

# バージョニングの有効化(重要)
resource "aws_s3_bucket_versioning" "versioning" {
  bucket = aws_s3_bucket.versioned_bucket.id

  versioning_configuration {
    status = "Enabled"  # "Enabled" または "Suspended" を指定
  }
}

# ライフサイクルポリシーの設定(コスト最適化)
resource "aws_s3_bucket_lifecycle_configuration" "versioning_lifecycle" {
  bucket = aws_s3_bucket.versioned_bucket.id

  rule {
    id     = "manage-old-versions"
    status = "Enabled"

    # 現行バージョンの管理
    transition {
      days          = 30
      storage_class = "STANDARD_IA"
    }

    transition {
      days          = 90
      storage_class = "GLACIER"
    }

    # 非現行バージョンの管理
    noncurrent_version_transition {
      noncurrent_days = 30
      storage_class   = "STANDARD_IA"
    }

    noncurrent_version_transition {
      noncurrent_days = 90
      storage_class   = "GLACIER"
    }

    # 古いバージョンの削除(365日後)
    noncurrent_version_expiration {
      noncurrent_days = 365
    }
  }

  rule {
    id     = "delete-markers-cleanup"
    status = "Enabled"

    # 削除マーカーのクリーンアップ
    expiration {
      expired_object_delete_marker = true
    }

    # 不完全なマルチパートアップロードのクリーンアップ
    abort_incomplete_multipart_upload {
      days_after_initiation = 7
    }
  }
}

# パブリックアクセスブロック(追加のセキュリティ)
resource "aws_s3_bucket_public_access_block" "versioned_bucket_pab" {
  bucket = aws_s3_bucket.versioned_bucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# サーバーサイド暗号化の設定
resource "aws_s3_bucket_server_side_encryption_configuration" "versioned_bucket_encryption" {
  bucket = aws_s3_bucket.versioned_bucket.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.bucket_key.arn
    }
    bucket_key_enabled = true
  }
}

# KMSキーの作成
resource "aws_kms_key" "bucket_key" {
  description             = "KMS key for versioned bucket encryption"
  deletion_window_in_days = 30
  enable_key_rotation     = true

  tags = {
    Name = "Versioned-Bucket-KMS-Key"
  }
}

# バケットロギングの設定(監査証跡)
resource "aws_s3_bucket_logging" "versioned_bucket_logging" {
  bucket = aws_s3_bucket.versioned_bucket.id

  target_bucket = aws_s3_bucket.log_bucket.id
  target_prefix = "versioned-bucket-logs/"
}

# ログ保存用バケット
resource "aws_s3_bucket" "log_bucket" {
  bucket = "my-versioned-bucket-logs"

  tags = {
    Name = "Versioned Bucket Logs"
    Type = "Logging"
  }
}

# ログバケットのバージョニング(ログも保護)
resource "aws_s3_bucket_versioning" "log_versioning" {
  bucket = aws_s3_bucket.log_bucket.id

  versioning_configuration {
    status = "Enabled"
  }
}

# MFA Delete の設定(追加のセキュリティ)
# 注意: Terraformでは直接設定できないため、AWS CLIでの手動設定が必要
resource "null_resource" "enable_mfa_delete" {
  provisioner "local-exec" {
    command = <<-EOT
      echo "MFA Delete must be enabled manually using AWS CLI with root account credentials:"
      echo "aws s3api put-bucket-versioning --bucket ${aws_s3_bucket.versioned_bucket.id} --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa 'arn:aws:iam::ACCOUNT:mfa/root-account-mfa-device MFA_CODE'"
    EOT
  }
}

# CloudWatchアラーム(バージョン数の監視)
resource "aws_cloudwatch_metric_alarm" "high_version_count" {
  alarm_name          = "s3-high-version-count-${aws_s3_bucket.versioned_bucket.id}"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 2
  metric_name         = "NumberOfObjects"
  namespace           = "AWS/S3"
  period              = 86400
  statistic           = "Average"
  threshold           = var.environment == "prod" ? 1000000 : 100000  # 環境別閾値
  alarm_description   = "Alert when S3 bucket has too many versions"
  alarm_actions       = [aws_sns_topic.alerts.arn]
  treat_missing_data  = "notBreaching"

  dimensions = {
    BucketName  = aws_s3_bucket.versioned_bucket.id
    StorageType = "AllStorageTypes"
  }
}

# ストレージコスト監視
resource "aws_cloudwatch_metric_alarm" "high_storage_cost" {
  alarm_name          = "s3-high-storage-cost-${aws_s3_bucket.versioned_bucket.id}"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 1
  metric_name         = "BucketSizeBytes"
  namespace           = "AWS/S3"
  period              = 86400
  statistic           = "Maximum"
  threshold           = 1073741824000  # 1TB
  alarm_description   = "Alert when S3 bucket storage exceeds 1TB"
  alarm_actions       = [aws_sns_topic.alerts.arn]

  dimensions = {
    BucketName  = aws_s3_bucket.versioned_bucket.id
    StorageType = "StandardStorage"
  }
}

# SNSトピック(アラート通知用)
resource "aws_sns_topic" "alerts" {
  name = "s3-versioning-alerts"
}

 

主要な修正ポイント:

  1. versioning_configuration.status = "Enabled":この設定が最も重要です。必ず”Enabled”に設定してください。
  2. ライフサイクルポリシー:古いバージョンのストレージコストを管理するために必須です。適切な保持期間を設定してください。
    • 本番環境: 最低90日間の保持を推奨
    • 開発環境: 30日間程度でコスト最適化
    • コンプライアンス要件に応じて調整
  3. noncurrent_version_expiration:古いバージョンを自動削除する期間を設定し、ストレージコストを最適化します。
  4. 削除マーカーのクリーンアップ:不要な削除マーカーを自動的に削除し、コストを削減します。
  5. 監視とアラート:バージョン数が異常に増加した場合に通知を受け取れるよう設定します。
  6. MFA Delete:重要なバケットでは、バージョンの恒久削除に多要素認証を要求することを強く推奨します。

最後に

この記事では、S3バケットのバージョニング機能を有効化する方法について、リスクと対策を解説しました。

バージョニングは、データ保護の基本的かつ重要な機能です。誤削除やランサムウェア攻撃からデータを守り、コンプライアンス要件を満たし、運用の安全性を向上させます。ただし、ストレージコストへの影響を考慮し、適切なライフサイクルポリシーと組み合わせて使用することが重要です。特に、MFA DeleteやObject Lockとの併用により、より堅牢なデータ保護体制を構築できます。

この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。 運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。 最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。

参考資料

この記事をシェアする

クラウドセキュリティ対策実践集一覧へ戻る

貴社の利用状況に合わせた見積もりを作成します。

料金プランを詳しく見る