1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

お名前ドットコムで取得した独自ドメインでAWSにhttpsのサイトを公開 with terraform

Posted at

手軽にサイトを公開したい

サイトを作りたいとか作って欲しいという依頼はよくある
この時の手軽さというのはかなり大切になる
手軽に再現性がある方法を紹介する
ただしドメインはお名前ドットコムで取得した場合のことを考える

構成

a.drawio (1).png
詳細は記事内で説明する

ドメインの取得

お名前ドットコムで独自ドメインを取得する
image.png

Route53との紐づけ

お名前.comで取得したドメインをRoute53のネームサーバで管理設定してみた
お名前.comで取得したドメインのホストゾーンをRoute53で作成することで、独自ドメインをAWSで設定できるようにする
Route53のホストゾーンの作成はterraformで行う

hostzone.tf
resource "aws_route53_zone" "host_zone" {
  provider     = aws.virginia
  name         = var.site_domain
}

作成が完了したらAWSマネジメントコンソールでRoute53にアクセス
image.png
ホストゾーンが作成されているので、その中から4件のNSレコードをお名前ドットコムに登録することで、AWSとお名前ドットコムを繋げる
※お名前ドットコムで登録が完了するまでは時間がかかる
image.png

ネームサーバの変更確認

nslookup -type=NS [取得したドメイン名]

ネームサーバにAWSの値が表示されれば変更が完了している。

ACMの発行

https通信を行うためにACMを発行する
ACMの発行はterraformで行う
先ほど追加した4件のNSレコードが必要となるステップ
証明書というのはただ発行してもドメインの所有者である証拠が無い、つまり証明書に効力が無い状態
例えばGoogleの証明書であっても発行するだけであれば誰でも自由に出来る
本当にドメインの所有者である場合は任意のDNS設定をできるはず
そのためAWSが指定するレコードを登録することを、AWSが確認できた時に初めて証明書を有効化することができる

acm.tf
# 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バケットの作成

公開したいリソースを置くための場所を作成する。

s3.tf
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.tf
# 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を配備して、アクセスしてみる
image.png
image.png
問題無くアクセスできた

ドメイン取得をRoute53にする方が気軽

今回はAWSとお名前ドットコムの2画面を触る必要があった
terraformだけで完結させる場合、ドメインの取得をお名前ドットコムではなくRoute53にする必要がある
ここはコストとの兼ね合いとなるが、気軽さを追求するならRoute53でのドメイン取得に軍配が上がる
お名前.comからAmazon Route 53へドメインを移管

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?