From 09928c1c20f6866c1b4de4220b0fccec9beecd2e Mon Sep 17 00:00:00 2001 From: ggtrd <103002419+ggtrd@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:17:39 +0200 Subject: [PATCH 1/2] add OVH support for cert-manager DNS01 challenge --- .../clusterissuer.dns01.webhook.ovh.yaml | 34 +++++++ modules/chart_cert_manager/main.tf | 89 ++++++++++++++++--- .../{values.yaml => values-cert_manager.yaml} | 0 .../values-cert_manager_webhook_ovh.yaml | 19 ++++ terraform.tfvars | 15 ++-- 5 files changed, 139 insertions(+), 18 deletions(-) create mode 100644 modules/chart_cert_manager/kube_objects/clusterissuer.dns01.webhook.ovh.yaml rename modules/chart_cert_manager/{values.yaml => values-cert_manager.yaml} (100%) create mode 100644 modules/chart_cert_manager/values-cert_manager_webhook_ovh.yaml diff --git a/modules/chart_cert_manager/kube_objects/clusterissuer.dns01.webhook.ovh.yaml b/modules/chart_cert_manager/kube_objects/clusterissuer.dns01.webhook.ovh.yaml new file mode 100644 index 0000000..63e9078 --- /dev/null +++ b/modules/chart_cert_manager/kube_objects/clusterissuer.dns01.webhook.ovh.yaml @@ -0,0 +1,34 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-prod +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: ${certificate_email} + privateKeySecretRef: + name: letsencrypt-prod + solvers: + - dns01: + webhook: + groupName: $group_name + solverName: ovh + config: + endpoint: ovh-eu + applicationKey: $application_key + applicationSecretRef: + key: applicationSecret + name: dns-challenge + consumerKey: $consumer_key + podTemplate: + metadata: + labels: + networking/traffic-allowed: "yes" + spec: + tolerations: + - key: "vendor" + operator: "Equal" + value: "cosmotech" + effect: "NoSchedule" + nodeSelector: + "cosmotech.com/tier": "services" \ No newline at end of file diff --git a/modules/chart_cert_manager/main.tf b/modules/chart_cert_manager/main.tf index ade92e7..a0b0509 100644 --- a/modules/chart_cert_manager/main.tf +++ b/modules/chart_cert_manager/main.tf @@ -18,8 +18,8 @@ resource "time_sleep" "wait_certmanager_crds" { # 1. CERT-MANAGER -data "template_file" "cert_values" { - template = file("${path.module}/values.yaml") +data "template_file" "chart_values_cert_manager" { + template = file("${path.module}/values-cert_manager.yaml") vars = { service_annotations = yamlencode(var.service_annotations) } @@ -34,7 +34,32 @@ resource "helm_release" "cert_manager" { create_namespace = true values = [ - data.template_file.cert_values.rendered + data.template_file.chart_values_cert_manager.rendered + ] +} + +# 1. (ADDITIONAL) CERT-MANAGER webhook chart for OVH +data "template_file" "chart_values_webhook_ovh" { + count = (var.cloud_provider == "kob" && var.dns_challenge_provider == "ovh") ? 1 : 0 + + template = file("${path.module}/values-cert_manager_webhook_ovh.yaml") + vars = { + group_name = kubernetes_secret.dns_challenge[0].data["groupName"] + } +} + +resource "helm_release" "cert_manager_webhook_ovh" { + count = (var.cloud_provider == "kob" && var.dns_challenge_provider == "ovh") ? 1 : 0 + + name = "cert-manager-webhook-ovh" + repository = "https://aureq.github.io/cert-manager-webhook-ovh/" + chart = "cert-manager-webhook-ovh" + version = "0.9.5" + namespace = "cert-manager" + create_namespace = true + + values = [ + data.template_file.chart_values_webhook_ovh[0].rendered ] } @@ -67,6 +92,14 @@ resource "kubectl_manifest" "letsencrypt_prod_http01" { # Trick here is to duplicate the dns-challenge secret from terraform-onprem from default namespace to cert-manager namespace # cert-manager requires to have this secret in its namespace. # This is to avoid creating namespace cert-manager in terraform-onprem +# +# Workflow is: +# -> [terraform-onprem] create DNS01 challenge requirements (examples: API keys, Azure App registration etc...) +# -> [terraform-onprem] create a secret in default/dns-challenge-terraform-onprem which contains the needed values to run a DNS01 challenge on the given provider +# -> [terraform-shared] create the cert-manager namespace +# -> [terraform-shared] copy the secret default/dns-challenge-terraform-onprem to cert-manager/default/dns-challenge +# -> [terraform-shared] create ClusterIssuer with specifics provider values stored in the cert-manager/default/dns-challenge +# -> [terraform-shared] run cert-manager to get a certificate data "kubernetes_secret" "dns_challenge_terraform_onprem" { metadata { name = "dns-challenge-terraform-onprem" @@ -87,6 +120,7 @@ resource "kubernetes_secret" "dns_challenge" { type = "Opaque" } +# ------ AZURE DNS ------ data "template_file" "clusterissuer_prod_dns01_azuredns" { count = (var.cloud_provider == "kob" && var.dns_challenge_provider == "azure") ? 1 : 0 @@ -102,7 +136,7 @@ data "template_file" "clusterissuer_prod_dns01_azuredns" { } resource "kubectl_manifest" "letsencrypt_prod_dns01_azuredns" { - count = var.cloud_provider == "kob" ? 1 : 0 + count = (var.cloud_provider == "kob" && var.dns_challenge_provider == "azure") ? 1 : 0 yaml_body = data.template_file.clusterissuer_prod_dns01_azuredns[0].rendered @@ -110,6 +144,32 @@ resource "kubectl_manifest" "letsencrypt_prod_dns01_azuredns" { helm_release.cert_manager ] } +# ------ AZURE DNS ------ + +# ------ WEBHOOK OVH ------ +data "template_file" "clusterissuer_prod_dns01_webhook_ovh" { + count = (var.cloud_provider == "kob" && var.dns_challenge_provider == "ovh") ? 1 : 0 + + template = file("${path.module}/kube_objects/clusterissuer.dns01.webhook.ovh.yaml") + vars = { + certificate_email = var.certificate_email + group_name = kubernetes_secret.dns_challenge[0].data["groupName"] + application_key = kubernetes_secret.dns_challenge[0].data["applicationKey"] + application_secret = kubernetes_secret.dns_challenge[0].data["applicationSecret"] + consumer_key = kubernetes_secret.dns_challenge[0].data["consumerKey"] + } +} + +resource "kubectl_manifest" "letsencrypt_prod_dns01_webhook_ovh" { + count = (var.cloud_provider == "kob" && var.dns_challenge_provider == "ovh") ? 1 : 0 + + yaml_body = data.template_file.clusterissuer_prod_dns01_webhook_ovh[0].rendered + + depends_on = [ + helm_release.cert_manager + ] +} +# ------ WEBHOOK OVH ------ # 3. CERTIFICATE @@ -120,22 +180,29 @@ data "template_file" "certificate" { } } +# depends on HTTP01 resource "kubectl_manifest" "certificate" { count = var.cloud_provider == "kob" ? 0 : 1 yaml_body = data.template_file.certificate.rendered - depends_on = [ - kubectl_manifest.letsencrypt_prod_http01[0] - ] + depends_on = [kubectl_manifest.letsencrypt_prod_http01[0]] } +# depends on DNS01 AzureDNS resource "kubectl_manifest" "certificate_dns01_azuredns" { - count = var.cloud_provider == "kob" ? 1 : 0 + count = (var.cloud_provider == "kob" && var.dns_challenge_provider == "azure") ? 1 : 0 yaml_body = data.template_file.certificate.rendered - depends_on = [ - kubectl_manifest.letsencrypt_prod_dns01_azuredns[0] - ] + depends_on = [kubectl_manifest.letsencrypt_prod_dns01_azuredns[0]] +} + +# depends on DNS01 Webhook OVH +resource "kubectl_manifest" "certificate_dns01_webhook_ovh" { + count = (var.cloud_provider == "kob" && var.dns_challenge_provider == "ovh") ? 1 : 0 + + yaml_body = data.template_file.certificate.rendered + + depends_on = [kubectl_manifest.letsencrypt_prod_dns01_webhook_ovh[0]] } diff --git a/modules/chart_cert_manager/values.yaml b/modules/chart_cert_manager/values-cert_manager.yaml similarity index 100% rename from modules/chart_cert_manager/values.yaml rename to modules/chart_cert_manager/values-cert_manager.yaml diff --git a/modules/chart_cert_manager/values-cert_manager_webhook_ovh.yaml b/modules/chart_cert_manager/values-cert_manager_webhook_ovh.yaml new file mode 100644 index 0000000..d281a1f --- /dev/null +++ b/modules/chart_cert_manager/values-cert_manager_webhook_ovh.yaml @@ -0,0 +1,19 @@ +# https://github.com/aureq/cert-manager-webhook-ovh/blob/main/charts/cert-manager-webhook-ovh/values.yaml +groupName: ${group_name} +certManager: + namespace: cert-manager + serviceAccountName: cert-manager +issuers: + - name: letsencrypt-prod + create: false +podLabels: + networking/traffic-allowed: "yes" +nodeSelector: + cosmotech.com/tier: services +resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 512Mi \ No newline at end of file diff --git a/terraform.tfvars b/terraform.tfvars index 794ab87..fbefa22 100644 --- a/terraform.tfvars +++ b/terraform.tfvars @@ -15,13 +15,14 @@ # cloud_provider = "aws" -# ## VARIABLES EXAMPLE FOR KOB (= On-Premise) -# cloud_provider = "kob" -# cluster_region = "" -# cluster_name = "kob-dev-devops" -# domain_zone = "onpremise.platform.cosmotech.com" -# dns_challenge_provider = "azure" -# state_host = "https://cosmotechstates.onpremise.platform.cosmotech.com" +## VARIABLES EXAMPLE FOR KOB (= On-Premise) +cloud_provider = "kob" +cluster_region = "" +cluster_name = "kob-dev-devops" +domain_zone = "onpremise.platform.cosmotech.com" +state_host = "https://cosmotechstates.onpremise.platform.cosmotech.com" +# DNS01 challenge provider can be "azure", "ovh" +dns_challenge_provider = "ovh" ## COMMON VARIABLES EXAMPLE From f83037adaa70508bad351be34eeda522ac2b1689 Mon Sep 17 00:00:00 2001 From: ggtrd <103002419+ggtrd@users.noreply.github.com> Date: Wed, 1 Apr 2026 11:16:13 +0200 Subject: [PATCH 2/2] fix chart cert-manager-webhook-ovh --- modules/chart_cert_manager/main.tf | 18 ++++++---- .../values-cert_manager_webhook_ovh.yaml | 35 +++++++++++++------ terraform.tfvars | 16 ++++----- 3 files changed, 44 insertions(+), 25 deletions(-) diff --git a/modules/chart_cert_manager/main.tf b/modules/chart_cert_manager/main.tf index a0b0509..f277fe7 100644 --- a/modules/chart_cert_manager/main.tf +++ b/modules/chart_cert_manager/main.tf @@ -17,7 +17,7 @@ resource "time_sleep" "wait_certmanager_crds" { } -# 1. CERT-MANAGER +# 1-0. CERT-MANAGER data "template_file" "chart_values_cert_manager" { template = file("${path.module}/values-cert_manager.yaml") vars = { @@ -38,13 +38,16 @@ resource "helm_release" "cert_manager" { ] } -# 1. (ADDITIONAL) CERT-MANAGER webhook chart for OVH + +# 1-1. (SITUATIONAL) CERT-MANAGER ADDITIONAL CONFIG FOR SPECIFICS PROVIDERS +# - OVH: install Helm Chart cert-manager-webhooks-ovh data "template_file" "chart_values_webhook_ovh" { count = (var.cloud_provider == "kob" && var.dns_challenge_provider == "ovh") ? 1 : 0 template = file("${path.module}/values-cert_manager_webhook_ovh.yaml") vars = { - group_name = kubernetes_secret.dns_challenge[0].data["groupName"] + group_name = kubernetes_secret.dns_challenge[0].data["groupName"] + certificate_email = var.certificate_email } } @@ -61,11 +64,13 @@ resource "helm_release" "cert_manager_webhook_ovh" { values = [ data.template_file.chart_values_webhook_ovh[0].rendered ] + + depends_on = [helm_release.cert_manager] } # 2. (MAIN) CLUSTER ISSUER HTTP-01 -# HTTP-01 challenges : https://cert-manager.io/docs/configuration/acme/http01/ +# HTTP-01 challenges : https://cert-manager.io/docs/configuration/acme/http01 data "template_file" "clusterissuer_prod_http01" { count = var.cloud_provider == "kob" ? 0 : 1 @@ -87,7 +92,7 @@ resource "kubectl_manifest" "letsencrypt_prod_http01" { # 2. (BIS) CLUSTER ISSUER DNS-01 -# DNS-01 challenges : https://cert-manager.io/docs/configuration/acme/dns01/2 +# DNS-01 challenges : https://cert-manager.io/docs/configuration/acme/dns01 # # Trick here is to duplicate the dns-challenge secret from terraform-onprem from default namespace to cert-manager namespace # cert-manager requires to have this secret in its namespace. @@ -95,9 +100,10 @@ resource "kubectl_manifest" "letsencrypt_prod_http01" { # # Workflow is: # -> [terraform-onprem] create DNS01 challenge requirements (examples: API keys, Azure App registration etc...) -# -> [terraform-onprem] create a secret in default/dns-challenge-terraform-onprem which contains the needed values to run a DNS01 challenge on the given provider +# -> [terraform-onprem] create a secret in default/dns-challenge-terraform-onprem which contains the needed values to run a DNS01 challenge with the given provider # -> [terraform-shared] create the cert-manager namespace # -> [terraform-shared] copy the secret default/dns-challenge-terraform-onprem to cert-manager/default/dns-challenge +# -> [terraform-shared] optionnally install custom webhooks # -> [terraform-shared] create ClusterIssuer with specifics provider values stored in the cert-manager/default/dns-challenge # -> [terraform-shared] run cert-manager to get a certificate data "kubernetes_secret" "dns_challenge_terraform_onprem" { diff --git a/modules/chart_cert_manager/values-cert_manager_webhook_ovh.yaml b/modules/chart_cert_manager/values-cert_manager_webhook_ovh.yaml index d281a1f..f00eca8 100644 --- a/modules/chart_cert_manager/values-cert_manager_webhook_ovh.yaml +++ b/modules/chart_cert_manager/values-cert_manager_webhook_ovh.yaml @@ -6,14 +6,27 @@ certManager: issuers: - name: letsencrypt-prod create: false -podLabels: - networking/traffic-allowed: "yes" -nodeSelector: - cosmotech.com/tier: services -resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 500m - memory: 512Mi \ No newline at end of file + kind: ClusterIssuer + acmeServerUrl: https://acme-v02.api.letsencrypt.org/directory + email: ${certificate_email} + ovhEndpointName: ovh-eu + ovhAuthenticationMethod: application + ovhAuthenticationRef: + applicationKeyRef: + name: dns-challenge + key: applicationKey + applicationSecretRef: + name: dns-challenge + key: applicationSecret + +# podLabels: +# networking/traffic-allowed: "yes" +# nodeSelector: +# cosmotech.com/tier: services +# resources: +# requests: +# cpu: 100m +# memory: 128Mi +# limits: +# cpu: 500m +# memory: 512Mi \ No newline at end of file diff --git a/terraform.tfvars b/terraform.tfvars index fbefa22..8588a28 100644 --- a/terraform.tfvars +++ b/terraform.tfvars @@ -15,14 +15,14 @@ # cloud_provider = "aws" -## VARIABLES EXAMPLE FOR KOB (= On-Premise) -cloud_provider = "kob" -cluster_region = "" -cluster_name = "kob-dev-devops" -domain_zone = "onpremise.platform.cosmotech.com" -state_host = "https://cosmotechstates.onpremise.platform.cosmotech.com" -# DNS01 challenge provider can be "azure", "ovh" -dns_challenge_provider = "ovh" +# ## VARIABLES EXAMPLE FOR KOB (= On-Premise) +# cloud_provider = "kob" +# cluster_region = "" +# cluster_name = "kob-dev-devops" +# domain_zone = "onpremise.platform.cosmotech.com" +# state_host = "https://cosmotechstates.onpremise.platform.cosmotech.com" +# # DNS01 challenge provider can be "azure", "ovh" +# dns_challenge_provider = "azure" ## COMMON VARIABLES EXAMPLE