Amazon CloudFront署名付きURLとオリジンのクエリ文字列を併用する

CloudFront署名付きURLでアクセス制限しつつ、オリジンにクエリ文字列を渡す構成を検証しました
2023.10.17

ども、大瀧です。

CloudFrontの署名付きURLは、アクセス制限の仕組みとして有効期限付きのURLを発行する機能です。署名付きURLの署名はクエリ文字列に付与する形式のため、本ブログではオリジンにクエリ文字列を渡す構成と併用できるのか試してみた結果を共有します。

署名付きURLとクエリ文字列の併用

結論から言うと、署名付きURLとオリジンに渡すクエリ文字列は併用できますが、署名付きURLのポリシー周りについていくつか注意点があります。

既定ポリシーとカスタムポリシー

CloudFrontの署名付きURLは2種類の形式があり、それぞれ既定ポリシーとカスタムポリシーと呼びます。以下のドキュメントに比較表があります。

既定ポリシーでは、署名付きURLを発行するタイミングでクエリ文字列の内容を決める必要があります。オリジンのWebアプリケーションの実装に依りますが、任意のクエリ文字列に呼応するような実装の場合、事前にクエリ文字列を決定することが難しい場合があるかもしれません。一方カスタムポリシーで利用できるワイルドカード文字(*記号)は、クエリ文字列にも適用できます。クエリ文字列をWebアプリケーションなどで動的に扱うのであれば、既定ポリシーよりもカスタムポリシーの方が柔軟に扱える点でオススメです。カスタムポリシーのURLの方が既定ポリシーよりも相対的に長くなるので、クライアントでURLの文字数制限が無いかなどに注意して利用しましょう。

署名付きURLはキャッシュキー非依存、しかし用途として設定が必要

CloudFrontにはキャッシュを区別するためのキャッシュキー設定があり、クエリ文字列をキャッシュキーに含めるかを選択できます。

署名付きURLの機能には依存しないため、署名付きURLを利用するためにキャッシュキーにクエリ文字列を設定する必要はありません。一方でキャッシュキーにクエリ文字列を含めないと、CloudFrontによってクエリ文字列が除去されたリクエストがオリジンに届きます。今回の記事のようなオリジンにクエリ文字列を渡したい構成の場合は、キャッシュポリシーにクエリ文字列を含めなくてはなりません。

動作確認

では、実際に試してみましょう。署名URLのアルゴリズムはドキュメントで公開されているので任意のアプリケーションで発行できますが、手軽に試すにはAWS CLIの aws cloudfront sign コマンドが便利です。 aws cloudfront sign は既定ポリシーとカスタムポリシーの両方に対応していますが、ポリシーをオプションで明示するわけではありません。カスタムポリシーのみサポートするオプション項目を指定するとカスタムポリシー、項目を指定しないと既定ポリシーの署名付きURLを発行する挙動になります。実際のロジックは↓のソースの_run_main関数の辺りにあります。

既定ポリシーの例

$ aws cloudfront sign \
  --key-pair-id K1234567890AB \
  --private-key file://xxx.private.pem \
  --date-less-than $((`date "+%s"` + 86400)) \
  --url "https://xxxxxxxxxxxxxx.cloudfront.net/?test=test"
https://xxxxxxxxxxxxxx.cloudfront.net/?test=test&Expires=1697547218&Signature=kvvRRnAbE9FPzSJXetHqZs2xt6m04RmbxZLVP6sMoj5n1T9DNE2HqsfQDlj~4mRtLsJd3wCqqTgPW0eYhVptP9j~PZddYFsmZKf8tuM~jVpyvNbf~cwIeMaEhJqd8GnIL8nOA5xWqXZlktljrH9brHiHaayWNQ8YBjXVOhziS34gbtuI3ogv372fHFCaNw7xXLMYD3s6ygIB0FApPenzQeBbL19oEpnTDwtL95GrYD78dKdfqR4bOmwp7VuSVT7KuuIqRvxNLZgG0-0pc60ZdgqSkAzzvyIU0g2ENp6IuRj3Z436Z1Clgyvf90Cl6yv-khbbqpXFVNLURLvGED3b3w__&Key-Pair-Id=K1234567890AB
$

--urlオプションに指定するURLにクエリ文字列を含めているのがポイントです。署名付きURLのクエリ文字列の先頭に指定したパラメータが含まれていることがわかります。

カスタムポリシーの例

--date-greater-thanオプションを指定して、カスタムポリシーの署名付きURLを発行します。

$ aws cloudfront sign \
  --key-pair-id K1234567890AB \
  --private-key file://xxx.private.pem \
  --date-less-than $((`date "+%s"` + 86400)) \
  --date-greater-than $((`date "+%s"`)) \
  --url "https://xxxxxxxxxxxxxx.cloudfront.net/*"
https://xxxxxxxxxxxxxx.cloudfront.net/*?Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly94eHh4eHh4eHh4eHh4eC5jbG91ZGZyb250Lm5ldC8qIiwiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6eyJBV1M6RXBvY2hUaW1lIjoxNjk3NTQ3Mjc0fSwiRGF0ZUdyZWF0ZXJUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE2OTc0NjA4NzR9fX1dfQ__&Signature=OQFUlaLDGnfiIxzRllaQxnQXwwJdP7AVAFkt3xstwHWnSj0nXALoZcp9y~KG2Fg5EsfPZJ3HOuTVx0e7QfU2qE0unl0mAp1X~xz4p4OyJMhofnvUToiL3xGplw6CeEFKDFQtLRKuJpm7EqYh7CItAG0xJZ56wIbDTFy7Gw5akz70inSG3n~EPRgnFbEFoULFr109Ig7eoa7R8zdrZPsSPQ9ZhRXdwQlj3DrJMd7dl79SJaHrSVdqgtFZvcSe4OJV8dWD9f1rZRhBHJDamqli86GmN0a5XkeEO7ksWrbZaOYaPfmPQfYoQd-ufVdXswpX1gQsbEIkfNeA3FCdS1bJaA__&Key-Pair-Id=K1234567890AB
$

カスタムポリシーの場合は--urlオプションのURLにワイルドカードを含めることができます。URLのうちホスト名より後ろの末尾にワイルドカードを入れることで、任意のクエリ文字列を署名付きURLに付与できます。ただし、aws cloudfront signコマンドは--urlオプションの文字列を署名付きURLの先頭に機械的に付与するので、ワイルドカードを指定する場合はコマンドの出力をそのままでは利用できません。以下のように実際にアクセスするパスに置換して利用しましょう。クエリ文字列のうち、署名付きURLで検証されるパラメータはURLの末尾に付与する必要があるため、オリジンに渡すクエリ文字列はそれらの前に挿入しましょう(以下の例のtest=test)。

https://xxxxxxxxxxxxxx.cloudfront.net/?test=test&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly94eHh4eHh4eHh4eHh4eC5jbG91ZGZyb250Lm5ldC8qIiwiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6eyJBV1M6RXBvY2hUaW1lIjoxNjk3NTQ3Mjc0fSwiRGF0ZUdyZWF0ZXJUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE2OTc0NjA4NzR9fX1dfQ__&Signature=OQFUlaLDGnfiIxzRllaQxnQXwwJdP7AVAFkt3xstwHWnSj0nXALoZcp9y~KG2Fg5EsfPZJ3HOuTVx0e7QfU2qE0unl0mAp1X~xz4p4OyJMhofnvUToiL3xGplw6CeEFKDFQtLRKuJpm7EqYh7CItAG0xJZ56wIbDTFy7Gw5akz70inSG3n~EPRgnFbEFoULFr109Ig7eoa7R8zdrZPsSPQ9ZhRXdwQlj3DrJMd7dl79SJaHrSVdqgtFZvcSe4OJV8dWD9f1rZRhBHJDamqli86GmN0a5XkeEO7ksWrbZaOYaPfmPQfYoQd-ufVdXswpX1gQsbEIkfNeA3FCdS1bJaA__&Key-Pair-Id=K1234567890AB

まとめ

CloudFront署名付きURLでアクセス制限しつつ、オリジンにクエリ文字列を渡す構成を検証してみました。カスタムポリシーのワイルドカード指定が柔軟に使えそうなので、別のブログ記事で実験してみようと思います。

参考URL