CloudFrontの署名付Cookieの設定でつまずいた、という話。

CloudFrontで署名付Cookieを扱う

会員限定、期間限定とか、特定のユーザーにだけコンテンツを公開したいと思ったら、AWSのCloudFrontなら簡単にできるらしい。

CloudFrontを使用してプライベートコンテンツを供給する
http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html

署名付URLもしくは署名付Cookieを発行して、ユーザーを限定してS3へのアセットへのアクセスを許可することができるとのこと。使い分けとしてはざっくり以下の通り。

  • 署名付URL: 単独の制限されたファイル(ダウンロードリンク等)に適している
  • 署名付Cookie: 複数の制限されたファイル(動画のストリーミング等)に適している

Cookieのほうが自分の用途にあってるので、こちらを選択。

署名付き Cookie の使用
http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html

CloudFrontのクロスドメインCookie問題

SDKを使って署名付Cookieを発行するわけですが、そうなるとこんな状況になります。

アプリ側のドメイン(署名付Cookieの発行) ==Cross Domain==> CloudFrontのドメイン(Cookieを判別してアクセス許可)

仕様上、別のドメインからはCookieは読めないわけなので、アプリとCloudFrontのサブドメイン以降は同じでなければいけない、ということになります。
本来、固有のドメインを取得して設定すればいいわけですが、まだ開発中のデモにお金かけたくない。。。

それなら、AWSがランダムに発行する xxxxxxxxx.cloudfront.net に合わせて、hostsファイルを設定してしまえばいいのでは? というわけで、local.cloudfront.net を設定してみました。

local.cloudfront.net ==Cross Domain==> xxxxxxxxx.cloudfront.net

start_time = (Time.now - 60).to_i
expire_time = 3.hours.from_now.to_i

policy = {
  Statement: [
    Resource: "https://local.cloudfront.net/sample/*",
    Condition: {
      DateLessThan: { "AWS:EpochTime" => expire_time },
      DateGreaterThan: { "AWS:EpochTime" => start_time }
    }
  ]
}

signer = Aws::CloudFront::CookieSigner.new(
  key_pair_id: ENV['AWS_CLOUDFRONT_KEY_PAIR_ID'],
  private_key_path: ENV['AWS_CLOUDFRONT_PRIVATE_KEY_PATH']
)
signer.signed_cookie('https://local.cloudfront.net/sample/*',
  policy: policy.to_json
).each do |key, value|
  cookies[key] = {
    value: value,
    domain: 'cloudfront.net',
    path: '/',
    secure: false
  }
end

これで cloudfront.net に署名付Cookieが設定されて、ローカルから xxxxxxxxx.cloudfront.net のコンテンツにアクセスできる。。。 と思いきやCookieが設定されないではないですか!

Public Suffix List (PSL) とは?

色々調べてようやくつきとめたのが Public Suffix の存在。別名 Effective Top Level Domain (eTLD)。

A "public suffix" is one under which Internet users can (or historically could) directly register names. Some examples of public suffixes are .com, .co.uk and pvt.k12.ma.us. The Public Suffix List is a list of all known public suffixes.
Public Suffixはその下にインターネットユーザーが直接名前を設定できるドメインです。例えば、.com、.co.uk、pvt.k12.ma.usがその例です。

Avoid privacy-damaging "supercookies" being set for high-level domain name suffixes
プライバシーを侵害するSupercookieの設定を避けるためにも使われます。
https://publicsuffix.org/

要するに、.com や .co.uk なんて不特定多数に使われるドメインでCookieの読み書きできたらプライバシー上問題なので、Public Suffix Listに乗っているドメインにはCookieは設定できないよ、ということです。

それを踏まえて、Listを見てみると。。。

cloudfront.net

ありました。cloudfront.net は .com や .co.uk と同じレベルにあるということです。

原因が分かったので、今度は hosts を local.xxxxxxxxx.cloudfront.net として、 Cookieの設定ドメインを xxxxxxxxx.cloudfront.net にして、無事成功。

考えてみれば当然のことなのですが、cloudfront.net という名前からは意外と気づきませんでした(未熟)。Publix Suffixは膨大なリストなのでクラウド系のサービス使うときはチェックしてみてください。