0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

東京リージョンとバージニア北部でACMを構築

Posted at

前書き

本記事では、Terraform を使用して、AWS Certificate Manager(ACM)
の証明書作成と、Route53 を用いた DNS 検証の方法について、備忘録も兼ねて構築内容を記載する。

ACMの概要

ACM(AWS Certificate Manager)は、AWS 上で SSL/TLS 証明書を簡易に発行・管理するサービスである。証明書の発行、更新、失効を自動化できるため、証明書管理の負担を大きく軽減できる。

ACM では、以下の二つの証明書管理方式をサポートする。

  • AWS が提供する無料のパブリック証明書を発行する
  • 外部で購入した証明書をインポートして利用する

ACM を利用する際の最重要ポイントは、証明書を利用する AWS サービスによって発行すべきリージョンが異なることである。特に CloudFront のみ例外で、必ず us-east-1(バージニア北部) で証明書を発行する必要がある。

主なサービスと必要リージョンは以下のとおり。

AWSサービス 証明書を発行すべきリージョン
CloudFront us-east-1(バージニア北部)
ALB / NLB 利用するリージョン
API Gateway(REST / HTTP) 利用するリージョン
AppSync 利用するリージョン

ACM の証明書を発行する際は、DNS 検証が一般的であり、Route53 に CNAME レコードを登録することで自動的に検証が行われる。Terraform では、ACM 証明書と Route53 レコードを同時に構築することで自動検証が可能となる。

前提条件

  • Terraformを動作させる環境が存在する
  • AWSの認証は、AWS-Vaultの設定方法を参考に設定している
  • Terraformのバージョンが v1.50 以上
  • 本記事では、下記の初期状態から構築を行う

構築手順

ディレクトリ構成としては、services/ 以下に環境固有の呼び出し用コードを配置し、modules 以下にリージョン別の ACM モジュールを配置する前提で説明する。

本構成のポイントは、Route53(DNS ホストゾーン)は1つだが ACM はリージョンごとに作成する必要がある。特に CloudFront 用の証明書は us-east-1 でのみ発行可能なため、バージニア北部リージョン専用モジュールを用意する構成で実装する。

servicesフォルダー内の構築内容

  • services/main.tf では、東京リージョン用バージニア北部リージョン用 の ACM モジュールをそれぞれ呼び出す
  • name_prefix(サブドメイン)と zone_id / zone_name(Route53 ホストゾーン情報)を共通入力として渡す
main.tf
# 東京リージョン用 ACM モジュールを呼び出して証明書の作成・検証を行う
module "acm_tokyo" {
  source = "../modules/acm/tokyo"

  name_prefix = local.name_prefix
  zone_id     = local.zone_id
  zone_name   = local.zone_name
}

# バージニア北部リージョン用 ACM モジュールを呼び出して証明書の作成・検証を行う
module "acm_virginia" {
  source = "../modules/acm/virginia"

  name_prefix = local.name_prefix
  zone_id     = local.zone_id
  zone_name   = local.zone_name
}
variables.tf
# example.com の Route53 ホストゾーン情報を取得する
data "aws_route53_zone" "acm_test" {
  name = "example.com"
}

# 取得したホストゾーンの ID と名前をローカル変数にセットする
locals {
  zone_id   = data.aws_route53_zone.acm_test.zone_id
  zone_name = data.aws_route53_zone.acm_test.name
}

# 証明書用サブドメインのプレフィックスを設定する
locals {
  name_prefix  = "acm-test"
}

services/ 層では、必要な値だけを渡すシンプルな構成としている

東京リージョンの構築内容

ALBAPI Gateway など東京リージョンで利用するサービス向けの ACM 証明書を作成する。DNS 検証のため、ACM が提供する domain_validation_options から CNAME レコードを Route53 に自動生成する構成を採用する。

tokyo_acm.tf
# 東京リージョンで ACM 証明書を発行する
resource "aws_acm_certificate" "acm_tokyo_test_com" {
  domain_name       = "${var.name_prefix}.${var.zone_name}"
  validation_method = "DNS"
}

# 発行した証明書に対して DNS 検証を実行する
resource "aws_acm_certificate_validation" "acm_tokyo_test_com" {
  certificate_arn = aws_acm_certificate.acm_tokyo_test_com.arn

  # 作成した Route53 の CNAME レコードの fqdn を抽出し、証明書の DNS 検証に渡す値として一覧化する
  validation_record_fqdns = [
    for r in aws_route53_record.acm_tokyo_test_com : r.fqdn
  ]
}

# ACM が要求する DNS 検証用 CNAME レコードを Route53 に自動作成する
resource "aws_route53_record" "acm_tokyo_test_com" {
  # ACM が要求する DNS 検証用 CNAME レコード情報を取り出し、Route53 レコードを自動生成するための map を作成する
  for_each = {
    for dvo in aws_acm_certificate.acm_tokyo_test_com.domain_validation_options :
    dvo.domain_name => {
      name         = dvo.resource_record_name
      type         = dvo.resource_record_type
      record_value = dvo.resource_record_value
    }
  }

  zone_id = var.zone_id
  name    = each.value.name
  type    = each.value.type
  ttl     = 60
  records = [each.value.record_value]
}
variables.tf
# 共通
variable "name_prefix" { type = string }

# ゾーンID、ゾーン名
variable "zone_id" { type = string }
variable "zone_name" { type = string }

注意

  • ACM 証明書は DNS 検証が完了すれば自動更新されるため、手動更新は不要
  • Route53 の CNAME は ACM が提示する値をそのまま登録する必要があり、コード化するとミスを防げる
  • 東京リージョンの証明書は CloudFront では利用できず、CloudFront 用は必ず us-east-1 で発行する必要がある

aws_route53_record.acm_tokyo_test_comの補足説明

Route53 に作成された CNAME レコードは、以下のような形になる。

aws_route53_record.acm_tokyo_test_com["acm-test.example.com"] = {
  fqdn    = "_abcd1234.acm-test.example.com"
  name    = "_abcd1234.acm-test.example.com"
  type    = "CNAME"
  ttl     = 60
  records = ["_efgh5678.acm-validations.aws"]
  zone_id = "Z123456789ABCDEFG"
}
項目名 説明
fqdn DNS に登録されるレコードの 完全なドメイン名(例: _xxxx.example.com) を示す。ACM の DNS 検証ではこの値を使って証明書を確認する
name CNAME レコードの「名前」部分(左側)。Route53 に登録されるレコード名で、どの名前を検証対象とするかを示す。ACM が検証用に自動生成する値
type DNS レコードの種類。ACM の DNS 検証では常に CNAME が使われる
ttl DNS レコードの有効期間(キャッシュ時間)。検証用途のため短めの値(例: 60 秒)が設定される
records CNAME レコードの「宛先」部分(右側)。AWS の検証サーバーを指す値で、ACM が自動生成する
zone_id このレコードが登録される Route53 のホストゾーン ID。対象ドメインの管理場所を示す

aws_acm_certificate.acm_tokyo_test_com.domain_validation_optionsの補足説明

ACM 証明書を作成すると、DNS 検証に必要な CNAME 情報が domain_validation_options に入る。中身は AWS が自動生成する以下のような値となる。

aws_acm_certificate.acm_tokyo_test_com.domain_validation_options = [
  {
    domain_name           = "acm-test.example.com"
    resource_record_name  = "_abcd1234.acm-test.example.com"
    resource_record_type  = "CNAME"
    resource_record_value = "_efgh5678.acm-validations.aws"
  }
]
項目名 説明
domain_name 証明書を発行する対象ドメイン名。ACM がこのドメインの所有者かどうかを DNS で確認する。
resource_record_name DNS CNAME レコードの「名前」部分(左側)。Route53 に登録する際の レコード名 にあたり、「どの名前に対して検証を行うか」を示す。ACM が検証用に自動生成する特殊な値。
resource_record_type DNS レコードの種類。ACM の DNS 検証では必ず CNAME が指定される。
resource_record_value DNS CNAME レコードの「値」部分(右側)。Route53 に登録する際の 宛先(どこへ向けるか) を示し、AWS の検証サーバーを指す。これも ACM が自動生成する。

バージニア北部リージョンの構築内容

証明書を us-east-1(バージニア北部) で作成する。Terraform では、provider ブロックに alias を付けることで、東京リージョン以外のリージョンを安全に扱える。

virginia_acm.tf
# AWS プロバイダーのバージョンを指定する
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "6.19.0"
    }
  }
}

# us-east-1(バージニア北部)を利用するためのプロバイダーを定義する
provider "aws" {
  alias  = "virginia"
  region = "us-east-1"
}

# バージニア北部で ACM 証明書を発行する
resource "aws_acm_certificate" "acm_virginia_test_com" {
  provider          = aws.virginia
  domain_name       = "${var.name_prefix}.${var.zone_name}"
  validation_method = "DNS"
}

# 発行した証明書に対して DNS 検証を実行する
resource "aws_acm_certificate_validation" "acm_virginia_test_com" {
  provider        = aws.virginia
  certificate_arn = aws_acm_certificate.acm_virginia_test_com.arn
  validation_record_fqdns = [
    for dvo in aws_acm_certificate.acm_virginia_test_com.domain_validation_options :
    dvo.resource_record_name
  ]
}
variables.tf
# 共通
variable "name_prefix" { type = string }

# ゾーンID、ゾーン名
variable "zone_id" { type = string }
variable "zone_name" { type = string }

注意

  • CloudFront は us-east-1 の証明書しか利用できないため、CloudFront 用に必ずバージニア北部で ACM を発行する
  • Route53 の CNAME レコードはリージョンに依存しないため、東京・バージニアどちらの ACM でも同じ DNS ゾーンで検証できる
  • provider alias を忘れると全て東京リージョンで作成されるため注意が必要

用語補足

  • プロバイダー : AWS のリソース(ACM、EC2、S3 など)を作成するために、Terraform 本体が AWS にアクセスする必要がある。この「AWS にアクセスするための機能」を提供するのが プロバイダー(provider)

GitHub

参考資料

感想

今回は、表題の構築内容についてまとめました。当初は 1 つの Terraform からバージニア北部リージョンに ACM をどのように構築すれば良いのか分からず、作業にかなり手間取りました。しかし、調査を進めるなかで構築方法を正しく理解でき、大きな学びにつながったと感じています。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?