Origin Access Control(OAC)
S3のオブジェクトをCloudFrontで配信する方法の1つ。
S3を非公開設定にしてCloudFrontからのみアクセスできるようにする。
設定方法
S3バケットの作成
S3バケットを作成する。aws_s3_bucket_public_access_blockで各ブロック設定をonにする。
resource "aws_s3_bucket" "example" {
  bucket = "example-bucket"
}
resource "aws_s3_bucket_public_access_block" "example" {
  bucket = aws_s3_bucket.example.id
  # 非公開設定
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}
applyするとS3のブロック設定は以下のようになる。

CloudFront オリジンアクセスコントロールの作成
OACを作成する。
resource "aws_cloudfront_origin_access_control" "front" {
  name                              = aws_s3_bucket.example.bucket
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}
nameは適宜わかりやすい名前をつける。上記の例ではバケット名を指定している。
origin_access_control_origin_typeにはs3を指定する。
applyするとオリジンアクセスコントロールの設定は以下のようになる。

CloudFrontディストリビューションの作成
CloudFrontディストリビューションを作成する。
resource "aws_cloudfront_distribution" "example" {
  # (省略)
  origin {
    domain_name              = "${aws_s3_bucket.example.bucket}.s3.ap-northeast-1.amazonaws.com"
    origin_id                = "${aws_s3_bucket.example.bucket}.s3.ap-northeast-1.amazonaws.com"
    # OAC の設定
    origin_access_control_id = aws_cloudfront_origin_access_control.front.id
  }
  # (省略)
}
originのorigin_access_control_idには先ほど作成したOACのIDを指定する。
applyするとCloudFrontディストリビューションの設定は以下のようになる。

上記設定はCloudFrontのディストリビューションのオリジン設定の編集画面で確認できる。
S3バケットポリシーの設定
S3バケット側にOACを受け入れるためのバケットポリシーを設定する。
resource "aws_s3_bucket_policy" "front_oac" {
  bucket = aws_s3_bucket.example.bucket
  policy = data.aws_iam_policy_document.example_oac.json
}
data "aws_iam_policy_document" "example_oac" {
  statement {
    principals {
      type        = "Service"
      identifiers = ["cloudfront.amazonaws.com"]
    }
    actions   = ["s3:GetObject"]
    resources = ["${aws_s3_bucket.example.arn}/*"]
    condition {
      test     = "StringEquals"
      variable = "aws:SourceArn"
      values = [aws_cloudfront_distribution.example.arn]
    }
  }
}
バケット内のオブジェクトに対するGetObjectアクションをCloudFrontからのみ許可するように設定する。
principalにはcloudfront.amazonaws.comを指定する。
conditionにはaws:SourceArnを指定し、値には先ほど作成したCloudFrontディストリビューションのARNを指定する。
\手を動かしながらTerraformを学びたい人にオススメ!/

