CloudFront + S3 で署名付き Cookie でプライベートコンテンツを配信する

2015.06.11

CloudFront でプライベートコンテンツを配信

CloudFront でプライベートコンテンツを配信するには、署名付き URL を使う方法が以前からありました。それに加え、今年3月に署名付き Cookie が使用できるようになりました。

Amazon Web Services ブログ: Amazon CloudFront 署名付きクッキーによるプライベートコンテンツ配信

ということで、今回は CloudFront の署名付き Cookie を使ったプライベートコンテンツの配信を試してみたいと思います。

オリジンアクセスアイデンティティの設定と CloudFront キーペアの作成

署名付き Cookie を使ったプライベートコンテンツの配信を行うには、まず以下の作業が必要です。

  • オリジンアクセスアイデンティティの設定
  • CloudFrontキーペアの作成

これらについては以下の記事と全く同じ手順ですので、こちらを参考に行いましょう。

CloudFront+S3で署名付きURLでプライベートコンテンツを配信する | Developers.IO

今回はsample.htmlという適当なHTMLファイルを配置します。ここまでの操作が済んだ時点でアクセスすると、下図のようになります。

cf-cookie01

Signatureの作成

Signatureを作成します。まずPolicyとなるJSONファイルを作りましょう。

policy.json

{
   "Statement":[
      {
         "Resource":"http://xxxxxxxxxxxxx.cloudfront.net/sample.html",
         "Condition":{
            "DateLessThan":{
               "AWS:EpochTime":1435676400
            }
         }
      }
   ]
}

こちらから、インデントを削除します。

{"Statement":[{"Resource":"http://xxxxxxxxxxxxx.cloudfront.net/sample.html","Condition":{"DateLessThan":{"AWS:EpochTime":1435676400}}}]}

次にBase64エンコード、そしてキーペアを使って暗号化を行います。詳しくは以下を見てください。

Linux コマンドおよび OpenSSL を使用して Base64 エンコードおよび暗号化を行う - Amazon CloudFront

次のようなコマンドを叩きます。

$ cat policy.json | openssl sha1 -sign pk.pem | openssl base64 | tr '+=/' '-_~'

こうして、以下のような値が作成できます。

Otj5ozMn4r9Cixu~W2j8593RmEKwGgYI74mlZmUTXLHOTtgLRTEBxj3oD6008nQa
jU3vHNtevb7QhlsWNA8c1NEkHB0XPrXM5PeokFABHq~cSRSL92yD4kz~m0ZGgvPz
Z8xjXm24n3hzRGPHoJKKakf9aH8xZVW~pWlFlZS8Bt5ZLNQb2Ak4pa5POV9U1mty
DYC6~rF6etMFYgnQgaBIkaMU4gEA32OzxFvWLVAkbzMOjTlhY2OlC1zJuOIWAKtI
Xm0xFtZX0M2QOr2l8YQogQiKVVJKNtcB8gF1PmZwE6MDyS2fZ60ZE~Q-akB5VZz2
OiWhy5QVzJ8d0YUok97XXX__

これでひとまず準備が整いました。あとは Cookie をセットして対象のURLにアクセスします。

Cookie は大きく3つの値をセットします。

  • CloudFront-Expires : 有効期限
  • CloudFront-Signature : 先ほど作成したSignature
  • CloudFront-Key-Pair-Id : 先ほど作成したキーペアのID

Cookie を設定するフォーマットは次の通りです。このうちDomainPathはオプションです。

Set-Cookie: 
Domain=optional domain name; 
Path=/optional directory path; 
Secure; 
HttpOnly; 
CloudFront-Expires=date and time in Unix time format (in seconds) and Coordinated Universal Time (UTC)

Set-Cookie: 
Domain=optional domain name; 
Path=/optional directory path; 
Secure; 
HttpOnly; 
CloudFront-Signature=hashed and signed version of the policy statement

Set-Cookie: 
Domain=optional domain name; 
Path=/optional directory path; 
Secure; 
HttpOnly; 
CloudFront-Key-Pair-Id=active CloudFront key pair Id for the key pair that you are using to generate the signature

これに当てはめてみると…

Set-Cookie: 
Secure; 
HttpOnly; 
CloudFront-Expires=1435676400

Set-Cookie: 
Secure; 
HttpOnly; 
CloudFront-Signature=Otj5ozMn4r9Cixu~W2j8593RmEKwGgYI74mlZmUTXLHOTtgLRTEBxj3oD6008nQa
jU3vHNtevb7QhlsWNA8c1NEkHB0XPrXM5PeokFABHq~cSRSL92yD4kz~m0ZGgvPz
Z8xjXm24n3hzRGPHoJKKakf9aH8xZVW~pWlFlZS8Bt5ZLNQb2Ak4pa5POV9U1mty
DYC6~rF6etMFYgnQgaBIkaMU4gEA32OzxFvWLVAkbzMOjTlhY2OlC1zJuOIWAKtI
Xm0xFtZX0M2QOr2l8YQogQiKVVJKNtcB8gF1PmZwE6MDyS2fZ60ZE~Q-akB5VZz2
OiWhy5QVzJ8d0YUok97XXX__

Set-Cookie: 
Secure; 
HttpOnly; 
CloudFront-Key-Pair-Id=XXXXXXXXXXXXXXXXXXX

こんな感じになります。ビューア(クライアント)からは、これらを;区切りで1つの値としてCookieとしてリクエストヘッダーにセットします。

コマンドから呼び出してみましょう。

$ curl -H 'Cookie:CloudFront-Expires=1435676400; CloudFront-Signature=Otj5ozMn4r9Cixu~W2j8593RmEKwGgYI74mlZmUTXLHOTtgLRTEBxj3oD6008nQajU3vHNtevb7QhlsWNA8c1NEkHB0XPrXM5PeokFABHq~cSRSL92yD4kz~m0ZGgvPzZ8xjXm24n3hzRGPHoJKKakf9aH8xZVW~pWlFlZS8Bt5ZLNQb2Ak4pa5POV9U1mtyDYC6~rF6etMFYgnQgaBIkaMU4gEA32OzxFvWLVAkbzMOjTlhY2OlC1zJuOIWAKtIXm0xFtZX0M2QOr2l8YQogQiKVVJKNtcB8gF1PmZwE6MDyS2fZ60ZE~Q-akB5VZz2OiWhy5QVzJ8d0YUok97XXX__; CloudFront-Key-Pair-Id=APKAJWC7ACW4A5CIM6RQ' http://xxxxxxxxxxxxx.cloudfront.net/sample.html

OKです!

<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>
<p>
Hello!
</p>
</body>
</html>

まとめ

以上、簡単ではありますが署名付き Cookie を利用したプライベートコンテンツの配信する手順でした。また機会があったら Ruby で作成するコードを書いてみたいと思います。