Terraformを活用してACMリソースを作成する手順を、各動作フローとともに詳しく整理しました。
今回は、Route 53に「api」「www」「blog」のサブドメインを登録済みのドメイン「example.com」に対して、ワイルドカード証明書を発行した。
1. 手順
1-1. acmを記述
acm.tf記載例
# ---------------------------------------------
# Certificate
# ---------------------------------------------
# ①:証明書を発行するためのACMリソースを記述
resource "aws_acm_certificate" "example_cert" {
domain_name = "*.${var.domain}" # ワイルドカード証明書のドメイン名
validation_method = "DNS" # DNS認証を使用
tags = {
Name = "wildcard-ssl/tls-cert"
}
depends_on = [
aws_route53_zone.example_zone # Route53ゾーンに依存
]
}
# ②:DNSレコードを作成してACM証明書の認証を行う(DNS認証)
resource "aws_route53_record" "route53_acm_dns_resolve" {
for_each = {
for dvo in aws_acm_certificate.example_cert.domain_validation_options :
dvo.domain_name => {
name = dvo.resource_record_name # レコード名
type = dvo.resource_record_type # レコードタイプ(通常はCNAME)
record = dvo.resource_record_value # レコード値
}
}
allow_overwrite = true # 既存のレコードを上書きする設定
zone_id = aws_route53_zone.example_zone.zone_id # Route53ゾーンのID
name = each.value.name # レコード名
type = each.value.type # レコードタイプ
ttl = 600 # TTL(キャッシュの有効時間)
records = [each.value.record] # 証明書の認証用レコード値
}
# DNSレコードを使ってACM証明書の認証を完了させる
resource "aws_acm_certificate_validation" "cert_valid" {
certificate_arn = aws_acm_certificate.example_cert.arn # 証明書のARN
validation_record_fqdns = [for record in aws_route53_record.route53_acm_dns_resolve : record.fqdn] # DNSレコードのFQDN
}
補足:変数のサンプル
# 変数のサンプル
variable "domain" {
description = "The domain name for the certificate"
type = string
default = "example.com"
}
# Route53ゾーンのリソース(例として)
resource "aws_route53_zone" "example_zone" {
name = "${var.domain}" # ドメイン名に基づいてゾーンを作成
}
2. 説明
①:証明書を発行するためのACMリソースを記述
今回は、ワイルドカード証明書、DNS検証で進めていきます。
domain_name = "*.${var.domain}" # ワイルドカード証明書のドメイン名
validation_method = "DNS" # DNS認証を使用 ACMでは"DNS/EMAIL"のみ
②:DNSレコードを作成してACM証明書の認証を行う(ドメイン所有者確認)
1. ACMリソースでvalidation_method = "DNS"
を選択すると、内部でdomain_validation_options
が生成されます。(validation_methodで"DNS"
を選択した場合はCNAMEレコード情報が生成される)
自動生成されたdomain_validation_optionsのサンプル
(ドメイン「example.com」にサブドメイン「api」「www」「blog」登録済みの場合)
"domain_validation_options": [
{
"domain_name": "api.example.com", // 証明書が発行されるドメイン名(例: api.example.com)
"resource_record_name": "_abcdef1234567890.api.example.com", // DNS検証用のCNAMEレコード名(例: _abcdef1234567890.api.example.com)
"resource_record_type": "CNAME", // DNSレコードタイプ(通常は "CNAME")
"resource_record_value": "_xyz9876543210.acm-validations.aws" // 設定すべきCNAMEレコードの値(ACMが提供する検証用のレコード値)
},
{
"domain_name": "www.example.com", // 証明書が発行される別のドメイン名(例: www.example.com)
"resource_record_name": "_ghijk1234567890.www.example.com", // このドメインの検証用CNAMEレコード名
"resource_record_type": "CNAME", // DNSレコードタイプ(通常は "CNAME")
"resource_record_value": "_uvw9876543210.acm-validations.aws" // 検証用のCNAMEレコード値
},
{
"domain_name": "blog.example.com", // 証明書が発行される別のドメイン名(例: blog.example.com)
"resource_record_name": "_lmnop1234567890.blog.example.com", // このドメインの検証用CNAMEレコード名
"resource_record_type": "CNAME", // DNSレコードタイプ(通常は "CNAME")
"resource_record_value": "_rst9876543210.acm-validations.aws" // 検証用のCNAMEレコード値
}
]
補足:route53.tf例
# Route 53ゾーンの設定(すでに存在しているゾーンを使用)
resource "aws_route53_zone" "example_zone" {
name = "example.com"
}
# api.example.com 用のAレコード
resource "aws_route53_record" "api_subdomain" {
zone_id = aws_route53_zone.example_zone.zone_id
name = "api.example.com" # サブドメイン名
type = "A" # Aレコード
ttl = 300 # TTL (秒)
records = ["192.0.2.1"] # ここに実際のIPアドレスを指定
}
# www.example.com 用のAレコード
resource "aws_route53_record" "www_subdomain" {
zone_id = aws_route53_zone.example_zone.zone_id
name = "www.example.com" # サブドメイン名
type = "A" # Aレコード
ttl = 300 # TTL (秒)
records = ["192.0.2.2"] # ここに実際のIPアドレスを指定
}
# blog.example.com 用のCNAMEレコード
resource "aws_route53_record" "blog_subdomain" {
zone_id = aws_route53_zone.example_zone.zone_id
name = "blog.example.com" # サブドメイン名
type = "CNAME" # CNAMEレコード
ttl = 300 # TTL (秒)
records = ["blog-content.example.com"] # ここにリダイレクト先を指定
}
2. 上記のdomain_validation_optionsを使って、対象のゾーンにCNAMEレコードを追加
(ワイルドカード証明書にしたいので、各サブドメインの情報を拾っています。)
for_eachを使ってdomain_validation_optionsの各バリューを用いマップを作成
resource "aws_route53_record" "route53_acm_dns_resolve" {
for_each = {
for dvo in aws_acm_certificate.example_cert.domain_validation_options :
dvo.domain_name => {
name = dvo.resource_record_name # レコード名
type = dvo.resource_record_type # レコードタイプ(通常はCNAME)
record = dvo.resource_record_value # レコード値
}
}
<<省略>>
for_each を使って作成されるマップ例
{
"api.example.com": {
"name": "_abcdef1234567890.api.example.com",
"type": "CNAME",
"record": "_xyz9876543210.acm-validations.aws"
},
"www.example.com": {
"name": "_ghijk1234567890.www.example.com",
"type": "CNAME",
"record": "_uvw9876543210.acm-validations.aws"
},
"blog.example.com": {
"name": "_lmnop1234567890.blog.example.com",
"type": "CNAME",
"record": "_rst9876543210.acm-validations.aws"
}
}
3. each.value.を用いfor_eachで代入した各属性値を取得し各レコードを作成
<<省略>>
allow_overwrite = true # 既存のレコードを上書きする設定
zone_id = aws_route53_zone.example_zone.zone_id # Route53ゾーンのID
name = each.value.name # レコード名
type = each.value.type # レコードタイプ
ttl = 600 # TTL(キャッシュの有効時間)
records = [each.value.record] # 証明書の認証用レコード値
}
まとめ
簡単にフローをまとめ
・キーペア作成
・CSR作成
・作成したCSRを認証局(CA)に送信
・DNS認証(ドメイン所有者確認)
・ドメイン所有者確認用に、CNAMEレコードを作成
・上記CNAMEレコードを使ってドメイン所有者を確認
・証明書発行
今回のacm.tfの記述で上記まで実装できます。
こちらの記事もどうぞ。
めも
ACMで利用される認証局(CA)
- ACMは主にAmazon Trust Services(ATS)を利用して証明書を発行
- 特定のユースケースや互換性の理由で、ACMはDigiCertとも提携している
参考サイト:
ACMの機能や利用方法、証明書の管理に関する詳細が記載されています。
ACMの概要、利点、ユースケースなど、サービス全般に関する情報が記載されています。