[AWS] CloudFront + S3 署名付きCookieでHLSコンテンツのプライベート配信


今、作ってる動画配信プラットフォームの備忘録として書きました。

構築中プラットフォームのイメージ

今回は、CloudFront + S3でHLSコンテンツを配信する構成に署名付きCookieを使用しプライベート配信を構築を
【署名付き Cookie を使用して HLS コンテンツを取得してみた】こちらを参考に手を動かして実際にやってみた。

署名付きCookieとは

ユーザーに特定のCookieがセットされていればコンテンツにアクセスできる仕組みです。
【AWS公式ドキュメント】署名付きCookieの使用
※CloudFront側での設定が必要です。

①ユーザーが有料コンテンツに支払いなどアクセス用件を満たすとアプリはSet-Cookieヘッダーをレスポンスで返し、ブラウザ(ビューワー)は名前と値のペアを格納

②ユーザーが有料コンテンツに対しリクエストをするタイミングで①でセットされた名前と値のペアを取得し、リクエストのCookieヘッダーに追加する。これが署名付きCookie

③CloudFrontは署名付きCookieの署名を検証しアクセス許可、拒否を判断する

署名付きCookieと署名付きURL

上述した署名付きCookieと似たサービスに署名付きURLという仕組みがあります。
結論、今回のHLS形式ような複数のファイルに対してアクセスを提供する場合は署名付きCookieが推奨されています。
【AWS公式ドキュメント】署名付き URL と署名付き Cookie の選択

やってみた

構成

CloudFront キーペア作成

【AWS公式ドキュメント】信頼された署名者の CloudFront キーペアを作成する

①rootアカウントでログイン、アカウント名クリックしマイセキュリティ資格情報を開く

CloudFront のキーペアを開き新しいキーペアの作成をクリックし、各キーをダウンロード(※取り扱い注意)

アクセスキーIDは後ほど使うのでメモ

S3にファイルを置く

特に指定なくバケットを作成しHLSコンテンツをアップロード

CloudFrontディストリビューション作成

Trusted SignerSelfにチェックを入れます。署名者は今回作成する、
ディストリビューションと同じアカウントにするので、Selfとします。
別のアカウントの署名者を使用する場合は、Specify Accountsにチェック

各項目設定後ディストリビューションの作成
Grant Read Permissions on BucketをYesにしているとOriginに指定したバケットにポリシーが追加される。

AWSの設定はここまで。

リクエスト

【S3に直接リクエスト】

【署名付きCookieなしでCloudFrontにアクセス】

それぞれ設定通りに弾いてくれています。

署名付きCookieを使ってリクエスト

署名付きCookieを使ってリクエストを送信するにはポリシーの作成が必要です。
ポリシーには規定ポリシーとカスタムポリシーの2種類が存在します。

説明 規定ポリシー カスタムポリシー
ポリシーを複数のオブジェクトへの使用 ×
アクセス開始日時の指定        × ○ (オプション)
アクセスできなくなる日時の指定
IPアドレス、IPアドレス範囲指定 × ○(オプション)

規定ポリシーとカスタムポリシーではセットするCookieが異なるので注意

【AWS公式ドキュメント】署名付きCookieの使用

規定ポリシー カスタムポリシー
CloudFront-Expires CloudFront-Policy
CloudFront-Key-Pair-Id CloudFront-Key-Pair-Id
CloudFront-Signature CloudFront-Signature

今回はHLS形式で複数のファイルに対してリクエストを送るのでカスタムポリシーを使います。

ポリシーの作成

policy.jsonを作成
AWS:EpochTimeには必要な終了日時をUnix時間形式で指定

policy.json
{
    "Statement":
    [
        {
            "Resource":"http://xxxxxx.cloudfront.net/*",
            "Condition":
            {
                "DateLessThan":
                {
                    "AWS:EpochTime":1630163409
                }
            }
        }
    ]
}

インデント等を取り除きます。

policy.json
{"Statement":[{"Resource":"http://xxxxxx.cloudfront.net/*","Condition":{"DateLessThan":{"AWS:EpochTime":1630163409}}}]}

①Base64エンコード

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

②署名されたBase64エンコード

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

※キーペア作成時にダウンロードしたキーを指定

それぞれで表示された文字列とCloudFront-Key-Pair-IdCookieにセットしてアクセス
CloudFront-Policy: ①で作成した文字列
CloudFront-Signature: ②で作成した文字列
CloudFront-Key-Pair-Id: メモしておいたアクセスキーID

今回は、Postmanを使って取得してみます。

ちゃんと取得出来ました!

気が向いたら次はLambdaとAWS Elemental MediaConvertの記事書きます。

[その他参考]
Protect Private Content using CloudFront Signed Cookies