すべてのユーザーが読み取り/書き込みを実行できるS3バケットポリシーの変更手順

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

この記事では、S3バケットのパブリックアクセス設定に関するセキュリティポリシーについて解説します。

ポリシーの説明

Amazon S3 の Security Hub コントロール – AWS Security Hub

このコントロールは、Amazon S3 汎用バケットがバケットレベルでパブリックアクセスをブロックするかどうかをチェックします。次の設定のいずれかが false に設定されている場合、コントロールは失敗します。

このポリシーは、S3バケットがインターネットから誰でもアクセスできないようにすることを求めています。パブリックアクセスを許可すると、機密データが漏洩したり、不正なアップロードや削除が行われたりするリスクが高まります。S3バケットには様々なデータが保存されるため、厳格なアクセス制御が必要です。

修復方法

AWSコンソールでの修正手順

  1. Amazon S3 > 対象バケットを選択し、アクセス許可をクリック
  2. ブロックパブリックアクセス(バケット限定)で「編集」をクリック

3. パブリックアクセスをすべてブロックにチェックを入れ、「変更の保存」をクリック

Terraformでの修復手順

S3バケットのセキュアな設定を実装するTerraformコードを作成します。

# S3バケットの基本設定
resource "aws_s3_bucket" "secure_bucket" {
  bucket = "secure-bucket-${data.aws_caller_identity.current.account_id}"

  # 重要:バケットを削除する前に内容の確認が必要
  force_destroy = false

  tags = {
    Environment = "Production"
    Security    = "High"
  }
}

# 重要: パブリックアクセスをすべてブロック
resource "aws_s3_bucket_public_access_block" "secure_bucket" {
  bucket = aws_s3_bucket.secure_bucket.id

  # すべてのパブリックアクセスをブロック
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# バケットのバージョニングを有効化
resource "aws_s3_bucket_versioning" "secure_bucket" {
  bucket = aws_s3_bucket.secure_bucket.id
  versioning_configuration {
    status = "Enabled"
  }
}

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

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

# 安全なバケットポリシーの設定
resource "aws_s3_bucket_policy" "secure_bucket" {
  bucket = aws_s3_bucket.secure_bucket.id

  # パブリックアクセスブロックが適用されるのを待つ
  depends_on = [aws_s3_bucket_public_access_block.secure_bucket]

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "SecureTransportOnly"
        Effect    = "Deny"
        Principal = "*"
        Action    = "s3:*"
        Resource = [
          aws_s3_bucket.secure_bucket.arn,
          "${aws_s3_bucket.secure_bucket.arn}/*"
        ]
        Condition = {
          Bool = {
            "aws:SecureTransport" = "false"
          }
        }
      },
      {
        Sid    = "AllowSpecificRoleAccess"
        Effect = "Allow"
        Principal = {
          AWS = [
            "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${var.allowed_role_name}"
          ]
        }
        Action = [
          "s3:GetObject",
          "s3:PutObject",
          "s3:ListBucket"
        ]
        Resource = [
          aws_s3_bucket.secure_bucket.arn,
          "${aws_s3_bucket.secure_bucket.arn}/*"
        ]
      }
    ]
  })
}

# アクセスログの保存先バケット
resource "aws_s3_bucket" "log_bucket" {
  bucket = "access-logs-${data.aws_caller_identity.current.account_id}"
}

# ログバケットのパブリックアクセスブロック
resource "aws_s3_bucket_public_access_block" "log_bucket" {
  bucket = aws_s3_bucket.log_bucket.id

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

# メインバケットのログ記録設定
resource "aws_s3_bucket_logging" "secure_bucket" {
  bucket = aws_s3_bucket.secure_bucket.id

  target_bucket = aws_s3_bucket.log_bucket.id
  target_prefix = "s3-access-logs/"
}

# 現在のAWSアカウントIDの取得
data "aws_caller_identity" "current" {}

# 変数定義
variable "allowed_role_name" {
  type        = string
  description = "Name of the IAM role allowed to access the bucket"
}

# 出力
output "bucket_name" {
  value       = aws_s3_bucket.secure_bucket.id
  description = "The name of the secure S3 bucket"
}

output "bucket_arn" {
  value       = aws_s3_bucket.secure_bucket.arn
  description = "The ARN of the secure S3 bucket"
}

重要な修正ポイントと実装手順を説明します:

  1. パブリックアクセスのブロック(最重要):
    resource "aws_s3_bucket_public_access_block" "secure_bucket" {
      bucket = aws_s3_bucket.secure_bucket.id
    
      block_public_acls       = true  # パブリックACLをブロック
      block_public_policy     = true  # パブリックポリシーをブロック
      ignore_public_acls      = true  # パブリックACLを無視
      restrict_public_buckets = true  # パブリックバケットを制限
    }
    
    
    • aws_s3_bucket_public_access_block リソースの4つの属性 (block_public_acls, block_public_policy, ignore_public_acls, restrict_public_buckets) をすべて true に設定することが、このポリシーに準拠するための最も重要な設定です。これにより、ACLやバケットポリシーによる意図しない公開を防ぎます。

    2. 安全なバケットポリシーの実装:

    • Terraformコード内の aws_s3_bucket_policy リソースでは、HTTPS通信 (aws:SecureTransport = false をDeny) を強制し、指定したIAMロール (var.allowed_role_name から生成したARN) のみにアクセスを許可 (AllowSpecificRoleAccess) するポリシーを設定しています。パブリックアクセスブロック設定と併用することで、よりセキュアになります。

    3. 暗号化の設定:

      # サーバーサイド暗号化の設定
      resource "aws_s3_bucket_server_side_encryption_configuration" "secure_bucket" {
        # ... (省略) ...
        rule {
          apply_server_side_encryption_by_default {
            sse_algorithm = "AES256"
          }
        }
      }
      
      • aws_s3_bucket_server_side_encryption_configuration リソースで、デフォルトのサーバーサイド暗号化 (SSE-S3) を有効にしています。

      4. ログ記録の有効化:

        # メインバケットのログ記録設定
        resource "aws_s3_bucket_logging" "secure_bucket" {
          # ... (省略) ...
          target_bucket = aws_s3_bucket.log_bucket.id # ログ専用バケット
          target_prefix = "s3-access-logs/"
        }
        
        • aws_s3_bucket_logging リソースで、別の安全なバケット (aws_s3_bucket.log_bucket) へのアクセスログ記録を設定しています。

        適用手順:

        1. 変数の設定:
        # terraform.tfvars
        allowed_role_name = "your-specific-role-name"
        
        

        2. Terraformの実行:

          terraform init
          terraform plan
          terraform apply
          

          最後に

          今回は、S3バケットのパブリックアクセス設定について解説しました。パブリックアクセスを許可すると、データ漏洩や不正アクセスのリスクが高まります。必ずパブリックアクセスをブロックし、厳格なアクセス制御を実施してください。

          この問題の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。

          運用が非常に楽に出来る製品になっていますので、ぜひ興味がある方はお問い合わせお待ちしております。

          最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです

          この記事をシェアする

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

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

          料金プランを詳しく見る