エラー MalformedPolicy: Policy has invalid resource で S3 のバケットポリシーを作成できなかった話 (Terraform)

問題の Terraform コンフィグ

まずは下記のコンフィグを apply する。
(provider 等の指定は省略している。)

resource "aws_s3_bucket" "b" {
  acl    = "private"
}

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

data "aws_iam_policy_document" "b" {
  statement {
    effect = "Allow"

    principals {
      type = "AWS"
      identifiers = [
        "arn:aws:iam::111111111111:role/iam-role-name",
        "arn:aws:iam::222222222222:role/iam-role-name"
      ]
    }

    actions = [
      "s3:AbortMultipartUpload",
      "s3:GetBucketLocation",
      "s3:GetObject",
      "s3:ListBucket",
      "s3:ListBucketMultipartUploads",
      "s3:PutObject",
      "s3:PutObjectAcl"
    ]

    resources = [
      "${aws_s3_bucket.b.arn}/",
      "${aws_s3_bucket.b.arn}/*"
    ]
  }
}

すると、S3バケットポリシーを作成するタイミングで下記のエラーが発生する。

aws_s3_bucket_policy.b: Still creating... [10s elapsed]
aws_s3_bucket_policy.b: Still creating... [20s elapsed]
aws_s3_bucket_policy.b: Still creating... [30s elapsed]
aws_s3_bucket_policy.b: Still creating... [40s elapsed]
aws_s3_bucket_policy.b: Still creating... [50s elapsed]
╷
│ Error: Error putting S3 policy: MalformedPolicy: Policy has invalid resource

原因

statement 内の resources の指定が誤っていた。

    resources = [
      "${aws_s3_bucket.b.arn}/",
      "${aws_s3_bucket.b.arn}/*"
    ]

${aws_s3_bucket.b.arn} の後の / が余計だった。

    resources = [
      "${aws_s3_bucket.b.arn}",
      "${aws_s3_bucket.b.arn}/*"
    ]

あらためてドキュメントを読む

docs.aws.amazon.com

ARN (Amazon Resource Name ) は下記の共通の形式を持っている。

arn:partition:service:region:namespace:relative-id

S3 の場合は region および namespace が省略されるので以下の通りである。

arn:aws:s3:::relative-id

S3 においてこの relative-id として許容されるのは bucket-name もしくは bucket-name/object-key らしい。
つまり、いずれにも当てはまらない bucket-name/ が存在したことによって MalformedPolicy と判断されたのであった。