🦔
[メモ] Amazon S3 + CloudFrontの2つのパターンとTerraformテンプレート
今回はAmazon S3 + CloudFrontのパターンの整理と、それぞれの構成をTerraformで作成するテンプレートを記録しておきます。
Amazon S3 + CloudFrontのパターン
現時点でのパターンは大きく2種類あるように見えています。なおレガシー扱いの別手段、ACM/Route53などとの組み合わせは考慮していません。
- S3 の静的ウェブホスティングを有効化: S3/CloudFrontどちらからもアクセス可能
- S3 の静的ウェブホスティングを無効化: CloudFrontからのみアクセス可能
それぞれの設定内容の違いは以下の通り。
種別 | リソース | 設定 | |
---|---|---|---|
静的ウェブホスティングを有効化 | S3 | ブロックパブリックアクセス | オフ |
静的ウェブサイトホスティング | オン | ||
bucket policy |
s3:GetObject を全リソースに許可 |
||
CloudFront | オリジンドメイン |
<bucket>.s3-website-<region>.amazonaws.com (Webサイトのエンドポイントを使用) |
|
静的ウェブホスティングを無効化 | S3 | ブロックパブリックアクセス | オン |
静的ウェブサイトホスティング | オフ | ||
bucket policy |
s3:GetObject を特定のCloudFrontにのみ許可 |
||
CloudFront | オリジンドメイン | <bucket>.s3.<region>.amazonaws.com |
|
オリジンアクセス | Origin access control settings |
Terraformテンプレート
それぞれのテンプレートの例は以下の通り。
静的ウェブホスティングを有効化
terraform {
required_version = ">= 1.0.0, < 2.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
# S3
resource "aws_s3_bucket" "example" {
bucket = "terraform-example-s3-cloudfront"
}
resource "aws_s3_bucket_public_access_block" "example" {
bucket = aws_s3_bucket.example.id
}
resource "aws_s3_bucket_website_configuration" "example" {
bucket = aws_s3_bucket.example.id
index_document {
suffix = "index.html"
}
}
resource "aws_s3_object" "example" {
bucket = aws_s3_bucket.example.id
key = "index.html"
source = "./index.html"
content_type = "text/html"
}
resource "aws_s3_bucket_policy" "example" {
bucket = aws_s3_bucket.example.id
policy = data.aws_iam_policy_document.example.json
}
data "aws_iam_policy_document" "example" {
statement {
sid = ""
effect = "Allow"
principals {
identifiers = ["*"]
type = "*"
}
actions = [
"s3:GetObject"
]
resources = [
"${aws_s3_bucket.example.arn}/*",
]
}
}
# CloudFront
data "aws_cloudfront_cache_policy" "example" {
name = "Managed-CachingOptimized"
}
data "aws_region" "current" {}
resource "aws_cloudfront_distribution" "example" {
enabled = true
default_root_object = "index.html"
origin {
origin_id = aws_s3_bucket.example.id
domain_name = "${aws_s3_bucket.example.bucket}.s3-website-${data.aws_region.current.name}.amazonaws.com"
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "http-only"
origin_ssl_protocols = ["SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"]
origin_read_timeout = 30
origin_keepalive_timeout = 5
}
}
viewer_certificate {
cloudfront_default_certificate = true
}
default_cache_behavior {
target_origin_id = aws_s3_bucket.example.id
viewer_protocol_policy = "redirect-to-https"
cached_methods = ["GET", "HEAD"]
allowed_methods = ["GET", "HEAD"]
cache_policy_id = data.aws_cloudfront_cache_policy.example.id
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
}
静的ウェブホスティングを無効化
terraform {
required_version = ">= 1.0.0, < 2.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
# S3
resource "aws_s3_bucket" "example" {
bucket = "terraform-sandbox-example-s3-cloudfront"
}
resource "aws_s3_bucket_public_access_block" "example" {
bucket = aws_s3_bucket.example.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_object" "example" {
bucket = aws_s3_bucket.example.id
key = "index.html"
source = "./index.html"
content_type = "text/html"
}
resource "aws_s3_bucket_policy" "example" {
bucket = aws_s3_bucket.example.id
policy = data.aws_iam_policy_document.example.json
}
data "aws_iam_policy_document" "example" {
statement {
principals {
type = "Service"
identifiers = ["cloudfront.amazonaws.com"]
}
actions = [
"s3:GetObject"
]
resources = [
"${aws_s3_bucket.example.arn}/*"
]
condition {
test = "StringEquals"
variable = "aws:SourceArn"
values = [
aws_cloudfront_distribution.example.arn,
]
}
}
}
# CloudFront
data "aws_cloudfront_cache_policy" "example" {
name = "Managed-CachingOptimized"
}
resource "aws_cloudfront_distribution" "example" {
enabled = true
default_root_object = "index.html"
origin {
origin_id = aws_s3_bucket.example.id
domain_name = aws_s3_bucket.example.bucket_regional_domain_name
origin_access_control_id = aws_cloudfront_origin_access_control.example.id
}
viewer_certificate {
cloudfront_default_certificate = true
}
default_cache_behavior {
target_origin_id = aws_s3_bucket.example.id
viewer_protocol_policy = "redirect-to-https"
cached_methods = ["GET", "HEAD"]
allowed_methods = ["GET", "HEAD"]
cache_policy_id = data.aws_cloudfront_cache_policy.example.id
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
}
resource "aws_cloudfront_origin_access_control" "example" {
name = aws_s3_bucket.example.bucket_domain_name
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}
Discussion