脳汁portal

アメリカ在住(だった)新米エンジニアがその日学んだIT知識を書き綴るブログ

AWS S3でStatic website hostingを使うけど、bucketへの直リンクアクセスを制限したい場合

AWS S3に配置した静的コンテンツを使ってcloud front経由でwebsiteを公開するときに、S3 bucket自体をoriginとして指定する場合はorigin access identityでcloud frontからのアクセスのみを許可するということが可能になる。

しかし、S3のstatic website hosting機能を使ってエンドポイントを発行した場合は、このorigin access identityが使えない
この場合S3 bucket側でcloud frontからのアクセスのみを許可するといったスマートなアクセス制限はできない。

IPアドレスによる制限は可能だが、ここで指定するIPは実際にアクセスするユーザのIPレンジではなく、cloud frontのIPを指定しなければいけない。それでもいいのだが、このIPは変わる可能性もあるし、大量にルールを書かなければいけないので避けたい。

解決方法としては、cloud frontからcustome headerとして任意の文字をrefererで送り、S3 bucket側でその特定のheaderがある場合のみGetObjectできるといったbucket policyを設定してやればよい

※static website hosting機能にこだわるのは、サブディレクトリでもindex補完機能を使いたいから
(cloud front側で使えるindex補完はrootディレクトリのみとなっている)


1. S3のwebsite hosting機能をonにする

f:id:portaltan:20190221155457p:plain

2. アクセスコントロール/bucket policyの編集を許可する

f:id:portaltan:20190221155638p:plain

3. bucket policyを設定する

{
    "Version": "2008-10-17",
    "Id": "http referer policy",
    "Statement": [
        {
            "Sid": "Referer-Allow",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::example-bucket/*",
            "Condition": {
                "StringLike": {
                    "aws:Referer": "foobar"
                }
            }
        },
        {
            "Sid": "Explicit deny to ensure requests are allowed only from specific referer.",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::example-bucket/*",
            "Condition": {
                "StringNotLike": {
                    "aws:Referer": "foobar"
                }
            }
        }
    ]
}

この時点でまず指定したheaderの有無でアクセス制限がかかっているか確認する

curl --header 'referer:foobar' ${static website hosting Endpoint URL}
→アクセスできる

curl --header 'referer:fizzbazz' ${static website hosting Endpoint URL}
→アクセスできない(403エラー)

4. cloudfrontの設定

  • Origin Domain Name
    • static website hostingのエンドポイントURLを入力
  • custome Header

後は普通に設定すればOKです
distributingが終わったら、一応cloudfrontのdomainにアクセスして確認しまs
(*****.cloudfront.netってやつ)

5. Route53

最後にRoute53で任意のドメインと上記のcloudfrontのドメインを紐づければ完成です