このページでは、署名付き Cookie の概要と、Cloud CDN で署名付き Cookie を使用する手順を説明します。署名付き Cookie は、ユーザーが Google アカウントを持っているかどうかに関係なく、期限付きで一連のファイルにアクセスできるようにするための手段です。
署名付き Cookie は、署名付き URL の代わりとなる手段です。アプリケーションでユーザーごとに数十、数百の URL に個別に署名するのが不可能な場合は、署名付き Cookie によってアクセスを保護できます。
署名付き Cookie で、次のことが可能になります。
- ユーザーを承認し、(各 URL に署名する代わりに)保護されたコンテンツへのアクセス用の期限付きトークンを提供する。
- ユーザーがアクセスできる範囲を特定の URL 接頭辞(
https://media.example.com/videos/
など)に限定し、その URL 接頭辞のみを範囲として、承認済みユーザーに保護されたコンテンツへのアクセス権を付与する。 - URL とメディア マニフェストを変更せずに、パッケージング パイプラインを簡素化し、キャッシュ可能性を高める。
上記とは異なり、アクセス範囲を特定の URL に限定する場合は、署名付き URL の使用を検討してください。
始める前に
署名付き Cookie を使用する前に、次のことを行います。
Cloud CDN が有効になっていることを確認します。手順については、Cloud CDN の使用をご覧ください。Cloud CDN を有効にする前にバックエンドで署名付き Cookie を構成できますが、Cloud CDN が有効になるまでその効果はありません。
必要に応じて、次のコマンドで Google Cloud CLI を最新バージョンに更新します。
gcloud components update
概要については、署名付き URL と署名付き Cookie をご覧ください。
署名付きリクエストの鍵の構成
署名付き URL または署名付き Cookie の鍵を作成するには、いくつかの手順が必要です。以降のセクションで、必要な手順を説明します。
セキュリティ上の考慮事項
次のような場合、Cloud CDN はリクエストを検証しません。
- リクエストが署名されていない。
- リクエストのバックエンド サービスまたはバックエンド バケットで Cloud CDN が有効になっていない。
レスポンスを配信する前に、署名付きリクエストを必ず送信元で検証する必要があります。これは、署名されたコンテンツと署名されていないコンテンツの両方を配信するために送信元が使用される可能性があり、また、クライアントが送信元に直接アクセスする可能性があるためです。
- Cloud CDN は、
Signature
クエリ パラメータまたはCloud-CDN-Cookie
HTTP Cookie がないリクエストをブロックしません。無効(または不正)なリクエスト パラメータを含むリクエストは拒否されます。 - アプリケーションが無効な署名を検出した場合は、必ずアプリケーションが
HTTP 403 (Unauthorized)
レスポンス コードを使って応答するようにしてください。HTTP 403
レスポンス コードはキャッシュに保存できません。 - 署名付きリクエストと署名がないリクエストに対するレスポンスは別々にキャッシュされるため、有効な署名付きリクエストへの正常なレスポンスは、署名のないリクエストの対応で使用されません。
- アプリケーションがキャッシュ可能なレスポンス コードを無効なリクエストに送信すると、今後、有効なリクエストが誤って拒否される可能性があります。
Cloud Storage バックエンドの場合は、有効な署名がないリクエストを Cloud Storage が拒否できるよう公開アクセス権を削除する必要があります。
次の表に動作をまとめます。
リクエストに署名があるか | キャッシュ ヒット | 動作 |
---|---|---|
いいえ | いいえ | バックエンドの配信元に転送します。 |
いいえ | はい | キャッシュから配信します。 |
はい | いいえ | 署名を検証します。有効な場合、バックエンドの配信元に転送します。 |
はい | はい | 署名を検証します。有効であればキャッシュから提供します。 |
署名付きリクエスト鍵を作成する
Cloud CDN の署名付き URL と署名付き Cookie のサポートを有効にするには、Cloud CDN が有効化されたバックエンド サービス、バックエンド バケット、またはその両方で 1 つ以上の鍵を作成します。
それぞれのバックエンド サービスまたはバックエンド バケットで、セキュリティのニーズに応じて鍵を作成、削除できます。1 つのバックエンドにつき、構成できる鍵は最大 3 つです。鍵を定期的にローテーションすることをおすすめします。そうするには、最も古い鍵を削除してから新しい鍵を追加し、その鍵で URL または Cookie に署名します。
バックエンドごとの鍵のセットは互いに独立しているので、複数のバックエンド サービスやバックエンド バケットで同じ鍵名を使用きます。鍵名の長さは最大 63 文字です。鍵の名前には、A~Z、a~z、0~9、_(アンダースコア)、-(ハイフン)を使用します。
鍵を作成するときは、外部に漏れないように注意してください。鍵を知っている人は誰でも、その鍵が Cloud CDN から削除されるまでは、Cloud CDN が受け入れる署名付き URL または署名付き Cookie を作成できるからです。鍵は、署名付き URL または署名付き Cookie の生成に使用された PC に保存されます。また Cloud CDN も、リクエストの署名を検証するために鍵を保存します。
鍵を非公開にする目的で、API リクエストへのレスポンスには鍵の値が含まれません。鍵を紛失してしまった場合は、新規作成する必要があります。
署名付きリクエスト鍵を作成する手順は次のとおりです。
コンソール
- Google Cloud コンソールで、[Cloud CDN] ページに移動します。
- キーを追加する送信元の名前をクリックします。
- [送信元の詳細] ページで、[編集] ボタンをクリックします。
- [Origin basics] セクションで、[次へ] をクリックして [Host and path rules] セクションを開きます。
- [Host and path rules] セクションで、[次へ] をクリックして [Cache performance] セクションを開きます。
- [制限付きコンテンツ] セクションで、[署名付き URL と署名付き Cookie を使用してアクセスを制限する] を選択します。
[署名鍵を追加] をクリックします。
- 新しい署名鍵の一意の名前を指定します。
[キーの作成方法] セクションで、[自動的に生成する] を選択します。または、[入力する] をクリックして、署名鍵の値を指定します。
前者の場合は、自動生成された署名鍵の値をプライベート ファイルにコピーします。これは、署名付き URL の作成に使用できます。
[完了] をクリックします。
[キャッシュ エントリの最長存続期間] セクションで値を入力し、単位を選択します。
[完了] をクリックします。
gcloud
gcloud
コマンドライン ツールは、指定されたローカル ファイルから鍵を読み取ります。鍵ファイルを作成するには、強いランダム性を持つ 128 ビットで生成し、base64 でエンコードしてから、文字 +
を -
に置き換え、文字 /
を _
に置き換える必要があります。詳細については、RFC 4648 をご覧ください。鍵に強いランダム性を与えることはきわめて重要です。UNIX 系のシステムでは、次のコマンドで強いランダム性を持つ鍵を生成して鍵ファイルに保存できます。
head -c 16 /dev/urandom | base64 | tr +/ -_ > KEY_FILE_NAME
鍵をバックエンド サービスに追加するには、次のコマンドを実行します。
gcloud compute backend-services \ add-signed-url-key BACKEND_NAME \ --key-name KEY_NAME \ --key-file KEY_FILE_NAME
鍵をバックエンド バケットに追加するには、次のコマンドを実行します。
gcloud compute backend-buckets \ add-signed-url-key BACKEND_NAME \ --key-name KEY_NAME \ --key-file KEY_FILE_NAME
Cloud Storage の権限を構成する
Cloud Storage を使用し、オブジェクトを読み取れるユーザーを限定している場合は、Cloud CDN にオブジェクトの読み取りアクセス権を付与する必要があります。それには、Cloud CDN サービス アカウントを Cloud Storage ACL に追加します。
サービス アカウントの作成は必要ありません。サービス アカウントは、プロジェクト内のバックエンド バケットに初めて鍵を追加するときに自動的に作成されます。
次のコマンドを実行する前に、少なくとも 1 つの鍵をプロジェクトのバックエンド バケットに追加します。こうしないと、このコマンドはエラーを伴って失敗します。これは、プロジェクト用に 1 つ以上の鍵を追加するまでは、Cloud CDN キャッシュ フィル サービス アカウントが作成されないためです。PROJECT_NUM
はプロジェクト番号に、BUCKET
はストレージ バケットに置き換えます。
gsutil iam ch \ serviceAccount:service-PROJECT_NUM@cloud-cdn-fill.iam.gserviceaccount.com:objectViewer \ gs://BUCKET
Cloud CDN サービス アカウント service-PROJECT_NUM@cloud-cdn-fill.iam.gserviceaccount.com
は、プロジェクトのサービス アカウントのリストには表示されません。これは、この Cloud CDN サービス アカウントがプロジェクトではなく Cloud CDN によって所有されているためです。
プロジェクト番号の詳細については、Google Cloud コンソール ヘルプ ドキュメントのプロジェクト ID とプロジェクト番号の特定をご覧ください。
最大キャッシュ時間をカスタマイズする
Cloud CDN は、バックエンドの Cache-Control
ヘッダーとは無関係に、署名付きリクエストのレスポンスをキャッシュに保存します。再検証を必要とすることなくキャッシュに保存できる時間の最大値を設定するには、signed-url-cache-max-age
フラグを使用します。このフラグのデフォルト値は 1 時間です。以下に示す方法で、この値を変更できます。
バックエンド サービスまたはバックエンド バケットの最大キャッシュ時間を設定するには、次のいずれかのコマンドを実行します。
gcloud compute backend-services update BACKEND_NAME --signed-url-cache-max-age MAX_AGE
gcloud compute backend-buckets update BACKEND_NAME --signed-url-cache-max-age MAX_AGE
署名付きリクエストキー名を一覧表示する
バックエンド サービスまたはバックエンド バケットの鍵を一覧表示するには、次のいずれかのコマンドを実行します。
gcloud compute backend-services describe BACKEND_NAME
gcloud compute backend-buckets describe BACKEND_NAME
署名付きリクエスト鍵を削除する
特定の鍵で署名されている URL が不要になった場合は、次のコマンドのいずれかを実行して、その鍵をバックエンド サービスまたはバックエンド バケットから削除します。
gcloud compute backend-services \ delete-signed-url-key BACKEND_NAME --key-name KEY_NAME
gcloud compute backend-buckets \ delete-signed-url-key BACKEND_NAME --key-name KEY_NAME
ポリシーの作成
署名付き Cookie のポリシーは、署名付き URL のクエリ パラメータに似た(:
文字で区切られた)一連の key-value
ペアです。例については、ユーザーへの Cookie の発行をご覧ください。
ポリシーは、リクエストを有効なものとするためのパラメータを表します。ポリシーには、ハッシュベースのメッセージ認証コード(HMAC)を使用して署名されます。Cloud CDN は各リクエストでこれを検証します。
ポリシーの形式とフィールドを定義する
次の 4 つの必須フィールドについて、次の順序で定義する必要があります。
URLPrefix
Expires
KeyName
Signature
署名付き Cookie のポリシーで使用される key-value
ペアでは大文字と小文字が区別されます。
URLPrefix
URLPrefix
は、URL セーフな base64 でエンコードされた URL 接頭辞を示します。これは、署名が有効になるすべてのパスを網羅します。
URLPrefix
にはスキーマ(http://
または https://
のいずれか)、FQDN、オプションのパスがエンコードされます。パスの末尾に /
を使用するかどうかは任意ですが、使用することをおすすめします。接頭辞にクエリ パラメータや ?
、#
などのフラグメントを含めないでください。
たとえば、https://media.example.com/videos
とすると、リクエストが次の両方にマッチングされます。
https://media.example.com/videos?video_id=138183&user_id=138138
https://media.example.com/videos/137138595?quality=low
接頭辞のパスは、厳密なディレクトリ パスではなく、テキスト部分文字列として使用されます。たとえば、接頭辞 https://example.com/data
は次の両方へのアクセス権を付与します。
/data/file1
/database
この誤りを防ぐには、すべての接頭辞の末尾に /
を使用することをおすすめします。ただし、https://media.example.com/videos/123
のように、意図的に接頭辞の末尾に部分的なファイル名を使用して、次のすべてへのアクセス権を付与することもできます。
/videos/123_chunk1
/videos/123_chunk2
/videos/123_chunkN
リクエストされた URL が URLPrefix
と一致しない場合、Cloud CDN はリクエストを拒否し、クライアントに HTTP 403
エラーを返します。
Expires
Expires
は、Unix タイムスタンプ(1970 年 1 月 1 日からの秒数)である必要があります。
KeyName
KeyName
は、バックエンド バケットまたはバックエンド サービスに対して作成された鍵の名前です。鍵名では大文字と小文字が区別されます。
Signature
Signature
は、URL セーフな Base64 でエンコードされた、Cookie ポリシーを構成するフィールドの HMAC-SHA-1 署名です。各リクエストでは、この署名が検証されます。リクエストの署名が無効な場合は、HTTP 403
エラーでリクエストが拒否されます。
署名付き Cookie をプログラムで作成する
次のコードサンプルは、署名付き Cookie をプログラムで作成する方法を示しています。
Go
Java
Python
署名付き Cookie の検証
署名付き Cookie を検証するプロセスは、署名付き Cookie の生成プロセスと基本的に同じです。たとえば、次の署名付き Cookie ヘッダーを検証するとします。
Cookie: Cloud-CDN-Cookie=URLPrefix=URL_PREFIX:Expires=EXPIRATION:KeyName=KEY_NAME:Signature=SIGNATURE; Domain=media.example.com; Path=/; Expires=Tue, 20 Aug 2019 02:26:49 GMT; HttpOnly
KEY_NAME
という名前の秘密鍵を使用して、署名を個別に生成し、SIGNATURE
と一致することを確認します。
ユーザーへの Cookie の発行
アプリケーションではユーザー(クライアント)ごとに、正しい署名付きポリシーを含む単一の HTTP Cookie を生成して発行する必要があります。
アプリケーション コードで HMAC-SHA-1 Signer を作成します。
選択した鍵を使用してポリシーに署名します。バックエンドに追加した鍵名(
mySigningKey
など)をメモしておきます。次の形式で Cookie ポリシーを作成します。名前と値の両方で大文字と小文字が区別されることに注意してください。
Name: Cloud-CDN-Cookie Value: URLPrefix=$BASE64URLECNODEDURLORPREFIX:Expires=$TIMESTAMP:KeyName=$KEYNAME:Signature=$BASE64URLENCODEDHMAC
Set-Cookie
ヘッダーの例:Set-Cookie: Cloud-CDN-Cookie=URLPrefix=aHR0cHM6Ly9tZWRpYS5leGFtcGxlLmNvbS92aWRlb3Mv:Expires=1566268009:KeyName=mySigningKey:Signature=0W2xlMlQykL2TG59UZnnHzkxoaw=; Domain=media.example.com; Path=/; Expires=Tue, 20 Aug 2019 02:26:49 GMT; HttpOnly
Cookie に含まれる
Domain
属性とPath
属性により、クライアントがその Cookie を Cloud CDN に送信するかどうかが決まります。
推奨事項と要件
保護されたコンテンツの配信元となるドメインとパス接頭辞に一致する
Domain
属性とPath
属性を明示的に設定します。これは、Cookie が発行されるドメインおよびパスと異なる可能性があります(example.com
とmedia.example.com
、/browse
と/videos
)。同じ
Domain
とPath
に対しては、所定の名前の Cookie を必ず 1 つだけ使用してください。競合する Cookie を発行していないことを確認してください。Cookie が競合すると、他のブラウザ セッション(ウィンドウまたはタブ)でコンテンツにアクセスできなくなる可能性があります。
必要に応じて
Secure
フラグとHttpOnly
フラグを設定します。Secure
を設定すると、Cookie が HTTPS 接続でのみ送信されます。HttpOnly
を設定すると、JavaScript で Cookie が使用不可になります。Cookie 属性の
Expires
とMax-Age
は省略可能です。これらを省略すると、Cookie はブラウザ セッション(タブ、ウィンドウ)が終了するまで存続します。キャッシュ フィルまたはキャッシュミスが発生すると、署名付き Cookie は、バックエンド サービスで定義された送信元に渡されます。コンテンツを配信する前に、各リクエストで署名付き Cookie の値を必ず検証してください。