Certificates ============ CloudNativePG was designed to natively support TLS certificates. To set up a cluster, the operator requires: - A server certification authority (CA) certificate - A server TLS certificate signed by the server CA - A client CA certificate - A streaming replication client certificate generated by the client CA .. note:: You can find all the secrets used by the cluster and their expiration dates in the cluster's status. ::: CloudNativePG is very flexible when it comes to TLS certificates. It primarily operates in two modes: 1. :ref:`Operator-Managed Mode ` – Certificates are internally managed by the operator in a fully automated way and signed using a CA created by CloudNativePG. 2. :ref:`User-provided certificates mode ` – Certificates are generated outside the operator and imported in the cluster definition as secrets. CloudNativePG integrates itself with `cert-manager `_ (See :ref:`Cert-manager example ` .) You can also choose a hybrid approach, where only part of the certificates is generated outside CNPG. .. note:: The operator and instances verify server certificates against the CA only, disregarding the DNS name. This approach is due to the typical absence of DNS names in user-provided certificates for the `-rw` service used for communication within the cluster. ::: .. note:: Beyond the CA-managed certificates listed above, the operator also uses a self-signed client certificate, generated in memory, to authenticate to the instance manager's status port. This certificate is not signed by the client CA: the instance manager trusts it by pinning its public-key fingerprint. See :ref:`Operator-to-instance authentication (`GHSA-7qwx-x8ff-3px9` ) ` . ::: Operator-Managed Mode --------------------- By default, the operator automatically generates a single Certificate Authority (CA) to issue both client and server certificates. These certificates are managed continuously by the operator, with automatic renewal 7 days before expiration (within a 90-day validity period). .. note:: You can adjust this default behavior by configuring the `CERTIFICATE_DURATION` and `EXPIRING_CHECK_THRESHOLD` environment variables. For detailed guidance, refer to the :ref:`Operator configuration ` . ::: .. note:: Certificate renewal does not cause any downtime for the PostgreSQL server, as a simple reload operation is sufficient. However, any user-managed certificates not controlled by CloudNativePG must be re-issued following the renewal process. ::: When generating certificates, the operator assumes that the Kubernetes cluster’s DNS zone is set to ``cluster.local`` by default. This behavior can be customized by setting the ``KUBERNETES_CLUSTER_DOMAIN`` environment variable. A convenient alternative is to use the :ref:`operator's configuration capability ` . Server certificates ^^^^^^^^^^^^^^^^^^^ Server CA secret ^^^^^^^^^^^^^^^^ The operator generates a self-signed CA and stores it in a generic secret containing the following keys: - ``ca.crt`` – CA certificate used to validate the server certificate, used as ``sslrootcert`` in clients’ connection strings. - ``ca.key`` – The key used to sign the server SSL certificate automatically. Server TLS secret ^^^^^^^^^^^^^^^^^ The operator uses the generated self-signed CA to sign a server TLS certificate. It’s stored in a secret of type ``kubernetes.io/tls`` and configured to be used as ``ssl_cert_file`` and ``ssl_key_file`` by the instances. This approach enables clients to verify their identity and connect securely. Server alternative DNS names ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In addition to the default ones, you can specify DNS server alternative names as part of the generated server TLS secret. Client certificates ^^^^^^^^^^^^^^^^^^^ Client CA secret ^^^^^^^^^^^^^^^^ By default, the same self-signed CA as the server CA is used. The public part is passed as ``ssl_ca_file`` to all the instances so it can verify client certificates it signed. The private key is stored in the same secret and used to sign client certificates generated by the ``kubectl cnpg`` plugin. Client ``streaming_replica`` certificate ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The operator uses the generated self-signed CA to sign a client certificate for the user ``streaming_replica`` , storing it in a secret of type ``kubernetes.io/tls`` . To allow secure connection to the primary instance, this certificate is passed as ``sslcert`` and ``sslkey`` in the replicas’ connection strings. User-provided certificates mode ------------------------------- .. _server-certificates-1: Server certificates ^^^^^^^^^^^^^^^^^^^ If required, you can also provide the two server certificates, generating them using a separate component such as `cert-manager `_ . To use a custom server TLS certificate for a cluster, you must specify the following parameters: - ``serverTLSSecret`` – The name of a secret of type ``kubernetes.io/tls`` containing the server TLS certificate. It must contain both the standard ``tls.crt`` and ``tls.key`` keys. - ``serverCASecret`` – The name of a secret containing the ``ca.crt`` key. .. note:: The operator still creates and manages the two secrets related to client certificates. ::: .. note:: The operator and instances verify server certificates against the CA only, disregarding the DNS name. This approach is due to the typical absence of DNS names in user-provided certificates for the `-rw` service used for communication within the cluster. ::: .. note:: If you want ConfigMaps and secrets to be reloaded by instances, you can add a label with the key `cnpg.io/reload` to it. Otherwise you must reload the instances using the `kubectl cnpg reload` subcommand. ::: Example ^^^^^^^ Given the following files: - ``server-ca.crt`` – The certificate of the CA that signed the server TLS certificate. - ``server.crt`` – The certificate of the server TLS certificate. - ``server.key`` – The private key of the server TLS certificate. Create a secret containing the CA certificate: .. code:: sh kubectl create secret generic my-postgresql-server-ca \ --from-file=ca.crt=./server-ca.crt Create a secret with the TLS certificate: .. code:: sh kubectl create secret tls my-postgresql-server \ --cert=./server.crt --key=./server.key Create a PostgreSQL cluster referencing those secrets: .. code:: bash kubectl apply -f - <`_ to set up a self-signed CA and generate the needed TLS server certificate: .. code:: yaml - -- apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: selfsigned-issuer spec: selfSigned: {} - -- apiVersion: v1 kind: Secret metadata: name: my-postgres-server-cert labels: cnpg.io/reload: "" - -- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: my-postgres-server-cert spec: secretName: my-postgres-server-cert usages: - server auth dnsNames: - cluster-example-lb.internal.mydomain.net - cluster-example-rw - cluster-example-rw.default - cluster-example-rw.default.svc - cluster-example-r - cluster-example-r.default - cluster-example-r.default.svc - cluster-example-ro - cluster-example-ro.default - cluster-example-ro.default.svc issuerRef: name: selfsigned-issuer kind: Issuer group: cert-manager.io Cert-manager creates a secret named ``my-postgres-server-cert`` . It contains all the needed files and can be referenced from a cluster as follows: .. code:: yaml apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example spec: instances: 3 certificates: serverTLSSecret: my-postgres-server-cert serverCASecret: my-postgres-server-cert storage: size: 1Gi You can find a complete example using cert-manager to manage both server and client CA and certificates in the :ref:`cluster-example-cert-manager.yaml ` deployment manifest. Client certificate ^^^^^^^^^^^^^^^^^^ If required, you can also provide the two client certificates, generating them using a separate component such as `cert-manager `_ or `HashiCorp vault `_ . To use a custom CA to verify client certificates for a cluster, you must specify the following parameters: - ``replicationTLSSecret`` – The name of a secret of type ``kubernetes.io/tls`` containing the client certificate for user ``streaming_replica`` . It must contain both the standard ``tls.crt`` and ``tls.key`` keys. - ``clientCASecret`` – The name of a secret containing the ``ca.crt`` key of the CA to use to verify client certificate. .. note:: The operator still creates and manages the two secrets related to server certificates. ::: .. note:: As the cluster isn't in control of the client CA secret key, you can no longer generate client certificates using `kubectl cnpg certificate` . ::: .. note:: If you want ConfigMaps and secrets to be automatically reloaded by instances, you can add a label with the key `cnpg.io/reload` to it. Otherwise, you must reload the instances using the `kubectl cnpg reload` subcommand. ::: Customizing the ``streaming_replica`` client certificate ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In some environments, it may not be possible to generate a certificate with the common name ``streaming_replica`` due to company policies or other security concerns, such as a CA shared across multiple clusters. In such cases, the user mapping feature can be used to allow authentication as the ``streaming_replica`` user with certificates containing different common names. To configure this setup, add a ``pg_ident.conf`` entry for the predefined map named ``cnpg_streaming_replica`` . For example, to enable ``streaming_replica`` authentication using a certificate with the common name ``streaming-replica.cnpg.svc.cluster.local`` , add the following to your cluster definition: .. code:: yaml apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example spec: postgresql: pg_ident: - cnpg_streaming_replica streaming-replica.cnpg.svc.cluster.local streaming_replica For further details on how ``pg_ident.conf`` is managed by the operator, see the :ref:`Mounting and PostgreSQL Configuration ` in the documentation. .. _cert-manager-example-1: Cert-manager example ^^^^^^^^^^^^^^^^^^^^ This simple example shows how to use `cert-manager `_ to set up a self-signed CA and generate the needed TLS server certificate: .. code:: yaml - -- apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: selfsigned-issuer spec: selfSigned: {} - -- apiVersion: v1 kind: Secret metadata: name: my-postgres-client-cert labels: cnpg.io/reload: "" - -- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: my-postgres-client-cert spec: secretName: my-postgres-client-cert usages: - client auth commonName: streaming_replica issuerRef: name: selfsigned-issuer kind: Issuer group: cert-manager.io Cert-manager creates a secret named ``my-postgres-client-cert`` that contains all the needed files. You can reference it from a cluster as follows: .. code:: yaml apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example spec: instances: 3 certificates: clientCASecret: my-postgres-client-cert replicationTLSSecret: my-postgres-client-cert storage: size: 1Gi You can find a complete example using cert-manager to manage both server and client CA and certificates in the :ref:`cluster-example-cert-manager.yaml ` deployment manifest. cluster-example-cert-manager.yaml ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: yaml apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: selfsigned-issuer spec: selfSigned: {} - -- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: server-ca spec: isCA: true commonName: my-selfsigned-server-ca secretName: server-ca-key-pair privateKey: algorithm: ECDSA size: 256 issuerRef: name: selfsigned-issuer kind: Issuer group: cert-manager.io - -- apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: server-ca-issuer spec: ca: secretName: server-ca-key-pair - -- apiVersion: v1 kind: Secret metadata: name: my-postgres-server-cert labels: cnpg.io/reload: "" - -- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: my-postgres-server-cert spec: secretName: my-postgres-server-cert usages: - server auth dnsNames: - cluster-example-lb.internal.mydomain.net - cluster-example-rw - cluster-example-rw.default - cluster-example-rw.default.svc - cluster-example-r - cluster-example-r.default - cluster-example-r.default.svc - cluster-example-ro - cluster-example-ro.default - cluster-example-ro.default.svc issuerRef: name: server-ca-issuer kind: Issuer group: cert-manager.io - -- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: client-ca spec: isCA: true commonName: my-selfsigned-client-ca secretName: client-ca-key-pair privateKey: algorithm: ECDSA size: 256 issuerRef: name: selfsigned-issuer kind: Issuer group: cert-manager.io - -- apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: client-ca-issuer spec: ca: secretName: client-ca-key-pair - -- apiVersion: v1 kind: Secret metadata: name: my-postgres-client-cert labels: cnpg.io/reload: "" - -- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: my-postgres-client-cert spec: secretName: my-postgres-client-cert usages: - client auth commonName: streaming_replica issuerRef: name: client-ca-issuer kind: Issuer group: cert-manager.io - -- apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example spec: instances: 3 certificates: serverTLSSecret: my-postgres-server-cert serverCASecret: my-postgres-server-cert clientCASecret: my-postgres-client-cert replicationTLSSecret: my-postgres-client-cert storage: size: 1Gi