Client TLS/SSL Connections ========================== .. Seealso:: Please refer to the :ref:`Certificates ` page for more details on how CloudNativePG supports TLS certificates. The CloudNativePG operator has been designed to work with TLS/SSL for both encryption in transit and authentication, on server and client sides. Clusters created using the CNPG operator comes with a Certification Authority (CA) to create and sign TLS client certificates. Through the ``cnpg`` plugin for ``kubectl`` you can issue a new TLS client certificate which can be used to authenticate a user instead of using passwords. Please refer to the following steps to authenticate via TLS/SSL certificates, which assume you have installed a cluster using the :: apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example spec: instances: 3 postgresql: pg_hba: - hostssl app all all cert storage: size: 1Gi manifest. According to the convention over configuration paradigm, that file automatically creates an ``app`` database which is owned by a user called ``app`` (you can change this convention through the ``initdb`` configuration in the ``bootstrap`` section). Issuing a new certificate ------------------------- .. Seealso:: Please refer to the :ref:`Certificates ` page for details on how to use the plugin for ``kubectl`` . You can create a certificate for the ``app`` user in the ``cluster-example`` PostgreSQL cluster as follows: .. code:: shell kubectl cnpg certificate cluster-app \ --cnpg-cluster cluster-example \ --cnpg-user app You can now verify the certificate with: .. code:: shell kubectl get secret cluster-app \ -o jsonpath="{.data[tls\.crt]}" \ | base64 -d | openssl x509 -text -noout \ | head -n 11 Output: .. code:: console Certificate: Data: Version: 3 (0x2) Serial Number: 5d:e1:72:8a:39:9f:ce:51:19:9d:21:ff:1e:4b:24:5d Signature Algorithm: ecdsa-with-SHA256 Issuer: OU = default, CN = cluster-example Validity Not Before: Mar 22 10:22:14 2021 GMT Not After : Mar 22 10:22:14 2022 GMT Subject: CN = app As you can see, TLS client certificates by default are created with 90 days of validity, and with a simple CN that corresponds to the username in PostgreSQL. This is necessary to leverage the ``cert`` authentication method for ``hostssl`` entries in ``pg_hba.conf`` . Testing the connection via a TLS certificate -------------------------------------------- Now we will test this client certificate by configuring a demo client application that connects to our CloudNativePG cluster. The following manifest called ``cert-test.yaml`` creates a demo Pod with a test application in the same namespace where your database cluster is running: .. code:: yaml apiVersion: apps/v1 kind: Deployment metadata: name: cert-test spec: replicas: 1 selector: matchLabels: app: webtest template: metadata: labels: app: webtest spec: containers: - image: ghcr.io/cloudnative-pg/webtest:1.6.0 name: cert-test volumeMounts: - name: secret-volume-root-ca mountPath: /etc/secrets/ca - name: secret-volume-app mountPath: /etc/secrets/app ports: - containerPort: 8080 env: - name: DATABASE_URL value: > sslkey=/etc/secrets/app/tls.key sslcert=/etc/secrets/app/tls.crt sslrootcert=/etc/secrets/ca/ca.crt host=cluster-example-rw.default.svc dbname=app user=app sslmode=verify-full - name: SQL_QUERY value: SELECT 1 readinessProbe: httpGet: port: 8080 path: /tx volumes: - name: secret-volume-root-ca secret: secretName: cluster-example-ca defaultMode: 0600 - name: secret-volume-app secret: secretName: cluster-app defaultMode: 0600 This Pod will mount secrets managed by the CloudNativePG operator, including: - ``sslcert`` : the TLS client public certificate - ``sslkey`` : the TLS client certificate private key - ``sslrootcert`` : the TLS Certification Authority certificate, that signed the certificate on the server to be used to verify the identity of the instances They will be used to create the default resources that ``psql`` (and other libpq based applications like ``pgbench`` ) requires to establish a TLS encrypted connection to the Postgres database. By default ``psql`` searches for certificates inside the ``~/.postgresql`` directory of the current user, but we can use the sslkey, sslcert, sslrootcert options to point libpq to the actual location of the cryptographic material. The content of the above files is gathered from the secrets that were previously created by using the ``cnpg`` plugin for kubectl. Now deploy the application: .. code:: shell kubectl create -f cert-test.yaml Then we will use created Pod as PostgreSQL client to validate SSL connection and authentication using TLS certificates we just created. A readiness probe has been configured to ensure that the application is ready when the database server can be reached. You can verify that the connection works by executing an interactive ``bash`` inside the Pod’s container to run ``psql`` using the necessary options. The PostgreSQL server is exposed through the read-write Kubernetes service. We will point the ``psql`` command to connect to this service: .. code:: shell kubectl exec -it cert-test -- bash -c "psql sslkey=/etc/secrets/app/tls.key sslcert=/etc/secrets/app/tls.crt sslrootcert=/etc/secrets/ca/ca.crt host=cluster-example-rw.default.svc dbname=app user=app sslmode=verify-full -c select version();" Output : .. code:: console version - ------------------------------------------------------------------------------------- - ----------------- PostgreSQL 16.1 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.3.1 20191121 (Red Hat 8.3.1-5), 64-bit (1 row) About TLS protocol versions --------------------------- By default, the operator sets both `ssl_min_protocol_version `_ and `ssl_max_protocol_version `_ to ``TLSv1.3`` . .. Important:: In PostgreSQL 11 these two GUC doesn't exists hence, in these specific version these values aren't set and will keep using the default ones. This assumes that the PostgreSQL operand images include an OpenSSL library that supports the ``TLSv1.3`` version. If not, or your client applications need a lower version number, you need to manually configure it in the PostgreSQL configuration as any other Postgres GUC.