[Terraform]親ドメインからサブドメインへの権限委任 〜 サブドメインのパブリック証明書を取得するまで

[Terraform]親ドメインからサブドメインへの権限委任 〜 サブドメインのパブリック証明書を取得するまで

Clock Icon2025.02.18

はじめに

皆様こんにちは、クラウド事業本部コンサルティング部のあかいけです。

最近、Route53で既存のドメインにサブドメインを追加(権限委任)する機会があり、
作業する際に私はふと思いました。
「Route53に限った話ではないけど、GUIで久しぶりに触るリソースだと画面構成が変わっていて困惑することがあるよなぁ…。」 と。

そこで今後を見据えて、今回はTerraformを使って作業してみることにしました。
なおGUIでの手順は以下をご参照ください。

やりたいこと

構成

  • 親ドメイン(委任元):example.org
  • サブドメイン(委任先):tes.example.org

add-subdomain (2)

前提として、親ドメイン(example.org)は作成済みとします。
今回新たに作成するリソースは以下の通りです。

  • 親ドメイン側
    • NSレコード (委任先のサブドメインのNSを指定)
  • サブドメイン側
    • ホストゾーン
    • CNAMEレコード (証明書検証用)
    • パブリック証明書(ACM)

手順

Terraformの全量は以下の通りです。
これをローカル環境にコピーして、

terraform 全量
provider.tf
terraform {
  required_version = ">= 1.10.0"
}

terraform {
  required_providers {
    aws = ">= 5.87.0"
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

# ACM用 プロバイダー
provider "aws" {
  alias  = "us-east-1"
  region = "us-east-1"
}
variables.tf
variable "base_domain" {
  type    = string
}

variable "sub_domain" {
  type    = string
}
main.tf
locals {
  sub_domain        = var.sub_domain
  base_domain        = var.base_domain
}

# 1.サブドメイン ホストゾーン作成
resource "aws_route53_zone" "main" {
  name = "${local.sub_domain}.${local.base_domain}"
}

# 2.親ドメイン 権限委任用NSレコード作成
data "aws_route53_zone" "root" {
  name         = local.base_domain
  private_zone = false
}

resource "aws_route53_record" "root_ns" {
  zone_id = data.aws_route53_zone.root.id
  name    = "${local.sub_domain}.${local.base_domain}"
  type    = "NS"
  ttl     = 300

  records = aws_route53_zone.main.name_servers
}

# 3.サブドメイン用 証明書発行
## パブリック証明書
resource "aws_acm_certificate" "main" {
  domain_name       = "${local.sub_domain}.${local.base_domain}"
  subject_alternative_names = ["*.${local.sub_domain}.${local.base_domain}"]
  validation_method = "DNS"
  provider          = "aws.us-east-1"

  lifecycle {
    create_before_destroy = true
  }
}

## ドメイン検証
resource "aws_acm_certificate_validation" "main" {
  provider                = "aws.us-east-1"
  certificate_arn         = aws_acm_certificate.main.arn
  validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]
}

## ドメイン検証用 CNAMEレコード
resource "aws_route53_record" "cert_validation" {
  for_each = {
    for dvo in aws_acm_certificate.main.domain_validation_options : dvo.domain_name => {
      name    = dvo.resource_record_name
      record  = dvo.resource_record_value
      type    = dvo.resource_record_type
      zone_id = aws_route53_zone.main.id
    }
  }
  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = each.value.zone_id
}
output.tf
output "domain" {
  value = aws_route53_zone.main.name
}

output "name_servers" {
  value = aws_route53_zone.main.name_servers
}

variables.tfに対象となるドメイン名を入力して、
(ファイル直書きに抵抗があれば、terraform apply時に指定してください)

variables.tf
variable "base_domain" {
  type    = string
  default = example.org
}

variable "sub_domain" {
  type    = string
  default = tes
}

あとはapplyしてください。

% terraform init
% terraform apply

リソース作成後、
以下のようにNSレコードが参照できれば正常に権限委任できています。

% dig +noall +answer tes.example.org. ns 
tes.example.org.       172800  IN      NS      ns-AAAA.awsdns-XX.org.
tes.example.org.       172800  IN      NS      ns-BBBB.awsdns-XX.co.uk.
tes.example.org.       172800  IN      NS      ns-CCCC.awsdns-XX.com.
tes.example.org.       172800  IN      NS      ns-DDDD.awsdns-XX.net.

設定内容

これ以降は具体的にどのような設定をしているか解説します。

1.サブドメイン ホストゾーン作成

まずサブドメインのホストゾーンを作成します。

main.tf
resource "aws_route53_zone" "main" {
  name = "${local.sub_domain}.${local.base_domain}"
}

2.親ドメイン 権限委任用NSレコード作成

親ドメインのホストゾーンは管理対象外の想定で、dataリソースとして参照しています。
委任先のNSはサブドメインのホストゾーンの属性を参照して、
権限委任用のNSレコードを作成します。

main.tf
data "aws_route53_zone" "root" {
  name         = local.base_domain
  private_zone = false
}

resource "aws_route53_record" "root_ns" {
  zone_id = data.aws_route53_zone.root.id
  name    = "${local.sub_domain}.${local.base_domain}"
  type    = "NS"
  ttl     = 300

  records = aws_route53_zone.main.name_servers
}

3.サブドメイン 証明書発行

最後にサブドメイン用にACMでパブリック証明書を発行します。
GUIで作成する場合、検証用のCNAMEレコードは自動作成されますが、
Terraformの場合は明示的に作成する必要があります。

main.tf
## パブリック証明書
resource "aws_acm_certificate" "main" {
  domain_name       = "${local.sub_domain}.${local.base_domain}"
  subject_alternative_names = ["*.${local.sub_domain}.${local.base_domain}"]
  validation_method = "DNS"
  provider          = "aws.us-east-1"

  lifecycle {
    create_before_destroy = true
  }
}

## ドメイン検証
resource "aws_acm_certificate_validation" "main" {
  provider                = "aws.us-east-1"
  certificate_arn         = aws_acm_certificate.main.arn
  validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]
}

## ドメイン検証用 CNAMEレコード
resource "aws_route53_record" "cert_validation" {
  for_each = {
    for dvo in aws_acm_certificate.main.domain_validation_options : dvo.domain_name => {
      name    = dvo.resource_record_name
      record  = dvo.resource_record_value
      type    = dvo.resource_record_type
      zone_id = aws_route53_zone.main.id
    }
  }
  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = each.value.zone_id
}

さいごに

以上、「親ドメインからサブドメインへの権限委任 〜 パブリック証明書を取得するまで」でした。
個人的にRoute53関連の設定は頻繁にやる作業ではないためか、毎回調べて思い出しながら作業している状況です…。
なのでこれからも、隙あらばIaC化していこうと思います。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.