バケットポリシーでS3のアクセス制限
S3を静的サイトホスティングでWeb公開するが、特定のIPかVPC内のEC2からのみアクセスできるように許可したい場合、バケットポリシーで制限できる。特定のIPかVPCなので条件をOR
でつなげる必要があるが、バケットポリシーのStatement
はリストになっていて複数入力でき、それらがOR
でつながる。
それ以外は以下のように記載する。
Id
,Sid
には適当な名前をいれる- Webアクセス制限なので
Action
にはs3:GetObject
を指定する Effect
にはAllow
を設定するIpAddress
で対象のIPを列挙するStringEquals
で対象のVPCのIDを設定する
3の「Effect
にはAllow
を設定する」は重要なポイント。Condition
の条件文を工夫したうえで全体のAction
にDeny
を設定し、Allow
のときと論理的には同じ制限をつくっても、うまくアクセス制限できない。S3はデフォルトで非公開設定になっているので、その非公開デフォルト設定に対して、特定のIPあるいはVPCを許可(Allow
)するというバケットポリシーを書かなくてはいけないため。
5の「StringEquals
で対象のVPCのIDを設定する」については、あらかじめS3へのVPCエンドポイントを作成しておかなければならない。VPCエンドポイントを作成しないと、VPCのプライベートサブネットからS3バケットへアクセスできない。また、VPC内からのアクセスであることをS3バケットが判断できない。
以上の点を踏まえると、バケットポリシーは次のようになる。
{
"Version": "2012-10-17",
"Id": "my-private-bucket-policy",
"Statement": [
{
"Sid": "Allow-from-specific-IP",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mybucket/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"XXX.XXX.XXX.XXX/32",
"YYY.YYY.YYY.YYY/28"
]
}
}
},
{
"Sid": "Allow-from-specific-VPC",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mybucket/*",
"Condition": {
"StringEquals": {
"aws:SourceVpc": "vpc-99999999"
}
}
}
]
}
Terraformによる設定
TerraformのVersion情報は以下の通り。
$ terrafrom --version
Terraform v0.11.5
+ provider.aws v1.35.0
Terraformでバケットの作成からWeb公開、VPCエンドポイントの作成、バケットポリシーの設定まで書く。
resource "aws_s3_bucket" "mybucket" {
bucket = "mybucket"
tags {
Name = "mybucket"
Environment = "dev"
}
website {
index_document = "index.html"
error_document = "error.html"
}
}
resource "aws_vpc_endpoint" "s3" {
vpc_id = "vpc-99999999"
service_name = "com.amazonaws.ap-northeast-1.s3"
route_table_ids = [
"rtb-WWWWWWWW",
"rtb-XXXXXXXX",
"rtb-YYYYYYYY",
"rtb-ZZZZZZZZ"
]
}
resource "aws_s3_bucket_policy" "my-private-bucket-policy" {
bucket = "${aws_s3_bucket.mybucket.id}"
policy =<<POLICY
{
"Version": "2012-10-17",
"Id": "private-bucket-policy",
"Statement": [
{
"Sid": "Allow-from-specific-IP",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": ["arn:aws:s3:::mybucket/*"],
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"XXX.XXX.XXX.XXX/32",
"YYY.YYY.YYY.YYY/28"
]
}
}
}
,
{
"Sid": "Allow-from-specific-VPC",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": ["arn:aws:s3:::mybucket/*"],
"Condition": {
"StringEquals": {
"aws:SourceVpc": [
"vpc-99999999"
]
}
}
}
]
}
POLICY
}