Skip to content

Создание сертификатов для доменов (terraform)

aleserche edited this page Apr 11, 2020 · 1 revision

Создание сертификатов для доменов (terraform)

В качестве примера будет использован хост доменов на aws (route53) и Let's Encrypt.

Requirement

  • aws
  • terraform
  • domain

Регистрация host zone и создание A-records

Перед тем как выпустить сертификаты, необходимо завести host zone, установить основные записи типа A и прописать для домена NS-сервера.

variables.tf - освновные переменные: регион и имя домена

variable "region" {
  default = "us-east-1"
}

variable "route_zone" {
  default = "nullpany.xyz"
}

providers.tf - для удобства, стейты хранятся в s3.

terraform {
  backend "s3" {
    bucket = "nullpany-devops"
    key = "common/terraform.tfstate"
    region = "us-east-1"
  }
}

provider "aws" {
  region = "${var.region}"
}

outputs.tf - указываем, что необходимо сохранить в стейте. Впоследвии они будут использоваться для выпуска сертификатов.

output "zone_id" {
  value = "${aws_route53_zone.main.id}"
}

output "zone_name" {
  value = "${aws_route53_zone.main.name}"
}

output "local_root_fqdn" {
  value = "${aws_route53_record.local_root.fqdn}"
}

main.tf - создание host zone двух A-records. Основной домен и wildcard-домен. Записи должны указывать на localhost (127.0.0.1).

resource "aws_route53_zone" "main" {
  name = "${var.route_zone}"
  force_destroy = true

  tags {
    Terraformed = "true"
  }
}

resource "aws_route53_record" "local_root" {
  zone_id = "${aws_route53_zone.main.id}"

  name = "${var.route_zone}"
  type = "A"

  ttl     = "300"
  records = ["127.0.0.1"]

  tags {
    Terraformed = "true"
  }
}

resource "aws_route53_record" "local_wildcard" {
  zone_id = "${aws_route53_zone.main.id}"

  name = "*.${var.route_zone}"
  type = "A"

  ttl     = "300"
  records = ["127.0.0.1"]

  tags {
    Terraformed = "true"
  }
}

Далее выполняем:

terraform init

Подтянется все необходимое для выполнения команд. Чтобы проверить, какие изменения будут внесены, нужно выполнить:

terraform plan

После провери можно запусить исполнение скриптов:

terraform apply

После успешного создание host zone, в панели управление регистратора домена необходимо прописать NS-сервера, которые были сгенерированы aws.

Выпуск сертификатов с помощью протокола acme

Переменные для выпуска сертификата аналогичны тому, что использовались при создании host zone

variables.tf

variable "region" {
  default = "us-east-1"
}

variable "route_zone" {
  default = "nullpany.xyz"
}

providers.tf - подключаем провайдер letsencrypt и указываем хранилище стейтов, которое использовалось на предыдущем шаге. Из него получим zone_id и fqdn

provider "acme" {
  server_url = "https://acme-v02.api.letsencrypt.org/directory"
}

data "terraform_remote_state" "common" {
  backend = "s3"

  config {
    bucket = "nullpany-devops"
    key = "common/terraform.tfstate"
    region = "us-east-1"
  }
}

main.tf - в данном скрипте указываем тип приватных ключей, email амдина для сертификатов и san, для которых будет действовать сертификат. Для удобства указывается один wildcard для основного домена и по одному wildcards домену для каждого проекта.

resource "tls_private_key" "private_key" {
  algorithm = "RSA"
}

resource "acme_registration" "acme_registration" {
  account_key_pem = "${tls_private_key.private_key.private_key_pem}"
  email_address   = "admin@${data.terraform_remote_state.common.local_root_fqdn}"
}

resource "acme_certificate" "local_certificate" {
  account_key_pem           = "${acme_registration.acme_registration.account_key_pem}"
  common_name               = "${data.terraform_remote_state.common.local_root_fqdn}"
  subject_alternative_names = [
    "*.${data.terraform_remote_state.common.local_root_fqdn}",
    "*.project-a.${data.terraform_remote_state.common.local_root_fqdn}",
    "*.project-b.${data.terraform_remote_state.common.local_root_fqdn}"
  ]

  dns_challenge {
    provider = "route53"

    config = {
      AWS_HOSTED_ZONE_ID = "${data.terraform_remote_state.common.zone_id}"
    }
  }
}

resource "local_file" "local_certificate" {
  content  = "${acme_certificate.local_certificate.certificate_pem}"
  filename = "cert.crt"
}

resource "local_file" "local_private_key" {
  content  = "${acme_certificate.local_certificate.private_key_pem}"
  filename = "cert.key"
}

Выполняем:

terraform init
terraform plan
terraform apply

В результате будут выпущены приватный ключ cert.key и сертификат cert.crt.