※本記事は社内ブログの内容を一部変えて転記しています。
背景
AWSのS3 + cloudfrontでwebサイトを公開する際に
wwwありのURL(https://www.sink-capital.com/)で公開を行ったのですが、
サブドメインなしのURL(https://sink-capital.com/)だと繋がらないことに気付いたため修正を行いました。
一般的な方法
基本的には
Amazon Route 53 を使って、サブドメイン(www)なしから、ありドメインへリダイレクト
に記載のある方法で、
サブドメインなしのURLから来たリクエストを、
全てサブドメインありのURLにリダイレクトすることを目指しました。
- サブドメインなしのURLからリクエストが来る
- route53のAレコードaliasでS3にリクエストを飛ばす
- S3の設定でサブドメインありのURLにリダイレクト
ただし上記の対応だとhttpsに対応できないという問題点がありました。
(route53とS3だと証明書を入れ込むことができないため)
今回の対応方法
webサイト自体の公開方法と同様にcloudfrontを利用してS3に接続を行いました。
- サブドメインなしのURLからリクエストが来る
- route53のAレコードaliasでcloudfrontにリクエストを飛ばす
- cloudfrontからS3にリクエストを流す
- S3の設定でサブドメインありのURLにリダイレクト
実際のコード(terraform)
cloudfront.tf
resource "aws_cloudfront_distribution" "sci_website" {
enabled = true
aliases = [
"${var.root_domain_name}"]
comment = "${terraform.workspace}-www-root-alias"
default_root_object = "index.html"
price_class = "PriceClass_All"
origin {
domain_name = "${var.root_domain_name}.s3-website-${var.region}.amazonaws.com"
origin_id = "S3-${aws_s3_bucket.sci_www_root_alias_bucket.bucket}"
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "http-only"
origin_ssl_protocols = [
"TLSv1"]
}
}
default_cache_behavior {
allowed_methods = [
"GET",
"HEAD"]
cached_methods = [
"GET",
"HEAD"]
target_origin_id = "S3-${aws_s3_bucket.sci_www_root_alias_bucket.bucket}"
forwarded_values {
query_string = true
cookies {
forward = "none"
}
}
viewer_protocol_policy = "https-only"
min_ttl = 3600
default_ttl = 10800
max_ttl = 86400
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
acm_certificate_arn = "${aws_acm_certificate.sci_com.arn}"
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1"
}
}
route53.tf
resource "aws_route53_record" "root" {
zone_id = "${var.route53_zone_id}"
name = "${var.root_domain_name}"
type = "A"
alias {
name = "${aws_cloudfront_distribution.sci_website.domain_name}"
zone_id = "${aws_cloudfront_distribution.sci_website.hosted_zone_id}"
evaluate_target_health = true
}
}
resource "aws_route53_record" "cert_validation" {
zone_id = "${var.route53_zone_id}"
name = "${aws_acm_certificate.sci_com.domain_validation_options.0.resource_record_name}"
type = "${aws_acm_certificate.sci_com.domain_validation_options.0.resource_record_type}"
ttl = 60
allow_overwrite = true
records = [
"${aws_acm_certificate.sci_com.domain_validation_options.0.resource_record_value}"]
}
resource "aws_acm_certificate" "sci_com" {
provider = "aws.ue1"
domain_name = "${var.root_domain_name}"
subject_alternative_names = []
validation_method = "DNS"
}
resource "aws_acm_certificate_validation" "sci_com_validation" {
provider = "aws.ue1"
certificate_arn = "${aws_acm_certificate.sci_com.arn}"
validation_record_fqdns = [
"${aws_route53_record.cert_validation.0.fqdn}"]
}
s3.tf
resource "aws_s3_bucket" "sci_www_root_alias_bucket" {
bucket = "${var.root_domain_name}"
acl = "private"
website {
redirect_all_requests_to = "https://www.${var.root_domain_name}"
}
}
variable.tf
※ドメイン名はお好きに
variable "route53_zone_id" {}
variable "root_domain_name" {
default = "sink-capital.com"
}
variable "region" {
default = "ap-northeast-1"
}
感想
terraform中に出てくる細かい設定がいくつかあり、
一つでも間違えると繋がらなかったりするので意外と大変でした。
特にキャッシュが残るせいで繋がったり繋がらなかったり。。。
ただterraformでかけたので心理的安全性はかなり高くなります。