Terraform Deployment of Cert-Manager + Cluster Issuers + certificates:
Create the following files:
variable "letsencrypt_email" {
type = string
description = "Email address that Let's Encrypt will use to send notifications about expiring certificates and account-related issues to."
sensitive = true
}
variable "letsencrypt_cloudflare_api_token" {
type = string
description = "Cloudflare API token with Zone-DNS-Edit and Zone-Zone-Read permissions, which is required for DNS01 challenge validation."
sensitive = true
}helm_cert.tf
#-------------------------------
# Certificate Manager
#-------------------------------
locals {
helm_certs_name = "cert-manager"
helm_certs_repo = "https://charts.jetstack.io"
helm_certs_version = "v1.11.0"
}
resource "kubernetes_namespace" "cert_manager" {
metadata {
name = local.helm_certs_name
}
depends_on = [module.aks]
}
resource "kubernetes_secret" "letsencrypt_cloudflare_api_token_secret" {
depends_on = [kubernetes_namespace.cert_manager]
metadata {
name = "letsencrypt-cloudflare-api-token-secret"
namespace = kubernetes_namespace.cert_manager.metadata.0.name
}
data = {
"api-token" = var.letsencrypt_cloudflare_api_token
}
}
resource "helm_release" "cert_manager" {
name = local.helm_certs_name
repository = local.helm_certs_repo
chart = "cert-manager"
version = local.helm_certs_version
namespace = local.helm_certs_name
depends_on = [kubernetes_namespace.cert_manager]
set {
name = "installCRDs"
value = true
}
}
resource "kubernetes_manifest" "letsencrypt_issuer_staging" {
manifest = yamldecode(templatefile(
"${path.module}/template/letsencrypt-issuer.tpl.yaml",
{
"name" = "letsencrypt-staging"
"email" = var.letsencrypt_email
"server" = "https://acme-staging-v02.api.letsencrypt.org/directory"
"api_token_secret_name" = kubernetes_secret.letsencrypt_cloudflare_api_token_secret.metadata.0.name
"api_token_secret_data_key" = keys(kubernetes_secret.letsencrypt_cloudflare_api_token_secret.data).0
}
))
depends_on = [helm_release.cert_manager]
}
resource "kubernetes_manifest" "letsencrypt_issuer_production" {
manifest = yamldecode(templatefile(
"${path.module}/template/letsencrypt-issuer.tpl.yaml",
{
"name" = "letsencrypt-production"
"email" = var.letsencrypt_email
"server" = "https://acme-v02.api.letsencrypt.org/directory"
"api_token_secret_name" = kubernetes_secret.letsencrypt_cloudflare_api_token_secret.metadata.0.name
"api_token_secret_data_key" = keys(kubernetes_secret.letsencrypt_cloudflare_api_token_secret.data).0
}
))
depends_on = [helm_release.cert_manager]
}
template/letsencrypt-issuer.tpl.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: ${name}
spec:
acme:
email: ${email}
server: ${server}
privateKeySecretRef:
name: issuer-account-key-${name}
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: ${api_token_secret_name}
key: ${api_token_secret_data_key}Execute:
$ terraform apply -target="helm_release.cert_manager"
$ terraform apply -target="kubernetes_manifest.letsencrypt_issuer_production"
$ terraform apply -target="kubernetes_manifest.letsencrypt_issuer_staging"cert staging (example):
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: api.<domain>.com.br
namespace: <namespace>
spec:
dnsNames:
- api.<domain>.com.br
secretName: api-pricing-tls
issuerRef:
name: letsencrypt-staging
kind: ClusterIssuer
cert production:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: api.<domain>.com.br
namespace: <namespace>
spec:
dnsNames:
- api.<domain>.com.br
secretName: api-pricing-tls
issuerRef:
name: letsencrypt-production
kind: ClusterIssuer