Certificates
============
.. raw:: html
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.
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:`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.