このページでは、署名付き URL の概要と、Cloud CDN で署名付き URL を使用する手順を説明します。署名付き URL は、ユーザーが Google アカウントを持っているかどうかにかかわらず、その URL を知っている全員にリソースへのアクセスを期間限定で許可する手段です。
署名付き URL は、リクエスト時における制限付きの権限と有効期限が設定された URL です。署名付き URL のクエリ文字列には認証情報が含まれているので、認証情報を持たないユーザーでもリソースに対して特定の操作を実行できます。署名付き URL を生成するときには、その URL に関連付けられたリクエストを行うのに十分な権限を持つユーザーまたはサービス アカウントを指定します。
署名付き URL を生成すると、その URL を所有するすべての人は、指定された期間内にその署名付き URL を使って特定のアクション(オブジェクトの読み取りなど)を実行できます。
また署名付き URL ではオプションの URLPrefix
パラメータを使用して、共通の接頭辞に基づき複数の URL へのアクセスを許可することもできます。
アクセスを特定の URL 接頭辞に限定する場合は、署名付き Cookie の使用を検討してください。
始める前に
署名付き URL を使用する前に、次のことを行います。
Cloud CDN が有効になっていることを確認します。手順については、Cloud CDN の使用をご覧ください。Cloud CDN を有効にする前にバックエンドで署名付き URL を構成できますが、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
署名付き URL
最後のステップは、URL に署名を付加して配布することです。URL に署名を付加するには、gcloud compute sign-url
コマンドを使用するか、独自のコードを記述します。多数の署名付き URL が必要な場合は、カスタムコードを使用したほうがパフォーマンスが向上します。
署名付き URL を作成する
gcloud compute sign-url
コマンドを使用して、署名付き URL を作成する手順は次のとおりです。この手順では、鍵の作成がすでに完了していることを前提としています。
コンソール
Google Cloud コンソールを使用して署名付き URL を作成することはできません。Google Cloud CLI を使用するか、次の例を使用してカスタムコードを作成できます。
gcloud
Google Cloud CLI には、URL に署名するためのコマンドがあります。このコマンドは、独自のコードの作成に関するセクションで説明されているアルゴリズムを実装します。
gcloud compute sign-url \ "URL" \ --key-name KEY_NAME \ --key-file KEY_FILE_NAME \ --expires-in TIME_UNTIL_EXPIRATION \ [--validate]
このコマンドは、base64url でエンコードされた鍵の値を KEY_FILE_NAME
から読み取ってデコードしてから、署名付き URL を出力します。この署名付き URL は、GET
リクエストや HEAD
リクエストに使用できます。
次に例を示します。
gcloud compute sign-url \ "https://example.com/media/video.mp4" \ --key-name my-test-key \ --expires-in 30m \ --key-file sign-url-key-file
URL
は、パス要素を持つ有効な URL でなければなりません。たとえば、http://example.com
は無効ですが、https://example.com/
と https://example.com/whatever
はどちらも有効な URL です。
省略可能な --validate
フラグがこのコマンドで指定されている場合は、生成された URL とともに HEAD
リクエストが送信され、HTTP レスポンス コードが出力されます。署名付き URL が正しい場合は、レスポンス コードと、バックエンドから送信された結果コードが同じになります。レスポンス コードが同じでない場合は、KEY_NAME
と指定したファイルの内容を再確認し、TIME_UNTIL_EXPIRATION
の値が数秒以上であることを確認してください。
--validate
フラグが指定されていない場合、以下のものは検証されません。
- 入力
- 生成された URL
- 生成された署名付き URL
署名付き URL をプログラムで作成する
次のサンプルコードは、署名付き URL をプログラムで作成する方法を示しています。
Go
Ruby
.NET
Java
Python
PHP
URL 接頭辞を含む署名付き URL をプログラマティックに作成する
次のコードサンプルは、URL 接頭辞を含む署名付き URL をプログラマティックに作成する方法を示しています。
Go
Java
Python
カスタム署名付き URL を生成する
署名付き URL を生成するコードを独自に作成する場合、次の形式またはアルゴリズムで URL を作成することを目標にしてください。すべての URL パラメータは大文字と小文字が区別され、次に示す順序で設定される必要があります。
https://example.com/foo?Expires=EXPIRATION&KeyName=KEY_NAME&Signature=SIGNATURE
署名付き URL を生成する方法は次のとおりです。
署名対象の URL に
Signature
クエリ パラメータがないことを確認します。この URL の有効期限を決めて、
Expires
クエリ パラメータを追加します。有効期限を UTC 時間(1970-01-01 00:00:00 UTC からの秒数)として指定してください。安全性を最大にするために、ユースケースに応じて可能な限り短い有効期間となるように値を設定してください。署名付き URL の有効期間が長くなるほど、偶発的かどうかを問わず、他のユーザーに URL が渡ってしまうリスクが高くなります。鍵の名前を設定します。URL に署名するには、URL を処理するバックエンド サービスまたはバックエンド バケットの鍵を使用する必要があります。最近追加した最新の鍵を使用して鍵をローテーションすることをおすすめします。
&KeyName=KEY_NAME
を追加して、鍵を URL に追加します。KEY_NAME
は、署名済みのリクエスト鍵の作成で作成した鍵を選び、その名前に置き換えます。URL に署名します。次の手順で署名付き URL を作成します。クエリ パラメータを指定する順序が、ステップ 1 の直前で説明したとおりであることと、大文字と小文字の区別も説明のとおりであることを確認してください。
a. URL 全体(先頭の
http://
またはhttps://
と末尾の&KeyName...
も含む)を HMAC-SHA1 でハッシュします。このときに、上で選択した鍵名に対応する秘密鍵を使用します。base64url エンコードされた鍵ではなく、16 バイトの秘密鍵をそのまま使用します。必要に応じてデコードしてください。b. base64url エンコードを使用して結果をエンコードします。
c.
&Signature=
を URL の末尾に付加し、その後にエンコード済みの署名を付加します。
署名付き URL に URL 接頭辞を使用する
クエリ パラメータ Expires
および KeyName
を含むリクエスト URL 全体を署名する代わりに、クエリ パラメータ URLPrefix
、Expires
、KeyName
だけに署名を付けることもできます。これにより、URLPrefix
と一致する複数の URL でクエリ パラメータ URLPrefix
、Expires
、KeyName
、Signature
の所定の組み合わせをそのまま再利用できるので、個別の URL ごとに新しい署名を作成する必要がなくなります。
次の例でハイライト表示されたテキストは、署名されるパラメータを示しています。Signature
は、通常どおり、最後のクエリ パラメータとして付加します。
https://media.example.com/videos/id/master.m3u8?userID=abc123&starting_profile=1&URLPrefix=aHR0cHM6Ly9tZWRpYS5leGFtcGxlLmNvbS92aWRlb3Mv&Expires=1566268009&KeyName=mySigningKey&Signature=8NBSdQGzvDftrOIa3WHpp646Iis=
完全なリクエスト URL に署名する場合と異なり、URLPrefix
で署名する場合はクエリ パラメータに署名することにはならないため、URL にクエリ パラメータを自由に含めることができます。また、完全なリクエスト URL 署名とは異なり、これらの追加のクエリ パラメータは、署名を構成するクエリ パラメータの前後の両方で指定できます。そのため、次の例も、署名付き URL 接頭辞を含む有効な URL です。
https://media.example.com/videos/id/master.m3u8?userID=abc123&URLPrefix=aHR0cHM6Ly9tZWRpYS5leGFtcGxlLmNvbS92aWRlb3Mv&Expires=1566268009&KeyName=mySigningKey&Signature=8NBSdQGzvDftrOIa3WHpp646Iis=&starting_profile=1
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
エラーを返します。
署名付き URL を検証する
署名付き URL を検証するプロセスは、署名付き URL の生成プロセスと基本的に同じです。たとえば、次の署名付き URL を検証するとします。
https://example.com/PATH?Expires=EXPIRATION&KeyName=KEY_NAME&Signature=SIGNATURE
KEY_NAME
という名前の秘密鍵を使用して、次の URL の署名を個別に生成できます。
https://example.com/PATH?Expires=EXPIRATION&KeyName=KEY_NAME
その後、SIGNATURE
と一致することを確認できます。
URLPrefix
を含む署名付き URL を検証する場合、次のようにします。
https://example.com/PATH?URLPrefix=URL_PREFIX&Expires=EXPIRATION&KeyName=KEY_NAME&Signature=SIGNATURE
まず、base64 でデコードされた URL_PREFIX
の値が https://example.com/PATH
の接頭辞であることを確認します。その場合、次の署名を計算できます。
URLPrefix=URL_PREFIX&Expires=EXPIRATION&KeyName=KEY_NAME
その後、SIGNATURE
と一致することを確認できます。
Cloud Storage バケットへの公開アクセスの削除
署名付き URL でコンテンツを適切に保護するために、送信元サーバーでそのコンテンツへの公開アクセスを許可しないことが重要です。Cloud Storage バケットを使用する場合、一般的な方法として、テスト用にオブジェクトを一時的に公開します。署名付き URL を有効にした後で、バケットに対する allUsers
(および該当する場合は allAuthenticatedUsers
)読み取り権限(言い換えると Storage オブジェクト閲覧者 IAM ロール)を削除することが重要です。
バケットに対する公開アクセスを無効にした後でも、個々のユーザーにオーナー権限などのアクセス権がある場合、署名付き URL なしで Cloud Storage にアクセスできます。
Cloud Storage バケットに対する公開 allUsers
読み取りアクセス権を削除するには、バケット内のすべてのオブジェクトを公開するで説明されている操作を逆に行います。
署名付き URL を配布して使用する
必要に応じて、Google Cloud CLI から返された URL、またはカスタムコードによって生成された URL を配布できます。HTTPS URL だけに署名することをおすすめします。HTTPS はセキュリティに優れたトランスポート手段であり、署名付き URL の Signature
コンポーネントが傍受されるのを防止できるからです。同様に、署名付き URL を配布するときは、TLS / HTTPS などのセキュアなトランスポート プロトコルを使用してください。