AWS CDK Study-2 ~静的サイト作成~

CloudFront+S3で静的サイトを構築します。

# 環境

```
% sw_vers
ProductName:		macOS
ProductVersion:		14.7.3
BuildVersion:		23H417
% aws --version
aws-cli/2.9.10 Python/3.9.11 Darwin/23.6.0 exe/x86_64 prompt/off
% cdk --version
2.178.2 (build 89c49cc)
% npm --version
11.1.0
% node --version
v20.17.0
```

# 実装したコード

次のコードを実装し、`cdk deploy`を実行しました。
構築されたS3バケットに簡単な`index.html`を入れ、アクセスできることが確認できました。

``` lib/static-web-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
import * as cloudfront_origins from 'aws-cdk-lib/aws-cloudfront-origins';
import { Construct } from 'constructs';

export class StaticWebStack extends cdk.Stack {
  public readonly staticWebBucket: s3.Bucket;
  public readonly accessLogBucket: s3.Bucket;
  public readonly distribution: cloudfront.Distribution;

  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const staticWebBucketName: string = 'sample-test-staticweb-bucket';
    this.staticWebBucket = new s3.Bucket(this, staticWebBucketName, {
      bucketName: staticWebBucketName,
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
    });

    const accessLogBucketName: string = 'sample-test-accesslog-bucket';
    this.accessLogBucket = new s3.Bucket(this, accessLogBucketName, {
      bucketName: accessLogBucketName,
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
      objectOwnership: s3.ObjectOwnership.OBJECT_WRITER,
    });

    const distributionId: string = 'sample-test-distribution';
    const distributionLogFilePrefix: string = 'sample-test-staticweb';
    this.distribution = new cloudfront.Distribution(this, distributionId, {
      defaultRootObject: 'index.html',
      defaultBehavior: {
        origin: cloudfront_origins.S3BucketOrigin.withOriginAccessControl(this.staticWebBucket),
      },
      enableLogging: true,
      logBucket: this.accessLogBucket,
      logFilePrefix: distributionLogFilePrefix,
    });

    new cdk.CfnOutput(this, 'cloudfront.Distribution_URL', {
      value: `https://${this.distribution.distributionDomainName}`,
    });
  }
}
```

# Note

つまずいたのが`accessLogBucket`の`objectOwnership: s3.ObjectOwnership.OBJECT_WRITER,`の部分です。

↓↓↓

`cdk deploy`を実行した際に、次のようなエラーが発生しました。

```
Resource handler returned message: "Invalid request provided: The S3 bucket that you specified for CloudFront logs does not enable ACL access: sample-test-accesslog-bucket.s3.ap-northeast-1.amazonaws.com (Service: CloudFront, Status Code: 400, Request ID: 3fdf0890-xxxx-yyyy-zzzz-266c52e0dbf8)"
```
どうやら、`accessLogBucket`のACLが有効になっていないために発生したエラーのようです。どこで有効にするのかを探していると、[こちら](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudfront.Distribution.html#logbucket)にこんな記述がありました。

> logBucket?
> Type: IBucket (optional, default: A bucket is created if enableLogging is true)
> 
> The Amazon S3 bucket to store the access logs in.
> 
> Make sure to set objectOwnership to s3.ObjectOwnership.OBJECT_WRITER in your custom bucket.

S3の`objectOwnership`に`s3.ObjectOwnership.OBJECT_WRITER`を設定してくださいとのこと。
指示(?)に従って、`accessLogBucket`に`objectOwnership: s3.ObjectOwnership.OBJECT_WRITER,`の記述を追記したところ、エラーが解消し、リソースが構築されました。

# Next

フロントエンドの構築ができたので、バックエンドの構築をしてみようかと考えています。
API Gateway+Lambdaになりそうかな？

# 参考

https://dev.classmethod.jp/articles/aws-cdk-enables-oac-configuration-on-cloudfront-distribution-with-l2-construct/

https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudfront.Distribution.html#logbucket