MediaLiveのVPC OutputからS3のVPCエンドポイント経由でアーカイブを出力してみた

AWS Elemental MediaLiveでVPC経由での出力機能を用いて、VPCエンドポイント(S3/Gatewayタイプ)を使ったS3への書き込みを試してみました。VPC内ではS3のプレフィックスリスト以外への通信も設定する必要がありました。
2021.02.19

はじめに

清水です。先日、AWS Elemental MediaLiveにこれまでのVPC経由での入力に加えて、VPC経由で出力する機能が新たに追加されました。

上記のエントリではMediaLiveからVPC経由で、WebDAVが稼働しているEC2にプライベートIPでHLS出力を書き込むことで動作確認をしてみました。MediaLiveのUser Guide「Delivering outputs via your VPC」の項目にはこのようなEC2への出力のほか、VPCエンドポイントを経由したS3バケットへの出力やDirect Connectを介した出力などが想定されるユースケースとして記載されています。

本エントリではこの中の1つ、MediaLiveからVPCエンドポイントを経由したS3バケットへの書き込みにトライしてみました。VPCエンドポイント(S3エンドポイント/Gatewayタイプ)とそこへの経路を準備したプライベートサブネットを用意し、MediaLiveのVPC Output機能で送信元をこのサブネットからとなるよう設定します。S3バケット側ではバケットポリシーを使いアクセス元を該当のVPCエンドポイントのみとすることなどで、セキュリティを高めることが可能です。

実際にこの構成を試していく中、当初はMediaLiveのVPC outputで指定するサブネットについて、S3のVPCエンドポイントのみの経路しか持たない(インターネット接続がない)ように設定してみました。しかしMediaLive側でS3バケットのリージョンが確認できない、というエラーとなってしまい、打開策としてNATゲートウェイを追加、サブネット内からインターネットへの通信が可能なよう経路を編集しました。これでMediaLiveからS3のvpcエンドポイント経由での書き込みが行え、またS3バケット側でもアクセス元を該当VPCエンドポイントのみとするようなバケットポリシー設定が可能となりました。

ネットワーク構成の準備

まずは今回想定するVPCなどネットワーク構成を準備します。当初はNATゲートウェイなし、プライベートサブネットではインターネットへの経路は持たない構成としていました。しかし後述しますがこの構成ですとMediaLiveでAlertが発生し、S3への書き込みが行えません。そのためNATゲートウェイを追加、プライベートサブネットでもインターネットへの経路を持つ構成としました。

なお「プライベートサブネット」という言葉がインターネットへの接続を有するサブネットを示すのかどうかは議論の余地があるかと思います。例えば、インターネットへの接続が可能なサブネットは「プロテクテッド(protected)」と呼ぶ、プライベートサブネットはインターネットへの接続ができないもの、とするケースもあります。例えば以下のエントリではこのようにプロテクテッドとプライベートをわけて呼んでいます。

しかし(上記のエントリにも記載があるのですが)今回はAWS公式ドキュメント「Amazon Virtual Private Cloud ユーザーガイド」に倣い、NATゲートウェイによりインターネットへの接続が可能なサブネットについても「プライベートサブネット」と呼ぶことにします。

NATゲートウェイなしの構成

まずはNATゲートウェイのない構成です。パブリック、プライベートの双方のサブネットにEC2インスタンスを1台ずつ起動しています。これは後述のバケットポリシーによりVPCエンドポイント経由のアクセスのみに限定したS3の状況を確認するのに使用しました。パブリックサブネットのEC2を踏み台にしてプライベートサブネットのEC2にSSHします。その他、ルートテーブル編集時の状況確認にも活躍しました。

MediaLiveについては、InputはVPCを使用せず、インターネットを介してそのまま映像を打ち上げます。そのためVPCの外にINPUTがあるイメージです。Outputについては本エントリの主題通りVPCを使用するので、プライベートサブネットにかかっている構成図となります。

また、前提としていずれのリソースも東京リージョンに作成します。

構成時のポイントとなった部分として、VPCエンドポイントの作成だけまとめておきます。VPCのマネジメントコンソール、Endpointsの項目から[Create Endpoint]で進みます。

VPCエンドポイントはS3のGatewayタイプを選択します。(Interfaceタイプではなく)

VPCとルートテーブルを編集するサブネットを選択します。サブネットはプライベートサブネットのみ選択しました。

ポリシーについては、今回はFull Accessとしています。

VPCエンドポイント作成後、実際にこの経路を利用するプライベートサブネットでルートが追加されているか確認しておきます。

NATゲートウェイありの構成

続いてNATゲートウェイを追加し、プライベートサブネットのルートテーブルを編集した構成です。プライベートサブネットからもインターネットへの接続が可能な状態になります。

NATゲートウェイなしの状態から、パブリックサブネットにNATゲートウェイリソースを作成します。さらに、プライベートサブネットのルートテーブルを編集してインターネットへ経路をNATゲートウェイとなるようルートを追加しておきます。

S3バケットの準備

続いて、MediaLiveの書き込み先となるS3バケットを準備します。バケット名とリージョンを東京リージョンに指定、その他の項目についてはデフォルトでバケットを作成します。

続いて、バケットポリシーを以下のように設定します。該当VPCエンドポイント以外からの操作を禁止するポリシーとなります。なお、"Action": "s3:*"なので設定後は該当VPCエンドポイント経由でないとバケットポリシーの削除も行えなくなります。(例えばAWSマネジメントコンソールからも操作不可。)まずは"Action": "s3:Put*"などとして動作を確認後、改めて"Action": "s3:*"として設定するのが良いかと思います。"Action": "s3:Put*"であれば、バケットポリシーの変更はできませんが、削除するDelete操作は該当VPCエンドポイント経由以外でも可能です。(実際、私はVPCエンドポイントのID(vpce-ではじまる)を記載すべきところをVPC ID(vpc-ではじまる)で記載してしまったことがあります。)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::medialive-vpc-output-s3",
        "arn:aws:s3:::medialive-vpc-output-s3/*"
      ],
      "Condition": {
        "StringNotEquals": {
          "aws:sourceVpce": "vpce-0931XXXXXXXXXXXXX"
        }
      }
    }
  ]
}

設定後、2つのサブネットそれぞれで起動しているEC2からS3バケットへのアクセスを確認しておきます。まずはパブリックサブネットに配置されたEC2、S3への接続はインターネットゲートウェイ経由となるのでアクセスすることはできません。

[ec2-user@ip-10-100-101-210 ~]$ aws s3 ls s3://medialive-vpc-output-s3/ --region ap-northeast-1

An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

続いて、プライベートサブネットに配置されたEC2です。S3へのアクセスはVPCエンドポイント経由となるのでアクセスが可能です。確認用に作成したtestfiles3 lsの結果として返ってきています。

[ec2-user@ip-10-100-201-68 ~]$ aws s3 ls s3://medialive-vpc-output-s3/ --region ap-northeast-1
2021-02-19 02:00:24          5 testfile

S3にアーカイブを出力するMediaLiveの準備

S3バケットの準備ができたら、続いてそのS3バケットにアーカイブを出力するMediaLiveリソースを準備していきます。本エントリではMediaLiveリソースの作成手順詳細は割愛し、ポイントとなるところのみ挙げていきます。なお検証目的のため、SINGLE_PIPELINEでリソースを作成しています。またMediaLiveのChannelリソースにアタッチするIAMロールはデフォルトのMedaiLiveAccessRole("Resource": "*"に対して、s3:ListBuckets3:PutObjects3:GetObjects3:DeleteObjectがAllowされている)を利用しています。

まずは「Channel and input details」の項目の「Output delivery」の箇所、VPC Outputの実際の設定部分ですね。Delivery methodではデフォルトのPublicからVPCに変更します。VPC settingsの項目が現れますので、該当するサブネット、そしてセキュリティグループを選択します。

セキュリティグループは選択したサブネットが属するVPCに関連づけられている必要があります。今回は以下のようなセキュリティグループを準備しました。Inbound、Outboundともにセキュリティグループ作成時のデフォルト状態となります。

続いてOutput groupsの項目です。基本的には通常のアーカイブ出力の際の設定と変わりません。output group typeとしてArchiveを選択します。

Archive group destinationではURLをs3ssl://medialive-vpc-output-s3/$dt$/としました。s3:ssl://に続くのは先ほど作成したS3バケット名です。その後/を挟んで変数データ識別子$dt$を入れています。この$dt$は実際にはMediaLiveのChannelをStartした日時にYYYYMMDDTHHMMSS形式で置き換わります。さらにMediaLiveのStartごとにこの開始日時のフォルダにアーカイブファイルがまとまるよう、末尾に/を付けています。(厳密にはS3上で幻想としてフォルダが見えているだけで、S3にフォルダという概念はありません。)

Outputの設定項目については、実際のファイル名の先頭に付与される「Name Modifier」をarchiveとしています。これで実際のファイルはarchive.000000.tsといった形式(数字部分がインクリメントされる)となります。

MediaLiveをStartさせてS3に書き出してみる

それでは実際にMediaLiveのChannelをStartさせて、MediaLiveへの映像の打ち上げを開始します。(今回はiPhone6sからZixi ONAIRを使ってRTMPで打ち上げています。)VPCエンドポイントを経由したS3へのアーカイブ書き出しはうまくいくのでしょうか。

NATゲートウェイなしの構成

まずはNATゲートウェイなし、MediaLiveのVPC Outputで指定したサブネットはS3へのVPCエンドポイントへの経路のみを持ち、インターネットアクセスができない状況で確認してみます。具体的な該当サブネットのルートテーブルは以下の状況です。

ChannelのStartと映像打ち上げを開始して少しすると、以下のようなAlertが上がってきてしまいました。

どうやらS3への書き込みに失敗しているようです。メッセージ内容にFailed to fetch region name for bucketとあることから、書き込み先となるS3バケットのリージョンを取得するのに失敗しているのではないか、と推測できます。

NATゲートウェイありの構成

上記の仮説を元に、該当サブネットにNATゲートウェイへの経路を追加して「NATゲートウェイあり」の構成に変更してみます。

この状態で再度、ChannelのStartと映像打ち上げを開始します。今度はAlertは上がってこないようです。しばらくしてから(今回はArchive settingsの「Rollover Interval」をデフォルトの300秒としているので、5分ほど経過後)、S3バケットの中身を確認してみましょう。S3にアーカイブファイルが書き込まれていることが確認できました!

[ec2-user@ip-10-100-201-68 ~]$ aws s3 ls s3://medialive-vpc-output-s3/ --region ap-northeast-1
                           PRE 20210219T044823/
2021-02-19 02:00:24          5 testfile
[ec2-user@ip-10-100-201-68 ~]$ aws s3 ls s3://medialive-vpc-output-s3/20210219T044823/ --region ap-northeast-1
2021-02-19 04:49:00  218725780 archive.000000.ts

S3バケット作成時に確認した通り、このS3バケットはバケットポリシーでVPCエンドポイント経由でのアクセスしか許可していません。NATゲートウェイを経由したインターネット接続ではアクセス不可となるので、MediaLiveのOutputがきちんとVPCエンドポイント経由でS3バケットに書き込んでいることが確認できます。

まとめ

AWS Elemental MediaLiveのVPC経由での出力ができるVPC Output機能を使ってVPCエンドポイント(S3/Gatewayタイプ)経由でアーカイブをS3に出力してみました。VPC Outputで指定する(実際にはMediaLiveのENIが作成される)サブネットについて、VPCエンドポイントでS3のみの通信を許可している状況ではFailed to fetch region name for bucketのエラーとなりS3に書き込みはできませんでした。しかしNATゲートウェイを利用してインターネットへの通信が許可された状況では、S3への書き込みが可能でした。

検証開始当時、インターネット接続がないVPCエンドポイントへの経路のみのサブネットでS3への書き込みができれば、出力ネットワークはインターネットとの通信がない、というような要件をクリアすることができるのかなと考えていました。残念ながら現状ではこの要件は簡単にはクリアできそうにありませんが、例えばS3バケットのリージョンを取得しているであろう通信先をある程度特定(おそらくAWSのIPアドレスだろうとip-ranges.jsonから推測?)し、限定することなどは不可能ではなさそうです。しかしIPアドレスレンジも膨大になりそうで、あまりやりたくはないですよね。また今回検証してみた、S3のGatewayタイプのVPCエンドポイントの他、先日InterfaceタイプのS3 VPCエンドポイント(PrivateLink)もリリースされました。しかしInterfaceタイプのS3用VPCエンドポイントでは、そのDNS名がvpce-xxxxxxxx-xxxxxxx.s3.ap-northeast-1.vpce.amazonaws.comと、標準のS3エンドポイントDNSと異なるものを使用します。このことからも現状では、MediaLiveのVPC OutputではInterfaceタイプのS3用VPCエンドポイントの使用は難しいと考えています。これら、インターネット接続のないサブネットからのGatewayタイプの利用、そしてInetrfaceタイプのVPCエンドポイント利用、将来的にアップデートで対応してくれることを期待しています。