From 2a96d9e948f3891e0b49aeef4f623c89649ac959 Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Sat, 21 Mar 2026 23:31:01 +1100 Subject: [PATCH] feat: add PuppetDB read-only database user and pooler (#69) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PuppetDB requires a separate read-only database user for its read pool. Without it, it refuses to use the write user for read queries and all /pdb/query/v4 calls fail with a 500. - Add puppetdb_read role via CNPG managed.roles with password sourced from a new postgres-read-credentials Vault secret - Grant CONNECT, USAGE, SELECT and default privileges to puppetdb_read via postInitApplicationSQL (must also be run manually on existing cluster) - Add puppet-postgres-pooler-ro Pooler (type: ro) routing to replicas - Add puppetdb-read-database-conf ConfigMap with read-database.conf mounted into /etc/puppetlabs/puppetdb/conf.d/ in the PuppetDB deployment - Wire OPENVOXDB_READ_POSTGRES_* env vars from the new secret 💘 Generated with Crush Assisted-by: Claude Sonnet 4.6 via Crush Reviewed-on: https://git.unkin.net/unkin/argocd-apps/pulls/69 --- apps/base/puppet/cnpg_cluster.yaml | 18 ++++++++++ apps/base/puppet/cnpg_pooler.yaml | 33 +++++++++++++++++++ .../puppet/configmap_puppetdb-config.yaml | 3 ++ .../configmap_puppetdb-read-database.yaml | 18 ++++++++++ apps/base/puppet/deployment_puppetdb.yaml | 16 +++++++++ apps/base/puppet/kustomization.yaml | 1 + apps/base/puppet/vaultstaticsecret.yaml | 17 ++++++++++ 7 files changed, 106 insertions(+) create mode 100644 apps/base/puppet/configmap_puppetdb-read-database.yaml diff --git a/apps/base/puppet/cnpg_cluster.yaml b/apps/base/puppet/cnpg_cluster.yaml index 7e0984a..3854bfe 100644 --- a/apps/base/puppet/cnpg_cluster.yaml +++ b/apps/base/puppet/cnpg_cluster.yaml @@ -19,6 +19,24 @@ spec: postInitApplicationSQL: - CREATE EXTENSION IF NOT EXISTS pg_trgm; - CREATE EXTENSION IF NOT EXISTS pgcrypto; + - GRANT CONNECT ON DATABASE puppetdb TO puppetdb_read; + - GRANT USAGE ON SCHEMA public TO puppetdb_read; + - GRANT SELECT ON ALL TABLES IN SCHEMA public TO puppetdb_read; + - ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO puppetdb_read; + managed: + roles: + - name: puppetdb_read + ensure: present + comment: PuppetDB read-only database user + login: true + superuser: false + createdb: false + createrole: false + inherit: true + replication: false + connectionLimit: -1 + passwordSecret: + name: postgres-read-credentials enablePDB: true enableSuperuserAccess: false failoverDelay: 0 diff --git a/apps/base/puppet/cnpg_pooler.yaml b/apps/base/puppet/cnpg_pooler.yaml index 45f64d0..b28d8b9 100644 --- a/apps/base/puppet/cnpg_pooler.yaml +++ b/apps/base/puppet/cnpg_pooler.yaml @@ -31,3 +31,36 @@ spec: topologyKey: kubernetes.io/hostname containers: [] type: rw +--- +apiVersion: postgresql.cnpg.io/v1 +kind: Pooler +metadata: + name: puppet-postgres-pooler-ro + namespace: puppet +spec: + cluster: + name: puppet-postgres + instances: 2 + pgbouncer: + parameters: + default_pool_size: "100" + max_client_conn: "400" + paused: false + poolMode: session + template: + metadata: + labels: + app: pooler-ro + spec: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - pooler-ro + topologyKey: kubernetes.io/hostname + containers: [] + type: ro diff --git a/apps/base/puppet/configmap_puppetdb-config.yaml b/apps/base/puppet/configmap_puppetdb-config.yaml index 419d45d..2246738 100644 --- a/apps/base/puppet/configmap_puppetdb-config.yaml +++ b/apps/base/puppet/configmap_puppetdb-config.yaml @@ -17,4 +17,7 @@ data: OPENVOXDB_POSTGRES_HOSTNAME: "puppet-postgres-pooler" OPENVOXDB_POSTGRES_DATABASE: "puppetdb" OPENVOXDB_POSTGRES_PORT: "5432" + OPENVOXDB_READ_POSTGRES_HOSTNAME: "puppet-postgres-pooler-ro" + OPENVOXDB_READ_POSTGRES_DATABASE: "puppetdb" + OPENVOXDB_READ_POSTGRES_PORT: "5432" PUPPETDB_JAVA_ARGS: "" diff --git a/apps/base/puppet/configmap_puppetdb-read-database.yaml b/apps/base/puppet/configmap_puppetdb-read-database.yaml new file mode 100644 index 0000000..0d48847 --- /dev/null +++ b/apps/base/puppet/configmap_puppetdb-read-database.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/component: puppetdb + app.kubernetes.io/instance: puppetserver + app.kubernetes.io/name: puppetserver + app.kubernetes.io/version: 8.8.0 + name: puppetdb-read-database-conf + namespace: puppet +data: + read-database.conf: | + read-database: { + subname: "//"${OPENVOXDB_READ_POSTGRES_HOSTNAME}":"${OPENVOXDB_READ_POSTGRES_PORT}"/"${OPENVOXDB_READ_POSTGRES_DATABASE} + username: ${OPENVOXDB_READ_POSTGRES_USER} + password: ${OPENVOXDB_READ_POSTGRES_PASSWORD} + } diff --git a/apps/base/puppet/deployment_puppetdb.yaml b/apps/base/puppet/deployment_puppetdb.yaml index 20482f7..4b81e01 100644 --- a/apps/base/puppet/deployment_puppetdb.yaml +++ b/apps/base/puppet/deployment_puppetdb.yaml @@ -59,6 +59,16 @@ spec: secretKeyRef: key: username name: postgres-credentials + - name: OPENVOXDB_READ_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: postgres-read-credentials + - name: OPENVOXDB_READ_POSTGRES_USER + valueFrom: + secretKeyRef: + key: username + name: postgres-read-credentials securityContext: allowPrivilegeEscalation: false capabilities: @@ -78,6 +88,9 @@ spec: volumeMounts: - mountPath: /opt/puppetlabs/server/data/puppetdb name: puppetdb-storage + - mountPath: /etc/puppetlabs/puppetdb/conf.d/read-database.conf + name: puppetdb-read-database-conf + subPath: read-database.conf initContainers: - name: create-log-dir image: docker.io/busybox:1.37 @@ -154,3 +167,6 @@ spec: - name: puppetdb-storage persistentVolumeClaim: claimName: puppetserver-puppetdb-claim + - name: puppetdb-read-database-conf + configMap: + name: puppetdb-read-database-conf diff --git a/apps/base/puppet/kustomization.yaml b/apps/base/puppet/kustomization.yaml index 1af70b6..7c43abd 100644 --- a/apps/base/puppet/kustomization.yaml +++ b/apps/base/puppet/kustomization.yaml @@ -12,6 +12,7 @@ resources: - vaultstaticsecret.yaml - configmap_puppetboard-config.yaml - configmap_puppetdb-config.yaml + - configmap_puppetdb-read-database.yaml - configmap_puppetserver-compiler-config.yaml - configmap_puppetserver-init-config.yaml - configmap_puppetserver-init-masters-config.yaml diff --git a/apps/base/puppet/vaultstaticsecret.yaml b/apps/base/puppet/vaultstaticsecret.yaml index a8f68bd..30f6820 100644 --- a/apps/base/puppet/vaultstaticsecret.yaml +++ b/apps/base/puppet/vaultstaticsecret.yaml @@ -35,6 +35,23 @@ spec: --- apiVersion: secrets.hashicorp.com/v1beta1 kind: VaultStaticSecret +metadata: + name: postgres-read-credentials + namespace: puppet +spec: + destination: + create: true + name: postgres-read-credentials + overwrite: true + hmacSecretData: true + mount: kv + path: kubernetes/namespace/puppet/default/postgres-read-credentials + refreshAfter: 5m + type: kv-v2 + vaultAuthRef: default +--- +apiVersion: secrets.hashicorp.com/v1beta1 +kind: VaultStaticSecret metadata: name: eyaml-keys namespace: puppet