話題の記事

[NEW] CloudFrontからS3への新たなアクセス制御方法としてOrigin Access Control (OAC)が発表されました!

CloudFrontからS3へのアクセス制限として従来のOAIに加えて、新たにOACが利用可能になりました。セキュリティが強化されSSE-KMSなどのサポートが行われています。OAIも引き続き利用可能ですが、今後はOACを使用しましょう。
2022.08.26

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

清水です。今朝(日本時間2022/08/26、現地時間2022/08/25)のアップデートでAWSのCDNサービスであるAmazon CloudFrontにOrigin Access Control (OAC)という機能が追加されました。CloudFrontからオブジェクトストレージサービスAmazon S3へのアクセス制限を行う新たな方法となります。これまでもOrigin Access Identity (OAI)という機能が利用できましたが、S3側のSSE-KMSに対応していないなどいくつか制限事項がありました。この制限事項をカバーし、よりきめ細やかなポリシーを行えるよう機能強化されたものがOACとなります。

このOACの発表とあわせて、CloudFront Developer Guide上ではこれまでのOAIによるアクセス制限方法は「legacy, not recommended」と記載されるようになりました。OAI自体がすぐに利用できなくなるということではありませんが、これからS3へのアクセス制限を実施する場合には新しいアクセス制限方法であるOACを使うのがよいでしょう。

本エントリでは、OAIの制限とOACで実現可能になったこと、またOACの利用方法について速報として簡単にまとめてみたいと思います。

OAIの制限事項とOACでの機能強化

まずはOAI (Origin Access Identity)とその制限事項について確認しておきましょう。Amazon S3をオリジンとしてCloudFrontを利用する場合に、S3へのアクセス制御の方法として利用することができます。

CloudFront側ではオリジンごとに利用するOAIを指定し、S3側ではバケットポリシーでそのOAIに対して読み取りや書き込みを許可する、というぐあいでした。このOAIを使うことで、S3バケットをパブリックアクセス可能にすることなく、CloudFrontからのアクセスのみを許可するということが可能です。CloudFrontからS3へのアクセス制限を行う場合には必須機能であるOAIですが、S3バケット側でAWS Key Management Service (AWS KMS)を使った暗号化、SSE-KMSを使用した場合に使用できない(対応していない)という制限がありました。

またAWS Signature Version 4 (SigV4)のみをサポートするリージョンのS3 *1 に対しては、PUTリクエストでのオブジェクトアップロード時にx-amz-content-sha256ヘッダを追加する必要があり、またPOSTリクエストがサポートされていない、という制限もありました。

新たに利用可能になったOAC (Origin Access Control)では、まずこれら2つの制限のサポートが行われています。SSE-KMSで暗号化されているS3バケットに対してもダウンロード、アップロードができるようになりました。またすべてのリージョンのS3バケット(もちろんSigV4のみ対応リージョンを含みます)に対して、POSTやPUTを含むリクエストが可能です。

セキュリティ体制についても強化され、短期間の資格情報とより頻繁な資格情報のローテーションがサポートされており、混乱した代理攻撃に対してより優れた保護が提供されているとのことです。

従来のOAIも引き続き利用可能ですが、2022年12月以降に新たに開設されるAWSリージョンではOACのみのサポートとなるようです。注意しておきましょう。

OACを使ってみる

シンプルにS3へのアクセス制限を行うパターン

それでは実際に新しいS3へのアクセス制限機能、OAC (Origin Access Control)を使用してみたいと思います。まずはシンプルなパターンとして、S3オリジンへのGETアクセスを行うケースです。これまでもOAI (Origin Access Identity)で実現可能でした。OAC利用の場合でも、OAIのときと比べてそれほど大きな違いはありません。

まずはS3バケットを作成します。ACLは無効にし、またBlock Public Accessはすべて有効にしました。暗号化はなしでS3バケットを作成します。

続いて、CloudFront側でこのS3バケットをオリジンとしてDistributionを作成します。Origin設定のOrigin accessの項目で「Origin access control settings」を選択します。[Create control settings]ボタンで新たなOACを作成します。

作成したOACを使って、CloudFront Distributionを作成します。

作成後の画面です。S3バケット側のポリシーを更新するよう促されます。ここで[Copy policy]のリンクをクリックするとクリップボードにポリシー例がコピーされます。また[Go to S3 bucket permissions to update policy]のリンクで、該当S3バケットのポリシー編集画面に遷移します。

遷移先のS3バケットPermissions画面、Bucket policyを[Edit]ボタンから変更します。内容は先ほどクリップボードにコピーされたものをそのまま利用しました。

以下が実際のバケットポリシーの内容です。CloudFrontのService Principal cloudfront.amazonaws.comを使用するなど、OAIのときと比べて少し違っていますね。

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::cloudfront-origin-access-control-test/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E1XXXXXXXXXXD4"
                }
            }
        }
    ]
}

参考として、OAIを使用したときのバケットポリシー例が以下です。(Developer Guide記載の例となります。)なおDeveloper Guideには、OAIからOACへの移行についても案内があります。

{
    "Version": "2012-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EH1HDMB1FH2TC"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
        }
    ]
}

さて、OACの設定としては以上で完了です。試しにS3バケット直下にcloudfront-origin-access-control-test.htmlというファイルを配置し、CloudFront経由でアクセスしてみました。問題なく参照できています、つまりCloudFrontからS3へのアクセスの際にOACが使われている、ということになります。(バケットポリシーの内容の通り、S3への直接のアクセスなどは拒否されます。)

SSE-KMS暗号化しているS3にアクセスするパターン

OACの基本的な使い方が確認できました。続いてOAC使用するにあたり明示的なメリットの1つであるSSE-KMS対応についても確認してみましょう。

まずはSSE-KMSで暗号化されたS3バケットを作成します。KMS CMKを作成するところから進めましょう。以下設定でCMKを作成しました。

続いてS3バケットを作成します。ACLは無効にし、またBlock Public Accessはすべて有効にしました。暗号化の設定でSSE-KMSによる暗号化を選択、KMS Keyは先ほど作成したものを選択します。

S3バケットを作成したら、続いてCloudFrontのマネジメントコンソールに移動しましょう。先ほどはDistribution作成時にOACを作成しましたが、個別にOACを作成してみましょう。Securityの項目のOrigin accessに進みます。Control settingsの[Create control settings]ボタンから作成画面に進み、必要事項を入力してCreateします。

ついでCloudFront Distributionを作成します。オリジンは先ほど作成した、SSE-KMSを有効にしたS3バケットです。Origin accessの項目でOrigin access control settingsを選択、作成したOACを選びます。

CloudFront Distribution作成後、先ほどと同じようにオリジンとなるS3バケットのバケットポリシーを更新します。

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::cloudfront-origin-access-control-sse-kms-test/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E1XXXXXXXXXXP1"
                }
            }
        }
    ]
}

S3バケットでSSE-KMSの暗号化を行っている場合は、ここからさらにKMS CMK側の権限変更が必要です。マネジメントコンソールの該当CMKのKey policyで以下を追加します。

        {
            "Sid": "AllowCloudFrontServicePrincipalSSE-KMS",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:root",
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": [
                "kms:Decrypt",
                "kms:Encrypt",
                "kms:GenerateDataKey*"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E1XXXXXXXXXXP1"
                }
            }
        }

最終的にKey policyは以下のようになりました。

{
    "Version": "2012-10-17",
    "Id": "key-consolepolicy-3",
    "Statement": [
        {
            "Sid": "Enable IAM User Permissions",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:root"
            },
            "Action": "kms:*",
            "Resource": "*"
        },
        {
            "Sid": "AllowCloudFrontServicePrincipalSSE-KMS",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789012:root",
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": [
                "kms:Decrypt",
                "kms:Encrypt",
                "kms:GenerateDataKey*"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E1XXXXXXXXXXP1"
                }
            }
        }
    ]
}

以上、(1) CloudFront側Origin設定でのOACの使用、(2) S3バケットポリシーでOACを使用しているCloudFront DistributionにS3バケット内オブジェクトの読み込みを許可、(3) KMSのKey policyでOACを使用しているるCloudFront Distributionにアクセス許可を追加、の3点を行います。この設定をしたあと、CloudFront経由でS3バケットにアップロードしたオブジェクトにアクセスしてみましょう。cloudfront-origin-access-control-sse-kms-test.htmlというファイルをアップロードしておきました。問題なくアクセスができましたね!

まとめ

Amazon CloudFrontでサポートされた、新たなS3へのアクセス制限機能、Origin Access Control (OAC)について速報としてお伝えしました。従来までのOrigin Access Identity (OAI)と比べた場合のOACの利点として、

  • SSE-KMSを使用して暗号化されているS3バケットのサポート
  • SigV4のみ対応のリージョンを含めたS3への動的リクエスト(POST, PUT)のサポート
  • 今後(2022年12月以降に)開設されるAWSリージョンを含めたすべてのリージョンでのサポート
  • 強化されたセキュリティ実装

といった点が挙げられます。OAIも引き続き利用可能ですが(ただし、2022年12月以降に新たに開設されるAWSリージョンではOACのみサポート)、セキュリティ面の強化もありますので、新たにCloudFrontからS3へのアクセス制限を行う場合にはOAC (origin Access Control)を使用していきましょう。

脚注

  1. 古くからあるリージョンではなく、比較的新しく作られたリージョンが対象です。身近なところだと大阪リージョンが該当します。詳細は「Amazon Simple Storage Service エンドポイントとクォータ - AWS 全般のリファレンス」を参照ください。