CloudFront のオリジンに別アカウントの CloudFront を設定する方法を検証してみた
こんにちは、岩城です。
CloudFront のオリジンに別アカウントの CloudFront を設定できるか検証する機会がありました。
ドキュメントを確認しても別の CloudFront をオリジンにする記載を見つけることができなかったので、実際に検証してみました。
検証の結果、CloudFront のオリジンに別アカウントの CloudFront を設定できることを確認しました。試した結果を共有したいと思います。
検証環境の構成
アカウント A にある CloudFront A のオリジンに、アカウント B にある CloudFront B を指定します。
CloudFront A はオリジンの指定以外はすべてデフォルトの設定です。代替ドメインは使用していません。
CloudFront B のオリジンには ALB を指定し、ALB は Nginx を起動する EC2 をターゲットに指定しました。
アカウント B の CloudFront、ALB、EC2 は特別なことをしていないので説明を割愛します。
ポイントは CloudFront A のキャッシュポリシーとオリジンリクエストポリシーを設定し、CloudFront B へのリクエスト時に Host ヘッダーを含めないようにすることです。
やってみた
アカウント A の CloudFront A にアカウント B の CloudFront B をオリジンに設定する場合、ディストリビューション ID で指定できないので CloudFront B のドメイン名を指定します。
デフォルトでは、キャッシュポリシーとオリジンリクエストポリシーがそれぞれ以下のように設定されます。
- キャッシュポリシー:
UseOriginCacheControlHeaders
- キャッシュキーに以下のヘッダーを含める
- Host
- Origin
- X-HTTP-Method-Override
- X-HTTP-Method
- X-Method-Override
- キャッシュキーに以下のヘッダーを含める
- オリジンリクエストポリシー:
Managed-AllViewer
- オリジンリクエスト時にビューワーリクエスト内のすべてのヘッダーを含める
この状態でリクエストしても 403 エラーが返ってきました。
$ curl https://dtocrgw3etyhb.cloudfront.net
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>403 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Bad request.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
<BR clear="all">
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: 8Il-pZ4nEly9PEhkOQ241jEp-g3neO6ty0PnEyFFZEvNC0wTqVFlXg==
</PRE>
<ADDRESS>
</ADDRESS>
</BODY></HTML>% H
どうやらデフォルトの設定では CloudFront がエラーを返すようです。
いろいろ検証していく中で、CloudFront B へのリクエストの際に Host ヘッダーを含めなければ 403 エラーを回避できることが分かりました。
ここからは Host ヘッダーを含めないようにキャッシュポリシーとオリジンリクエストポリシーを設定していきます。
今回の検証環境では UseOriginCacheControlHeaders
を利用しているので、Host ヘッダーを含めないようにしたいです。
そこで Host ヘッダーだけ除外するように、カスタムキャッシュポリシーを作成します。
作成したカスタムキャッシュポリシーをビヘイビアに設定します。
本エントリでは Nginx の Welcome ページを表示するだけなので、デフォルトのビヘイビアに設定します。
キャッシュポリシーに作成したカスタムキャッシュポリシーを設定します。
この設定だけで問題ないと思っていましたが、まだ 403 エラーが返ってきます。
$ curl https://dtocrgw3etyhb.cloudfront.net -I
HTTP/2 403
content-type: text/html
content-length: 915
server: CloudFront
date: Fri, 31 Jan 2025 04:44:49 GMT
x-amz-cf-pop: NRT20-P3
x-amz-cf-pop: NRT20-P3
via: 1.1 9f3afcae73a1e7f65d5fe03eb566d7b8.cloudfront.net (CloudFront), 1.1 fd9db9ca6ccd98e08f5755e952dfb2e4.cloudfront.net (CloudFront), 1.1 1b2ec020d55b8b35f77724dc49853982.cloudfront.net (CloudFront)
x-cache: Error from cloudfront
x-amz-cf-pop: NRT57-P2
x-amz-cf-id: 75xVgsDbiY28s3HkqjC-pn1-fANDn188RTlzuuAMuMm1_iU_O4Sg1w==
そこでオリジンリクエストポリシーに AllViewerExceptHostHeader
を設定して、オリジンリクエストから Host ヘッダーを除外します。
再度 CloudFront A にアクセスするとレスポンスコード 200 が返ってきて
$ curl https://dtocrgw3etyhb.cloudfront.net -I
HTTP/2 200
content-type: text/html
content-length: 615
date: Fri, 31 Jan 2025 04:45:57 GMT
server: nginx/1.22.1
last-modified: Tue, 27 Aug 2024 13:55:08 GMT
etag: "66cddabc-267"
accept-ranges: bytes
x-amz-cf-pop: NRT20-P3
via: 1.1 72b6df55f745a3c5200761c1287f682e.cloudfront.net (CloudFront), 1.1 49b964f897a5e1c9f9d0e182630ef7ca.cloudfront.net (CloudFront)
x-cache: Miss from cloudfront
x-amz-cf-pop: NRT57-P2
x-amz-cf-id: idup61Joej5NQvrDVYNdlSjRnsIVp4_n37nkoVrFj7j4CgYB8mNryQ==
アカウント A の CloudFront A からアカウント B の CloudFront B を経由して、Nginx の Welcome ページを表示できることを確認しました。
おわりに
UseOriginCacheControlHeaders
と AllViewerExceptHostHeader
を併用することで、403 エラーを回避できることを確認しました。
そもそも、CloudFront のオリジンに CloudFront を指定できることや、オリジンリクエストの際に Host ヘッダーを除外するなど、ドキュメントに記載がないので本番利用の際は、十分に検証のうえ導入をご検討ください。
本エントリがどなたかのお役に立てれば幸いです。