Add Let's Encrypt DNS-01 clouddns ClusterIssuers
ci/woodpecker/pr/vector-test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful

unkin.net public DNS is delegated to Google Cloud DNS, so publicly-trusted
wildcard certs need an ACME issuer using cert-manager's clouddns DNS-01
solver. The existing vault-issuer (internal PKI) is unchanged.

- Add ClusterIssuers letsencrypt (prod) and letsencrypt-staging, both using
  a dns01 clouddns solver with a GCP service-account key.
- Sync that key from Vault KV into Secret cert-manager-clouddns via a
  VaultStaticSecret + VaultAuth (role cert_manager_clouddns) and a dedicated
  cert-manager-clouddns service account.
- Wire the new files into the base kustomization.
- Whitelist cert-manager.io ClusterIssuer in the platform AppProject.

The clouddns project and the KV secret value are set out-of-band.

Claude-Session: https://claude.ai/code/session_01JUoARVdmhxKQHyyyp1pxeT
This commit is contained in:
Ben Vincent
2026-08-02 17:07:18 +10:00
parent 8d70149467
commit 779e448686
7 changed files with 89 additions and 0 deletions
@@ -0,0 +1,19 @@
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: admin@unkin.net
privateKeySecretRef:
name: letsencrypt-staging-account-key
solvers:
- dns01:
# project must match the GCP project hosting the unkin.net Cloud DNS zone
cloudDNS:
project: REPLACE-WITH-GCP-PROJECT
serviceAccountSecretRef:
name: cert-manager-clouddns
key: key.json
@@ -0,0 +1,19 @@
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@unkin.net
privateKeySecretRef:
name: letsencrypt-account-key
solvers:
- dns01:
# project must match the GCP project hosting the unkin.net Cloud DNS zone
cloudDNS:
project: REPLACE-WITH-GCP-PROJECT
serviceAccountSecretRef:
name: cert-manager-clouddns
key: key.json
@@ -5,6 +5,11 @@ kind: Kustomization
resources:
- namespace.yaml
- serviceaccount.yaml
- serviceaccount_cert-manager-clouddns.yaml
- clusterrole.yaml
- clusterrolebinding.yaml
- vmservicescrape.yaml
- vaultauth.yaml
- vaultstaticsecret_clouddns.yaml
- clusterissuer_letsencrypt.yaml
- clusterissuer_letsencrypt-staging.yaml
@@ -0,0 +1,11 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: cert-manager-clouddns
namespace: cert-manager
labels:
app.kubernetes.io/name: cert-manager-config
app.kubernetes.io/instance: cert-manager-config
app.kubernetes.io/component: clouddns-solver
automountServiceAccountToken: true
+18
View File
@@ -0,0 +1,18 @@
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: default
namespace: cert-manager
spec:
method: kubernetes
mount: k8s/au/syd1
vaultConnectionRef: vso-system/default
allowedNamespaces:
- cert-manager
kubernetes:
role: cert_manager_clouddns
serviceAccount: cert-manager-clouddns
audiences:
- vault
tokenExpirationSeconds: 600
@@ -0,0 +1,15 @@
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: clouddns
namespace: cert-manager
spec:
vaultAuthRef: default
mount: kv
type: kv-v2
path: service/kubernetes/au/syd1/cert-manager/clouddns
refreshAfter: 5m
destination:
name: cert-manager-clouddns
create: true
+2
View File
@@ -84,6 +84,8 @@ spec:
kind: Certificate
- group: 'cert-manager.io'
kind: Issuer
- group: 'cert-manager.io'
kind: ClusterIssuer
- group: 'gateway.networking.k8s.io'
kind: GatewayClass
- group: 'networking.k8s.io'