Hugo + CloudFront + S3 + GitHub Actions でCI/CD付きブログサイトを構築してみる Part2-1 作成するリソースの確認 s3バケット(静的サイト)

## 作成経緯
https://qiita.com/Tanamachi_kaoru/items/ade2c4822817d3d80d87

この続き。
参考サイトからcloudformationで作成している部分の要素をterraformに落とし込むため、確認を行う。
まずはs3バケット(静的サイト)から。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185852/b017d04e-b7b4-c304-eef1-6d3a7cd9d9f1.png)
この記事はそのメモやまとめです。
すでに設定済みの項目がいくつかある。
試行錯誤しながらやったので、手順として不要かもしれない。**あくまでメモ用。**


# s3バケット(静的サイト)
[参考サイト](https://dev.classmethod.jp/articles/cloudfront-and-s3-using-hugo-with-github-actions/)のCFでは以下のような記載になっている。
今回は知識をつけるということもあり、ひと要素づつ分解して見ていく。
<details>
<summary>s3バケット(静的サイト)</summary>

```
  # ------------------------------------------------------------------------------------ #
  # S3
  # ------------------------------------------------------------------------------------ #
  # Static site bucket
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub ${ProjectName}-${Environment}-${S3BucketName}-${AWS::AccountId}
      OwnershipControls:
        Rules:
          - ObjectOwnership: "BucketOwnerEnforced"
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: "AES256"
            BucketKeyEnabled: false
      LifecycleConfiguration:
        Rules:
          - Id: AbortIncompleteMultipartUpload
            AbortIncompleteMultipartUpload:
              DaysAfterInitiation: 7
            Status: "Enabled"
          - Id: NoncurrentVersionExpiration
            NoncurrentVersionExpiration:
              NewerNoncurrentVersions: 3
              NoncurrentDays: 1
            Status: Enabled
  # Bucket Policy for CloudFront
  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Statement:
          - Action: s3:GetObject
            Effect: Allow
            Resource: !Sub arn:aws:s3:::${ProjectName}-${Environment}-${S3BucketName}-${AWS::AccountId}/*
            Principal:
              AWS: !Sub arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${CloudFrontOriginAccessIdentity}
```

</details>

## BucketName
こちらは名前のまま、バケット名を定義している
```
BucketName: !Sub ${ProjectName}-${Environment}-${S3BucketName}-${AWS::AccountId}
```
## OwnershipControls
```
      OwnershipControls:
        Rules:
          - ObjectOwnership: "BucketOwnerEnforced"
```
https://dev.classmethod.jp/articles/s3-bucket-owner-enforced/
https://dev.classmethod.jp/articles/s3-acl-error-from-202304/
バケットのすべてのオブジェクトのACLを『バケットを所有しているアカウント』のものとすることができるようです。現状はこれは書いておくべき項目のようです。
ACL(ネットワークアクセスコントロールリスト)についてですが、現在はバケットポリシーで十分であり、特殊な場合を除いてはACLは無効化することがAWSの公式より推奨されています。
(以下はバケット作成時の画面です)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185852/aaae45f1-4d27-b455-c518-ea388cdeef42.png)
**つまりこの記述によってACL無効化設定を行っています。**

terraformだとこんな感じの記述になるようです。
https://blog-benri-life.com/aws-terraform-s3-acl-disable/
## PublicAccessBlockConfiguration
```
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True
```
ブロックパブリックアクセスの設定です。
静的サイトとして公開するのになぜパブリックアクセスがブロックされるのか？と疑問に思ったのですが、あとの方でOrigin Access Identity(OAI)の設定をしているようでした。
簡単に言うとcloudfrontのみがs3の静的コンテンツのみにアクセスでき、ユーザーはcloudfront上からしかコンテンツにアクセスできない(s3へ直接ユーザーがコンテンツにアクセスできない)という設定です。
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html
> オリジンアクセスコントロール (OAC) を作成して設定する前に、Amazon S3 バケットオリジンを持つ CloudFront ディストリビューションが必要です。このオリジンは、ウェブサイトエンドポイントとして設定されたバケットではなく、通常の S3 バケットである必要があります

とあるように、用意するのは通常のs3バケットでよく、通常のs3バケットはパブリックアクセスをブロックする設定が望ましいのでこのようにしているようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185852/f59736b1-e1f7-5380-846e-3a0fa5dc4244.png)
## VersioningConfiguration
```
      VersioningConfiguration:
        Status: Enabled
```
バケットのバージョニングの設定です。
今回は有効になっていますが、静的コンテンツについてはgitで管理する、コストを掛けたくない自分には不要な設定かと思ったので、実際は無効化する予定です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185852/506d706c-98e5-bfd7-da07-0fb4905b775a.png)
## BucketEncryption
```
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: "AES256"
            BucketKeyEnabled: false
```
暗号化の設定です。
AES256だとSSE-S3を利用するようです。
BucketKeyEnabledについてはSSE-KMSの場合のオプションなので、SSE-S3の場合は無効にします。
SSE-S3については[こちら](https://blog.usize-tech.com/s3-encryption/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185852/2f4a401f-1e79-9973-a9a1-a2af41d11775.png)
## LifecycleConfiguration
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/lifecycle-configuration-examples.html
```
      LifecycleConfiguration:
        Rules:
          - Id: AbortIncompleteMultipartUpload
            AbortIncompleteMultipartUpload:
              DaysAfterInitiation: 7
            Status: "Enabled"
          - Id: NoncurrentVersionExpiration
            NoncurrentVersionExpiration:
              NewerNoncurrentVersions: 3
              NoncurrentDays: 1
            Status: Enabled
```
ライフサイクルの設定です。項目がいくつかあるのでそれぞれに付いて確認する。
```
      LifecycleConfiguration:
        Rules: #ライフサイクルルールであるという宣言
          - Id: AbortIncompleteMultipartUpload  #ルールのIDです
            AbortIncompleteMultipartUpload: #不完全なマルチパートアップロードを削除する
              DaysAfterInitiation: 7 #7日後
            Status: "Enabled"
          - Id: NoncurrentVersionExpiration
            NoncurrentVersionExpiration: #いくつまでバージョニングするか
              NewerNoncurrentVersions: 3 #3個のバージョニングを保持します
              NoncurrentDays: 1 #3バージョン以下のバーションは1日後に削除される
            Status: Enabled
```
コンソールだとバケットの「管理」タブのこの部分が該当
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185852/b22f05cc-8d53-6f92-3222-8837cfbca8ca.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185852/ce6fcf4a-9272-9d64-60cb-d90aa5fb3353.png)
## BucketPolicy
バケットポリシーの設定です。
```
  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Statement:
          - Action: s3:GetObject
            Effect: Allow
            Resource: !Sub arn:aws:s3:::${ProjectName}-${Environment}-${S3BucketName}-${AWS::AccountId}/*
            Principal:
              AWS: !Sub arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${CloudFrontOriginAccessIdentity}
```
この部分でOAIを定義しているようです。ここではgetのみ許可している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185852/c427e8c2-4e28-f978-5932-55d54342da6d.png)

# ここで問題が……
今までOrigin Access Identity(OAI)を利用する前提で書いていましたが、
現在はOrigin Access Control (OAC)という新機能が登場しており、OAIはレガシー扱いになっているようで、新規で作成する場合はOACを公式で推奨しているようです。
なので制作するサイトでもOACを利用したいと思います。
> ・セキュリティ – OAC は、短期間のクレデンシャル、頻繁なクレデンシャルのローテーション、およびリソースベースのポリシーのような強化されたセキュリティプラクティスで実装されています。これらは、ディストリビューションのセキュリティポスチャを強化し、混乱する代理のような攻撃に対してより良い保護を提供します。
・包括的な HTTP メソッドのサポート – OAC は GET、PUT、POST、PATCH、DELETE、OPTIONS、および HEAD をサポートしています。
・SSE-KMS – OAC は、SSE-KMS で暗号化された S3 オブジェクトのダウンロードとアップロードをサポートしています。
・すべての AWS リージョンでの S3 にアクセス – OAC は、既存のリージョンと将来のすべてのリージョンを含む、すべての AWS リージョンでの S3 へのアクセスをサポートしています。一方、OAI は既存の AWS リージョンと 2022 年 12 月までに開始されるリージョンでのみサポートされます。

https://aws.amazon.com/jp/blogs/news/amazon-cloudfront-introduces-origin-access-control-oac/
https://blog.serverworks.co.jp/cloudfront-oai-to-oac
https://dev.classmethod.jp/articles/amazon-cloudfront-origin-access-control/
https://qiita.com/hayao_k/items/8558042d52be4f29c6e6

# ハマったところとか
意外と要素それぞれについて解説しているサイトがなかった。
英語の公式を見る→Deeplで翻訳が結構早かった。

# 次にやること
- cloudfront/cloudforntログ保存用s3バケットのcfファイルの分解
- 必要なAWSのリソースをterraformで作成
- HUGOでHPをいい感じに編集する
- GitHub Actionsの設定