CloudFront+S3でブログに使う画像を配信したい

こんにちは、駆け出し12冠エンジニアのアスカです。今回は自前ブログのための画像配信環境をセットアップしていきます。
# 画像配信用のS3とCloudFrontをセットアップする
s3とCloudFrontディストリビューション、アクセス制御に使うOACを作成していきます。
OACとはOrigin Access Controlの略でCloudFrontからS3へのアクセスを制御します。従来はOrigin Access Identity(OAI)が利用されていた部分ですね。
CDKで作成していきます。
## インフラコード(CDK)作成とデプロイ
以下のブログを参考にさせていただきました。
https://qiita.com/ta__k0/items/bd700a074c394aa4d6f4

```ruby:backend-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class BackendStack extends cdk.Stack {
  public readonly contentsBucket: cdk.aws_s3.IBucket;
  public readonly distribution: cdk.aws_cloudfront.IDistribution;
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

     // S3を作成
     this.contentsBucket = new cdk.aws_s3.Bucket(this, 'ContentsBucket', {
      blockPublicAccess: cdk.aws_s3.BlockPublicAccess.BLOCK_ALL,
    });

    // OACを作成
    const cfnOriginAccessControl = new cdk.aws_cloudfront.CfnOriginAccessControl(this, 'OriginAccessControl', {
      originAccessControlConfig: {
        name: 'OriginAccessControlForContentsBucket',
        originAccessControlOriginType: 's3',
        signingBehavior: 'always',
        signingProtocol: 'sigv4',
        description: 'Access Control',
      },
    });
    // CloudFrontを作成
    this.distribution = new cdk.aws_cloudfront.Distribution(this, 'Distribution', {
      comment: 'distribution.',
      defaultBehavior: {
        origin: new cdk.aws_cloudfront_origins.S3Origin(this.contentsBucket),
        allowedMethods: cdk.aws_cloudfront.AllowedMethods.ALLOW_ALL,
      },
      defaultRootObject: 'index.html',
      httpVersion: cdk.aws_cloudfront.HttpVersion.HTTP2_AND_3,
    });

    const cfnDistribution = this.distribution.node.defaultChild as cdk.aws_cloudfront.CfnDistribution;
    // OAI削除（勝手に設定されるため）
    cfnDistribution.addPropertyOverride('DistributionConfig.Origins.0.S3OriginConfig.OriginAccessIdentity', '');
    // OAC設定
    cfnDistribution.addPropertyOverride('DistributionConfig.Origins.0.OriginAccessControlId', cfnOriginAccessControl.attrId);

     // S3 - BucketPolicy
     const contentsBucketPolicyStatement = new cdk.aws_iam.PolicyStatement({
      actions: ['s3:GetObject'],
      effect: cdk.aws_iam.Effect.ALLOW,
      principals: [
        new cdk.aws_iam.ServicePrincipal('cloudfront.amazonaws.com'),
      ],
      resources: [`${this.contentsBucket.bucketArn}/*`],
    });
    contentsBucketPolicyStatement.addCondition('StringEquals', {
      'AWS:SourceArn': `arn:aws:cloudfront::${this.account}:distribution/${this.distribution.distributionId}`
    })
    this.contentsBucket.addToResourcePolicy(contentsBucketPolicyStatement);
  }
}
```

## リソースの確認
コンソール画面でS3とCloudFront ディストリビューションが作成されている事を確認します。デプロイで問題が発生しなければ必要なリソースが立ち上がっているはずです。

## CloudFront経由での画像配信がされるか確認
以下の手順で確認作業を行います。
1. テスト用の画像(cloudfront_test.png)をアップロード
1. アップロードした画像のURLを確認
(https://<バケット名>.s3.ap-northeast-1.amazonaws.com/cloudfront_test.png)
1. CloudFrontディストリビューションドメイン名を確認
1. https://ディストリビューションドメイン名/cloudfront_test.png にアクセスして画像が表示されるか確認
今回はディストリビューションドメイン名がd39oe90ddnxn3x.cloudfront.netだったので、以下のURLにアクセスしました。
https://d39oe90ddnxn3x.cloudfront.net/cloudfront_test.png
すると、しっかり表示される事が確認出来ました。
![Qiita](https://d39oe90ddnxn3x.cloudfront.net/cloudfront_CDN.png)

# 参考
以下の記事を参考にさせていただきました。ありがとうございます。
- https://qiita.com/ta__k0/items/bd700a074c394aa4d6f4
- https://qiita.com/wtod/items/8d96b18464bb011fc363