CloudFrontのOrigin Access Control が CDK で簡単に設定できるようになりました 🎉

# はじめに
本記事は、[ANGEL Calendar](https://qiita.com/organizations/2024-angel-dojo) の13日目の記事です！
9月中は毎日欠かさず技術記事が投稿されるので、是非他の記事もチェックしてみてください！

https://qiita.com/har1101/items/637ba82948aa7670fb9f

# CDK で Origin Access Control の設定が簡単にできるようになった 🙌
CDK v.2.156.0 の機能追加で、 L2 Construct に Origin Access Control (OAC) の機能が追加されました！
本記事では、Constructの L1/L2/L3 の違いと、OACの簡単なご紹介、そしてCDKを使った新しいOACの定義方法についてご紹介します。

# CDK Contruct の L1 / L2 / L3 って何？

CDKのライブラリは、AWSリソースをどの程度抽象化しているかによってL1/L2/L3に分かれています。
OACはこれまでL1 Constructで定義することしかできず、コードが煩雑になってしまっていました。
L2 Construct が提供されたことで、抽象度があがり、可読性が上がったコードを書けるようになりました！

**L1 Construct**: AWSのCloudFormationリソースをそのままCDKで使えるようにしたものです。基本的にはCloudFormationで使うプロパティがそのままCDKのコード内で使われます。具体的には、`CfnBucket` などが該当します。L2・L３ Construct が提供されていない場合はL1を利用するしかないのですが、コード量は多くなる傾向があります。

**L2 Construct**: AWSリソースを少し抽象化して、デフォルトの設定や便利なメソッドを提供してくれるものです。例えば、`Bucket` というL2 Constructを使うと、S3バケットの定義をシンプルに記述でき、開発者の負担を軽減します。

**L3 Construct**: さらに高い抽象化レベルのコンストラクトで、簡単な定義で複数のAWSリソースをまとめて一気に作ることができます。例えば、`aws_ecs_patterns.ApplicationLoadBalancedFargateService` は Amazon ECS クラスターで実行され、Application Load BalancerによってフロントされるAWS Fargate サービスを少しの定義で一気に作れます。

# Origin Access Control(OAC) って何？
S3でWebサイトなどの公開コンテンツを公開する場合、表示速度の向上やコスト効率化のためにCloudFrontをAmazon S3の前段に構築してキャッシュさせるというアーキテクチャを選択することが多いです。
そして、この構成の場合、ユーザーのリクエストはCloudFrontを経由してのみアクセスさせることを前提としており、S3に直接アクセスしてほしくありません。
OACを利用することで、S3をPublicに公開することなくCloudFrontからコンテンツを公開することができ、オリジンを保護できます。
オリジンアクセスのコントロール方法としてOrigin Access Identity(OAI)もありますが、[現在はOACの利用が推奨されています](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html)。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48812/70cb1330-d409-d3ca-75e1-2a07da31708a.png)

# CDK で OAC を定義する
それでは、新しいConstructを利用してOACを設定してみましょう。

## 事前準備： CDK のバージョンアップ
CDKのバージョンはCDK v.2.156.0 以上でなければいけません。以下のコマンドでバージョンを確認し、必要であればアップデートしましょう。

バージョン確認コマンド
```shell
cdk --version
```

バージョンアップコマンド
```shell
npm install -g aws-cdk
```

## 事前準備： CDK のプロジェクト作成
以下のコマンドでCDKのプロジェクトを作成します。今回はTypeScriptを選びました。
```shell
cdk init app --language=typescript
```

プロジェクトが作成できたら、以下のコマンドを実行して初期設定を完了させましょう。AWSの認証情報が開発環境に設定されている必要があるのでご注意ください。
```shell
cdk bootstrap
```

## コードの作成
では、いよいよコードを変更してデプロイしていきましょう。`lib`フォルダに生成されているファイルを変更します。
S3のバケット名はすべてのアカウントで一意になる必要があります。また、大文字は利用できません。デプロイに失敗したら変更してみてください。

```typescript
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
import { CfnOutput } from "aws-cdk-lib";

export class SampleStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // S3 Bucket
    const bucket = new s3.Bucket(this, 'HostingBucket', {
      bucketName: '20240913-angel-calendar',
      enforceSSL: true,
    });

    // CloudFront ディストリビューション
    const distribution = new cloudfront.Distribution(this, 'Distribution', {
      defaultRootObject: 'index.html',
      defaultBehavior: {
        // S3 バケットへのアクセス制御を設定 (OAC)
        origin: origins.S3BucketOrigin.withOriginAccessControl(bucket),
      },
    });

    // CloudFront URL を出力
    new CfnOutput(this, 'Distribution DomainName', { value: distribution.domainName })
  }
}
```

コードが変更できたら、以下のコマンドで環境へデプロイします。
```shell
cdk deploy
```

## デプロイ結果の確認
デプロイが完了したら、AWSマネジメントコンソールからCloudFrontの設定を見てみましょう。
CloudFrontのページにアクセスして、**オリジン**タブをクリックし、オリジンを選択して**編集**ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48812/39d5f452-3c47-6a6c-3b87-6213d2e33f08.png)

オリジンアクセスの項目を見ると、OACが選択されています 🎉

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48812/9327143c-9e07-7ecb-632b-d8e097a97870.png)

# 終わりに
L1コンストラクトの提供しかなかった時と比べると、とてもシンプルに定義することができました！
CDKはオープンソースであり、開発者の皆様の貢献で成り立っています。
こういった素敵なアップデート、本当に感謝が止まりません🙏
皆さんも是非試してみてくださいね！