infisical icon indicating copy to clipboard operation
infisical copied to clipboard

Self-Signed TLS/SSL certs for connection to Postgres and Redis

Open chakraborty29 opened this issue 9 months ago • 1 comments

I am trying to deploy a HA Infisical on-premise with K8s and looking to follow the reference architecture but I am struggling to find documentation on how to use my own self-signed certificates to secure the connection between the Infiscal app and my cloudnative-pg postgres instance.

My initial thoughts are with the useExistingPostgresSecret in the helm chart

useExistingPostgresSecret:
    # -- Set to true if using an existing Kubernetes secret that contains PostgreSQL connection string
    enabled: false
    existingConnectionStringSecret:
      # -- Kubernetes secret name containing the PostgreSQL connection string
      name: ""
      # -- Key name in the Kubernetes secret that holds the connection string
      key: ""

Where the connection string can be set like this:

postgresql://${USERNAME}:${PASSWORD}@${DB_HOST}:5432/${DB_NAME}?ssl=true&sslmode=verify-full&sslrootcert=${SSL_ROOT_CERT_PATH}

But with cloudnative-pg the secret that hosts the username and password is already created, and you can't reference a secrete in a secret. Limiting the postgres connection to just a URI makes this customization much more difficult. Along with the fact that the helm chart doesn't provide anything on mounting volumes or extra secrets to allow extra parameters for postgres or redis.

Authentik's configuration does a good job with connections to posgres and redis with TLS. It would be nice to see something like this for Infiscal.

chakraborty29 avatar Apr 12 '25 21:04 chakraborty29

I am currently testing a solution which seems to be promising, as I refine it I will open a PR. The updated will entail the following changes to the helm chart templating to allow custom URI parameters to let helm construct the DB_CONNECTION_URI string based on passed in secrets to keep the DB username and passwords a secret, and to able to pass in custom sslrootcert from a kubernetes secret.

infisical.yaml

...
        env:
        {{- if and .Values.postgresql.useExistingPostgresSecret.enabled .Values.postgresql.useExistingPostgresSecret.customURIParameters.enabled }}
        {{- $pgParams := .Values.postgresql.useExistingPostgresSecret.customURIParameters }}
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: {{ $pgParams.usernameSecret.name }}
              key: {{ $pgParams.usernameSecret.key }}
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ $pgParams.passwordSecret.name }}
              key: {{ $pgParams.passwordSecret.key }}
        - name: DB_CONNECTION_URI
          {{- $sslParams := "" }}
          {{- if and $pgParams.ssl.enabled $pgParams.ssl.mode }}
          {{- $sslParams = printf "?sslmode=%s&sslrootcert=%s" $pgParams.ssl.mode $pgParams.ssl.rootCertPath }}
          {{- end }}
          value: "postgresql://$(DB_USER):$(DB_PASSWORD)@{{ $pgParams.host }}:{{ $pgParams.port }}/{{ $pgParams.database }}{{ $sslParams }}"
        {{- else if .Values.postgresql.useExistingPostgresSecret.enabled }}
...

Now to pass in custom parameters in values.yaml:

  useExistingPostgresSecret:
    ...
    customURIParameters:
      # -- Set to true if using custom URI parameters for PostgreSQL connection
      enabled: false
      # -- Hostname for PostgreSQL connection
      host: ""
      # -- Port for PostgreSQL connection. Default is 5432
      port: 5432
      # -- Database name for PostgreSQL connection
      database: ""

      usernameSecret:
        # -- Kubernetes secret name containing the PostgreSQL username
        name: ""
        # -- Key name in the Kubernetes secret that holds the PostgreSQL username
        key: ""

      passwordSecret:
        # -- Kubernetes secret name containing the PostgreSQL password
        name: ""
        # -- Key name in the Kubernetes secret that holds the PostgreSQL password
        key: ""

      ssl:
        # -- Set to true if using SSL for PostgreSQL connection
        enabled: false
        # -- SSL mode for PostgreSQL connection. Default is "verify-ca"
        mode: "verify-ca"
        # -- Path to the Root CA certificate file for SSL connection. Default is "/etc/postgres-certs/ca.crt"
        rootCertPath: "/etc/postgres-certs/ca.crt"

To pass in the sslrootcert, we need to mount the cert:

infisical:
...
  extraVolumes:
    - name: postgres-ca-cert
      secret:
        secretName: custom-ca
        items:
          - key: ca.crt
            path: ca.crt
  
  extraVolumeMounts:
    - name: postgres-ca-cert
      mountPath: /etc/postgres-certs
      readOnly: true

To test the change, I ran the following command:

helm install infisical-test ./infisical-standalone --dry-run --debug -f values.yaml > rendered.yaml

And the output of rendered.yaml to verify that this worked:

# Source: infisical-standalone/templates/infisical.yaml
apiVersion: apps/v1
kind: Deployment
...
spec:
  ...
  template:
    ...
    spec:
      ...
      containers:
        ...
        env:
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: pg-infisical-admin-credentials-secret
              key: username
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: pg-infisical-admin-credentials-secret
              key: password
        - name: DB_CONNECTION_URI
          value: "postgresql://$(DB_USER):$(DB_PASSWORD)@pg-infisical-rw.infisical.svc.cluster.local:5432/pg-infisical?sslmode=verify-ca&sslrootcert=/etc/postgres-certs/ca.crt"

We can implement similar updates to the template for read replicas and for redis.

Would love to hear your thoughts on this @maidul98 , I think this feature would make implementing the K8s HA reference architecture a lot more secure and managing the "secret zero" to the database that will hold the cluster secrets a lot more secure.

chakraborty29 avatar Apr 13 '25 02:04 chakraborty29

What's the proper URI to use for Redis using TLS with self-signed certs? I don't want my connections to Redis using cleartext either.

josh-at-innotegrity avatar May 07 '25 00:05 josh-at-innotegrity