[update] Amazon CloudFrontのorigin request policyでblock list形式(“all except”)をサポートしました!

CloudFrontのorigin request policyで「指定したもの以外をオリジンリクエスト時に含める」という設定方法ができるようになりました。Host以外のすべてのheaderを含める、といった設定が簡単に実現できます。
2023.02.24

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

はじめに

清水です。AWSのCDNサービスであるAmazon CloudFrontでorigin request policyに「指定した以外のものすべて」というようなblock list形式での指定ができるようになるアップデートがありました。アップデート情報は本日(2023/02/24 17:00)時点でAmazon CloudFront Developer GuideDocument historyに記載されています。(2023/02/22付でのDocument更新でした。)

Document history - Amazon CloudFront

2020年7月にAmazon CloudFrontでサポートされたCache policyとOrigin request policy、これまでCache KeyのQuery stringsならびにCookiesでは「指定した以外のものすべて」という「All except」な指定が可能でした。Origin request policyでもこのような指定ができれば便利だし設定の手間も減るんだけど、という要望もあったかと思います。このたび、Origin request policyのHeaders、Query strings、Cookiesの3種の設定すべてで「All except」な設定ができるようになりました!

またあわせてmanaged origin request policyでこの「All except」な指定方法を使ったAllViewerExceptHostHeaderが選択できるようになっています。(上記、Document historyで本アップデートの下に記載されている項目がこのアップデートとなります。)こちらはそのpolicy名称の通り、Host header以外のHeadersのすべて、そしてすべてのQuery Strings、すべてのCookiesをオリジンリクエスト時に使用するpolicyとなっています。Amazon CloudFront Developer Guideによるとこのpolicyは、Amazon API GatewayおよびAWS Lambda function URLオリジンで利用することを想定されているとのことです。

これまでのOrigin request policyの設定方法とアップデート内容の確認

まずはOrigin request policyでの「All except」なblock list形式での指定ができる前の設定方法と、今回のアップデート内容である「All except」な設定方法をそれぞれ確認してみましょう。

Cache policyとOrigin request policyがサポートされた2022年7月のAWS Blogを確認してみます。

Origin request policyのHeadersの指定ではNoneWhitelistAll Viewer headers and whitelisted CloudFront-* Headers、そしてAll viewer headersのいずれかから選択する、というかたちでした。そしてQuery stringsとCookiesについては、AllNoneWhitelistのいずれかからの選択です。Whitelist形式でオリジンリクエスト時に含める内容を明示的に指定することはできていましたが、「指定したものを除いたすべて」というBlock list形式の指定はできなかったわけです。

Amazon CloudFront Announces Cache and Origin Request Policies | Networking & Content Delivery

なお、Origin request policyではなくCache policyのほうのCache keyについては、Query StringsとCookiesに対して、All-exceptとして「指定したものを除いたすべて」という指定がこのころから可能でした。

Amazon CloudFront Announces Cache and Origin Request Policies | Networking & Content Delivery

さて、今回のアップデートではOrigin request policyでAll-exceptな指定ができるようになったわけです。さっそくCloudFrontのマネジメントコンソール、Create origin request policy画面を確認してみましょう。Headers、Query strings、CookiesのいずれでもAll exceptな指定ができるようになっていますね!

Origin request policyでall exceptな指定をしてみる

マネジメントコンソールからOrigin request policyでAll exceptな指定ができるようになっていることが確認できました。続いて、実際にこの設定を行ったCloudFront Distributionを作成し、動作を確認してみましょう。

オリジンサーバの準備

まずはオリジンサーバの準備です。EC2上でApache HTTP Server + PHPが稼働する環境を準備しました。このEC2のPublic IPv4 DNSをCloudFrontのOrigin domainとして指定します。

EC2上では以下2つのパスで下記のコードを準備しました。オリジン側で受け取ったHeaders(含むCookies)、Query Stringsをレスポンスとして返すという内容です。

  • /origin-request-policy-all-except/all-check.php
  • /origin-request-policy-all-except/all-except-check.php
<?php
foreach (getallheaders() as $name => $value) {
    echo "$name: $value"."\n";
}
echo "Query-Strings: ".$_SERVER['QUERY_STRING']."\n";
?>

All exceptなorigin request policyの作成

続いて今回のアップデート内容All exceptを使ったOrigin request policyを作成します。以下の内容のpolicyとしました。

  • Headers
    • All viewer headers except
      • Host
  • Query strings
    • All query strings except
      • ref
  • Cookies
    • All cookies except
      • session_id

任意のNameとDescriptionを指定して、policyを作成します。

All exceptを使ったOrigin request policyが作成できました!

Distributionとbehaviorの作成

All exceptを使ったOrigin request policyが作成できました。続いてこのpolicyを使用するCloudFront Distributionを作成します。以下、Distribution作成のポイントとなる点のみスクリーンショットを掲示します。

Originは先ほど準備したEC2を使用します。Origin domainの項目でC2のPublic IPv4 DNSを指定します。

Default cache behavior(Default (*)では先ほど作成したAll exceptを使ったOrigin request policyは使わずmanaged policyのAllViewerAndCloudFrontHeaders-2022-06を指定しています。Cache policyはCachingDisabledとしました。

Distributionが作成できたら、default以外のbehaviorを1つ作成します。対象となるPath patternは以下です、先ほどオリジンとなるEC2に準備したファイルの1つですね。

  • Path pattern
    • /origin-request-policy-all-except/all-except-check.php

このPath patternに対し、先ほど作成したAll exceptを使ったOrigin request policyを設定します。 (ここでは名称がAllExceptTestというpolicyとなります。)またCache policyはCachingDisabledを選択しました。

Distributionならびに追加のbehaviorの設定ができました。

All exceptなorigin request policyの動作確認

それでは実際に、All exceptを指定したorigin request policyの動作を確認してみましょう。まずはこれを指定していないbehavior(Default cache behavior)となる以下のパスです。AllViewerAndCloudFrontHeaders-2022-06のorigin request policyが適用されます。Query StringsとCookiesも以下のように指定しました。

  • Path
    • /origin-request-policy-all-except/all-check.php
  • Query Strings
    • ref=0123abc&split-pages=false
  • Cookies
    • session_id=01234abcd

curlコマンドでCloudFrontにリクエストを行います。レスポンス内容でオリジン側が受けっとたリクエストの内容を確認しましょう。オリジン側ではQuery Strings、Cookiesのいずれも確認できていることがわかりますね。またHost headerはリクエストと同じcloudfront.netドメインとなっています、これもOrigin request policyでオリジンリクエストの際にそのまま使用するよう(オリジンに転送するよう)設定しているからですね。

% curl "https://d2vjxxxxxxxxxx.cloudfront.net/origin-request-policy-all-except/all-check.php?ref=0123abc&split-pages=false" --cookie "session_id=01234abcd"

Host: d2vjxxxxxxxxxx.cloudfront.net
User-Agent: curl/7.79.1
X-Amz-Cf-Id: EXmSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXJw==
Connection: Keep-Alive
Via: 2.0 b3f4xxxxxxxxxxxxxxxxxxxxxxxx8bd0.cloudfront.net (CloudFront)
Cookie: session_id=01234abcd
X-Forwarded-For: 2axx:xxxx:xxxx:xx::xx:x85
Accept: */*
CloudFront-Is-Mobile-Viewer: false
CloudFront-Is-Tablet-Viewer: false
CloudFront-Is-SmartTV-Viewer: false
CloudFront-Is-Desktop-Viewer: true
CloudFront-Is-IOS-Viewer: false
CloudFront-Is-Android-Viewer: false
CloudFront-Viewer-HTTP-Version: 2.0
CloudFront-Viewer-Country: JP
CloudFront-Viewer-Country-Name: Japan
CloudFront-Viewer-Country-Region: 13
CloudFront-Viewer-Country-Region-Name: Tokyo
CloudFront-Viewer-City: Tokyo
CloudFront-Viewer-Postal-Code: 102-0082
CloudFront-Viewer-Time-Zone: Asia/Tokyo
CloudFront-Viewer-Latitude: 35.68930
CloudFront-Viewer-Longitude: 139.68990
CloudFront-Forwarded-Proto: https
CloudFront-Viewer-Address: 2axx:xxxx:xxxx:xx::xx:x85:28xx4
CloudFront-Viewer-TLS: TLSv1.3:TLS_AES_128_GCM_SHA256:fullHandshake
Query-Strings: ref=0123abc&split-pages=false

続いて本題となる、All exceptなorigin request policyを指定したbehaviorにリクエストをして確認してみましょう。以下の内容でリクエストを行いました。(Pathからall exceptなorigin request policyを指定したbehaviorに振り分けられます。)

  • Path
    • /origin-request-policy-all-except/all-except-check.php
  • Query Strings
    • ref=0123abc&split-pages=false
  • Cookies
    • session_id=01234abcd

オリジン側で受けっとたリクエスト、Host headerについてはcloudfront.netドメインではなくOrigin domainで指定したEC2のPublic IPv4 DNSとなっていることがわかります。こちらはDeveloper Guideにも記載がありますが、Host headerを除外するよう設定した場合、CloudFront側で新たなHost headerとしてOrigin domainが使用されるという挙動となっています。またQuery Stringsについては指定したrefに該当するref=0123abcが除外されています。Cookieについてもsession_idに該当するsession_id=01234abcdがまるっと除外されていることがわかりますね。

% curl "https://d2vjxxxxxxxxxx.cloudfront.net/origin-request-policy-all-except/all-except-check.php?ref=0123abc&split-pages=false" --cookie "session_id=01234abcd"

Host: ec2-18-XXX-XXX-172.ap-northeast-1.compute.amazonaws.com
User-Agent: curl/7.79.1
X-Amz-Cf-Id: S0JmXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXhA==
Connection: Keep-Alive
Via: 2.0 af58xxxxxxxxxxxxxxxxxxxxxxxx6a10.cloudfront.net (CloudFront)
X-Forwarded-For: 2axx:xxxx:xxxx:xx::xx:x85
Accept: */*
CloudFront-Is-Mobile-Viewer: false
CloudFront-Is-Tablet-Viewer: false
CloudFront-Is-SmartTV-Viewer: false
CloudFront-Is-Desktop-Viewer: true
CloudFront-Is-IOS-Viewer: false
CloudFront-Is-Android-Viewer: false
CloudFront-Viewer-HTTP-Version: 2.0
CloudFront-Viewer-Country: JP
CloudFront-Viewer-Country-Name: Japan
CloudFront-Viewer-Country-Region: 13
CloudFront-Viewer-Country-Region-Name: Tokyo
CloudFront-Viewer-City: Tokyo
CloudFront-Viewer-Postal-Code: 102-0082
CloudFront-Viewer-Time-Zone: Asia/Tokyo
CloudFront-Viewer-Latitude: 35.68930
CloudFront-Viewer-Longitude: 139.68990
CloudFront-Forwarded-Proto: https
CloudFront-Viewer-Address: 2axx:xxxx:xxxx:xx::xx:x85:21xx2
CloudFront-Viewer-TLS: TLSv1.3:TLS_AES_128_GCM_SHA256:fullHandshake
Query-Strings: split-pages=false

さらに同じPath(All exceptなorigin request policyが適用されるPath)へのリクエストで、Query StringsとCookiesを追加してリクエストを行ってみます。

  • Path
    • /origin-request-policy-all-except/all-except-check.php
  • Query Strings
    • language=ja&ref=0123abc&split-pages=false
  • Cookies
    • cookie1=value1; session_id=01234abcd; cookie2=value2

追加したQuery StringsとCookiesの内容については、origin request policyでexceptとして指定はしていないので、オリジン側で確認ができます。またexceptとしてしていしたものは引き続きオリジン側では確認できません。またQuery Strings、Cookiesともに追加の際に、CloudFront側で除外対象となるものを真ん中になるよう指定してみたのですが、きれいに該当部分だけが除外されていることが確認できます。

% curl "https://d2vjxxxxxxxxxx.cloudfront.net/origin-request-policy-all-except/all-except-check.php?language=ja&ref=0123abc&split-pages=false" --cookie "cookie1=value1; session_id=01234abcd; cookie2=value2"

Host: ec2-18-XXX-XXX-172.ap-northeast-1.compute.amazonaws.com
User-Agent: curl/7.79.1
X-Amz-Cf-Id: gwf6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX2g==
Connection: Keep-Alive
Via: 2.0 9c65xxxxxxxxxxxxxxxxxxxxxxxxf86c.cloudfront.net (CloudFront)
Cookie: cookie1=value1; cookie2=value2
X-Forwarded-For: 2axx:xxxx:xxxx:xx::xx:x85
Accept: */*
CloudFront-Is-Mobile-Viewer: false
CloudFront-Is-Tablet-Viewer: false
CloudFront-Is-SmartTV-Viewer: false
CloudFront-Is-Desktop-Viewer: true
CloudFront-Is-IOS-Viewer: false
CloudFront-Is-Android-Viewer: false
CloudFront-Viewer-HTTP-Version: 2.0
CloudFront-Viewer-Country: JP
CloudFront-Viewer-Country-Name: Japan
CloudFront-Viewer-Country-Region: 13
CloudFront-Viewer-Country-Region-Name: Tokyo
CloudFront-Viewer-City: Tokyo
CloudFront-Viewer-Postal-Code: 102-0082
CloudFront-Viewer-Time-Zone: Asia/Tokyo
CloudFront-Viewer-Latitude: 35.68930
CloudFront-Viewer-Longitude: 139.68990
CloudFront-Forwarded-Proto: https
CloudFront-Viewer-Address: 2axx:xxxx:xxxx:xx::xx:x85:24xx0
CloudFront-Viewer-TLS: TLSv1.3:TLS_AES_128_GCM_SHA256:fullHandshake
Query-Strings: language=ja&split-pages=false

新たに追加されたManaged policy「AllViewerExceptHostHeader」も確認してみる

今回のアップデート内容であるorigin request policyでのAll exceptを使用したHeaders/Query Strings/Cookiesの指定について確認ができました。さてこのアップデートと同じタイミングで、Managedな Origin request policyにAllViewerExceptHostHeaderという名称のものが追加されていることを冒頭でもお伝えしました。このManaged policyについて、CloudFrontマネジメントコンソールから確認してみましょう。

「Policies > Origin request」を確認します。Managed policiesの一覧にAllViewerExceptHostHeaderが追加されていますね。

このManaged policy AllViewerExceptHostHeaderの詳細についても確認してみましょう。HeadersではAll viewer headers excepthostが指定されています。CookiesとQuery stringsはどちらもAllの設定です。

まとめ

Amazon CloudFrontのorigin request policyで「指定した以外のものすべて」というAll exceptなHeaders/Query Strings/Cookiesの指定ができるようになったアップデートについてお伝えしました。これまで事前に想定しうるパターンを列挙、それらをすべてWhitelistで指定すれば同様のことは実現できなくはなかったのかもしれませんが、block list形式で指定したいという場合のズバリ解決策になるアップデートかと思います。あわせてアップデートのあったManaged policy AllViewerExceptHostHeaderDeveloper Guide内の説明でもありましたが、オリジン側の要件としてHost headerにCloudFront domainではなくOrigin domainが必要、という要件に対しての解決策になる本アップデート、他のケースにも色々と活用できるのではないでしょうか。

おまけ: Twitterに投稿された本アップデートの情報

(2023/02/27追記)

今回のCloudFrontのアップデートについて、CloudFrontの製品開発者と思われる方からTwitterに投稿されたコメントを発見しました。

もともと本アップデートについてはTwitter上でのフィードバックが発端となっていたようです。改めてフィードバックの大切さを実感しますよね。

またこのアップデートにあわせてManaged policy AllViewerExceptHostHeaderほか、CloudFrontマネジメントコンソール上でも細かなアップデートがあったようです。以下、Tweetの引用で紹介したいと思います。

オリジンにAPI Gatewayなどを選択した場合に、デフォルトとなるCache policy/Origin request policyがそのオリジンに適したものになりました。このAPI Gatewayの例ではデフォルトのCache policyがCaching Disabledに、またOrigin request policyが今回のアップデートのあったAllViewerExceptHostHeaderとなっていますね。

さらに、オリジンに対して不適切となるpolicyについては選択不可となりましました。このAPI Gatewayの例では、Origin request policyについてAll ViewerはCloudFrontアクセス時のHost headerをオリジンリクエストの際にも利用してしまうので不適切です。(API Gatewayが正しく動作しません。)あらかじめマネジメントコンソール上でも選択不可となることで、不用意に設定してしまうことを防ぐことができますね。