CloudFront Origin Access Control(OAC)によるS3オリジン保護:OAIからの移行と推奨構成

目次

概要

Amazon CloudFrontを使用してS3バケットのコンテンツを配信する場合、S3バケットへの直接アクセスをブロックし、CloudFront経由のアクセスのみを許可する構成が求められます。この要件を実現するための仕組みとして、従来は Origin Access Identity(OAI)が使用されてきましたが、現在は後継の Origin Access Control(OAC) が推奨されています。

本記事では、OACがなぜ推奨されるのか、OAIとの技術的な違い、署名動作の選択肢、バケットポリシーの正しい構成、そしてOAIからOACへの移行パスについて解説します。OAIの基本的な概念については、S3とCloudFrontを使った静的サイトの公開:CloudFrontからのみアクセスする方法を参照してください。

OACを使用したCloudFront→S3のアクセス制御構成図(SigV4署名フロー含む)
OACを使用したCloudFront→S3のアクセス制御構成図(SigV4署名フロー含む)
クラウドおさる

S3 オリジンを CloudFront 経由だけに絞る仕組みを、レガシーの OAI ではなく後継の OAC で組み直して確かめる記事でござる。署名動作の選び方とバケットポリシーの書き方まで、順に見ていくのでござるな。

この記事のメリット

  • OAIとOACの機能差を比較表で正確に把握できる
  • OACが推奨される技術的理由(SigV4署名、全リージョン対応、SSE-KMS対応、動的リクエスト対応)を理解できる
  • OACの3つの署名動作オプションの使い分けを理解できる
  • OAC用のS3バケットポリシーの正しい記述方法を習得できる
  • CloudFrontディストリビューションIDをPrincipalに指定する方式やIAMユーザーを使用する方式が推奨されない理由を説明できる
  • OAIからOACへの移行手順を把握できる
  • SCS試験のCloudFrontオリジン保護に関する問いに正確に答えられるようになる

執筆者とキャラクター紹介

執筆者:土肥(とひ)

株式会社ジェニュインの代表であり元エンジニア。これまでオンプレミスと AWS 環境のインフラ業務を担当。AWS 認定資格の学習で得た知識を、ハンズオンとともに解説するのが得意。直近では新人の教育も行っており、これから技術を学ぶ方が納得できる解説を心がけています。基礎編・Cloud Practitioner の記事では、解説役としても登場します。

土肥

クラウドおさる

クラウドおさる

はじめましてでござる。弊猿はクラウドおさる。IT インフラが異常に発達した猿山から、雲に乗って地上の AWS を学びに降りてきたのでござる。

クラウドおさる

基礎編や Cloud Practitioner の記事では、とひさんに素朴な疑問をぶつける役でござるな。Security - Specialty などの記事では、要所でワンポイントや注意点をひとこと添えるでござる。

クラウドおさる

猿山にもデータセンターや監視当番があって、地上で起きることはだいたい猿山にも同じ仕組みがあるのでござる。例え話がつい猿山に寄るのは、弊猿の癖でござる。

技術解説

OAI(Origin Access Identity)の制限事項

OAIはCloudFront経由でのみS3バケットにアクセスさせる仕組みとして長年使用されてきましたが、以下の制限事項があります。

  • リージョンの制約: 2022年12月以降に追加されたAWSリージョンではOAIが使用できない
  • SSE-KMS非対応: AWS KMSで暗号化されたS3オブジェクトにアクセスできない
  • GETとHEADのみ対応: PUT、DELETE、PATCHなどの動的リクエストに対応していない
  • レガシーな仕組み: OAI は CloudFront が管理する特別なユーザー(オリジンアクセスアイデンティティ)をバケットポリシーの Principal に指定する方式で、現在は後継の OAC を使うことが推奨されている

これらの制限を解消するために、OACが導入されました。

OACとOAIの比較

項目OAI(Origin Access Identity)OAC(Origin Access Control)
認証の仕組みCloudFront が管理する特別なユーザー(OAI)を Principal に指定CloudFront がリクエストに SigV4 署名を付与
対応リージョン2022年12月以前のリージョンのみすべてのAWSリージョン
SSE-KMSサポート非対応対応
対応HTTPメソッドGET、HEADGET、HEAD に加えて PUT、DELETE などの動的リクエスト
バケットポリシーのPrincipalOAI固有のARNサービスプリンシパル(cloudfront.amazonaws.com)
アクセス制御の条件なしAWS:SourceArnでディストリビューションを特定
署名動作の設定なし3つのオプションから選択可能
対応オリジンタイプS3のみS3、MediaStore、MediaPackage v2、Lambda関数URL、VPCオリジン
ステータスレガシー(非推奨)推奨

OACが推奨される理由

新規構築でOACが推奨される主な理由は以下の通りです。

  • SigV4署名の使用: OACはAWS Signature Version 4(SigV4)を使用してリクエストに署名します。SigV4はAWSの標準的な認証方式であり、すべてのAWSリージョンで使用できます
  • SSE-KMS暗号化への対応: S3バケットにAWS KMS(aws:kms)で暗号化されたオブジェクトが格納されている場合でも、OACを通じてアクセスできます。OAIではKMS暗号化されたオブジェクトにアクセスできないため、別途対策が必要でした
  • 動的リクエストへの対応: OACはPUT、DELETEといったHTTPメソッドにも対応しており、S3へのファイルアップロードやオブジェクト削除をCloudFront経由で行う構成が実現できます
  • セキュリティの強化: AWS:SourceArn条件を使用して、特定のCloudFrontディストリビューションからのアクセスのみを許可できます。OAIでは条件による制約がなく、同一アカウント内の他のディストリビューションからもアクセスが可能でした
OAIとOACの認証フローの違いを示す比較図
OAIとOACの認証フローの違いを示す比較図

OACの署名動作オプション

OACを作成する際に、署名動作(Signing behavior)を選択できます。3つの値があり、ユースケースに応じて使い分けます。

API/CLI の値コンソールの表記説明ユースケース
always「署名リクエスト (推奨)」CloudFrontがオリジンへのすべてのリクエストに署名を付与するS3オリジンへのアクセスをCloudFront経由のみに制限する一般的なケース(推奨)
never「リクエストに署名しない」CloudFrontはリクエストに署名を付与しないオリジンが独自の認証を行う場合、またはパブリックアクセスが許可されたオリジンの場合
no-override「署名リクエスト (推奨)」+「認証ヘッダーを上書きしない」ビューワーのリクエストにAuthorizationヘッダーが含まれていない場合のみ署名を付与する。含まれている場合はそのまま転送するビューワーが独自の認証情報をオリジンに送信する必要がある場合

コンソールの「署名動作」はラジオボタン2つ(「リクエストに署名しない」「署名リクエスト (推奨)」)で表示され、no-override は「署名リクエスト (推奨)」を選んだうえで、その下の「認証ヘッダーを上書きしない」チェックボックスをオンにすることで指定します。

S3オリジンの保護を目的とする場合は、always(「署名リクエスト (推奨)」のみを選択した状態)を使用します。

クラウドおさる

S3 オリジンを守るなら署名動作は always、コンソールでは「署名リクエスト (推奨)」だけを選んだ状態でござる。no-override はビューワーの Authorization ヘッダーがあればそのまま転送するので、目的が違うのでござるな。

OAC用のS3バケットポリシー

OACを使用する場合、S3バケットポリシーではサービスプリンシパル cloudfront.amazonaws.com をPrincipalに指定し、AWS:SourceArn条件で特定のCloudFrontディストリビューションからのアクセスのみを許可します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipalReadOnly",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-bucket-name/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/EXXXXXXXXXX"
                }
            }
        }
    ]
}

ポイント:

  • Principalにサービスプリンシパルを指定することで、CloudFrontサービス全体を信頼します
  • AWS:SourceArn条件により、許可するCloudFrontディストリビューションを1つに特定します。この条件がないと、同一アカウント内のすべてのCloudFrontディストリビューションからアクセスが可能になってしまいます
  • PUTやDELETEも許可する場合は、Actionにs3:PutObjectやs3:DeleteObjectを追加します
クラウドおさる

AWS:SourceArn の条件を外すと、同じアカウント内のどのディストリビューションからでも読めてしまうのでござる。猿山のバナナ倉庫も「監視当番なら誰でも可」にしたら、よその持ち場の当番まで入れてしまうでござろう。ディストリビューションを 1 つに特定するまでがセットでござるぞ。

推奨されないアプローチとその理由

S3オリジンへのアクセスをCloudFront経由に制限する方法として、OAC以外のアプローチが検討されることがありますが、以下の理由から推奨されません。

CloudFrontディストリビューションIDをPrincipalに直接指定する方式

バケットポリシーでCloudFrontディストリビューションのARNをPrincipalとして直接指定する方法は、S3バケットポリシーではサポートされていません。PrincipalにはIAMユーザー、IAMロール、AWSアカウント、またはAWSサービスプリンシパルのみを指定できます。

IAMユーザーを作成してCloudFrontに認証情報を持たせる方式

IAMユーザーのアクセスキーをCloudFrontに設定してS3にアクセスする方法は、以下の問題があります。

  • アクセスキーの管理が必要になり、キーのローテーションを定期的に行う運用負荷が発生する
  • アクセスキーが漏洩した場合のセキュリティリスクが高い
  • CloudFrontにはIAMユーザーの認証情報を設定する仕組みが用意されていない

OACはこれらの課題をすべて解決し、AWSが推奨するマネージドな方式でS3オリジンを保護します。

OAIからOACへの移行パス

既存のCloudFrontディストリビューションでOAIを使用している場合、OACへの移行は以下の手順で行えます。移行中もダウンタイムは発生しません。

  1. OACを作成する: CloudFrontコンソールまたはAPIでOACを新規作成する
  2. ディストリビューションのオリジン設定を更新する: OAIからOACに切り替える
  3. S3バケットポリシーを更新する: OAI用のポリシー(OAIのARNをPrincipalに指定)を、OAC用のポリシー(サービスプリンシパルとAWS:SourceArn条件を使用)に変更する
  4. 動作確認: CloudFront経由でのアクセスが正常に動作することを確認する
  5. OAIを削除する: 移行が完了したら、不要になったOAIを削除する

移行時の注意点として、S3バケットポリシーの更新とディストリビューションの設定変更を同時に行うことが推奨されます。バケットポリシーのみを先に更新すると、OAI経由のアクセスが失敗する可能性があります。移行期間中は、OAI用とOAC用の両方のステートメントをバケットポリシーに記述しておくことで、安全に移行できます。

フリーランス案件
クラウドおさる
クラウドキャリアフリーランス

AWS の実務経験があるなら、単価を上げにいく

AWS に特化したフリーランスエージェントです。以下は取り扱い案件の一例です。設計・SRE・セキュリティ・生成 AI の領域で、専門を掛け合わせるほど単価が上がります。

横にスクロールできます。掲載時点の情報のため、募集が終了している場合があります。条件の近い案件をご紹介しますので、お気軽にご相談ください。

実践

前提条件

以下のリソースが作成済みであること。

リソース種別リソース名用途
S3バケットoac-demo-bucket-<アカウントID>CloudFrontのオリジンとなる静的コンテンツ格納用

S3バケットには、動作確認用のHTMLファイル(index.html)がアップロードされていることを前提とします。index.htmlの内容は任意ですが、以下のような簡易的な内容で構いません。

<!DOCTYPE html>
<html>
<head><title>OAC Demo</title></head>
<body><h1>CloudFront OAC Demo Page</h1></body>
</html>

S3バケットの「ブロックパブリックアクセス」設定は、すべてのオプションが有効(ブロック)の状態にしておきます。

OACの作成

AWSマネジメントコンソールにログインし、リージョンが ap-northeast-1(東京)であることを確認します(CloudFront はグローバルサービスですが、オリジンとなるS3バケットは東京リージョンに作成しています)。

上部の検索バーに CloudFront と入力し、表示された「CloudFront」を選択します。

左側ナビゲーションの「オリジンアクセス」を選択します。

「コントロール設定を作成」をクリックすると、「コントロール設定を作成」ダイアログが開きます。以下の内容を入力します。

  • 名前: oac-demo-s3-access
  • 説明 – オプション: OAC demo for S3 origin protection
  • 署名動作: 署名リクエスト (推奨)(「認証ヘッダーを上書きしない」チェックボックスはオフのままにします)
  • オリジンタイプ: S3
  • 「Use SigV4a signing protocol」はオフのままにします
OACの作成ダイアログ(名前、署名動作、オリジンタイプの入力内容)
OACの作成ダイアログ(名前、署名動作、オリジンタイプの入力内容)

「Create」をクリックします。

OACが作成され、一覧に表示されることを確認します。

CloudFrontディストリビューションの作成

左側ナビゲーションの「ディストリビューション」を選択し、「ディストリビューションを作成」をクリックします。

ディストリビューションの作成は5つのステップに分かれています。

ステップ1「Choose a plan」では、料金プランを選択します。ここでは従量課金の「Pay as you go」を選択し、「Next」をクリックします(月額固定のプランはWAFやDNSなどをまとめた有料プランです)。

ステップ2「Get started」では、ディストリビューション名に oac-demo と入力し、「Next」をクリックします。

ステップ3「Specify origin」では、オリジンとセキュリティ保護の設定を行います。

  • S3 origin: oac-demo-bucket-<アカウントID>.s3.ap-northeast-1.amazonaws.com(「Browse S3」からバケットを選択できます)
  • Origin path – optional: 空欄のままにします
  • 「Allow private S3 bucket access to CloudFront – Recommended」にチェックを入れます
  • オリジン設定: Use recommended origin settings
  • キャッシュ設定: デフォルトのままにします
ディストリビューション作成のオリジン設定画面(S3オリジンとプライベートアクセス許可の指定)
ディストリビューション作成のオリジン設定画面(S3オリジンとプライベートアクセス許可の指定)

現在の作成ウィザードには、既存のOACを選択する項目がありません。「Allow private S3 bucket access to CloudFront」にチェックを入れると、CloudFrontがこのディストリビューション専用のOACを自動作成し、S3バケットポリシーも自動で書き込みます。先ほど作成した oac-demo-s3-access に切り替える手順は、後述の「オリジンのOACを差し替える」で行います。

「Next」をクリックします。

ステップ4「Enable security」では、AWS WAF によるセキュリティ保護の有効化を選択します。ここでは「セキュリティ保護を有効にしないでください」を選択し、「Next」をクリックします(WAFを有効にすると追加料金が発生します)。

ステップ5「Review and create」で設定内容を確認し、「ディストリビューションを作成」をクリックします。

作成が完了すると、「新しいディストリビューションが正常に作成されました。」というメッセージとともに詳細画面が表示されます。「ディストリビューションドメイン名」(例: d1234567890abc.cloudfront.net)をメモしておきます。

ディストリビューション作成完了画面(ディストリビューションドメイン名が確認できる状態)
ディストリビューション作成完了画面(ディストリビューションドメイン名が確認できる状態)

オリジンのOACを差し替える

ウィザードが自動作成したOACを、先ほど作成した oac-demo-s3-access に差し替えます。

ディストリビューションの詳細画面で「オリジン」タブを選択します。

オリジンの一覧から oac-demo-bucket-<アカウントID>.s3.ap-northeast-1.amazonaws.com の行を選択し、「編集」をクリックします。

「オリジンアクセス」で以下を確認・設定します。

  • オリジンアクセス: Origin access control settings (recommended) が選択されていること
  • Origin access control: ドロップダウンから oac-demo-s3-access を選択します
オリジン編集画面(Origin access control で作成済みのOACを選択した状態)
オリジン編集画面(Origin access control で作成済みのOACを選択した状態)

画面下部の青いメッセージにある「ポリシーをコピー」をクリックすると、このディストリビューションからのアクセスだけを許可するバケットポリシーをコピーできます(S3バケットポリシーがまだ設定されていない場合に使用します)。

「変更を保存」をクリックします。

デフォルトルートオブジェクトを設定する

ルートURL(/)へのアクセスで index.html を返すように、デフォルトルートオブジェクトを設定します。

ディストリビューションの詳細画面で「一般」タブを選択し、「設定」セクションの「編集」をクリックします。

  • Default root object – optional: index.html
  • Price class: Use only North America and Europe(コスト削減のため)
  • その他の項目はデフォルトのままにします

「変更を保存」をクリックします。

S3バケットポリシーを確認する

ディストリビューション作成時に「Allow private S3 bucket access to CloudFront」を有効にしたため、S3バケットポリシーはCloudFrontによって自動的に設定されています。内容を確認します。

上部の検索バーに S3 と入力し、表示された「S3」を選択します。

バケット一覧から oac-demo-bucket-<アカウントID> を選択します。

「アクセス許可」タブを選択します。

「バケットポリシー」セクションに、以下のようなポリシーが設定されていることを確認します。

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::oac-demo-bucket-<アカウントID>/*",
            "Condition": {
                "ArnLike": {
                    "AWS:SourceArn": "arn:aws:cloudfront::<アカウントID>:distribution/<ディストリビューションID>"
                }
            }
        }
    ]
}
S3バケットポリシー(CloudFrontが自動設定したOAC用ポリシー)
S3バケットポリシー(CloudFrontが自動設定したOAC用ポリシー)

Principal にサービスプリンシパル cloudfront.amazonaws.com が、Condition に AWS:SourceArn によるディストリビューションの指定が入っている点を確認します。ポリシーが設定されていない場合は、「編集」から上記の内容(またはオリジン編集画面でコピーしたポリシー)を貼り付けて「変更の保存」をクリックします。

このポリシーは対象をディストリビューションのARNで絞っており、OAC のIDは含まれません。そのため、前の手順でOACを差し替えてもバケットポリシーを書き換える必要はありません。

>

なお、技術解説で示したポリシー例では条件演算子に StringEquals を使っていますが、コンソールが自動生成するポリシーは ArnLike を使います。ARNを完全一致で指定する場合はどちらでも同じ結果になります。

クラウドおさる

バケットポリシーはディストリビューションの ARN で絞っていて、OAC の ID は入っていないのでござる。だから OAC を差し替えても、ポリシーを書き換えずに済んだのでござるな。

動作確認:CloudFront経由のアクセス

ディストリビューションのステータスが「デプロイ済み」になったことを確認します。デプロイには数分かかります。

ブラウザで CloudFront のドメイン名にアクセスします。

https://d1234567890abc.cloudfront.net/

index.htmlの内容が正常に表示されることを確認します。

CloudFront経由でアクセスした際のブラウザ画面(index.htmlの内容が表示されている状態)
CloudFront経由でアクセスした際のブラウザ画面(index.htmlの内容が表示されている状態)

動作確認:S3への直接アクセスがブロックされること

S3バケットのオブジェクトURLに直接アクセスし、アクセスが拒否されることを確認します。

ブラウザで以下のURLにアクセスします。

https://oac-demo-bucket-<アカウントID>.s3.ap-northeast-1.amazonaws.com/index.html

以下のようなAccessDeniedエラーが表示されることを確認します。

<Error>
  <Code>AccessDenied</Code>
  <Message>Access Denied</Message>
  <RequestId>...</RequestId>
  <HostId>...</HostId>
</Error>
S3への直接アクセス時のAccessDeniedエラー画面
S3への直接アクセス時のAccessDeniedエラー画面

これにより、S3バケットへの直接アクセスがブロックされ、CloudFront経由でのみコンテンツにアクセスできることが確認できます。

クラウドおさる

OAI と OAC の機能差、とくに SSE-KMS や PUT・DELETE への対応と、バケットポリシーの Principal に何を書くかが問われる観点でござる。ディストリビューション ID を Principal に書く方式や、IAM ユーザーのキーを持たせる方式と取り違えぬよう気をつけるのでござる。

まとめ

  • OACはOAIの後継であり、新規構築ではOACの使用が推奨されています
  • OACはSigV4署名を使用し、すべてのAWSリージョン、SSE-KMS暗号化、PUT/DELETEなどの動的リクエストに対応しています
  • OACの署名動作は3つの値(always / never / no-override)から選択でき、S3オリジン保護にはalways(コンソールの「署名リクエスト (推奨)」)を使用します
  • バケットポリシーでは、サービスプリンシパル cloudfront.amazonaws.com をPrincipalに指定し、AWS:SourceArn条件で特定のディストリビューションからのアクセスのみを許可します
  • CloudFrontディストリビューションIDをPrincipalに指定する方式やIAMユーザーの認証情報を使用する方式は推奨されません
  • OAIからOACへの移行はダウンタイムなしで行え、移行期間中は両方のポリシーを並存させることで安全に切り替えられます

参照先

フリーランス案件
クラウドおさる
クラウドキャリアフリーランス

AWS の実務経験があるなら、単価を上げにいく

AWS に特化したフリーランスエージェントです。以下は取り扱い案件の一例です。設計・SRE・セキュリティ・生成 AI の領域で、専門を掛け合わせるほど単価が上がります。

横にスクロールできます。掲載時点の情報のため、募集が終了している場合があります。条件の近い案件をご紹介しますので、お気軽にご相談ください。

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

株式会社ジェニュイン(https://genuine-pt.jp)の代表取締役.

2018年〜インフラエンジニアとしてキャリアをスタートし、オンプレミスのネットワーク・サーバ環境で3年半、クラウド環境で4年半の8年間エンジニアとして従事。
2021年に佐藤氏の創業した株式会社Luxyを引き継ぎ、代表に就任。
その後アガルートグループ内の株式会社ジェニュインと合併。
合併後同社代表に就任。

目次