CloudFrontでセキュア(許可された人のみ)な配信を実現するには、Lambda@Edgeを実装するか、署名付きURLか署名付きCookieを使う事になります。
Lambda@Edgeよりも署名付きの方が、処理をAWSに任せられるのでシンプルに実現できます。
署名付きURLは、URLにパラメータを入れる事になるので、リクエスト毎に入れられる場合に使える。ワイルドカード(*)で複数ファイルを対象にする事もできる。
一方、署名付きCookieは、URLにパラメータを入れるのが難しい場合(ストリーミング配信等)に使えます。Cookieなので期限や複数同時に対応できるようにPath指定もした方が良さそう。
パブリックキーを作成
https://us-east-1.console.aws.amazon.com/cloudfront/v3/home#/publickey/create
パブリックキーを作成 パブリックキー 名前: cloudfront_public_key ※公開鍵のファイル名(拡張子なし)にしてみました。ドットは使えない キー: (作成した公開鍵の内容)※下記のコマンドで作成 [パブリックキーを作成]
% openssl genrsa -out cloudfront_private_key.pem 2048 % openssl rsa -pubout -in cloudfront_private_key.pem -out cloudfront_public_key.pem % cat cloudfront_public_key.pem
キーグループを作成
https://us-east-1.console.aws.amazon.com/cloudfront/v3/home#/keygrouplist/create
キーグループを作成 キーグループ 名前: cloudfront_public_key_group ※パブリックキー名に「_group」を付けてみました パブリックキー: cloudfront_public_keyを選択 [キーグループを作成]
ビヘイビアを作成
今回は構築済みのディストリビューションを使います。
→ CloudFront(S3オリジン)構築とawsコマンド(S3, CloudFront)メモ
また、今回は「/auth」ディレクトリ以下に制限を掛けるので、ビヘイビアを作りますが、
全体を対象にする場合はデフォルトのを編集するか、構築時に指定してください。
https://us-east-1.console.aws.amazon.com/cloudfront/v3/home#/distributions
対象のディストリビューション選択 ビヘイビア ビヘイビアを作成
ビヘイビアを作成 設定 パスパターン: /auth/* 〜ここからはデフォルトと同じのを選択 ※これ大事!〜 オリジンとオリジングループ: デフォルトと同じのを選択 ビューワー ビューワープロトコルポリシー: ●Redirect HTTP to HTTPS 許可されたHTTPメソッド: ●GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE HTTPメソッドをキャッシュ: ■オプション 〜ここまで〜 ビューワーのアクセスを制限する: ●Yes 信頼された認可タイプ: ●Trusted key groups (recommended) ※デフォルト キーグループを追加: 上記で作成したキーグループ名を選択 〜ここからはデフォルトと同じのを選択 ※これ大事!〜 キャッシュキーとオリジンリクエスト キャッシュポリシー: CachingOptimized ※デフォルト レスポンスヘッダーポリシー: CORS-With-Preflight 〜ここまで〜 [ビヘイビアを作成]
<省略(デフォルトと同じのを選択 ※これ大事!)>
→ 6. プリフライトリクエストに応答できず一部ユーザーが表示できず
<省略(デフォルトと同じのを選択 ※これ大事!)>
動作確認
動画を変換して設置しましたが、S3にアップロードしても良い。
→ S3設置トリガーで自動変換と、MediaConvertでCMAFを暗号化(未解決)してみる
% curl -i https://cdn.nightonly.com/auth/Big%20Buck%20Bunny.mp4_20220520002719/Big%20Buck%20Bunny.m3u8 HTTP/2 403 content-type: text/html content-length: 526 date: Thu, 19 May 2022 11:44:06 GMT last-modified: Wed, 02 Sep 2020 11:29:13 GMT etag: "0f2ee0533109062bc0ed22032229f69d" accept-ranges: bytes server: AmazonS3 vary: Origin x-cache: Error from cloudfront via: 1.1 2b20977f9e276750dc3347b53d99bae4.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-P2 x-amz-cf-id: 1JeRYrGgD0sQZcN1Zn_CifM1bGN99rup4tIiMwerYfEkCpUDOOtWcg== age: 47483 <html> <head> <meta name="robots" content="noindex" /> <title>Not Found</title> </head> <body> Not Found<br/> <!-- IE bug support dumy data 123456789012345678901234567890123456789012345678901234567890 123456789012345678901234567890123456789012345678901234567890 123456789012345678901234567890123456789012345678901234567890 123456789012345678901234567890123456789012345678901234567890 123456789012345678901234567890123456789012345678901234567890 123456789012345678901234567890123456789012345678901234567890 --> </body> </html>
エラーページで403を設定しているとそのページが返却される。
(S3に存在しなくても、署名がエラーでも403になる)
デバッグ時は解り難いので、一時的に外します。
MissingKeyが返却されるのでOK
% curl -i https://cdn.nightonly.com/auth/Big%20Buck%20Bunny.mp4_20220520002719/Big%20Buck%20Bunny.m3u8 HTTP/2 403 server: CloudFront date: Fri, 20 May 2022 00:57:45 GMT content-type: text/xml content-length: 146 vary: Origin x-cache: Error from cloudfront via: 1.1 2005babf9e16815c80be6808c6f595b0.cloudfront.net (CloudFront) x-amz-cf-pop: NRT12-C2 x-amz-cf-id: d8MdxP0kpFNxqQESzsYCSc8I0bXXQalB_L9MtU69e0zTr79FBLCcwg== <?xml version="1.0" encoding="UTF-8"?> <Error> <Code>MissingKey</Code> <Message>Missing Key-Pair-Id query parameter or cookie value</Message> </Error>
署名付きURLを試す
sign — AWS CLI 1.24.4 Command Reference
AWSコマンドで発行
% aws cloudfront sign \ --url https://cdn.nightonly.com/auth/Big%20Buck%20Bunny.mp4_20220520002719/Big%20Buck%20Bunny.m3u8 \ --key-pair-id K1**********X2 \ --private-key file://cloudfront_private_key.pem \ --date-less-than 2022-05-21T15:10:00+09:00 https://cdn.nightonly.com/auth/Big%20Buck%20Bunny.mp4_20220520002719/info.json?Expires=1653112080&Signature=fgTNi4pfrUFltHF65HcR2hQq08p63zOeyt2zSBRj9GDrkYc2vxo3~kudSm~i6F2zZeAup1SsRb1ujjYYR7oYzapR0kJqx~Fjb-E1~Kpz2ZN6XOhYDR0BxI5va1Cylx~4jSGl~01w4iA~~G5s9CwUYWV7WS6oe7JklijQVyVqzHkuTF~8H937I2jkXie5sUEFLII4iwPlGQYgj-x2Dfx8VD3iGM8Poclz6JO7-Yr8ctcbYg23LWbVNEp1vp3BfsbQEE~~CeOryz9mWnCcyoniBlmZwmmwngoJTqWmnndmpU9fQryocG9ZzcALWYuXf7NUbf8GmiGcFEVuXDtDqeG~Gg__&Key-Pair-Id=K1**********X2
url: 対象のURL(*を使う場合は–date-greater-thanの指定も必要)
key-pair-id: キーグループのパブリックキー(下記、画像参照)
private-key: 作成した秘密鍵(絶対パスで指定する場合は「file:///Users/xxx/xxx.pem」)
date-less-than: 有効期限の終了日時
動作確認
出力されたURLにリクエスト → 200で内容が返却される
% curl -i "https://cdn.nightonly.com/auth/Big%20Buck%20Bunny.mp4_20220520002719/Big%20Buck%20Bunny.m3u8?Expires=1653113400&Signature=fThfpMfITzArdvP5FVljmdTK-SVVTM9noxYpS8JNYxI6g7Ufl6f0SX1Eb6P7KD3jAWzwJLmTcxk0a8mETPpQMGN7rIyT7jVk2sAkJj5d1-wKpG4U1A6MxD92aLXFrpZiW57AhNI03wzKvZBigb6Nt1Z-0GY53HpGGIqYG4G7X4eqdGc0LTuVTgEkGLZUs3Ps~nsCTaWRLagfCIxP6HR1CZQDuvmIc~EJ6feR58NQta2~dWBBEeTAp1WhD35Jg98Qeb4Q8o2xVgMCvAZpDiIsJ-gXbyywxG2qrfVk39av8PYXsL2wsW4jGxTF2FU7~yRH9uO8WxrPrCQVFNBDG3xvsw__&Key-Pair-Id=K1**********X2" HTTP/2 200 content-type: application/vnd.apple.mpegurl content-length: 213 date: Sat, 21 May 2022 06:07:06 GMT last-modified: Fri, 20 May 2022 00:28:53 GMT etag: "3106d77c498a94487ddd4ce1a1139656" accept-ranges: bytes server: AmazonS3 vary: Origin x-cache: Miss from cloudfront via: 1.1 c9203ba15af2ae82294719bd8bb5fcce.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-P2 x-amz-cf-id: k-hDi4NHN-uPNSZBxc_9gEBy_e5kadMJZYN08uuUVvwGoCdBM8TZHQ== #EXTM3U #EXT-X-VERSION:3 #EXT-X-INDEPENDENT-SEGMENTS #EXT-X-STREAM-INF:BANDWIDTH=1165158,AVERAGE-BANDWIDTH=727352,CODECS="avc1.4d401f,mp4a.40.2",RESOLUTION=1280x720,FRAME-RATE=24.000 Big%20Buck%20Bunny_video.m3u8
終了日時以降にリクエスト → 403(AccessDenied)になる
% curl -i "https://cdn.nightonly.com/auth/Big%20Buck%20Bunny.mp4_20220520002719/Big%20Buck%20Bunny.m3u8?Expires=1653113400&Signature=fThfpMfITzArdvP5FVljmdTK-SVVTM9noxYpS8JNYxI6g7Ufl6f0SX1Eb6P7KD3jAWzwJLmTcxk0a8mETPpQMGN7rIyT7jVk2sAkJj5d1-wKpG4U1A6MxD92aLXFrpZiW57AhNI03wzKvZBigb6Nt1Z-0GY53HpGGIqYG4G7X4eqdGc0LTuVTgEkGLZUs3Ps~nsCTaWRLagfCIxP6HR1CZQDuvmIc~EJ6feR58NQta2~dWBBEeTAp1WhD35Jg98Qeb4Q8o2xVgMCvAZpDiIsJ-gXbyywxG2qrfVk39av8PYXsL2wsW4jGxTF2FU7~yRH9uO8WxrPrCQVFNBDG3xvsw__&Key-Pair-Id=K1**********X2" HTTP/2 403 server: CloudFront date: Sat, 21 May 2022 06:30:01 GMT content-type: text/xml content-length: 110 vary: Origin x-cache: Error from cloudfront via: 1.1 c840859ec974616ca6ae517a4e6900e8.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-P2 x-amz-cf-id: U9b1q0XpPJoSC-SrXh8CVoecCopAtiAJVTX9lOZh2-MlXjFgIf6HEw== <?xml version="1.0" encoding="UTF-8"?><Error><Code>AccessDenied</Code><Message>Access denied</Message></Error>%
署名付きCookieを試す
カスタムポリシーを使用する署名付き Cookie の設定 – Amazon CloudFront
opensslで作成
エポック秒(UNIX秒)変換 : Developer Tools
JST「2022-05-21 18:30:00」→「1653125400」
CloudFront-Policyに設定する値
% echo '{"Statement":[{"Resource":"https://cdn.nightonly.com/auth/Big%20Buck%20Bunny.mp4_20220520002719/*","Condition":{"DateLessThan":{"AWS:EpochTime":1653125400}}}]}' > policy.json % cat policy.json | openssl base64 | tr '+=/' '-_~' eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9jZG4ubmlnaHRvbmx5 LmNvbS9hdXRoL0JpZyUyMEJ1Y2slMjBCdW5ueS5tcDRfMjAyMjA1MjAwMDI3MTkv KiIsIkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6 MTY1MzEyNTQwMH19fV19Cg__
CloudFront-Signatureに設定する値
% cat policy.json | openssl sha1 -sign cloudfront_private_key.pem | openssl base64 | tr '+=/' '-_~' NLzCFTsnDHLkg1Od~S3GYs64bxbvIB8LaD9X-2DKWrtUxxJKx2swif6lrsCP-hgq FFJ8AP8HN0u82OzKQmQr~8mlzVt6PqH~640jXetlE3MIe-X~8Txsy7SNsPvuIrWr MpjeeusBa~xzhnwXAF4Ek~h2AyNUuPv8NF8a7olPYOntkWzJj9GLzUG6TChEfsB8 iBw-eSaNwmHm0twzijl7jlgKxTsoYJr6Jv3p54sUFzmw3W1-VSbOUKafRnhuTjil SKfc498I1yfnjawBzFKpZMcd4Vi7lKWJ0GA7GSjX8Mzm6HUPXhloRft0sVePrBhA Sd43gIzchwx2NIcqYsCT6A__
動作確認
CloudFront-Policy: 上記で作成した値
CloudFront-Signature: 上記で作成した値
CloudFront-Key-Pair-Id: キーグループのパブリックキー(下記、画像参照)
終了日時前にリクエスト → 200で内容が返却される
% curl -i -H 'Cookie:CloudFront-Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9jZG4ubmlnaHRvbmx5LmNvbS9hdXRoL0JpZyUyMEJ1Y2slMjBCdW5ueS5tcDRfMjAyMjA1MjAwMDI3MTkvKiIsIkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTY1MzEyNTQwMH19fV19Cg__' \ -H 'Cookie:CloudFront-Signature=NLzCFTsnDHLkg1Od~S3GYs64bxbvIB8LaD9X-2DKWrtUxxJKx2swif6lrsCP-hgqFFJ8AP8HN0u82OzKQmQr~8mlzVt6PqH~640jXetlE3MIe-X~8Txsy7SNsPvuIrWrMpjeeusBa~xzhnwXAF4Ek~h2AyNUuPv8NF8a7olPYOntkWzJj9GLzUG6TChEfsB8iBw-eSaNwmHm0twzijl7jlgKxTsoYJr6Jv3p54sUFzmw3W1-VSbOUKafRnhuTjilSKfc498I1yfnjawBzFKpZMcd4Vi7lKWJ0GA7GSjX8Mzm6HUPXhloRft0sVePrBhASd43gIzchwx2NIcqYsCT6A__' \ -H 'Cookie:CloudFront-Key-Pair-Id=K1**********X2' \ https://cdn.nightonly.com/auth/Big%20Buck%20Bunny.mp4_20220520002719/Big%20Buck%20Bunny.m3u8 HTTP/2 200 content-type: application/vnd.apple.mpegurl content-length: 213 date: Sat, 21 May 2022 06:07:06 GMT last-modified: Fri, 20 May 2022 00:28:53 GMT etag: "3106d77c498a94487ddd4ce1a1139656" accept-ranges: bytes server: AmazonS3 vary: Origin x-cache: Hit from cloudfront via: 1.1 31644ad9395bb6bc6190c221b30bd768.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C4 x-amz-cf-id: CcNdce7uCgYN0yGbzFIezZUydXGxVp7CfLDHA_EuhtWmGVRJd1BFSQ== age: 11788 #EXTM3U #EXT-X-VERSION:3 #EXT-X-INDEPENDENT-SEGMENTS #EXT-X-STREAM-INF:BANDWIDTH=1165158,AVERAGE-BANDWIDTH=727352,CODECS="avc1.4d401f,mp4a.40.2",RESOLUTION=1280x720,FRAME-RATE=24.000 Big%20Buck%20Bunny_video.m3u8
終了日時以降にリクエスト → 403(AccessDenied)になる
HTTP/2 403 server: CloudFront date: Sat, 21 May 2022 09:30:50 GMT content-type: text/xml content-length: 110 vary: Origin x-cache: Error from cloudfront via: 1.1 c8cb49c2b391bae10c56b1a57df509d0.cloudfront.net (CloudFront) x-amz-cf-pop: NRT57-C4 x-amz-cf-id: vrL8QcESB9QdTcJjAdEVat43dpzjxIZslrPe1LXmbm8ecTrmj1CR2A== <?xml version="1.0" encoding="UTF-8"?><Error><Code>AccessDenied</Code><Message>Access denied</Message></Error>