当社はインフラ、バックエンド、フロントエンドすべてをこなすフルスタックな開発会社ですが(ハード面も若干ハンダ付け、600Vまでの電気工事も。あまりやりませんが)AWSの保守や構築のみという依頼も多いです。CloudFormationも使っていますが先日、Application Load BalancerのログをS3に出すためのテンプレートを書いたところ何故かAccess Denied for bucket. Please check S3bucket permission (Service: AmazonElasticLoadBalancing; Status Code: 400; Error Code: InvalidConfigurationRequest)とか出てスタック作成に失敗。何故かこれがなかなか直せなくてハマるという罠を経験しました。一体どこを間違えたのか。
ぐぐるといくつか似たようなテンプレートの例が見つかったので試しにそのまま真似してみても同じエラー。yml内の記述の仕方に細かい違いはあるものの、どれも合ってるように見えたんですがね…。
https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-access-logs.html
上記参考にコンソールからバケットを作ってみると動くので、CloudFormationテンプレートをエラーが出なくなるまで削ってそこから記述を追加していくというやり方で、試行錯誤の末動くものができ上がりました。想定外に時間がかかってイラっとしたので、動いたものを以下に貼っておきます。
Resources: CeatantLogBucket: Type: AWS::S3::Bucket DeletionPolicy: Delete Properties: BucketName: !Sub "ceatant-${Environment}-log" LifecycleConfiguration: Rules: - Id: AutoDelete Status: Enabled ExpirationInDays: 365 PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True IgnorePublicAcls: True RestrictPublicBuckets: True CeatantLogBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref CeatantLogBucket PolicyDocument: Id: AlblogsBucketPolicy Version: "2012-10-17" Statement: - Sid: AWSConsoleStmt Effect: Allow Action: s3:PutObject Resource: !Join - '' - - 'arn:aws:s3:::' - !Ref CeatantLogBucket - '/*/AWSLogs/' - !Ref AWS::AccountId - '/*' Principal: AWS: "582318560864" - Sid: AWSLogDeliveryWrite Effect: Allow Action: s3:PutObject Resource: !Join - '' - - 'arn:aws:s3:::' - !Ref CeatantLogBucket - '/*/AWSLogs/' - !Ref AWS::AccountId - '/*' Principal: Service: delivery.logs.amazonaws.com Condition: StringEquals: s3:x-amz-acl: bucket-owner-full-control - Sid: AWSLogDeliveryAclCheck Effect: Allow Action: s3:GetBucketAcl Resource: !Join - '' - - 'arn:aws:s3:::' - !Ref CeatantLogBucket Principal: Service: delivery.logs.amazonaws.com
ALBとNLBで記述が若干違うらしいのですがこれはALB用のものです。ポリシーのうち一つのPrincipalにelb-account-idが入るのですがこれはリージョン毎に固定の値がIDになっていて初見でわかりにくいポイント。上記公式ドキュメントに表が載っていて、ap-northeast-1の場合は582318560864になります。
これで後はAWS::ElasticLoadBalancingV2::LoadBalancerのaccess_logs.s3.enabledをTrueに、access_logs.s3.bucketで上記バケットを指定、access_logs.s3.prefixを適当に指定してやれば出力できました。やれやれ。ただそれだけのことなんですが、記録を残しておきます。