📡

DNSにRoute53を利用できない時にTerraformでCloudFrontに独自ドメインを設定するまでの流れ

2022/01/23に公開

実務をしていく中で、DNSにRoute53を利用できないことがありました。(すでに外部に委託しているDNSサービスを利用しないといけない場合など)

その案件ではTerraformをツールとして利用していましたので、その際にやったことを誰かの参考になるかもしれないのでアウトプットいたいします。

何をするのか

  • S3をOriginとしてCloudFrontを作成する
  • そのCloudFrontのエンドポイントのURLに独自ドメインを利用する(仮にhoge.comと呼称)
  • AWS ACMを利用して、SSL証明書を発行して独自ドメインでセキュアな通信ができるようにする

作業の流れ

CloudFrontを作成して、ACMの証明書を使って独自ドメインでHTTPS通信を行える様にするまでは以下の流れになります。

  • 独自ドメインを取得する
  • S3とCloudFrontを作成する
  • ACMを使ってSSL証明書作成を依頼
  • ↑ACMから、ドメインを保有していることの証明のため特定の値をCNAMEサーバーに登録する様に指令が出るため、それに従ってCNAMEの登録を行う
    • https://docs.aws.amazon.com/ja_jp/acm/latest/userguide/dns-validation.html
    • 要するに 「証明書を発行するのはいいけど、本当にそのドメインの所有者だよね?所有者ならそのドメインに任意のDNS設定をできるはずだから、AWSで指定する内容でレコード登録してみてよ!それが確認できたら有効な証明書として扱ってあげるからさ!」ということのようです
  • DNSレコードの設定が有効になったらCloudFrontに独自ドメインでアクセスして確認してみる

Terraformを利用していて、ネームサーバーにRoute53を利用している場合全てTerraform内で作業が完了します。(ACMから出されたドメイン検証も、全てRoute53で設定できますからね)

ですが、今回は独自ドメインはAWS外で取得、ネームサーバーにRoute53は使えないという制限があるため、以下の様な作業の流れとなります

  • (手動)独自ドメインを取得する
  • (Terraform)S3とCloudFrontを作成する
  • (Terraoform)ACMを使ってSSL証明書作成を依頼
  • (手動)↑ACMから、ドメインを保有していることの証明のため特定の値をCNAMEサーバーに登録する様に指令が出るため、それに従ってCNAMEの登録を行う
  • (手動)DNSレコードの設定が有効になったらCloudFrontに独自ドメインでアクセスして確認してみる

ドメイン取得周りとDNS設定作業で手作業が発生します

設定の流れ

独自ドメインの取得

今回はお名前.comを利用しました!

今回はこの辺りの作業は焦点ではないため、割愛いたします。

Terraformで必要なリソースをプロビジョニング(S3・CloudFront・ACM)

以下コードの一部を記載しております。

全文はこちらのリポジトリに配置しておりますので、ご参照ください。

https://github.com/bun913/aws_network_practice/tree/main/cloudfront_s3_acm

terraform.tfvars(git管理外) の内容

root_domain = "hoge.com" #取得したドメイン名を設定してください
main.tf
# 今回2つバケットとCloudFrontを用意してそれぞれSSL通信できることを確認
locals {
  webassets = [
    {
      "bucket_name" : "acm-practice-1",
      "acl" : "private"
    },
    {
      "bucket_name" : "acm-practice-2",
      "acl" : "private"
    }
  ]
}
module "webassets" {
  source      = "./modules/webassets/"
  tags        = var.tags
  bucket_list = local.webassets
}

module "cert" {
  source      = "./modules/cert/"
  root_domain = var.root_domain
}
modules/webassets/main.tf
resource "aws_cloudfront_distribution" "s3_distribution" {
  for_each = { for index, b in var.bucket_list : index => b }
  enabled  = true
  origin {
    domain_name = aws_s3_bucket.origin[each.key].bucket_regional_domain_name
    origin_id   = aws_s3_bucket.origin[each.key].id
    s3_origin_config {
      origin_access_identity = aws_cloudfront_origin_access_identity.oai[each.value.bucket_name].cloudfront_access_identity_path
    }
  }
  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = aws_s3_bucket.origin[each.key].id
    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }
    viewer_protocol_policy = "allow-all"
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
  }
  restrictions {
    geo_restriction {
      restriction_type = "whitelist"
      locations        = ["JP"]
    }
  }
  viewer_certificate {
    # NOTE: 今回は手動でSSL証明書を検証する作業と紐づける作業が必要という前提
    cloudfront_default_certificate = true
  }
}

modules/cert/main.tf
# CloudFrontの証明書設定ではus-east-1にしないといけないため
provider "aws" {
  alias  = "virginia"
  region = "us-east-1"
}
# 証明書発行リクエスト
resource "aws_acm_certificate" "cert" {
  # ワイルドカード証明書を発行
  # 例えば shop.hoge.com のような子ドメインが出てきても対応できるように
  domain_name               = "*.${var.root_domain}"
  # ↑だと *.hoge.com は適用できるが hoge.com自体が対象とならないため指定しておく
  subject_alternative_names = [var.root_domain]
  validation_method         = "DNS"
  provider                  = aws.virginia
  lifecycle {
    create_before_destroy = true
  }
}

modules/webassets/policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Statement1",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${oai_arn}"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::${bucket_name}/*"
    }
  ]
}

これらを適用することで S3・CloudFrontなどがプロビジョニングされます。

ACMでAWSから指定されたドメイン検証のためのレコード登録値を確認する

↑までしておくことで ACMへの証明書発行リクエストまで済んでいる状態となるため、AWSマネジメントコンソールからACMを確認します。

以下の様に証明書発行リクエストが終わり、以下の様に「保留中」のステータスになっています。

写真は途切れていますが、この右側の方にドメイン検証用に登録する必要のあるCNAMEレコードの値が記載されているため、DNSサーバーに登録します。

※ ちなみにここでAWS側から提示されるCNAMEのレコード値は、ドメイン名が同じであれば一度この証明書を破棄して、再度ACMで証明書を発行しても同じ値が提示される様です。ですので、一度外部DNSサーバーで値を登録しておけば、うっかりACMの証明書を削除しても同じドメインで作り直せば再度のドメイン検証は不要のようです。

DNSサーバーへのドメインの登録

今回はRoute53を使わないという制約があるため、手動で設定する必要があります。

例えばお名前.com では以下の様な手順で設定を行います。

https://www.onamae.com/guide/p/70

設定した内容

  • 独自ドメインでCloudFrontにアクセスできる様にCloudFrontの「ディストリビューションドメイン名」(https://hogehoge.cloudfront.net の様な形式)をCNAMEレコードに登録
    • CNAME名: hogehoge.cloudfront.net
    • CNAME値: hoge.com
  • ↑でAWS側から指定されたCNAMEの値を登録

設定後私の場合は、5分もしない間にAWSマネジメントコンソールでACMで発行した証明書をみてみると、有効なステータスになっておりました!

あとはS3に適当な画像ファイルなどを配置して、CloudFrontに独自ドメインでアクセスしてその画像が表示されることを確認しました!!

Discussion