公開日

AWS S3 + CloudFront のCORS設定手順

(image)AWS S3 + CloudFront のCORS設定手順

(画像はAWS-CloudDesignPatternから引用)

フォントファイルの豆腐化問題

Font Awesomeのようなフォントファイルを外部ホスト(例えばS3など)から読み込もうとする場合、Access-Control-Allow-OriginのヘッダでAllowされていないOriginからのリクエストの場合、いわゆるフォントの豆腐現象が起きます。これはCORS(Cross-Origin Resource Sharing) の設定が正しくなされていないためです。今回はAWSのS3+CloudFrontの構成でフォントファイルを配信したいので、S3およびCloudFrontのCORS設定手順および確認方法について説明します。

S3の設定

CORSの設定はS3のバケットのプロパティ設定から行えます。

s3 bucket property

XMLをサンプルとして下記のように設定できます。

CORS Configuration

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>http://sample.jp</AllowedOrigin>
        <AllowedOrigin>https://sample.jp</AllowedOrigin>
        <AllowedMethod>HEAD</AllowedMethod>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3600</MaxAgeSeconds>
        <ExposeHeader>ETag</ExposeHeader>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

AllowedOriginで許可したいOriginのURLを設定、AllowedMethodで許可したいHTTPリクエストメソッドを指定します。それぞれ複数並べることで複数の値を設定することが可能となっています。

確認手順

正しく設定されているかを確認するために下記のようにcurlコマンドを使って検証してみましょう。

$ curl -X GET -I -H "Origin: http://sample.jp" https://s3-ap-northeast-1.amazonaws.com/bucket/path
HTTP/1.1 200 OK
x-amz-id-2: xxx
x-amz-request-id: xxx
Date: xxx
Access-Control-Allow-Origin: http://sample.jp
Access-Control-Allow-Methods: GET
Access-Control-Expose-Headers: ETag
Access-Control-Max-Age: 3600
Access-Control-Allow-Credentials: true
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Last-Modified: xxx
ETag: "xxx"
Accept-Ranges: bytes
Content-Type: application/json
Content-Length: 14356
Server: AmazonS3

Access-Control-Allow-Origin: http://sample.jp のレスポンスがヘッダが返ってきており、正しく AllowOrigin されていることが確認できました。

CloudFront

実運用の際はS3から配信ではなく、CloudFrontと組み合わせて利用するケースが多いかと思います。

Amazon S3 での CloudFront の設定が済んでいることを前提として進めていいきます。

CloudFrontの CORS 設定

CORSの設定のためには、対象クラウドフロント設定から Behaviors を選択しデフォルトパスパターンの設定を変更する必要があります。OriginヘッダーがS3まで通る必要があるのでOriginヘッダーを Whitelist Headers に加えてやります。

確認手順

S3と同じく、curlで確認してみます。

$ curl -X GET -I -H "Origin: http://sample.jp"  https://xxx.cloudfront.net/bucket/path
HTTP/1.1 200 OK
Content-Type: binary/octet-stream
Content-Length: 123
Connection: keep-alive
Date: xxx
Access-Control-Allow-Origin: http://sample.jp
Access-Control-Allow-Methods: GET
Access-Control-Expose-Headers: ETag
Access-Control-Max-Age: 3600
Access-Control-Allow-Credentials: true
Last-Modified: xxx
ETag: "xxx"
Accept-Ranges: bytes
Server: AmazonS3
Vary: Origin
Age: 9
X-Cache: Hit from cloudfront
Via: 1.1 xxxx.cloudfront.net (CloudFront)
X-Amz-Cf-Id: xxx

S3と同じくAccess-Control-Allow-Originヘッダが設定されていることを確認できました。めでたしめでたし。

設定にあたっての注意事項

  • 不正な設定状態のままリクエストをすると、設定を変えたのにもかかわらず、CloudFrontにその不正な状態が残ったままになることがあるっぽい
    • その場合は Invalidationを行い、キャッシュをCloudFrontから消してみると解決するかも
    • Invalidation や設定変更反映はけっこう時間かかるので注意(試行錯誤のスピード落ちるのでもっと速くしてほしいところ…)
  • 現時点ではCloudFrontは HTTP/2 未対応
  • ブラウザからアクセスされるOriginヘッダは末尾スラッシュ無しである点に注意

参考