Helm chart of SonarQube expose JDBC password via ConfigMap

Problem

We use the default CNPG Secret, which provides all the data needed for accessing the database. It has the following structure:

apiVersion: v1
data:
  dbname: YXBw
  fqdn-jdbc-uri: amRiYzpwb3N0Z3Jlc3FsOi8vc29uYXJxdWJlLWNucGctY2x1c3Rlci1ydy5zb25hcnF1YmUuc3ZjLmNsdXN0ZXIubG9jYWw6NTQzMi9hcHA/cGFzc3dvcmQ9SHh5M1c2QUdxdHhvbkNtV3N4WUpiU3FoVXVMTkZRSGU2VUZ2eWQ4R0ZnOXFnQldRZTg4cks3RnY5SkRzVXA5SyZ1c2VyPWFwcA==
  fqdn-uri: cG9zdGdyZXNxbDovL2FwcDpIeHkzVzZBR3F0eG9uQ21Xc3hZSmJTcWhVdUxORlFIZTZVRnZ5ZDhHRmc5cWdCV1FlODhySzdGdjlKRHNVcDlLQHNvbmFycXViZS1jbnBnLWNsdXN0ZXItcncuc29uYXJxdWJlLnN2Yy5jbHVzdGVyLmxvY2FsOjU0MzIvYXBw
  host: c29uYXJxdWJlLWNucGctY2x1c3Rlci1ydw==
  jdbc-uri: amRiYzpwb3N0Z3Jlc3FsOi8vc29uYXJxdWJlLWNucGctY2x1c3Rlci1ydy5zb25hcnF1YmU6NTQzMi9hcHA/cGFzc3dvcmQ9SHh5M1c2QUdxdHhvbkNtV3N4WUpiU3FoVXVMTkZRSGU2VUZ2eWQ4R0ZnOXFnQldRZTg4cks3RnY5SkRzVXA5SyZ1c2VyPWFwcA==
  password: SHh5M1c2QUdxdHhvbkNtV3N4WUpiU3FoVXVMTkZRSGU2VUZ2eWQ4R0ZnOXFnQldRZTg4cks3RnY5SkRzVXA5Sw==
  pgpass: c29uYXJxdWJlLWNucGctY2x1c3Rlci1ydzo1NDMyOmFwcDphcHA6SHh5M1c2QUdxdHhvbkNtV3N4WUpiU3FoVXVMTkZRSGU2VUZ2eWQ4R0ZnOXFnQldRZTg4cks3RnY5SkRzVXA5Swo=
  port: NTQzMg==
  uri: cG9zdGdyZXNxbDovL2FwcDpIeHkzVzZBR3F0eG9uQ21Xc3hZSmJTcWhVdUxORlFIZTZVRnZ5ZDhHRmc5cWdCV1FlODhySzdGdjlKRHNVcDlLQHNvbmFycXViZS1jbnBnLWNsdXN0ZXItcncuc29uYXJxdWJlOjU0MzIvYXBw
  user: YXBw
  username: YXBw
kind: Secret
metadata:
  annotations:
    cnpg.io/operatorVersion: 1.27.0
  creationTimestamp: "2025-12-18T08:32:24Z"
  labels:
    cnpg.io/cluster: sonarqube-cnpg-cluster
    cnpg.io/reload: "true"
    cnpg.io/userType: app
  name: sonarqube-cnpg-cluster-app
  namespace: sonarqube
  ownerReferences:
  - apiVersion: postgresql.cnpg.io/v1
    controller: true
    kind: Cluster
    name: sonarqube-cnpg-cluster
    uid: 1f57fc23-933c-4414-98c4-3a99a0bbb861
  resourceVersion: "29074989"
  uid: 4308dd21-d7c6-4595-abb2-a662c7029405
type: kubernetes.io/basic-auth

Decoded:

dbname: app
fqdn-jdbc-uri: jdbc:postgresql://sonarqube-cnpg-cluster-rw.sonarqube.svc.cluster.local:5432/app?password=Hxy3W6AGqtxonCmWsxYJbSqhUuLNFQHe6UFvyd8GFg9qgBWQe88rK7Fv9JDsUp9K&user=app
fqdn-uri: postgresql://app:Hxy3W6AGqtxonCmWsxYJbSqhUuLNFQHe6UFvyd8GFg9qgBWQe88rK7Fv9JDsUp9K@sonarqube-cnpg-cluster-rw.sonarqube.svc.cluster.local:5432/app
host: sonarqube-cnpg-cluster-rw
jdbc-uri: jdbc:postgresql://sonarqube-cnpg-cluster-rw.sonarqube:5432/app?password=Hxy3W6AGqtxonCmWsxYJbSqhUuLNFQHe6UFvyd8GFg9qgBWQe88rK7Fv9JDsUp9K&user=app
password: Hxy3W6AGqtxonCmWsxYJbSqhUuLNFQHe6UFvyd8GFg9qgBWQe88rK7Fv9JDsUp9K
pgpass: |
  sonarqube-cnpg-cluster-rw:5432:app:app:Hxy3W6AGqtxonCmWsxYJbSqhUuLNFQHe6UFvyd8GFg9qgBWQe88rK7Fv9JDsUp9K
port: "5432"
uri: postgresql://app:Hxy3W6AGqtxonCmWsxYJbSqhUuLNFQHe6UFvyd8GFg9qgBWQe88rK7Fv9JDsUp9K@sonarqube-cnpg-cluster-rw.sonarqube:5432/app
user: app
username: app

If we try to use the following Helm chart values to set the JDBC string:

jdbcOverwrite:
  enabled: true
  {{ $cnpgClusterCredentials := exec "kubectl" (list "get" "secret" "sonarqube-cnpg-cluster-app" "-n" "sonarqube" "-o" "json") | fromJson }}
  jdbcUrl: {{ index $cnpgClusterCredentials.data "jdbc-uri" | b64dec }}
  jdbcUsername: {{ $cnpgClusterCredentials.data.user | b64dec }}
  jdbcSecretName: sonarqube-cnpg-cluster-app
  jdbcSecretPasswordKey: password

The JDBC URL exposes the password in a ConfigMap:

  apiVersion: v1
  kind: ConfigMap
  metadata:
    name: sonarqube-sonarqube-jdbc-config
    labels:
      app: sonarqube
      chart: sonarqube-2025.4.2
      release: sonarqube
      heritage: Helm
  data:
-   SONAR_JDBC_USERNAME: "postgres"
-   SONAR_JDBC_URL: "jdbc:postgresql://sonarqube-cnpg-cluster-rw.sonarqube:5432/\*?password=tKbo9ouXd73Li4vyrg5RadzyTz6etKtMNcB0igG4KXeDPUZNeso9NOYKEWK5iBPl&user=postgres"
+   SONAR_JDBC_USERNAME: "app"
+   SONAR_JDBC_URL: "jdbc:postgresql://sonarqube-cnpg-cluster-rw.sonarqube:5432/app?password=Hxy3W6AGqtxonCmWsxYJbSqhUuLNFQHe6UFvyd8GFg9qgBWQe88rK7Fv9JDsUp9K&user=app"

This can be worked around by performing manipulations with Helm templating, but it would be nice not to expose credentials in this way, as I only discovered this issue while debugging. Potentially, anyone who has access to ConfigMaps in the Kubernetes cluster can gain access to the SonarQube database.

This in development environment, so i can expose credentials in ticket

1 Like