ALBからS3コンテンツを配信してみた
Amazon S3のコンテンツを配信したい場合、S3の静的ウェブサイトホスティングを使用したり、S3の前段にCloudFront(CDN)を配置して配信することが多いかと思います。今回は、3つ目の選択肢として、S3をALBから配信する構成について紹介します。
S3バケットをプライベートにしたまま、ALBレイヤーでHTPS通信化や認証やセキュリティグループのアクセス制限を行うことができます。アプリケーションで利用するALBにS3配信を集約させることも可能です。また、外部・内部どちらのALBでも採用できます。
- オンプレミスからプライベート通信によるS3アクセス
- 認証付きURL/CookieでS3コンテンツを配信する代替案として、ALB認証でS3配信
などで有用です。
構成ポイント
本構成の肝はALBのターゲットにS3のインターフェース型VPCエンドポイントのIPを指定することです。昔からあるゲートウェイ型エンドポイントではありません。
以下の様な特徴があります
- S3バケットの公開は不要。S3のバケットポリシーではこのVPCエンドポイントからのアクセスを許可すればよい
- ターゲットを利用するALBは外部(internet-facing)でも内部(internal)もよい
- ALBからのヘルスチェックでは、リクエストヘッダーの制約から200 OKとはならない
- クライアントからの通信はALBを経由するため、HTTPS通信する場合、S3バケット名をドメイン名に合わせ、ALBにACM証明書をインストール
ウォークスルー
S3に対してカスタムドメイン(s3.example.com 等)でALB経由でHTTPS通信してみます。
VPC
VPCを作成し、ALB向けとS3 VPCエンドポイント向けのセキュリティグループを作成します。
ALB向けのセキュリティグループでは、適切なIPレンジからのHTTPS通信を許可します。
VPCエンドポイント向けのセキュリティグループでは、ALB向けセキュリティグループをソースとしたHTTP(ALBヘルスチェックからのリクエスト)およびHTTPS(クライアントからリクエスト)通信を許可します。
S3のインターフェース型VPCエンドポイント
S3のインターフェース型VPCエンドポイントを作成します。
このエンドポイントには、先程作成したVPCエンドポイント向けのセキュリティグループをアタッチします。
S3バケット
ALBをアクセスする際のドメインと同じ名前のバケット名を作成します。
バケットポリシーで、インターフェース型VPCエンドポイントからの参照を許可します。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Access-to-specific-VPCE-only", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": [ "arn:aws:s3:::バケット名", "arn:aws:s3:::バケット名/*" ], "Condition": { "StringEquals": { "aws:SourceVpce": "VPCエンドポイント" } } } ] }
このポリシーの以下の変数を実環境に合わせて調整してください。
- バケット名(s3.example.com など)
- VPCエンドポイント(vcpe-1234 など)
ACM
S3をALB配信するドメイン向けのTLS証明書を取得します。
ALBターゲット
ALBに指定するターゲットを作成します。
ターゲットにはS3インターフェース型エンドポイントのIPアドレスを指定します。
- ターゲット
- タイプ:IPアドレス
- プロトコル : HTTPS
- ヘルスチェック :
- プロトコル : HTTP
- パス : /
- サクセスコード : 307
ヘルスチェックの設定には注意が必要です。
ALBのヘルスチェックリクエストでは、ホスト情報をカスタマイズできません。そのため、本来のアクセス時(ホスト名=バケット名)のように、200 OKのレスポンスステータスが返ってきません。サクセスコードを非200番の 307 等に設定しましょう。
試しに、VPC内のEC2からS3のVPCエンドポイントのIPアドレスに向けて、S3の実在するオブジェクトのパス /index.html
を指定してホスト名の有り・無しでリクエストしてみましょう。
ホスト名を渡す
S3バケット名と同じホストを渡すと、 200 OK
が返ります
$ curl -H 'Host: s3.example.com' -D - 172.31.42.253/index.html HTTP/1.1 200 OK x-amz-id-2: Yr3UfhFrPZroQHhVqPB6KqjADkZ2YV/qRGfvzgrl8LtjDaSRP27PzRog3oGB8zejQaRJp93YujU= x-amz-request-id: PD0DFTAGHN43561C Date: Sun, 19 May 2024 04:29:05 GMT Last-Modified: Fri, 17 May 2024 05:49:07 GMT ETag: "b1946ac92492d2347c6235b4d2611184" x-amz-server-side-encryption: AES256 Accept-Ranges: bytes Content-Type: text/html Server: AmazonS3 Content-Length: 6 hello
ホスト名を渡さない
ホストを渡さないと、301 Moved Permanently
が返ります
$ curl -D - 172.31.42.253/index.html HTTP/1.1 301 Moved Permanently x-amz-bucket-region: us-east-1 x-amz-request-id: FCB7CZ5PWAJR5KCH x-amz-id-2: S+9+4wTMYFpOnKAszTq7uLMN3EIqCS0sP8ndoCifV11NXuUcsHHwn4E4moBdja0DP6W5VQpjHg0= Content-Type: application/xml Transfer-Encoding: chunked Date: Sun, 19 May 2024 04:31:38 GMT Server: AmazonS3 <?xml version="1.0" encoding="UTF-8"?> <Error> <Code>PermanentRedirect</Code> <Message>The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.</Message> <Endpoint>s3.amazonaws.com</Endpoint> <Bucket>index.html</Bucket> <RequestId>FCB7CZ5PWAJR5KCH</RequestId> <HostId>S+9+4wTMYFpOnKAszTq7uLMN3EIqCS0sP8ndoCifV11NXuUcsHHwn4E4moBdja0DP6W5VQpjHg0=</HostId> </Error>
ヘルスチェックのデフォルト設定(/
にHostヘッダーを渡さない)
ホストを渡さず、存在しないオブジェクトを指定すると、 301 Moved Permanently
が返ります
$ curl -D - 172.31.42.253/ HTTP/1.1 307 Temporary Redirect x-amz-id-2: 69mwFG+F3gy8vsPnBx11KD0eJDHdVfmsU3LMxUDVuLLMEY08AKAv61uK4yQ3EIQvn7g5Prt4YzA= x-amz-request-id: Z2C6K86KCEH14AAR Date: Sun, 19 May 2024 04:37:45 GMT Location: https://aws.amazon.com/s3/ Server: AmazonS3 Content-Length: 0
ALB
Internet-facing OR Internalな ALBを作成します。要件に合わせて選択してください。
- HTTPS(443)通信のターゲット: 作成したターゲット
- 証明書 : 作成したACMの証明証
- セキュリティグループ : 冒頭で作成したセキュリティグループ
Route 53
Route 53のゾーン内にAliasレコードでALBのエンドポイントを登録します。
疎通確認
最後にALB経由でS3アクセスします。
$ curl -D - https://s3.example.com/index.html HTTP/2 200 date: Sun, 19 May 2024 04:55:13 GMT content-type: text/html content-length: 6 x-amz-id-2: oQ5lOebhzGBEV+J5E5ejyRyX1eAI5S1umYfuz+5isyb5Phkm89i0VJ2fW0OCZMOiYGAu7JmpVEA= x-amz-request-id: EZY4G2BDAMS9AQ7B last-modified: Fri, 17 May 2024 05:49:07 GMT etag: "b1946ac92492d2347c6235b4d2611184" x-amz-server-side-encryption: AES256 accept-ranges: bytes server: AmazonS3 hello
無事、200 OKステータスとコンテンツが返ってきました。
まとめ
ALBからS3配信する方法を紹介しました。
オンプレミスからのプライベート通信のような内部ALBとの連携やアクセス制限が要件にある場合、ALB経由の配信も有力です。
ぜひご検討ください。