CloudFormationでALBアクセスログ設定時のエラー

#1. 背景
CloudFormationでALBを構築する際、アクセスログ設定を記述したがバケットポリシー関連でエラーが出てハマったので、備忘録として書きます。

#2. エラーメッセージ
以下のようなメッセージが出てハマりました。

```
Access Denied for bucket: {バケット名}. Please check S3bucket permission (Service: AmazonElasticLoadBalancing; Status Code: 400; Error Code: InvalidConfigurationRequest; Request ID: XXXXX; Proxy: null)　
```

#3. YAML記述（修正前）
ALB, S3記述箇所は以下。（東京リージョンでデプロイ前提なのでPrincipalは直打ちしてます。）

```yaml:template.yml
  # ------------------------------------------------------------#
  #  S3 for Internet ALB Log
  # ------------------------------------------------------------#
  S3forInternetALBLogs:
    Type: AWS::S3::Bucket
    DeletionPolicy: Delete
    Properties:
      BucketName: !Sub "${PJPrefix}-alb-logs"
      LifecycleConfiguration:
        Rules:
          - Id: AutoDelete
            Status: Enabled
            ExpirationInDays: 14
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

  #BucketPolicy
  ELBLogBucketPolicy:
    Type: "AWS::S3::BucketPolicy"
    Properties:
      Bucket: !Ref S3forInternetALBLogs
      PolicyDocument:
        Id: "AWSCFn-AccessLogs-Policy-20180920"
        Version: "2012-10-17"
        Statement:
          - Sid: "AlbLogs"
            Effect: "Allow"
            Action:
              - "s3:PutObject"
            Resource: !Sub "arn:aws:s3:::${S3forInternetALBLogs}/AWSLogs/${AWS::AccountId}/*"
            Principal:
              AWS:
                - "582318560864"

  # ------------------------------------------------------------#
  #  Internet ALB
  # ------------------------------------------------------------#
  InternetALB:
    Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer'
    DependsOn: ELBLogBucketPolicy
    Properties:
      Name: !Sub "${PJPrefix}-alb-outer"
      Tags:
        - Key: Name
          Value: !Sub "${PJPrefix}-alb-outer"
      Scheme: internet-facing
      LoadBalancerAttributes:
        - Key: deletion_protection.enabled
          Value: false
        - Key: access_logs.s3.enabled
          Value: true
        - Key: routing.http2.enabled
          Value: true
        - Key: routing.http.drop_invalid_header_fields.enabled
          Value: false
        - Key: idle_timeout.timeout_seconds
          Value: 60
        - Key: access_logs.s3.bucket
          Value: !Ref S3forInternetALBLogs
        - Key: access_logs.s3.prefix
          Value: "prod"
      SecurityGroups:
        - !Ref ALBSecurityGroup
      Subnets:
        - { "Fn::ImportValue": !Sub "${PJPrefix}-PublicSubnet2" }
        - { "Fn::ImportValue": !Sub "${PJPrefix}-PublicSubnet3" }
      Type: application
```


#4. 原因
ALBアクセスログ用のS3バケット名にプレフィックスを指定しているのに、バケットポリシーのResourceにプレフィックスの記述を加えてなかったのが原因でした。
具体的には、ALBで`access_logs.s3.prefix`のvalueを`"prod"`としておりバケット名にもプレフィックスがつくので、バケットポリシーのResource名にも`"prod"`をつけないといけません。


#5. YAML記述（修正後）
特に関連する箇所を以下に抜粋。Resoruceで`/AWSLogs/`→`/prod/AWSLogs/`に修正しています。
こちらでデプロイしたところ無事成功しました。

```yaml:template_mod.yml
  # ------------------------------------------------------------#
  #  S3 for Internet ALB Log
  # ------------------------------------------------------------#
  #BucketPolicy
  ELBLogBucketPolicy:
        Statement:
          - Sid: "AlbLogs"
            Effect: "Allow"
            Action:
              - "s3:PutObject"
            Resource: !Sub "arn:aws:s3:::${S3forInternetALBLogs}/prod/AWSLogs/${AWS::AccountId}/*"
            Principal:

  # ------------------------------------------------------------#
  #  Internet ALB
  # ------------------------------------------------------------#
  InternetALB:
      LoadBalancerAttributes:
        - Key: access_logs.s3.prefix
          Value: "prod"

```

#6. 最後に
よく見たら[クラメソさん記事](https://dev.classmethod.jp/articles/bucket-policy-elb-yaml/)の解説欄にも同様のことが書いてました。