👾

AWS Certificate Manager で 2つのリージョンで証明書を発行してみる

2024/06/04に公開

はじめに

業務で東京と大阪のリージョンで証明書を発行する必要があったので試しにやってみました💪
基本的にコンソールで操作して必要そうなリソースを確認してから Terraform 化してみました。
以下は Terraform 化の実験した内容の作業メモです📝

フォルダ構成

Amazon Route53 はグローバルサービスで、 AWS Certificate Manager(以下ACM) はリージョナルサービスなので domain 用のモジュールと acm 取得用のモジュールに分けてみました。

├── locals.tf
├── main.tf
├── modules
│   ├── acm
│   │   ├── acm.tf
│   │   ├── outputs.tf
│   │   ├── provider.tf
│   │   └── variables.tf
│   └── domain
│       ├── dns.tf
│       ├── outputs.tf
│       ├── provider.tf
│       └── variables.tf
└── provider.tf

domain モジュール

ACM でドメイン自体取得している場合はすでにゾーンがあると思いますが一応作成しています。

provider.tf
terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}
variables.tf
variable "my_domain" {
  type = string
}
dns.tf
resource "aws_route53_zone" "main" {
  name = var.my_domain
}
outputs.tf
output "cert_arn" {
  value = aws_acm_certificate.cert.arn
}

acm モジュール

variables.tf
variable "domain_name" {
  type = string
}

variable "zone_id" {
  type = string
}

acm.tf がメインの証明書発行処理になります。
今回は DNS 認証方式で行っています。

acm.tf
resource "aws_acm_certificate" "cert" {
  domain_name               = var.domain_name
  subject_alternative_names = ["*.${var.domain_name}"]
  validation_method         = "DNS"

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "cert_validation" {
  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
    }
  }

  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  type            = each.value.type
  ttl             = "300"

  zone_id = var.zone_id
}

resource "aws_acm_certificate_validation" "cert_valid" {
  certificate_arn         = aws_acm_certificate.cert.arn
  validation_record_fqdns = [for record in aws_route53_record.cert_validation : record.fqdn]
}

acm モジュールの中に aws_route53_record があるのがしっくり来ませんが証明書を発行するためという位置付けかと思うのでこちらに配置しています。

outputs.tf
output "cert_arn" {
  value = aws_acm_certificate.cert.arn
}

モジュールの使い方

locals.tf
locals {
  my_domain = "ここにドメインを書いておく"
}
main.tf
module "domain" {
  source       = "./modules/domain"
  my_domain    = local.my_domain

  providers = {
    aws = aws.osaka
  }
}

module "acm_osaka" {
  source      = "./modules/acm"
  domain_name = module.domain.domain_name
  zone_id     = module.domain.zone_id

  providers = {
    aws = aws.osaka
  }
}

module "acm_tokyo" {
  source      = "./modules/acm"
  domain_name = module.domain.domain_name
  zone_id     = module.domain.zone_id

  providers = {
    aws = aws.tokyo
  }
}

あとは terraform を実行すれば acm_osaka, acm_tokyo の output で定義した cert_arn が使えるようになるので ロードバランサーのリスナーなどに証明書を設定できます。

最後に

つまづいたところといえばゾーンを新しく作成してしまったので Route53 の登録済みドメインのネームサーバーの値を変更し忘れてなかなか証明書が発行されませんでした😅
それと何度も apply したり deploy していたら DNS がキャッシュされてなかなか証明書が発行されなくなって次の日までかかったこともありました😇

ただ、終わってみると結構シンプルにできることが分かりました。
お試しください👾

レスキューナウテックブログ

Discussion