feat(chart): pg password via ExternalSecret/OpenBao (A-Chunk 1)
Per-instance Postgres password sourced from OpenBao via External
Secrets Operator. Dual-mode for the migration window:
- postgres.passwordVaultPath unset → legacy postgres-secret.yaml
renders with .Values.postgres.password (helm lookup + random
fallback, bit-exact existing behaviour for live instances).
- postgres.passwordVaultPath set → postgres-password-externalsecret.yaml
renders an ExternalSecret that produces the same <release>-pg
Secret (POSTGRES_USER/PASSWORD/DB) from OpenBao path
`tenants/<tenant.id>/instances/<instance.code>/pg`.
Exactly one of the two templates ships per instance (mutually
exclusive `if`s on .Values.postgres.passwordVaultPath). The Postgres
StatefulSet envFroms <release>-pg unchanged.
OpenBao policy already grants the per-cluster ESO read on
`v3/data/tenants/<tenantID>/*` (buildEsoPolicy in tower's
openbao_auth_setup.go) — the new instances/<code>/pg subpath is
covered. No policy change required.
A `required` directive on the ExternalSecret asserts tenant.id is
present when passwordVaultPath is set — fails loud at helm template
time if Tower forgot to populate it.
deletionPolicy: Retain on the ExternalSecret. Postgres PGDATA on
disk hashes to the password in the Secret; an accidental ESO
removal must not cascade into the Secret disappearing.
Chart 0.1.6 → 0.1.7. Verified locally: helm template both modes,
helm lint clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
51
templates/postgres-password-externalsecret.yaml
Normal file
51
templates/postgres-password-externalsecret.yaml
Normal file
@@ -0,0 +1,51 @@
|
||||
{{- if .Values.postgres.passwordVaultPath }}
|
||||
# postgres-password-externalsecret.yaml — per-instance Postgres password
|
||||
# sourced from OpenBao via ESO. Produces the same `<release>-pg` Secret
|
||||
# shape (POSTGRES_USER + POSTGRES_PASSWORD + POSTGRES_DB) that the legacy
|
||||
# postgres-secret.yaml produces, so postgres-statefulset.yaml is unchanged.
|
||||
#
|
||||
# Rendered only when `.Values.postgres.passwordVaultPath` is set. The
|
||||
# legacy postgres-secret.yaml renders when that field is empty —
|
||||
# exactly one of the two ships per instance. Tower-managed migration
|
||||
# in Chunk 3 flips overlays from the legacy path to this one.
|
||||
#
|
||||
# OpenBao path convention: `tenants/<tenantID>/instances/<code>/pg`
|
||||
# with a `password` field. Covered by the per-cluster ESO policy
|
||||
# `eso-tenant-<cluster>` (buildEsoPolicy in Go) which already grants
|
||||
# read on `v3/data/tenants/<tenantID>/*`. No policy change required.
|
||||
apiVersion: external-secrets.io/v1beta1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: {{ include "instance.fullname" . }}-pg
|
||||
labels:
|
||||
{{- include "instance.labels" . | nindent 4 }}
|
||||
spec:
|
||||
refreshInterval: "1h"
|
||||
secretStoreRef:
|
||||
name: {{ .Values.postgres.externalSecretsStoreRef | default "openbao-platform" }}
|
||||
kind: ClusterSecretStore
|
||||
target:
|
||||
name: {{ include "instance.fullname" . }}-pg
|
||||
creationPolicy: Owner
|
||||
# Retain — never delete the Secret on ExternalSecret deletion. The
|
||||
# postgres pod's PGDATA on disk is locked to the password hash in
|
||||
# this Secret; an accidental ESO removal must not cascade into the
|
||||
# Secret disappearing and forcing a password rotation (which would
|
||||
# then drift from pg_authid).
|
||||
deletionPolicy: Retain
|
||||
template:
|
||||
type: Opaque
|
||||
engineVersion: v2
|
||||
data:
|
||||
POSTGRES_USER: {{ .Values.postgres.user | quote }}
|
||||
POSTGRES_PASSWORD: "{{ `{{ .password }}` }}"
|
||||
POSTGRES_DB: {{ .Values.postgres.database | quote }}
|
||||
data:
|
||||
- secretKey: password
|
||||
remoteRef:
|
||||
key: tenants/{{ required "postgres.passwordVaultPath requires .Values.tenant.id (set by Tower at create time)" .Values.tenant.id }}/instances/{{ .Values.instance.code }}/pg
|
||||
property: password
|
||||
conversionStrategy: Default
|
||||
decodingStrategy: None
|
||||
metadataPolicy: None
|
||||
{{- end }}
|
||||
Reference in New Issue
Block a user