cloudfront.netがPublic Suffixで困ったという話

  • 0
    いいね
  • 0
    コメント

    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は膨大なリストなのでクラウド系のサービス使うときはチェックしてみてください。