IVS Low-Latency StreamingのPlayback Restriction PolicyでStrict Origin Enforcement有効時の挙動を確認してみた

Strict Origin Enforcementを有効にすると、リクエスト時のOriginヘッダが指定した値以外のものだった際にplaylistやsegments自体をレスポンスに含まず、403でエラーを返します。より厳密に再生制限が可能です。
2024.03.13

はじめに

清水です。先日2024/02/01のアップデートで、Amazon Interactive Video Service (Amazon IVS)のLow-Latency Streamingでポリシーによる再生制限ができるPlayback restriction policiesが利用可能になりました。

本DevelopersIOでも以下エントリで速報としてお届けしています。

上記のエントリではPlayback Restriction Policyの2つの機能、geo-blockingとcross-origin resource sharing (CORS)レスポンスヘッダそれぞれで、設定の際の基本的な挙動について確認しています。ただし、 Strict Origin Enforcemnet というオプションについては動作を省略していました。このStrict Origin Enforcement、デフォルトの無効状態ではOriginヘッダによる制限がトップレベルのマニフェスファイル(IVSの用語ではMultivariant playlist)のみに適用されます。Strict Origin Enforcementを有効にすることで、Multivariant playliset以外のすべてのリクエストに対しても、Originヘッダによる制限を適用するという機能のようです。

Note on strict origin enforcement: This is an optional setting that can be used to strengthen the origin restriction specified with allowed origins. By default, the origin restriction applies only to the multivariant playlist. If strict origin enforcement is enabled, the server will enforce a requirement that the requesting origin matches the token for all playback requests (including multivariant playlist, variant playlist, and segments). This means that all clients (including non-browser clients) will have to provide a valid origin-request header with each request. Use the setOrigin method to set the header in the IVS iOS and Android player SDKs. It is set automatically in web browsers except iOS Safari. For iOS Safari, you need to add crossorigin="anonymous" to the video element, to ensure that the origin request header is sent. Example: <video crossorigin="anonymous"></video>.

Console Instructions (Playback Restriction Policy) - Amazon Interactive Video Service

本エントリでは、このStrict Origin Enforcementを有効に設定して、Playback Restriction PolicyのAllowed Originで指定したOriginヘッダを用いてアクセスした場合、または指定したOriginヘッダを用いずにアクセスした場合の挙動を確認してみましたのでまとめてみます。なかなかの長文エントリとなってしまいました。左側のインデックスを活用していただきつつ、まずは結果が確認したい、という場合は「検証結果のまとめ」から確認いただくとよいかと思います。

なお本ブログエントリの内容、具体的にはレスポンスヘッダの詳細やレスポンスのステータスコードなどといった細かな挙動について、User Guideに記載されていない項目は変更される可能性がないとは言い切れません。あくまでUser Guide記載の挙動を基準に処理などを行いましょう。また、今回の動作検証ではCORSのプリフライトリクエストについては考慮していません。

動作確認環境や確認内容について

動作確認を行った検証環境についてあらかじめまとめておきます。

リソースは以下環境のAWS CLIで作成、操作しました。

% aws --version
aws-cli/2.15.17 Python/3.11.6 Darwin/22.6.0 exe/x86_64 prompt/off

AWS CLIでのIVS Playback restriction policiesの操作については以下ブログエントリを参照ください。

上記エントリを執筆した先日2024/02/02の段階ではAWS CLI v2ではPlayback restriction policiesに対応していませんでしたが、2.15.17からサポートしたようです。

IVS Low-Latency Streaming Channelの作成とストリーミング実施

Channelは以下で作成しました。デフォルト設定でaws ivs create-channelを実行しています。

% aws ivs create-channel \
    --name "strict-origin-enforcement-test-channel"
{
    "channel": {
        "arn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd",
        "authorized": false,
        "ingestEndpoint": "62xxxxxxxx2b.global-contribute.live-video.net",
        "insecureIngest": false,
        "latencyMode": "LOW",
        "name": "strict-origin-enforcement-test-channel",
        "playbackRestrictionPolicyArn": "",
        "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8",
        "preset": "",
        "recordingConfigurationArn": "",
        "tags": {},
        "type": "STANDARD"
    },
    "streamKey": {
        "arn": "arn:aws:ivs:ap-northeast-1:123456789012:stream-key/LAxxxxxxxx23",
        "channelArn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd",
        "tags": {},
        "value": "sk_ap-northeast-1_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    }
}

Channel作成後、AWSマネジメントコンソールからストリーミングを行っています。操作方法などについては以下を参照ください。

マネジメントコンソールからストリーミングを行い、aws ivs get-streamコマンドで配信中の状態であること、ならびにPlayback URLを確認しておきます。

% aws ivs get-stream \
    --channel-arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd"
{
    "stream": {
        "channelArn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd",
        "health": "HEALTHY",
        "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8",
        "startTime": "2024-02-08T06:33:01+00:00",
        "state": "LIVE",
        "streamId": "st-1HxxxxxxxxxxxxxxxxxxxyT",
        "viewerCount": 0
    }
}

リクエスト対象の各ファイルについて

続いて、動作を確認した(実際にリクエストを行った)ファイルについて確認しておきましょう。

まずはPlayback URLで得られる以下URLです。HLSの再生に必要なマニフェストファイルの中でも、最上位(起点)となるトップレベルのマニフェスファイルですね。Amazon IVS Low-Latency Streamingの用語(Glossary - Amazon Interactive Video Service)としては Multivariant playlist と呼んでいますので、本ブログエントリでも以降はこの呼称とします。

  • https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8

このMultivariant playlistの中身は、以下のように複数のマニフェストファイルで構成されています。Rendition(Adaptive Bitrate (ABR) Streamingの解像度やビットレートの組み合わせ)ごとに異なるプレイリストとなっているぐあいですね。子プレイリストなどとも呼ばれますが、ここでもIVSのUser Guideにならい 本エントリでは variant playlist と称することとします。なお、Renditionの数はIVSのChannel Typeや入力動画の解像度等によって異なります。

#EXTM3U
#EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-65acdc.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707375471.67"
#EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1"
#EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]"
#EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="1495.671007"
#EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05"
#EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012"
#EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列1]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列2]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列3]).m3u8

このファイル内、複数のRenditionの中で一番上位のプレイリストファイル、ここではNAME="480p"のものにアクセスします。

#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列1]).m3u8

variant playlistにアクセスすると、数秒ごとに区切られた動画ファイルで構成されたプレイリストが得られます。セグメントファイルと呼ばれるものですね。こちらもIVS User Guideにならい、 segments と本エントリ内では表記します。

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:771
#EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:771
#EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:1542.002
#EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:1574.053
#EXT-X-DATERANGE:ID="playlist-creation-1707375550",CLASS="timestamp",START-DATE="2024-02-07T22:59:10.452-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707375550.45"
#EXT-X-DATERANGE:ID="source-1707375520",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T06:58:40.089Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live"
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:40.089Z
#EXTINF:2.012,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列1].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:42.101Z
#EXTINF:2.017,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列2].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:44.118Z
#EXTINF:1.978,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列3].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:46.096Z
#EXTINF:2.012,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列4].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:48.108Z
#EXTINF:2.014,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列5].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:50.122Z
#EXTINF:1.980,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列6].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:52.102Z
#EXTINF:2.013,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列7].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:54.115Z
#EXTINF:1.980,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列8].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:56.095Z
#EXTINF:2.013,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列9].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:58:58.108Z
#EXTINF:1.980,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列10].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:59:00.088Z
#EXTINF:2.011,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列11].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:59:02.099Z
#EXTINF:2.015,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列12].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:59:04.114Z
#EXTINF:1.978,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列13].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:59:06.092Z
#EXTINF:2.016,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列14].ts
#EXT-X-PREFETCH:https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列15].ts
#EXT-X-PREFETCH:https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列16].ts

最下部にはLL-HLS (Low-Latency HLS)用の#EXT-X-PREFETCHに続きsegmentsへのURLが並びますが、今回はその#EXT-X-PREFETCHタグの1つ上にあるsegmentsへアクセスすることとします。

#EXT-X-PROGRAM-DATE-TIME:2024-02-08T06:59:06.092Z
#EXTINF:2.016,live
https://video-edge-65acdc.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列14].ts

以上で、アクセス対象となる multivariant playlistvariant playlist 、そして segments について、どのファイルであるかの確認ができました。

Playback Restriction Policyを適用していない状態でのレスポンスヘッダの確認

確認の対象となるストリーミング再生のためのファイルについて確認できたところで、まずはPlayback Restriction Policyを適用していない状態でのレスポンスヘッダについて確認してみましょう。以下3パターンで確認していきたいと思います。

まず1つ目のパターンでは、リクエスト時に "https://allowed-origin.example.net" という値のOriginヘッダを付与します。このOriginヘッダの値は動画プレイヤーを埋め込んだWebサイトの想定です。意図したOriginヘッダの値であるため、レスポンスではCORS用の適切なAccess-Control-Allow-Originヘッダが含まれることが期待されます。このパターンは 許可想定のOriginヘッダ値を付与したリクエスト と表記することとします。

以下がリクエスト実行のフォーマットです。curlコマンドを用いて実行します。

  • curl -i -H "Origin: https://allowed-origin.example.net" <アクセス対象の各ファイル>

なおcurlコマンドに-iオプションを付与してレスポンスボディに加えてレスポンスヘッダを表示させています。-Iオプションでレスポンスヘッダのみを表示させることも考えたのですが、GETリクエストとHEADリクエストの違いないのか、-Iオプションでは一部ファイルで付与されるレスポンスヘッダ内でtransfer-encoding: chunkedがなくなっていたため、本エントリ内では-iオプションを使用することとしました。

2つ目パターンでは、リクエスト時に "https://not-allowed-origin.example.net" という値のOriginヘッダを付与します。このOriginヘッダは動画プレイヤーを埋め込んだ正しいWebサイト ではない ホスト名という想定です。Playback Restriction Policyを使用することで、レスポンスに適切なAccess-Control-Allow-Originヘッダを含まずに再生を制限することが期待されます。 許可をしていない想定のOriginヘッダ値を付与したリクエスト と表記します。

  • curl -i -H "Origin: https://not-allowed-origin.example.net" <アクセス対象の各ファイル>

3つ目のパターンは、リクエスト時にOriginヘッダを指定しないものです。こちらもPlayback Restriction Policyを使用することで、レスポンスに適切なAccess-Control-Allow-Originヘッダを含まずに再生を制限することが期待されます。 Originヘッダなしのリクエスト と称します。

  • curl -i <アクセス対象の各ファイル>

確認する3つのパターンを抑えたところで、実際にまずは、Playback Restriction Policyを適用していない状態でのレスポンスヘッダを確認してみます。

許可想定のOriginヘッダ値を付与したリクエスト

まずは許可想定のOriginヘッダ値を付与したリクエストです。multivariant playlist、variant playlist、segmentsのいずれでも、レスポンスヘッダにaccess-control-allow-origin: *Access-Control-Allow-Origin: *)が付与されていることがわかります。Playback Restriction Policyを適用していない状態ではOriginヘッダの値によるストリーミングの再生制限は行われません。許可を想定したOriginヘッダ値を付与してリクエストしても、すべてのWebサイト(ドメイン)に対して再生が許可される値が*の値でaccess-control-allow-originヘッダがレスポンスとして返されます。

multivariant playlist

% curl -i -H "Origin: https://allowed-origin.example.net" "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8"
HTTP/2 200
content-type: application/vnd.apple.mpegurl
content-length: 6123
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:26:33 GMT
access-control-allow-origin: *
x-amzn-trace-id: Root=1-65xxxx29-57xxxxxxxxxxxxxxxxxxxxc3
x-amzn-trace-id: Root=1-65xxxx29-57xxxxxxxxxxxxxxxxxxxxc3
x-cache: Miss from cloudfront
via: 1.1 09xxxxxxxxxxxxxxxxxxxxxxxxxxxxf6.cloudfront.net (CloudFront)
x-amz-cf-pop: HKG54-C1
x-amz-cf-id: 03xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==

#EXTM3U
#EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-b02154.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707377193.14"
#EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1"
#EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]"
#EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="3217.135438"
#EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05"
#EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012"
#EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列4]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列5]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列6]).m3u8

variant playlist

% curl -i -H "Origin: https://allowed-origin.example.net" "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列4]).m3u8"
HTTP/1.1 200 OK
cache-control: no-cache, no-store, private
content-type: application/vnd.apple.mpegurl
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:27:57 GMT
transfer-encoding: chunked
access-control-allow-origin: *

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:1634
#EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:1634
#EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:3267.999
#EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:3301.959
#EXT-X-DATERANGE:ID="playlist-creation-1707377277",CLASS="timestamp",START-DATE="2024-02-07T23:27:57.887-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707377277.89"
#EXT-X-DATERANGE:ID="source-1707377246",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:27:26.086Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live"
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:26.086Z
#EXTINF:2.021,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列17].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:28.107Z
#EXTINF:2.006,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列18].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:30.113Z
#EXTINF:1.986,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列19].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:32.099Z
#EXTINF:2.009,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列20].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:34.108Z
#EXTINF:1.979,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列21].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:36.087Z
#EXTINF:2.016,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列22].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:38.103Z
#EXTINF:1.978,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列23].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:40.081Z
#EXTINF:2.017,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列24].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:42.098Z
#EXTINF:2.011,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列25].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:44.109Z
#EXTINF:1.980,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列26].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:46.089Z
#EXTINF:2.010,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列27].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:48.099Z
#EXTINF:1.984,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列28].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:50.083Z
#EXTINF:2.013,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列29].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:52.096Z
#EXTINF:2.010,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列30].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:27:54.106Z
#EXTINF:1.980,live
https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列31].ts
#EXT-X-PREFETCH:https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列32].ts
#EXT-X-PREFETCH:https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列33].ts

segments

% curl -i -H "Origin: https://allowed-origin.example.net" "https://video-edge-b02154.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列31].ts"
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, private
Content-Type: application/octet-stream
Date: Thu, 08 Feb 2024 07:29:16 GMT
Transfer-Encoding: chunked

Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.

許可をしていない想定のOriginヘッダ値を付与したリクエスト

続いて許可をしていない想定のOriginヘッダ値を付与したリクエストです。繰り返しになりますが、Playback Restriction Policyを適用していない状態ではOriginヘッダによる制限は行われません。このパターンでもmultivariant playlist、variant playlist、segmentsそれぞれでヘッダにaccess-control-allow-origin: *Access-Control-Allow-Origin: *)が付与されたレスポンスが返り、いずれのWebサイトでもストリーミング再生が可能となります。

multivariant playlist

% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8"
HTTP/2 200
content-type: application/vnd.apple.mpegurl
content-length: 6123
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:32:08 GMT
access-control-allow-origin: *
x-amzn-trace-id: Root=1-65xxxx78-3fxxxxxxxxxxxxxxxxxxxx2f
x-amzn-trace-id: Root=1-65xxxx78-3fxxxxxxxxxxxxxxxxxxxx2f
x-cache: Miss from cloudfront
via: 1.1 d5xxxxxxxxxxxxxxxxxxxxxxxxxxxx4e.cloudfront.net (CloudFront)
x-amz-cf-pop: KIX50-P1
x-amz-cf-id: cjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==

#EXTM3U
#EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-ab9cf4.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707377528.08"
#EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1"
#EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]"
#EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="3552.077476"
#EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05"
#EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012"
#EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列7]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列8]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列9]).m3u8%

variant playlist

% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列7]).m3u8"
HTTP/1.1 200 OK
cache-control: no-cache, no-store, private
content-type: application/vnd.apple.mpegurl
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:34:05 GMT
transfer-encoding: chunked
access-control-allow-origin: *

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:1819
#EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:1819
#EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:3637.999
#EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:3670.039
#EXT-X-DATERANGE:ID="playlist-creation-1707377645",CLASS="timestamp",START-DATE="2024-02-07T23:34:05.165-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707377645.16"
#EXT-X-DATERANGE:ID="source-1707377616",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:33:36.086Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live"
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:36.086Z
#EXTINF:2.011,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列34].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:38.097Z
#EXTINF:2.013,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列35].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:40.110Z
#EXTINF:1.983,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列36].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:42.093Z
#EXTINF:2.016,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列37].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:44.109Z
#EXTINF:2.007,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列38].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:46.116Z
#EXTINF:2.016,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列39].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:48.132Z
#EXTINF:1.978,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列40].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:50.110Z
#EXTINF:1.978,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列41].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:52.088Z
#EXTINF:2.013,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列42].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:54.101Z
#EXTINF:1.985,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列43].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:56.086Z
#EXTINF:2.012,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列44].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:33:58.098Z
#EXTINF:1.984,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列45].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:34:00.082Z
#EXTINF:2.008,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列46].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:34:02.090Z
#EXTINF:2.012,live
https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列47].ts
#EXT-X-PREFETCH:https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列48].ts
#EXT-X-PREFETCH:https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列49].ts

segments

% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://video-edge-ab9cf4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列47].ts"
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, private
Content-Type: application/octet-stream
Date: Thu, 08 Feb 2024 07:34:48 GMT
Transfer-Encoding: chunked

Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.

Originヘッダなしのリクエスト

続いてはOriginヘッダがない場合のリクエストについての確認です。こちらもPlayback Restriction Policyを適用していない状態では、いずれのファイルへのリクエストでもそれぞれレスポンスヘッダにaccess-control-allow-origin: *Access-Control-Allow-Origin: *)が付与されていました。Originヘッダがない場合にはAccess-Control-Allow-Originヘッダを返さない、という環境もあるかと思いますが(例えばAmazon S3はこのような動作だった認識です)、IVSでPlayback Restriction Policyを適用していない場合は、リクエスト時にOriginヘッダがなくともレスポンスとしてaccess-control-allow-origin: *Access-Control-Allow-Origin: *)が返ってくる、という動作になります。

multivariant playlist

% curl -i "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8"
HTTP/2 200
content-type: application/vnd.apple.mpegurl
content-length: 6126
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:37:19 GMT
access-control-allow-origin: *
x-amzn-trace-id: Root=1-65xxxxaf-3axxxxxxxxxxxxxxxxxxxxf6
x-amzn-trace-id: Root=1-65xxxxaf-3axxxxxxxxxxxxxxxxxxxxf6
x-cache: Miss from cloudfront
via: 1.1 cexxxxxxxxxxxxxxxxxxxxxxxxxxxx40.cloudfront.net (CloudFront)
x-amz-cf-pop: KIX50-P1
x-amz-cf-id: -sxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==

#EXTM3U
#EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-b01e58.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707377839.86"
#EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1"
#EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]"
#EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="3863.862990"
#EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05"
#EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012"
#EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列10]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列11]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列12]).m3u8%

variant playlist

% curl -i "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列10]).m3u8"
HTTP/1.1 200 OK
cache-control: no-cache, no-store, private
content-type: application/vnd.apple.mpegurl
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:37:50 GMT
transfer-encoding: chunked
access-control-allow-origin: *

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:1931
#EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:1931
#EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:3862.004
#EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:3895.958
#EXT-X-DATERANGE:ID="playlist-creation-1707377870",CLASS="timestamp",START-DATE="2024-02-07T23:37:50.717-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707377870.72"
#EXT-X-DATERANGE:ID="source-1707377840",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:37:20.091Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live"
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:20.091Z
#EXTINF:2.010,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列50].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:22.101Z
#EXTINF:1.981,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列51].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:24.082Z
#EXTINF:2.020,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列52].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:26.102Z
#EXTINF:2.007,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列53].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:28.109Z
#EXTINF:1.985,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列54].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:30.094Z
#EXTINF:2.007,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列55].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:32.101Z
#EXTINF:1.980,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列56].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:34.081Z
#EXTINF:2.016,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列57].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:36.097Z
#EXTINF:1.979,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列58].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:38.076Z
#EXTINF:2.012,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列59].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:40.088Z
#EXTINF:2.014,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列60].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:42.102Z
#EXTINF:1.985,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列61].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:44.087Z
#EXTINF:2.044,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列62].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:46.131Z
#EXTINF:1.974,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列63].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:37:48.105Z
#EXTINF:1.980,live
https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列64].ts
#EXT-X-PREFETCH:https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列65].ts
#EXT-X-PREFETCH:https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列66].ts

segments

% curl -i "https://video-edge-b01e58.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列64].ts"
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, private
Content-Type: application/octet-stream
Date: Thu, 08 Feb 2024 07:38:25 GMT
Transfer-Encoding: chunked

Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.

Playback Restriction Policyの作成と適用

Playback Restriction Policyを適用していない場合、リクエスト時のOriginヘッダの有無そしてその内容(値)にかかわらずレスポンスヘッダにはaccess-control-allow-origin: *Access-Control-Allow-Origin: *)が含まれており、Originヘッダによるストリーミング再生の制限制限は行われていないことが確認できました。

続いてPlayback Restriction Policyを適用した状態での確認に入りますが、その前にPlayback Restriction Policyの作成とChannelへの適用を行います。

Playback Restriction Policyの作成

Playback Restriction Policyの作成もAWS CLIで行います。以下のようにaws ivs create-playback-restriction-policyコマンドで作成しました。ストリーミング再生を許可するサイトドメインとして https://allowed-origin.example.net--allowed-originsオプションで指定します。またStrict Origin Enforcmentについてはオプションで指定を行わず、デフォルトの無効状態で作成します。("enableStrictOriginEnforcement": false

% aws ivs create-playback-restriction-policy \
    --name "strict-origin-enforcement-test-policy" \
    --allowed-origins '["https://allowed-origin.example.net"]'
{
    "playbackRestrictionPolicy": {
        "allowedCountries": [],
        "allowedOrigins": [
            "https://allowed-origin.example.net"
        ],
        "arn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB",
        "enableStrictOriginEnforcement": false,
        "name": "strict-origin-enforcement-test-policy",
        "tags": {}
    }
}

Playback Restriction PolicyのChannelへのアタッチ

続いて作成したPlayback Restriction PolicyをChannelリソースに関連付けます。Channelでライブストリーム中はアタッチできない(UpdateChannelでエラーとなってしまう)ため、マネジメントコンソールからライブストリームを中断してaws ivs update-channelコマンドを実行しました。

aws ivs update-channelコマンド実行前、さきほどの「Playback Restriction Policyを適用していない状態でのレスポンスヘッダの確認」を行った状態ではPolicyは未設定でした。

% aws ivs get-channel \
    --arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd"
{
    "channel": {
        "arn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd",
        "authorized": false,
        "ingestEndpoint": "62xxxxxxxx2b.global-contribute.live-video.net",
        "insecureIngest": false,
        "latencyMode": "LOW",
        "name": "strict-origin-enforcement-test-channel",
        "playbackRestrictionPolicyArn": "",
        "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8",
        "preset": "",
        "recordingConfigurationArn": "",
        "tags": {},
        "type": "STANDARD"
    }
}

aws ivs update-channelを実行します。"playbackRestrictionPolicyArn"に値が含まれていることが確認できますね。

% aws ivs update-channel \
    --arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd" \
    --playback-restriction-policy-arn "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB"
{
    "channel": {
        "arn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd",
        "authorized": false,
        "ingestEndpoint": "62xxxxxxxx2b.global-contribute.live-video.net",
        "insecureIngest": false,
        "latencyMode": "LOW",
        "name": "strict-origin-enforcement-test-channel",
        "playbackRestrictionPolicyArn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB",
        "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8",
        "preset": "",
        "recordingConfigurationArn": "",
        "tags": {},
        "type": "STANDARD"
    }
}
% aws ivs get-channel \
    --arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd"
{
    "channel": {
        "arn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd",
        "authorized": false,
        "ingestEndpoint": "62xxxxxxxx2b.global-contribute.live-video.net",
        "insecureIngest": false,
        "latencyMode": "LOW",
        "name": "strict-origin-enforcement-test-channel",
        "playbackRestrictionPolicyArn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB",
        "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8",
        "preset": "",
        "recordingConfigurationArn": "",
        "tags": {},
        "type": "STANDARD"
    }
}

Playback Restriction PolicyをChannelにアタッチ後、再度AWSマネジメントコンソールからストリームを行います。aws ivs get-streamコマンドでライブストリーミング中であることを確認しておきましょう。

% aws ivs get-stream \
    --channel-arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd"
{
    "stream": {
        "channelArn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd",
        "health": "HEALTHY",
        "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8",
        "startTime": "2024-02-08T07:46:11+00:00",
        "state": "LIVE",
        "streamId": "st-1CxxxxxxxxxxxxxxxxxxxpY",
        "viewerCount": 0
    }
}

Playback Restriction PolicyでAllowed Originを追加した状態でのレスポンスヘッダの確認

Playback Restriction PolicyをアタッチしたChannelの準備ができ、ライブストリーミングを再開しました。この状態、Playback Restriction PolicyでAllowed Originを追加した状況下でレスポンスヘッダの確認をしてみましょう。

ChannelにアタッチしているPlayback Restriction Policyでは"allowedOrigins"として許可対象の "https://allowed-origin.example.net" を追加、Strict Origin Enforcmentは無効の状態です。

% aws ivs get-playback-restriction-policy \
    --arn "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB"
{
    "playbackRestrictionPolicy": {
        "allowedCountries": [],
        "allowedOrigins": [            "https://allowed-origin.example.net"
        ],
        "arn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB",
        "enableStrictOriginEnforcement": false,
        "name": "strict-origin-enforcement-test-policy",
        "tags": {}
    }
}

許可想定のOriginヘッダ値を付与したリクエスト

まずは許可想定のOriginヘッダ値を付与したリクエストです。multivariant playlistではレスポンスヘッダとして、許可想定としたホスト名である https://allowed-origin.example.net を値にしたaccess-control-allow-originヘッダ、 access-control-allow-origin: https://allowed-origin.example.net が含まれていました。

variant playlistならびにsegmentsでは、access-control-allow-origin: *Access-Control-Allow-Origin: *)とaccess-control-allow-originヘッダの値はワイルドカード *で、どのホスト名でもCORSを許可する状態です。最上位のmultivariant playlistでのみ、ホスト名(埋め込みWebサイトのドメイン)を制限している状況ですね。

multivariant playlist

% curl -i -H "Origin: https://allowed-origin.example.net" "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8"
HTTP/2 200
content-type: application/vnd.apple.mpegurl
content-length: 6125
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:48:08 GMT
access-control-allow-origin: https://allowed-origin.example.net
x-amzn-trace-id: Root=1-65xxxx38-6cxxxxxxxxxxxxxxxxxxxxdd
x-amzn-trace-id: Root=1-65xxxx38-6cxxxxxxxxxxxxxxxxxxxxdd
x-cache: Miss from cloudfront
via: 1.1 22xxxxxxxxxxxxxxxxxxxxxxxxxxxx46.cloudfront.net (CloudFront)
x-amz-cf-pop: KIX50-P1
x-amz-cf-id: DJxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==

#EXTM3U
#EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-785cca.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707378488.38"
#EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1"
#EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]"
#EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="122.377198"
#EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05"
#EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012"
#EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列13]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列14]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列15]).m3u8%

variant playlist

% curl -i -H "Origin: https://allowed-origin.example.net" "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列13]).m3u8"
HTTP/1.1 200 OK
cache-control: no-cache, no-store, private
content-type: application/vnd.apple.mpegurl
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:49:11 GMT
transfer-encoding: chunked
access-control-allow-origin: *

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:77
#EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:77
#EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:153.986
#EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:186.018
#EXT-X-DATERANGE:ID="playlist-creation-1707378551",CLASS="timestamp",START-DATE="2024-02-07T23:49:11.912-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707378551.91"
#EXT-X-DATERANGE:ID="source-1707378522",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:48:42.623Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live"
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:42.623Z
#EXTINF:2.010,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列67].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:44.633Z
#EXTINF:1.980,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列68].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:46.613Z
#EXTINF:2.012,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列69].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:48.625Z
#EXTINF:2.016,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列70].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:50.641Z
#EXTINF:1.982,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列71].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:52.623Z
#EXTINF:2.011,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列72].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:54.634Z
#EXTINF:1.981,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列73].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:56.615Z
#EXTINF:2.010,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列74].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:48:58.625Z
#EXTINF:2.017,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列75].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:49:00.642Z
#EXTINF:1.979,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列76].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:49:02.621Z
#EXTINF:2.012,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列77].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:49:04.633Z
#EXTINF:1.977,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列78].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:49:06.610Z
#EXTINF:2.018,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列79].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:49:08.628Z
#EXTINF:2.009,live
https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列80].ts
#EXT-X-PREFETCH:https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列81].ts
#EXT-X-PREFETCH:https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列82].ts

segments

% curl -i -H "Origin: https://allowed-origin.example.net" "https://video-edge-785cca.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列80].ts"
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, private
Content-Type: application/octet-stream
Date: Thu, 08 Feb 2024 07:50:12 GMT
Transfer-Encoding: chunked

Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.

許可をしていない想定のOriginヘッダ値を付与したリクエスト

続いて、許可をしていない想定のOriginヘッダ値を付与したリクエスト行ってみます。multivariant playlistではレスポンスに access-control-allow-origin ヘッダは含まれておらず、CORSエラーとなり動画再生が制限される状態となります。

ただし、variant playlistならびにsegmentsではaccess-control-allow-origin: *Access-Control-Allow-Origin: *)となっています。access-control-allow-originヘッダの値はワイルドカード *で、どのホスト名でもCORSを許可する状態ですね。最上位のmultivariant playlistでのみ再生制限を行っていることが確認できます。

multivariant playlist

% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8"
HTTP/2 200
content-type: application/vnd.apple.mpegurl
content-length: 6125
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:50:59 GMT
x-amzn-trace-id: Root=1-65xxxxe3-58xxxxxxxxxxxxxxxxxxxxf5
x-amzn-trace-id: Root=1-65xxxxe3-58xxxxxxxxxxxxxxxxxxxxf5
x-cache: Miss from cloudfront
via: 1.1 4bxxxxxxxxxxxxxxxxxxxxxxxxxxxxe4.cloudfront.net (CloudFront)
x-amz-cf-pop: KIX50-P1
x-amz-cf-id: Y5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==

#EXTM3U
#EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-0465f4.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707378659.60"
#EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1"
#EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]"
#EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="293.600672"
#EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05"
#EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012"
#EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列16]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列17]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列18]).m3u8%

variant playlist

% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列16]).m3u8"
HTTP/1.1 200 OK
cache-control: no-cache, no-store, private
content-type: application/vnd.apple.mpegurl
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:52:14 GMT
transfer-encoding: chunked
access-control-allow-origin: *

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:168
#EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:168
#EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:335.981
#EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:368.029
#EXT-X-DATERANGE:ID="playlist-creation-1707378734",CLASS="timestamp",START-DATE="2024-02-07T23:52:14.364-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707378734.36"
#EXT-X-DATERANGE:ID="source-1707378704",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:51:44.618Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live"
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:44.618Z
#EXTINF:2.013,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列83].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:46.631Z
#EXTINF:1.978,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列84].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:48.609Z
#EXTINF:2.019,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列85].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:50.628Z
#EXTINF:2.006,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列86].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:52.634Z
#EXTINF:1.983,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列87].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:54.617Z
#EXTINF:2.012,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列88].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:56.629Z
#EXTINF:1.981,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列89].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:51:58.610Z
#EXTINF:2.010,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列90].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:52:00.620Z
#EXTINF:2.016,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列91].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:52:02.636Z
#EXTINF:1.981,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列92].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:52:04.617Z
#EXTINF:2.010,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列93].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:52:06.627Z
#EXTINF:1.983,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列94].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:52:08.610Z
#EXTINF:2.011,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列95].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:52:10.621Z
#EXTINF:2.015,live
https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列96].ts
#EXT-X-PREFETCH:https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列97].ts
#EXT-X-PREFETCH:https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列98].ts

segments

% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://video-edge-0465f4.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列96].ts"
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, private
Content-Type: application/octet-stream
Date: Thu, 08 Feb 2024 07:52:51 GMT
Transfer-Encoding: chunked

Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.

Originヘッダなしのリクエスト

Originヘッダなしでのリクエストも確認してみます。許可をしていない想定のOriginヘッダ値を付与したリクエストの場合と同様、multivariant playlistではレスポンスにaccess-control-allow-originヘッダを含まないこと、またvariant playlistならびにsegmentsではaccess-control-allow-origin: *Access-Control-Allow-Origin: *)となっていることが確認できます。

multivariant playlist

% curl -i "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8"
HTTP/2 200
content-type: application/vnd.apple.mpegurl
content-length: 6125
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:53:26 GMT
x-amzn-trace-id: Root=1-65xxxx76-16xxxxxxxxxxxxxxxxxxxx57
x-amzn-trace-id: Root=1-65xxxx76-16xxxxxxxxxxxxxxxxxxxx57
x-cache: Miss from cloudfront
via: 1.1 52xxxxxxxxxxxxxxxxxxxxxxxxxxxxe6.cloudfront.net (CloudFront)
x-amz-cf-pop: HKG54-C1
x-amz-cf-id: JKxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==

#EXTM3U
#EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-0465ec.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707378806.41"
#EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1"
#EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]"
#EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="440.407106"
#EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05"
#EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012"
#EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列19]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列20]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列21]).m3u8%

variant playlist

% curl -i "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列19]).m3u8"
HTTP/1.1 200 OK
cache-control: no-cache, no-store, private
content-type: application/vnd.apple.mpegurl
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:53:55 GMT
transfer-encoding: chunked
access-control-allow-origin: *

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:219
#EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:219
#EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:437.982
#EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:470.032
#EXT-X-DATERANGE:ID="playlist-creation-1707378835",CLASS="timestamp",START-DATE="2024-02-07T23:53:55.196-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707378835.20"
#EXT-X-DATERANGE:ID="source-1707378806",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:53:26.619Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live"
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:26.619Z
#EXTINF:2.013,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列99].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:28.632Z
#EXTINF:1.978,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列100].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:30.610Z
#EXTINF:2.013,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列101].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:32.623Z
#EXTINF:2.050,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列102].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:34.673Z
#EXTINF:1.946,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列103].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:36.619Z
#EXTINF:2.014,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列104].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:38.633Z
#EXTINF:1.977,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列105].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:40.610Z
#EXTINF:2.017,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列106].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:42.627Z
#EXTINF:2.012,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列107].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:44.639Z
#EXTINF:1.977,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列108].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:46.616Z
#EXTINF:2.015,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列109].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:48.631Z
#EXTINF:1.980,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列110].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:50.611Z
#EXTINF:2.013,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列111].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:53:52.624Z
#EXTINF:2.015,live
https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列112].ts
#EXT-X-PREFETCH:https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列113].ts
#EXT-X-PREFETCH:https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列114].ts

segments

% curl -i "https://video-edge-0465ec.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列112].ts"
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, private
Content-Type: application/octet-stream
Date: Thu, 08 Feb 2024 07:54:21 GMT
Transfer-Encoding: chunked

Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.

Allowed Originに加えてStrict Origin Enforcementを有効にした状態でのレスポンスヘッダの確認

Playback Restriction Policyを適用していない状態のレスポンスヘッダ、そしてPlayback Restriction PolicyでAllowed Originを追加した(Strict Origin Enforcementを無効の)状態でのレスポンスヘッダを確認してきました。

さて、いよいよ本エントリの本題、Strict Origin Enforcementを有効にした状態でのレスポンスヘッダを確認していきましょう。

まずはPlayback Restriction Policyで無効だったStrict Origin Enforcementを有効にします。Playback Restriction PolicyのChannelへのアタッチ時はライブストリームの中断を伴いましたが、Playback Restriction Policyの変更自体はChannel側のライブストリーミングの中断は伴わずに実施できました。(Update ChannelかUpdate Policyかの違いですね。)

変更前の状態を確認しておきます。

% aws ivs get-stream \
    --channel-arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd"
{
    "stream": {
        "channelArn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd",
        "health": "HEALTHY",
        "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8",
        "startTime": "2024-02-08T07:46:11+00:00",
        "state": "LIVE",
        "streamId": "st-1CxxxxxxxxxxxxxxxxxxxpY",
        "viewerCount": 0
    }
}
 % aws ivs get-playback-restriction-policy \
    --arn "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB"
{
    "playbackRestrictionPolicy": {
        "allowedCountries": [],
        "allowedOrigins": [
            "https://allowed-origin.example.net"
        ],
        "arn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB",
        "enableStrictOriginEnforcement": false,
        "name": "strict-origin-enforcement-test-policy",
        "tags": {}
    }
}

aws ivs update-playback-restriction-policyコマンドを実行してStrict Origin Enforcementを有効にします。

% aws ivs update-playback-restriction-policy \
    --arn "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB" \
    --enable-strict-origin-enforcement
{
    "playbackRestrictionPolicy": {
        "allowedCountries": [],
        "allowedOrigins": [
            "https://allowed-origin.example.net"
        ],
        "arn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB",
        "enableStrictOriginEnforcement": true,
        "name": "strict-origin-enforcement-test-policy",
        "tags": {}
    }
}

Allowed Originとして登録している内容(ホスト名)とStrict Origin Enfocementが有効になっていること、そしてライブストリーミング中であることを確認しておきましょう。

% aws ivs get-playback-restriction-policy \
    --arn "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB"
{
    "playbackRestrictionPolicy": {
        "allowedCountries": [],
        "allowedOrigins": [
            "https://allowed-origin.example.net"
        ],
        "arn": "arn:aws:ivs:ap-northeast-1:123456789012:playback-restriction-policy/SixxxxxxxxaB",
        "enableStrictOriginEnforcement": true,
        "name": "strict-origin-enforcement-test-policy",
        "tags": {}
    }
}
% aws ivs get-stream \
    --channel-arn "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd"
{
    "stream": {
        "channelArn": "arn:aws:ivs:ap-northeast-1:123456789012:channel/wkxxxxxxxxxd",
        "health": "HEALTHY",
        "playbackUrl": "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8",
        "startTime": "2024-02-08T07:46:11+00:00",
        "state": "LIVE",
        "streamId": "st-1CxxxxxxxxxxxxxxxxxxxpY",
        "viewerCount": 0
    }
}

許可想定のOriginヘッダ値を付与したリクエスト

まずは許可想定のOriginヘッダ値を付与したリクエストです。「Playback Restriction PolicyでAllowed Originを追加した状態でのレスポンスヘッダの確認」のとき、つまりStrict Origin Enforcementが無効だったときと同様の結果となりました。

multivariant playlistではレスポンスヘッダとして、許可想定としたホスト名である https://allowed-origin.example.net を値にした access-control-allow-originヘッダ、 access-control-allow-origin: https://allowed-origin.example.net が含まれています。

またvariant playlistならびにsegmentsでは、access-control-allow-origin: *Access-Control-Allow-Origin: *)とaccess-control-allow-originヘッダの値はワイルドカード *で、どのホスト名でもCORSを許可する状態です。

multivariant playlist

% curl -i -H "Origin: https://allowed-origin.example.net" "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8"
HTTP/2 200
content-type: application/vnd.apple.mpegurl
content-length: 6269
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:59:06 GMT
access-control-allow-origin: https://allowed-origin.example.net
x-amzn-trace-id: Root=1-65xxxxca-4exxxxxxxxxxxxxxxxxxxx96
x-amzn-trace-id: Root=1-65xxxxca-4exxxxxxxxxxxxxxxxxxxx96
x-cache: Miss from cloudfront
via: 1.1 e0xxxxxxxxxxxxxxxxxxxxxxxxxxxx7e.cloudfront.net (CloudFront)
x-amz-cf-pop: NRT57-C1
x-amz-cf-id: s0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==

#EXTM3U
#EXT-X-SESSION-DATA:DATA-ID="NODE",VALUE="video-edge-785e36.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE-TYPE",VALUE="weaver_cluster"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-NODE",VALUE="video-weaver.tyo03"
#EXT-X-SESSION-DATA:DATA-ID="SUPPRESS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="SERVER-TIME",VALUE="1707379146.31"
#EXT-X-SESSION-DATA:DATA-ID="TRANSCODESTACK",VALUE="2023-Transcode-QS-V1"
#EXT-X-SESSION-DATA:DATA-ID="USER-IP",VALUE="[アクセス元IPv4アドレス]"
#EXT-X-SESSION-DATA:DATA-ID="SERVING-ID",VALUE="[32文字のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ABS",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="VIDEO-SESSION-ID",VALUE="[19桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="BROADCAST-ID",VALUE="[11桁の数字]"
#EXT-X-SESSION-DATA:DATA-ID="STREAM-TIME",VALUE="780.311823"
#EXT-X-SESSION-DATA:DATA-ID="FUTURE",VALUE="true"
#EXT-X-SESSION-DATA:DATA-ID="USER-COUNTRY",VALUE="JP"
#EXT-X-SESSION-DATA:DATA-ID="MANIFEST-CLUSTER",VALUE="tyo03"
#EXT-X-SESSION-DATA:DATA-ID="ORIGIN",VALUE="pdx05"
#EXT-X-SESSION-DATA:DATA-ID="C",VALUE="[1000文字超のランダムな文字列]"
#EXT-X-SESSION-DATA:DATA-ID="CUSTOMER_ID",VALUE="123456789012"
#EXT-X-SESSION-DATA:DATA-ID="CONTENT_ID",VALUE="wkxxxxxxxxxd"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="480p30",NAME="480p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=1427999,RESOLUTION=852x480,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="480p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列22]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="360p30",NAME="360p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=630000,RESOLUTION=640x360,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="360p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列23]).m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="160p30",NAME="160p",AUTOSELECT=YES,DEFAULT=YES
#EXT-X-STREAM-INF:BANDWIDTH=230000,RESOLUTION=284x160,CODECS="avc1.4D401F,mp4a.40.2",VIDEO="160p30",FRAME-RATE=30.000
https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列24]).m3u8%

variant playlist

% curl -i -H "Origin: https://allowed-origin.example.net" "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列22]).m3u8"
HTTP/1.1 200 OK
cache-control: no-cache, no-store, private
content-type: application/vnd.apple.mpegurl
vary: Accept-Encoding
date: Thu, 08 Feb 2024 07:59:43 GMT
transfer-encoding: chunked
access-control-allow-origin: *

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:392
#EXT-X-NET-LIVE-VIDEO-LIVE-SEQUENCE:392
#EXT-X-NET-LIVE-VIDEO-ELAPSED-SECS:783.987
#EXT-X-NET-LIVE-VIDEO-TOTAL-SECS:818.011
#EXT-X-DATERANGE:ID="playlist-creation-1707379183",CLASS="timestamp",START-DATE="2024-02-07T23:59:43.636-08:00",END-ON-NEXT=YES,X-SERVER-TIME="1707379183.64"
#EXT-X-DATERANGE:ID="source-1707379152",CLASS="live-video-net-stream-source",START-DATE="2024-02-08T07:59:12.624Z",END-ON-NEXT=YES,X-NET-LIVE-VIDEO-STREAM-SOURCE="live"
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:12.624Z
#EXTINF:2.014,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列115].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:14.638Z
#EXTINF:1.978,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列116].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:16.616Z
#EXTINF:2.016,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列117].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:18.632Z
#EXTINF:1.979,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列118].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:20.611Z
#EXTINF:2.013,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列119].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:22.624Z
#EXTINF:2.014,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列120].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:24.638Z
#EXTINF:1.980,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列121].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:26.618Z
#EXTINF:2.013,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列122].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:28.631Z
#EXTINF:1.976,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列123].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:30.607Z
#EXTINF:2.013,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列124].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:32.620Z
#EXTINF:2.051,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列125].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:34.671Z
#EXTINF:1.946,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列126].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:36.617Z
#EXTINF:2.011,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列127].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:38.628Z
#EXTINF:1.981,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列128].ts
#EXT-X-PROGRAM-DATE-TIME:2024-02-08T07:59:40.609Z
#EXTINF:2.013,live
https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列129].ts
#EXT-X-PREFETCH:https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列130].ts
#EXT-X-PREFETCH:https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列131].ts

segments

% curl -i -H "Origin: https://allowed-origin.example.net" "https://video-edge-785e36.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列129].ts"
HTTP/1.1 200 OK
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, private
Content-Type: application/octet-stream
Date: Thu, 08 Feb 2024 08:00:16 GMT
Transfer-Encoding: chunked

Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.

許可をしていない想定のOriginヘッダ値を付与したリクエスト

続いて、許可をしていない想定のOriginヘッダ値を付与したリクエストを確認してみます。許可をしていない想定のホスト名である https://not-allowed-origin.example.net をOriginヘッダ値としてリクエストを行った場合、HTTPステータスコード403が返りリクエストに失敗しました。Playlisetが取得できていない状況ですね。またエラーメッセージとしてplayback_auth_errorが返され、再生時の認証エラーであることが確認できます。Originヘッダの値をみて、正しいもの(ここではPlayback Restriction Policyに設定した https://allowed-origin.example.net )の場合にのみリクエストに応答する、という挙動になっているように見て取れます。なお、レスポンス自体にはaccess-control-allow-origin: *がヘッダとして付与されています。

許可をしていない想定のOriginヘッダ値を付与したリクエストではmultivariant playlistが取得できないため、実際にはvariant playlistならびにsegmentsのURLもわからない、という状況になります。ですが今回は動作検証のため、許可想定のOriginヘッダ値 https://allowed-origin.example.net を付与してmultivariant playlisetを取得し直し、そのプレイリスト内のvariant playlistに対して許可をしていない想定のOriginヘッダ値でリクエストを行いました。variant playlisetのリクエストに対してもHTTPステータスコード403が返り、こちらもリクエストに失敗してplaylistが取得できないという状況になりました。エラーメッセージとしてdisallowed originとも返されています。またレスポンス自体にはaccess-control-allow-origin: *がヘッダとして付与されていました。

segmentsのURLの確認についてもvariant playlistのときと同様、許可想定のOriginヘッダ値 https://allowed-origin.example.net を付与してvariant playlistを取得し直して、そのプレイリスト内のsegmentsに対して許可をしていない想定のOriginヘッダ値でリクエストを行いましす。こちらもHTTPステータスコード403と、disallowed originのメッセージがレスポンスされます。またAccess-Control-Allow-Origin: *ヘッダもレスポンスに含まれていました。

multivariant playlist

% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8"
HTTP/2 403
content-type: application/json
content-length: 159
date: Thu, 08 Feb 2024 08:01:17 GMT
access-control-allow-origin: *
x-amzn-trace-id: Root=1-65xxxx4d-49xxxxxxxxxxxxxxxxxxxx6b
x-amzn-trace-id: Root=1-65xxxx4d-49xxxxxxxxxxxxxxxxxxxx6b
x-cache: Error from cloudfront
via: 1.1 06xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcc.cloudfront.net (CloudFront)
x-amz-cf-pop: HKG54-C1
x-amz-cf-id: f9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==

[{"url":"/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8","error":"playback_auth_error","error_code":"playback_auth_error","type":"error"}]%

variant playlist

いちどcurl -i -H "Origin: https://allowed-origin.example.net" <multivariant playlist>で取得したプレイリスト内のvariant playlistを対象にリクエストを行います。

% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列25]).m3u8"
HTTP/1.1 403 Forbidden
vary: Accept-Encoding
x-error-message: disallowed origin
date: Thu, 08 Feb 2024 08:02:21 GMT
content-length: 0
access-control-allow-origin: *

segments

いちどcurl -i -H "Origin: https://allowed-origin.example.net" <variant playlist>で取得したプレイリスト内のsegmentsに対してリクエストを行います。

% curl -i -H "Origin: https://not-allowed-origin.example.net" "https://video-edge-4ff448.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列132].ts"
HTTP/1.1 403 Forbidden
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, private
Content-Length: 17

disallowed origin

Originヘッダなしのリクエスト

Originヘッダなしでのリクエストについても確認します。基本的には「許可をしていない想定のOriginヘッダ値を付与したリクエスト」と同様の結果になりました。HTTPステータスコード403が返り、multivariant playlist、variant playlist、そしてsegmentsのいずれも取得に失敗します。なおこの動作のため、variant playlistとsegmentsの取得には許可想定のOriginヘッダ値 https://allowed-origin.example.net を付与してリクエストをし直しています。「許可をしていない想定のOriginヘッダ値を付与したリクエスト」の場合と同様のやり方ですね。

「許可をしていない想定のOriginヘッダ値を付与したリクエスト」の場合との細かな違いとしてvariant playlisetとsegmentsについては、エラーメッセージがdisallowed originではなく、origin requiredになっていました。Originヘッダがない、という実態に即したエラーメッセージが返ってきたぐあいですね。そのほか、レスポンスにaccess-control-allow-origin: *Access-Control-Allow-Origin: *)が含まれていた点は同じでした。

multivariant playlist

% curl -i "https://62xxxxxxxx2b.ap-northeast-1.playback.live-video.net/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8"
HTTP/2 403
content-type: application/json
content-length: 159
date: Thu, 08 Feb 2024 08:03:36 GMT
access-control-allow-origin: *
x-amzn-trace-id: Root=1-65xxxxd8-0cxxxxxxxxxxxxxxxxxxxx25
x-amzn-trace-id: Root=1-65xxxxd8-0cxxxxxxxxxxxxxxxxxxxx25
x-cache: Error from cloudfront
via: 1.1 02xxxxxxxxxxxxxxxxxxxxxxxxxxxxb4.cloudfront.net (CloudFront)
x-amz-cf-pop: KIX50-P1
x-amz-cf-id: FAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==

[{"url":"/api/video/v1/ap-northeast-1.123456789012.channel.wkxxxxxxxxxd.m3u8","error":"playback_auth_error","error_code":"playback_auth_error","type":"error"}]

variant playlist

いちどcurl -i -H "Origin: https://allowed-origin.example.net" <multivariant playlist>で取得したプレイリスト内のvariant playlistを対象にリクエストを行います。

% curl -i "https://video-weaver.tyo03.hls.live-video.net/v1/playlist/[800文字超のランダムな文字列26]).m3u8"
HTTP/1.1 403 Forbidden
vary: Accept-Encodinga
x-error-message: origin required
date: Thu, 08 Feb 2024 08:04:30 GMT
content-length: 0
access-control-allow-origin: *

segments

いちどcurl -i -H "Origin: https://allowed-origin.example.net" <variant playlist>で取得したプレイリスト内のsegmentsに対してリクエストを行います。

% curl -i "https://video-edge-4fe7c8.tyo03.hls.live-video.net/v1/segment/[900文字超のランダムな文字列133].ts"
HTTP/1.1 403 Forbidden
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, private
Content-Length: 15

origin required

検証結果のまとめ

(1) Playback Restriction Policyを適用していない状態、(2) Playback Restriction PolicyでAllowed Originを追加した状態(ただしStrict Origin Enforcementは無効)、(3) Playback Restriction PolicyでAllowed Originに加えてStrict Origin Enforcementを有効にした状態、それぞれでの、(a) 許可想定のOriginヘッダ値を付与したリクエスト、(b) 許可をしていない想定のOriginヘッダ値を付与したリクエスト、(c) Originヘッダなしのリクエスト、それぞれを3種のファイルに対して確認してきました。

ここでいちど検証結果について、Access-Control-Allow-Originヘッダの値の表としてまとめてみます。「ヘッダなし」についてはレスポンスにAccess-Control-Allow-Originヘッダ自体が含まれていないことを示します。

また「Allowed Originに加えてStrict Origin Enforcementを有効にした状態でのレスポンスヘッダの確認」の表については、Access-Control-Allow-Originヘッダの値のみではなく、HTTPステータスコードとエラーメッセージについて記載しています。

Playback Restriction Policyを適用していない状態でのレスポンスヘッダの確認

multivariant
playlist
variant
playlist
segments
許可想定の
Originヘッダ値を付与したリクエスト
* * *
許可をしていない想定の
Originヘッダ値を付与したリクエスト
* * *
Originヘッダなしの
リクエスト
* * *

Playback Restriction Policyを適用していない状態では、常にレスポンスヘッダにaccess-control-allow-origin: *Access-Control-Allow-Origin: *)が含まれていいました。どのWebサイトでもストリーミングの再生は制限されていない、という状態です。またリクエストにOriginヘッダが含まれていなくても、Access-Control-Allow-Originヘッダがワイルドカード * の値で返るためCORSエラーが発生して再生できない、といったことはありません。

Playback Restriction PolicyでAllowed Originを追加した状態でのレスポンスヘッダの確認

multivariant
playlist
variant
playlist
segments
許可想定の
Originヘッダ値を付与したリクエスト
Originヘッダと同じ値(ホスト名) * *
許可をしていない想定の
Originヘッダ値を付与したリクエスト
ヘッダなし * *
Originヘッダなしの
リクエスト
ヘッダなし * *

リクエスト時のOriginヘッダの値が、ストリーミング再生を許可したWebサイトのホスト名と異なる場合や、そもそもOriginヘッダがない場合、Playback Restriction PolicyでAllowed Originを追加している状態では、multivariant playlistのレスポンスにAccess-Control-Allow-Originヘッダを含まないという結果になりました。これで、ストリーミング再生を許可していないWebサイトでは、CORSエラーが発生してストリーミング再生が不可能となります。

ただし、multivariant playlist自体は取得が可能でプレイリスト内容が確認できます。そこから辿れるvariant playlistとsegmentsについては引き続きワイルドカード *の値のAccess-Control-Allow-Originヘッダがレスポンスとして付与されます。Webサイト上の再生プレイヤーにvariant playlistを指定する、といった方法でAllowed Originに追加していないWebサイトからでも動画の再生、segmentsへのアクセスなどは理論上可能となります。今回の検証のようにcurlコマンドを利用する、またCORSのAccess-Control-Allow-Originヘッダを無視する動画プレイヤーを利用するなどとした場合に、ストリーミングの再生が可能になってしまうわけです。

Allowed Originに加えてStrict Origin Enforcementを有効にした状態でのレスポンスヘッダの確認

multivariant
playlist
variant
playlist
segments
許可想定の
Originヘッダ値を付与したリクエスト
Originヘッダと同じ値(ホスト名) * *
許可をしていない想定の
Originヘッダ値を付与したリクエスト
403
playback_auth_error
*
403
disallowed origin
*
403
disallowed origin
*
Originヘッダなしのリクエスト 403
playback_auth_error
*
403
origin required
*
403
origin required
*

Allowed Originに加えてStrict Origin Enforcementを有効にした状態ではどうでしょうか。許可想定のOriginヘッダを付与したリクエストに対してはStrict Origin Enforcementが無効の状態と変わりません。Originヘッダの値が再生を許可していないWebサイトのホスト名やOriginヘッダがない場合は、一律で403となりplaylistやsegmentsの内容が取得できません。Originヘッダの値を認証に使用し、正しい値を持たなければplaylist、segments自体を返さすストリーミング再生を一切行わせない、という挙動になっていますね。

まとめ

Amazon IVS Low-Latency StreamingのPlayback restriction policiesでStrict Origin Enforcementを有効にした際の挙動について、playlistやsegmentsにcurlコマンドでリクエストして確認してみました。

Playback restriction policiesでのみ再生制限をした場合(Strict Origin Enforcementが無効な場合)、レスポンスのAccess-Control-Allow-Originヘッダによって再生制限が行われ、playlistなどの情報自体は取得することができます。この情報を悪用させたくない、という場合はStrict Origin Enforcementを有効にしましょう。リクエスト時のOriginヘッダの値がAllowed Originで指定したものではない場合は、playlistやsegments自体が返らなくなります。その名称のとおり、より厳密にストリーミング再生の制限ができるわけですね。

指定したWebサイトでのみ再生を許可するといった場合にはこのPlayback restriction policies、厳密な制限の場合にはStrict Origin Enforcementを有効にして利用しましょう。またストリーミングを再生可能なユーザ自体を限定したい、といった場合にJSON Web Token (JWT)を使った再生制限、プライベートチャンネルと上手に使い分けていきましょう。