手軽にサイトを公開したい
サイトを作りたいとか作って欲しいという依頼はよくある
この時の手軽さというのはかなり大切になる
手軽に再現性がある方法を紹介する
ただしドメインはお名前ドットコムで取得した場合のことを考える
構成
ドメインの取得
お名前ドットコムで独自ドメインを取得する
Route53との紐づけ
お名前.comで取得したドメインをRoute53のネームサーバで管理設定してみた
お名前.comで取得したドメインのホストゾーンをRoute53で作成することで、独自ドメインをAWSで設定できるようにする
Route53のホストゾーンの作成はterraformで行う
resource "aws_route53_zone" "host_zone" {
provider = aws.virginia
name = var.site_domain
}
作成が完了したらAWSマネジメントコンソールでRoute53にアクセス
ホストゾーンが作成されているので、その中から4件のNSレコードをお名前ドットコムに登録することで、AWSとお名前ドットコムを繋げる
※お名前ドットコムで登録が完了するまでは時間がかかる
ネームサーバの変更確認
nslookup -type=NS [取得したドメイン名]
ネームサーバにAWSの値が表示されれば変更が完了している。
ACMの発行
https通信を行うためにACMを発行する
ACMの発行はterraformで行う
先ほど追加した4件のNSレコードが必要となるステップ
証明書というのはただ発行してもドメインの所有者である証拠が無い、つまり証明書に効力が無い状態
例えばGoogleの証明書であっても発行するだけであれば誰でも自由に出来る
本当にドメインの所有者である場合は任意のDNS設定をできるはず
そのためAWSが指定するレコードを登録することを、AWSが確認できた時に初めて証明書を有効化することができる
# https通信のためにACM証明書を定義
resource "aws_acm_certificate" "cert" {
provider = aws.virginia
domain_name = var.site_domain
validation_method = "DNS"
lifecycle {
create_before_destroy = true
}
tags = {
Environment = var.environment
}
}
# ACMのDNS検証用レコードの生成
resource "aws_route53_record" "cert" {
for_each = {
for dvo in aws_acm_certificate.cert.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
provider = aws.virginia
allow_overwrite = true
name = each.value.name
type = each.value.type
records = [each.value.record]
zone_id = aws_route53_zone.host_zone.zone_id
ttl = 60
depends_on = [aws_acm_certificate.cert, aws_route53_zone.host_zone]
}
# ACMのDNS検証用レコードのチェック
resource "aws_acm_certificate_validation" "cert" {
provider = aws.virginia
certificate_arn = aws_acm_certificate.cert.arn
validation_record_fqdns = flatten([values(aws_route53_record.cert)[*].fqdn])
depends_on = [aws_acm_certificate.cert, aws_route53_record.cert]
}
S3バケットの作成
公開したいリソースを置くための場所を作成する。
resource "aws_s3_bucket" "s3_static_bucket" {
bucket = "${var.project}-${var.environment}-${var.site_domain}"
force_destroy = true
}
# CloudFrontからのオリジンアクセスアイデンティティ付きアクセスに対してReadのみを許可する
resource "aws_s3_bucket_policy" "s3_static_bucket" {
bucket = aws_s3_bucket.s3_static_bucket.id
policy = data.aws_iam_policy_document.s3_static_bucket.json
depends_on = [ aws_s3_bucket_public_access_block.s3_static_bucket ]
}
data "aws_iam_policy_document" "s3_static_bucket" {
statement {
effect = "Allow"
actions = ["s3:GetObject"]
resources = ["${aws_s3_bucket.s3_static_bucket.arn}/*"]
principals {
type = "AWS"
identifiers = [aws_cloudfront_origin_access_identity.site.iam_arn]
}
}
}
resource "aws_s3_bucket_public_access_block" "s3_static_bucket" {
bucket = aws_s3_bucket.s3_static_bucket.id
block_public_acls = true
block_public_policy = false
ignore_public_acls = true
restrict_public_buckets = false
}
cloudfrontの作成
https通信のために発行したACM(SSL証明書)をアタッチするためにcloudfrontを利用(S3にはアタッチ不可能)
また独自ドメインとcloudfrontを紐づけることで、独自ドメインでのアクセスを可能とする
# CloudFrontの配信元の識別子
locals {
s3_origin_id = "s3-origin-${var.site_domain}"
}
# PrivateなS3 Bucketにアクセスするためにオリジンアクセスアイデンティティを利用する
resource "aws_cloudfront_origin_access_identity" "site" {
comment = local.s3_origin_id
}
# CloudFrontのディストリビューション設定
resource "aws_cloudfront_distribution" "s3_distribution" {
origin {
domain_name = aws_s3_bucket.s3_static_bucket.bucket_regional_domain_name
origin_id = local.s3_origin_id
s3_origin_config {
origin_access_identity = aws_cloudfront_origin_access_identity.site.cloudfront_access_identity_path
}
}
enabled = true
is_ipv6_enabled = true
comment = var.site_domain
default_root_object = "index.html"
aliases = [var.site_domain]
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = local.s3_origin_id
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
viewer_protocol_policy = "redirect-to-https"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
price_class = "PriceClass_200"
restrictions {
geo_restriction {
restriction_type = "none"
}
}
tags = {
Environment = "${var.environment}"
}
viewer_certificate {
acm_certificate_arn = aws_acm_certificate_validation.cert.certificate_arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1"
}
}
#Aliasレコード
resource "aws_route53_record" "site" {
zone_id = aws_route53_zone.host_zone.zone_id
name = var.site_domain
type = "A"
alias {
name = aws_cloudfront_distribution.s3_distribution.domain_name
zone_id = aws_cloudfront_distribution.s3_distribution.hosted_zone_id
evaluate_target_health = false
}
}
ブラウザから独自ドメインによるhttps通信ができるか確認
今回作成したS3バケットにルートにindex.htmlを配備して、アクセスしてみる
問題無くアクセスできた
ドメイン取得をRoute53にする方が気軽
今回はAWSとお名前ドットコムの2画面を触る必要があった
terraformだけで完結させる場合、ドメインの取得をお名前ドットコムではなくRoute53にする必要がある
ここはコストとの兼ね合いとなるが、気軽さを追求するならRoute53でのドメイン取得に軍配が上がる
お名前.comからAmazon Route 53へドメインを移管