やりたかったこと
s3にuploadした画像を cache distributionパターンで管理しアクセスできるようにしたい。
Infrastructure as Code100%を目指しているので、リソースの作成はterraformで!
※ 独自ドメインでアクセスできるようにしたいのでroute53の設定もしますが、SSL証明書は発行してある前提です。Cloud Frontはus-eastで発行しないと作成できないので要注意です!(罠)
構成
作成手順
上の構成図の下から順に作っていこうと思います👍
全てのterraformコードを載せています。
S3の作成
resource "aws_s3_bucket" "image-bucket" {
bucket = "image-bucket"
acl = "private"
region = "ap-northeast-1"
}
まず上記のコードのみapplyしてみましょう。
そしてコンソールからimage-bucketにimageをuploadし、 https://s3-ap-northeast-1.amazonaws.com/image-bucket/image.png
にアクセス。
privateバケットなのでアクセスできないはずですね。
Origin Access Identityの作成
上記の通りS3に直接アクセスすることはできませんが、Cloud Frontからはアクセスできるようにするため、Origin Access Identityを作成します。あとでS3のPolicyに紐づけることで、Cloud Frontからのアクセスを許可できます。
resource "aws_cloudfront_origin_access_identity" "origin_access_identity" {
comment = "origin access identity for s3"
}
S3のPolicyを作成
principalsのidentifiersで先ほど作成したOrigin Access Identityを指定し、Cloud Front → S3 bucket の一部アクションを許可をします。
data "aws_iam_policy_document" "cf_to_s3_policy" {
statement {
actions = ["s3:GetObject", "s3:ListBucket"]
resources = [
"${aws_s3_bucket.image-bucket.arn}",
"${aws_s3_bucket.image-bucket.arn}/*",
]
principals {
type = "AWS"
identifiers = ["${aws_cloudfront_origin_access_identity.origin_access_identity.iam_arn}"]
}
}
}
そしてこのpolicyをs3に繋げてあげます。
resource "aws_s3_bucket_policy" "cf-to-s3" {
bucket = "${aws_s3_bucket.image-bucket.id}"
policy = "${data.aws_iam_policy_document.cf_to_s3_policy.json}"
}
Cloud Frontの作成
よしなに指定する箇所
- origin/domain_name
- S3バケットのドメイン名
- s3_origin_config/origin_access_identity
- Origin Access Identityのパス
- aliases
- 名前解決させたい独自のドメイン名
- viewer_certificate/acm_certificate_arn
- 独自ドメインを発行したacmのarn(us-eastである必要があります)
他パラメータの補足
- default_cache_behavior
- cacheサーバーの細かい設定
- price_class
- cacheサーバーとして利用する地域のクラスを選択
- restrictions
- ユーザーリクエストの地域制限を設定、white listとblack listを登録できる
resource "aws_cloudfront_distribution" "s3_distribution" {
origin {
domain_name = "${aws_s3_bucket.image-bucket.bucket_regional_domain_name}"
origin_id = "${aws_s3_bucket.image-bucket.id}"
s3_origin_config {
origin_access_identity = "${aws_cloudfront_origin_access_identity.origin_access_identity.cloudfront_access_identity_path}"
}
}
enabled = true
is_ipv6_enabled = false
comment = "comment"
logging_config {
include_cookies = false
bucket = "${aws_s3_bucket.image-bucket.bucket_domain_name}"
prefix = "prefix"
}
aliases = ["sample.com"]
default_cache_behavior {
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "${aws_s3_bucket.image-bucket.id}"
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
viewer_protocol_policy = "allow-all"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
price_class = "PriceClass_200"
restrictions {
geo_restriction {
restriction_type = "none"
}
}
tags = {
Environment = "dev"
}
viewer_certificate {
acm_certificate_arn = "arn:aws:acm:us-east-1:xxx:certificate/xxx"
ssl_support_method = "vip"
}
}
Cloud Frontの設定は、us-eastしか受け付けない問題から始まり、restrictionsをサーバーの話かと思いwhite listに日本(JP)を入れずに設定してしまったりと(自分もアクセスできなくなるw)ちょっと詰まりました・・・。
さて、Cloud Front→S3まではできたのでapplyしてみましょう。
(Cloud Frontの作成は30minほどかかります😓)
Cloud Frontが無事に作成されたら、domain nameを確認しアクセスしてみましょう。リクエストが成功し、S3にuploadした画像をみることができました🎉
route53のRecordの作成
最後に独自ドメインからもアクセスできるようにします。
よしなに指定する箇所
- zone_id
- HostedZoneのid
- name
- アクセスできるようにするドメイン名
- records
- cnameの値=先ほど作成したCloud Front Distributionのドメイン名(xxx.cloudfront.net)
resource "aws_route53_record" "cname" {
zone_id = "xxx"
name = "sample.com"
type = "CNAME"
ttl = "300"
records = ["${aws_cloudfront_distribution.s3_distribution.domain_name}"]
}