Static Website Hosting を特定の VPC にだけ公開する
Posted on
- #aws
 
Amazon S3 の Static Website Hosting は静的コンテンツを HTTP で公開するのにとても便利です。
この機能を使って VPC 内から HTTP でアクセスできるプライベートリポジトリを作りたかったのですが、特定の VPC にだけ公開する方法を知らなかったので調べてみました。
VPC エンドポイントを設定する
VPC エンドポイントを作らないと、インターネット経由のアクセスになってしまうので VPC 単位で制限できません。まずは VPC エンドポイントを設定して、プライベートネットワークから S3 にアクセスできるようにします。
バケットポリシーを設定する
Static Website Hosting を有効にしたあと、S3 のバケットポリシーを設定します。 aws:SourceVpc と aws:SourceVpce という条件キーがあるのでこれが使えそうです。
上記ドキュメントに例が載っているのですが、Static Website Hosting の場合はこのポリシーではアクセスできません。自分はここでハマりました。
Static Website Hosting を特定の VPC に公開するバケットポリシーはこんな感じです。
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example.com/*",
      "Condition": {
        "StringEquals": {
          "aws:sourceVpc": "vpc-xxxxxxxx"
        }
      }
    }
  ]
}
肝になるのは Condition のところだけで、他は Static Website Hosting の通常のポリシーです。 aws:SourceVpce を使っても同じように制限できます。
ちなみに、上記のバケットポリシーは明示的な Deny を設定していないので、他の VPC から AWS CLI などでアクセスすることは可能です。それも制限したいときは明示的な Deny を追加します(これがドキュメントに載っている例です)。
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "*",
      "Resource": "arn:aws:s3:::example.com/*",
      "Condition": {
        "StringNotEquals": {
          "aws:sourceVpc": "vpc-xxxxxxxx"
        }
      }
    },
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example.com/*",
      "Condition": {
        "StringEquals": {
          "aws:sourceVpc": "vpc-xxxxxxxx"
        }
      }
    }
  ]
}
バケットポリシーは、明示的な Deny > 明示的な Allow > 暗黙的な Deny の順で評価されるので、最初のステートメントで StringNotEquals を使って許可する VPC 以外を Deny しています。
まとめ
Static Website Hosting を特定の VPC に公開するには、
- VPC エンドポイントを設定する
 - バケットポリシーに 
Conditionを追加する 
の 2 つの手順が必要です。自分は VPC エンドポイントを設定していない VPC で検証を始めてしまったので、ゴールにたどり着くまで時間がかかってしまいました。