From 0c0254b03de1cfecf7f128cd576c51b514b96922 Mon Sep 17 00:00:00 2001 From: Nik Afiq Date: Wed, 6 May 2026 01:21:22 +0900 Subject: [PATCH] feat: add CA sync service account, roles, role bindings, and cron job for certificate rotation management --- manifests/cert-manager/ca-sync.yaml | 153 ++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 manifests/cert-manager/ca-sync.yaml diff --git a/manifests/cert-manager/ca-sync.yaml b/manifests/cert-manager/ca-sync.yaml new file mode 100644 index 0000000..e913016 --- /dev/null +++ b/manifests/cert-manager/ca-sync.yaml @@ -0,0 +1,153 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ca-sync + namespace: ca-installer +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: ca-cert-reader + namespace: cert-manager +rules: + - apiGroups: [""] + resources: ["secrets"] + resourceNames: ["internal-ca-cert"] + verbs: ["get"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: ca-sync-read-cert + namespace: cert-manager +subjects: + - kind: ServiceAccount + name: ca-sync + namespace: ca-installer +roleRef: + kind: Role + name: ca-cert-reader + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: ca-configmap-writer + namespace: ca-installer +rules: + - apiGroups: [""] + resources: ["configmaps"] + resourceNames: ["ca-installer-files"] + verbs: ["get", "patch", "update"] + - apiGroups: ["apps"] + resources: ["deployments"] + resourceNames: ["ca-installer"] + verbs: ["get", "patch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: ca-sync-write-configmap + namespace: ca-installer +subjects: + - kind: ServiceAccount + name: ca-sync + namespace: ca-installer +roleRef: + kind: Role + name: ca-configmap-writer + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: ca-sync + namespace: ca-installer +spec: + schedule: "0 3 * * *" # daily at 3am + jobTemplate: + spec: + template: + spec: + serviceAccountName: ca-sync + restartPolicy: OnFailure + containers: + - name: sync + image: bitnami/kubectl:latest + command: + - /bin/sh + - -c + - | + set -e + + # Get current CA cert from cert-manager namespace + kubectl get secret internal-ca-cert -n cert-manager \ + -o jsonpath='{.data.tls\.crt}' | base64 -d > /tmp/ca.crt + + # Get fingerprint of new vs existing cert + NEW_FP=$(openssl x509 -noout -fingerprint -in /tmp/ca.crt) + CURRENT_B64=$(kubectl get configmap ca-installer-files -n ca-installer \ + -o jsonpath='{.data.ca\.crt}' | base64 | tr -d '\n') + echo "$CURRENT_B64" | base64 -d > /tmp/ca-current.crt + CURRENT_FP=$(openssl x509 -noout -fingerprint -in /tmp/ca-current.crt 2>/dev/null || echo "none") + + if [ "$NEW_FP" = "$CURRENT_FP" ]; then + echo "CA cert unchanged, skipping update" + exit 0 + fi + + echo "CA cert changed, updating ConfigMap..." + NEW_B64=$(base64 /tmp/ca.crt | tr -d '\n') + + cat > /tmp/ca.mobileconfig << MOBILEEOF + + + + + PayloadContent + + + PayloadCertificateFileName + homelab-ca.crt + PayloadContent + ${NEW_B64} + PayloadDescription + Installs the Homelab internal CA certificate + PayloadDisplayName + Homelab Internal CA + PayloadIdentifier + home.arpa.ca.cert + PayloadType + com.apple.security.root + PayloadUUID + e546899f-249d-4334-ae04-bd1092ca299b + PayloadVersion + 1 + + + PayloadDescription + Trust the Homelab internal certificate authority + PayloadDisplayName + Homelab CA Trust + PayloadIdentifier + home.arpa.ca.profile + PayloadRemovalDisallowed + + PayloadType + Configuration + PayloadUUID + 729e611e-5f03-4f63-a41c-b9b2973c2311 + PayloadVersion + 1 + + + MOBILEEOF + + kubectl create configmap ca-installer-files -n ca-installer \ + --from-file=ca.crt=/tmp/ca.crt \ + --from-file=ca.mobileconfig=/tmp/ca.mobileconfig \ + --dry-run=client -o yaml | kubectl apply -f - + + kubectl rollout restart deployment/ca-installer -n ca-installer + echo "Done" \ No newline at end of file