【アップデート】Amazon CloudFront で Origin Access Control (OAC) が利用開始されました!

AWS

2022.8.26

Topics

おはようございます。Mr.oldtypeです。
基本的に夜行性の僕ですが、今週は妻に釣られ毎日6時半に起きてTHE TIME,を見ることが出来てます。すごいえらい。
んでたまたまTwitterを見てて下記アップデートを目撃しました。
Amazon CloudFront launches Origin Access Control (OAC)

OAC…?OAIの進化系…?もしやこれ神アップデートなのでは?と思いさっそく調べてみました。

OAI と何が違うのか

一番の変更点は「S3のサーバーサイド暗号化にカスタマー管理キーが使えるようになったこと」です。所謂SSE-KMSを施したS3オブジェクトをCloudFront経由で配信できるようになりました。
OAIでもSSE-S3を使ってオブジェクトの暗号化を行えてましたが、CloudTrailに複合証跡が残らないなどデメリットもありました。
これでより安心してS3を暗号化することが出来ます。

やってみた

リソースをつくります

まず今までと同じ要領でCloudFront+S3の環境を構築します。
terraformを使ってサクッと作りました。
cloudfront.tf

data "aws_cloudfront_origin_request_policy" "managed_allviewer" {
    name = "Managed-AllViewer"
}

data "aws_cloudfront_cache_policy" "CachingOptimized" {
    name = "Managed-CachingOptimized"
}
resource "aws_cloudfront_distribution" "distribution" {
    origin {
        domain_name = aws_s3_bucket.bucket.bucket_regional_domain_name
        origin_id   = aws_s3_bucket.bucket.id
        s3_origin_config {
        origin_access_identity = aws_cloudfront_origin_access_identity.oai.cloudfront_access_identity_path
        }
    }

    enabled = true

    default_root_object = "index.html"

    default_cache_behavior {
        allowed_methods        = ["GET", "HEAD"]
        cached_methods         = ["GET", "HEAD"]
        target_origin_id       = aws_s3_bucket.bucket.id
        cache_policy_id        = data.aws_cloudfront_cache_policy.CachingOptimized.id
        viewer_protocol_policy = "redirect-to-https"
    }

    restrictions {
        geo_restriction {
        restriction_type = "whitelist"
        locations        = ["JP"]
        }
    }
    viewer_certificate {
        cloudfront_default_certificate = true
    }
}

resource "aws_cloudfront_origin_access_identity" "oai" {}

s3.tf

resource "aws_s3_bucket" "bucket" {
    bucket = "${var.prj}-${var.env}-s3"
}
resource "aws_s3_bucket_acl" "bucket_acl" {
    bucket = aws_s3_bucket.bucket.bucket
    acl    = "private"
}

resource "aws_s3_bucket_policy" "bucket" {
    bucket = aws_s3_bucket.bucket.id
    policy = data.aws_iam_policy_document.oai.json
}

data "aws_iam_policy_document" "oai" {
    statement {
        sid    = "Allow CloudFront"
        effect = "Allow"
        principals {
    type        = "AWS"
    identifiers = [aws_cloudfront_origin_access_identity.oai.iam_arn]
    }
    actions = [
        "s3:GetObject"
        ]

    resources = [
        "${aws_s3_bucket.bucket.arn}/*"
        ]
    }
}

provider.tfとvariables.tfは省略します。

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.
できました。

コンソールで確認

CloudFrontのオリジンを編集から確認してみます。

OAIが設定されてました。うん?なんかLegacyとか書いてあって新しいrecommendedが生えてますね。こちらが今回のアップデートOACさんです。

最初は「コントロール設定を作成」からOACを作成します。

作成後「変更を保存」する前に(後でもいいですが)OAC用のバケットポリシーをコピーしてオリジンS3に貼り付けます。ここはまだ手動でやる必要があるみたいです。

バケットポリシーの更新が終わったらCloudFrontのディストリビューションドメイン名でアクセスしてみましょう。
OAIの時と同様問題なくアクセス出来てると思います。

SSE-KMSを試してみる

これだけだと面白くないので、SSE-KMSを使って暗号化したS3オリジンを使ってみましょう。
まずカスタマーマネージドキーを用意します。AWSマネージドキーではキーポリシーの編集が出来ないので、今回は使うことができません。
参考:AWS Key Management Service – キーの作成
この時、必ずキータイプは対象型を選択してください。S3は非対称キーをサポートしていないため、オブジェクトのアップロードが出来なくなります。
参考:Amazon Simple Storage Service – AWS Key Management Service (SSE-KMS) でサーバー側の暗号を使ってデータを保護します。

カスタマーCMKを作成したら、キーポリシーの編集を押し、CloudFrontサービスへアクセスを許可します。

{
    "Id": "key-consolepolicy-1",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::ACCOUNT_ID:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "Allow access for Key Administrators",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::ACCOUNT_ID:user/YOUR_IAM_USER"
            },
            "Action": [
                "kms:Create*",
                "kms:Describe*",
                "kms:Enable*",
                "kms:List*",
                "kms:Put*",
                "kms:Update*",
                "kms:Revoke*",
                "kms:Disable*",
                "kms:Get*",
                "kms:Delete*",
                "kms:TagResource",
                "kms:UntagResource",
                "kms:ScheduleKeyDeletion",
                "kms:CancelKeyDeletion"
            ],
            "Resource": "*"
        },
        {
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "cloudfront.amazonaws.com"
                ]
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:GenerateDataKey*"
            ],
            "Resource": "*"
            "Condition":{
                "StringEquals":{
                    "aws:SourceArn”: “arn:aws:cloudfront::ACCOUNT_ID:distribution/DISTRIBUTION_ID"
                }
            }
        }
    ]
}

Condition属性はなくても大丈夫ですが、あると任意のCloudFrontディストリビューションのみにアクセス許可が出来るのでよりセキュアです。

キーポリシーの編集が完了したら、S3のプロパティ画面で先ほどのカスタマーCMKのARNをコピペします。

完了したらオブジェクトを再度アップロードし、CloudFrontのディストリビューションドメイン名でアクセスしてみましょう。
OAIの場合は下記のようにAccessDeniedになってしまいますが…

OACにすることでページを表示することができました。

まとめ

OAIはもうレガシーとのことなので、これからはOACを使いましょう。

テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!

Mr.oldtype

クラウドを楽しくする、をテーマに活動しています。 2021/2022 APN Top Engineer。 でしょうね、ミスター・オールドタイプ。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら