diff --git a/environments/clusters/prod/postgresql-tls-sync-kustomization.yaml b/environments/clusters/prod/cert-manager-kustomization.yaml similarity index 75% rename from environments/clusters/prod/postgresql-tls-sync-kustomization.yaml rename to environments/clusters/prod/cert-manager-kustomization.yaml index 25cb701..9ae8ed0 100644 --- a/environments/clusters/prod/postgresql-tls-sync-kustomization.yaml +++ b/environments/clusters/prod/cert-manager-kustomization.yaml @@ -1,7 +1,7 @@ apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: - name: postgresql-tls-sync + name: cert-manager-issuer namespace: flux-system spec: interval: 5m0s @@ -11,4 +11,4 @@ spec: sourceRef: kind: GitRepository name: platform-config - path: ./services/platform/postgresql-tls-sync + path: ./services/platform/cert-manager diff --git a/environments/clusters/prod/kustomization.yaml b/environments/clusters/prod/kustomization.yaml index efd66c3..561e8b9 100644 --- a/environments/clusters/prod/kustomization.yaml +++ b/environments/clusters/prod/kustomization.yaml @@ -2,7 +2,9 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - namespaces.yaml - - postgresql-tls-sync-kustomization.yaml + - cert-manager-kustomization.yaml + - postgresql-tls-platform-kustomization.yaml + - postgresql-tls-database-kustomization.yaml - postgresql-prod-kustomization.yaml - stunnel-server-kustomization.yaml - stunnel-client-prod-kustomization.yaml @@ -10,4 +12,4 @@ resources: - accounts-prod-kustomization.yaml - observability-kustomization.yaml -# Sync marker for Flux reconciliation on postgresql-prod.svc.plus. +# cert-manager owns postgresql-tls in each namespace; no cross-namespace sync job. diff --git a/environments/clusters/prod/postgresql-tls-database-kustomization.yaml b/environments/clusters/prod/postgresql-tls-database-kustomization.yaml new file mode 100644 index 0000000..7835d42 --- /dev/null +++ b/environments/clusters/prod/postgresql-tls-database-kustomization.yaml @@ -0,0 +1,16 @@ +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: postgresql-tls-database + namespace: flux-system +spec: + interval: 5m0s + prune: true + wait: true + timeout: 10m0s + sourceRef: + kind: GitRepository + name: platform-config + path: ./services/database/postgresql-tls + dependsOn: + - name: cert-manager-issuer diff --git a/environments/clusters/prod/postgresql-tls-platform-kustomization.yaml b/environments/clusters/prod/postgresql-tls-platform-kustomization.yaml new file mode 100644 index 0000000..aebba72 --- /dev/null +++ b/environments/clusters/prod/postgresql-tls-platform-kustomization.yaml @@ -0,0 +1,16 @@ +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: postgresql-tls-platform + namespace: flux-system +spec: + interval: 5m0s + prune: true + wait: true + timeout: 10m0s + sourceRef: + kind: GitRepository + name: platform-config + path: ./services/platform/postgresql-tls + dependsOn: + - name: cert-manager-issuer diff --git a/environments/clusters/prod/stunnel-server-kustomization.yaml b/environments/clusters/prod/stunnel-server-kustomization.yaml index 2361080..53bbf90 100644 --- a/environments/clusters/prod/stunnel-server-kustomization.yaml +++ b/environments/clusters/prod/stunnel-server-kustomization.yaml @@ -13,5 +13,5 @@ spec: name: platform-config path: ./services/database/stunnel-server dependsOn: - - name: postgresql-tls-sync + - name: postgresql-tls-database - name: postgresql-prod diff --git a/services/database/postgresql-tls/certificate.yaml b/services/database/postgresql-tls/certificate.yaml new file mode 100644 index 0000000..243b83a --- /dev/null +++ b/services/database/postgresql-tls/certificate.yaml @@ -0,0 +1,14 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: postgresql-tls + namespace: database +spec: + secretName: postgresql-tls + commonName: postgresql-prod.svc.plus + dnsNames: + - postgresql-prod.svc.plus + issuerRef: + name: svc-plus-selfsigned + kind: ClusterIssuer + group: cert-manager.io diff --git a/services/database/postgresql-tls/kustomization.yaml b/services/database/postgresql-tls/kustomization.yaml new file mode 100644 index 0000000..dc8cf7b --- /dev/null +++ b/services/database/postgresql-tls/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: database +resources: + - certificate.yaml diff --git a/services/database/postgresql/README.md b/services/database/postgresql/README.md index e996c0b..a95992f 100644 --- a/services/database/postgresql/README.md +++ b/services/database/postgresql/README.md @@ -21,6 +21,8 @@ directory. Otherwise the ExternalSecrets controller will report Use `scripts/seed-vault-postgresql.sh` from a trusted admin shell to write the expected Vault keys from local environment variables or existing K8s Secrets. -The ingress domain is `postgresql-prod.svc.plus` for this prod cluster. The shared TLS Secret for `postgresql-tls` is synchronized by the -`platform/postgresql-tls-sync` GitOps CronJob into `database/postgresql-tls`, which -`stunnel-server` consumes directly. Do not commit the secret values to Git. +The ingress domain is `postgresql-prod.svc.plus` for this prod cluster. TLS for +`postgresql-tls` is now owned directly by cert-manager in both the `platform` +and `database` namespaces, so `stunnel-server` can mount the database-local +Secret without any cross-namespace sync job. Do not commit the secret values to +Git. diff --git a/services/platform/cert-manager/clusterissuer.yaml b/services/platform/cert-manager/clusterissuer.yaml new file mode 100644 index 0000000..3935b5d --- /dev/null +++ b/services/platform/cert-manager/clusterissuer.yaml @@ -0,0 +1,6 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: svc-plus-selfsigned +spec: + selfSigned: {} diff --git a/services/platform/postgresql-tls-sync/kustomization.yaml b/services/platform/cert-manager/kustomization.yaml similarity index 72% rename from services/platform/postgresql-tls-sync/kustomization.yaml rename to services/platform/cert-manager/kustomization.yaml index 78b4e11..d8ada67 100644 --- a/services/platform/postgresql-tls-sync/kustomization.yaml +++ b/services/platform/cert-manager/kustomization.yaml @@ -1,4 +1,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - - postgresql-tls-sync.yaml + - clusterissuer.yaml diff --git a/services/platform/postgresql-tls-sync/postgresql-tls-sync.yaml b/services/platform/postgresql-tls-sync/postgresql-tls-sync.yaml deleted file mode 100644 index caed2fc..0000000 --- a/services/platform/postgresql-tls-sync/postgresql-tls-sync.yaml +++ /dev/null @@ -1,120 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: postgresql-tls-placeholder - namespace: platform -spec: - type: ClusterIP - ports: - - port: 80 - targetPort: 80 - protocol: TCP - name: http - selector: - app.kubernetes.io/name: postgresql-tls-placeholder ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: postgresql-tls - namespace: platform - annotations: - external-dns.alpha.kubernetes.io/hostname: postgresql-prod.svc.plus -spec: - ingressClassName: caddy - tls: - - hosts: - - postgresql-prod.svc.plus - secretName: postgresql-tls - rules: - - host: postgresql-prod.svc.plus - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: postgresql-tls-placeholder - port: - number: 80 ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: postgresql-tls-sync - namespace: platform ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: postgresql-tls-sync-source - namespace: platform -rules: - - apiGroups: [""] - resources: ["secrets"] - resourceNames: ["postgresql-tls"] - verbs: ["get", "list", "watch"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: postgresql-tls-sync-target - namespace: database -rules: - - apiGroups: [""] - resources: ["secrets"] - resourceNames: ["postgresql-tls"] - verbs: ["get", "create", "update", "patch"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: postgresql-tls-sync-source - namespace: platform -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: postgresql-tls-sync-source -subjects: - - kind: ServiceAccount - name: postgresql-tls-sync - namespace: platform ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: postgresql-tls-sync-target - namespace: database -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: postgresql-tls-sync-target -subjects: - - kind: ServiceAccount - name: postgresql-tls-sync - namespace: platform ---- -apiVersion: batch/v1 -kind: CronJob -metadata: - name: postgresql-tls-sync - namespace: platform -spec: - schedule: "* * * * *" - concurrencyPolicy: Forbid - jobTemplate: - spec: - template: - spec: - serviceAccountName: postgresql-tls-sync - restartPolicy: OnFailure - containers: - - name: sync - image: bitnami/kubectl:latest - command: - - /bin/sh - - -ec - - | - kubectl -n platform get secret postgresql-tls -o yaml \ - | sed '/^ resourceVersion:/d;/^ uid:/d;/^ creationTimestamp:/d;/^ managedFields:/d;/^ annotations:/d;/^ ownerReferences:/d;/^ namespace:/d;/^ selfLink:/d' \ - | kubectl -n database apply -f - diff --git a/services/platform/postgresql-tls/certificate.yaml b/services/platform/postgresql-tls/certificate.yaml new file mode 100644 index 0000000..334b6fd --- /dev/null +++ b/services/platform/postgresql-tls/certificate.yaml @@ -0,0 +1,14 @@ +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: postgresql-tls + namespace: platform +spec: + secretName: postgresql-tls + commonName: postgresql-prod.svc.plus + dnsNames: + - postgresql-prod.svc.plus + issuerRef: + name: svc-plus-selfsigned + kind: ClusterIssuer + group: cert-manager.io diff --git a/services/platform/postgresql-tls/ingress.yaml b/services/platform/postgresql-tls/ingress.yaml new file mode 100644 index 0000000..db61e39 --- /dev/null +++ b/services/platform/postgresql-tls/ingress.yaml @@ -0,0 +1,24 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: postgresql-tls + namespace: platform + annotations: + external-dns.alpha.kubernetes.io/hostname: postgresql-prod.svc.plus +spec: + ingressClassName: caddy + tls: + - hosts: + - postgresql-prod.svc.plus + secretName: postgresql-tls + rules: + - host: postgresql-prod.svc.plus + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: postgresql-tls-placeholder + port: + number: 80 diff --git a/services/platform/postgresql-tls/kustomization.yaml b/services/platform/postgresql-tls/kustomization.yaml new file mode 100644 index 0000000..ed65498 --- /dev/null +++ b/services/platform/postgresql-tls/kustomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: platform +resources: + - certificate.yaml + - placeholder-service.yaml + - ingress.yaml diff --git a/services/platform/postgresql-tls/placeholder-service.yaml b/services/platform/postgresql-tls/placeholder-service.yaml new file mode 100644 index 0000000..a509edd --- /dev/null +++ b/services/platform/postgresql-tls/placeholder-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgresql-tls-placeholder + namespace: platform +spec: + type: ClusterIP + ports: + - port: 80 + targetPort: 80 + protocol: TCP + name: http + selector: + app.kubernetes.io/name: postgresql-tls-placeholder