【小ネタ】TerraformでALBアクセスログに暗号化したS3バケットを指定すると失敗して困った話

S3バケットのデフォルト暗号化をちゃんと理解していますか?
2021.02.28

おばんです!コンサル部のinomaso(@inomasosan)です。

TerraformでALBアクセスログに暗号化したS3バケットを指定すると、terraform apply時にエラーとなり困っていました。
今回はエラーを調査し、原因と対応方法が分かったのでブログにまとめます。

この記事で学べること

  • S3バケットのデフォルト暗号化
  • Terraformでのコードの書き方

環境

今回実行した環境は以下の通りです。

  • macOS Catalina 10.15.7
  • Terraform 0.14.7
  • AWSプロバイダー 3.30.0

エラー事象

1.コード

弊社の以下ブログのELB のアクセスログの設定についてを参考に、S3バケットのデフォルト暗号化を追加しました。

####################
# S3
####################
resource "aws_s3_bucket" "alb_logs" {
  acl    = "private"

  # S3バケットのデフォルト暗号化
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        kms_master_key_id = "aws/s3"
        sse_algorithm     = "aws:kms"
      }
    }
  }

}

# 東京リージョン(ap-northeast-1)の
# Elastic Load Balancing アカウント ID(582318560864)
data "aws_elb_service_account" "main" {}

# S3 Bucket Policy
data "aws_iam_policy_document" "alb_logs" {
  statement {
    effect    = "Allow"
    actions   = [ "s3:PutObject" ]
    resources = [ "${aws_s3_bucket.alb_logs.arn}/*" ]
    principals {
      type = "AWS"
      identifiers = [ data.aws_elb_service_account.main.arn ]
    }
  }
}

resource "aws_s3_bucket_policy" "alb_logs" {
  bucket = aws_s3_bucket.alb_logs.id
  policy = data.aws_iam_policy_document.alb_logs.json
}


# ALB
resource "aws_lb" "front_ext_alb" {
  name                       = "lb"
  internal                   = false
  load_balancer_type         = "application"
  security_groups            = [ "sg-0123456789012" ]
  subnets                    = [ "subnet-0123456789012", "subnet-1234567890123"]

  access_logs {
    bucket  = aws_s3_bucket.lb_logs.bucket
    prefix  = "PREFIX"
    enabled = true
  }
}

2.結果

terraform apply中に、S3Bucket validation transient issueというエラーメッセージが出力され失敗してしまいました。

Error: failure configuring LB attributes: InvalidConfigurationRequest: S3Bucket validation transient issue  
    status code: 400, request id: 6d9ff881-db65-4855-9693-bf4a4d6c0915

調査

1.原因

エラーメッセージをググってみると、以下のブログよりデフォルト暗号化にAWS-KMSを選択したのがが原因とわかりました。

2.コード改善

S3バケットのデフォルト暗号化をSSE-S3に変更しました。
変更箇所は11行目の sse_algorithm = "AES256" となります。

####################
# S3
####################
resource "aws_s3_bucket" "alb_logs" {
  acl    = "private"

  # S3バケットのデフォルト暗号化
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }

}

# 東京リージョン(ap-northeast-1)の
# Elastic Load Balancing アカウント ID(582318560864)
data "aws_elb_service_account" "main" {}

# S3 Bucket Policy
data "aws_iam_policy_document" "alb_logs" {
  statement {
    effect    = "Allow"
    actions   = [ "s3:PutObject" ]
    resources = [ "${aws_s3_bucket.alb_logs.arn}/*" ]
    principals {
      type = "AWS"
      identifiers = [ data.aws_elb_service_account.main.arn ]
    }
  }
}

resource "aws_s3_bucket_policy" "alb_logs" {
  bucket = aws_s3_bucket.alb_logs.id
  policy = data.aws_iam_policy_document.alb_logs.json
}


# ALB
resource "aws_lb" "front_ext_alb" {
  name                       = "lb"
  internal                   = false
  load_balancer_type         = "application"
  security_groups            = [ "sg-0123456789012" ]
  subnets                    = [ "subnet-0123456789012", "subnet-1234567890123"]

  access_logs {
    bucket  = aws_s3_bucket.lb_logs.bucket
    prefix  = "PREFIX"
    enabled = true
  }
}

S3バケットのデフォルト暗号化って?

S3バケットのデフォルト暗号化は、SSE-S3SSE-KMSのいずれかを選択することができます。
詳しくはS3 バケットの Amazon S3 デフォルト暗号化をご参照願います。

Amazon S3 のデフォルトの暗号化により、S3 バケットのデフォルト暗号化の動作を設定できます。バケットにデフォルト暗号化を設定して、バケットに保存される際にすべての新しいオブジェクトが暗号化されるようにします。オブジェクトは、Amazon S3 で管理されたキー (SSE-S3) または AWS Key Management Service (AWS KMS) に保存されたカスタマーマスターキー (CMK) のいずれかと、サーバー側の暗号化を使用して暗号化されます。

何でSSE-S3にすると解決するの?

SSE-S3の場合、暗号化に関するバケットポリシー追加は不要となります。 詳しくは以下のAWSドキュメントをご参照願います。

まとめ

S3バケットのデフォルト暗号化を利用した場合、バケットポリシーの変更有無を曖昧に理解していたので、きちんと整理する良い機会となりました! この記事が、どなたかのお役に立てば幸いです。それでは!