Certificates
============

CloudNativePG has been designed to natively support TLS certificates. In
order to set up a ``Cluster`` , the operator requires:

-  a server Certification Authority (CA) certificate

-  a server TLS certificate signed by the server Certification Authority

-  a client Certification Authority certificate

-  a streaming replication client certificate generated by the client
   Certification Authority

..  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, and
primarily operates in two modes:

1. :ref:`**operator managed** <#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>`  : certificates are generated outside the operator and
   imported in the cluster definition as secrets - CloudNativePG
   integrates itself with cert-manager (see examples below)

You can also choose a hybrid approach, where only part of the
certificates is generated outside CNPG.

Operator managed mode
---------------------

By default, the operator generates a single Certification Authority and
uses it for both client and server certificates, which are then managed
and renewed automatically.

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 Server SSL certificate
   automatically

Server TLS Secret
^^^^^^^^^^^^^^^^^

The operator uses the generated self-signed CA to sign a server TLS
certificate, 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 so that clients can verify their identity and connect
securely.

Server alternative DNS names
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

You can specify DNS server alternative names that will be part of the
generated server TLS secret in addition to the default ones.

Client Certificates
^^^^^^^^^^^^^^^^^^^

Client CA Secret
^^^^^^^^^^^^^^^^

The same self-signed CA as the Server CA is used by default. The public
part will be passed as ``ssl_ca_file`` to all the instances in order to
be able to verify client certificates it signed. The private key will be
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`` . This certificate will be passed as
``sslcert`` and ``sslkey`` in replicas’ connection strings, to allow
securely connecting to the primary instance.

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 <https://cert-manager.io/>`_  . In
order 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 will still create and manage the two secrets related to client certificates.

..  Note::
   If you want ConfigMaps and Secrets to be **automatically** reloaded by instances, you can add a label with key `cnpg.io/reload`  to it, otherwise you will have to reload the instances using the `kubectl cnpg reload`  subcommand.

See below for a complete example.

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:

::

   kubectl create secret generic my-postgresql-server-ca \
     --from-file=ca.crt=./server-ca.crt

Create a secret with the TLS certificate:

::

   kubectl create secret tls my-postgresql-server \
     --cert=./server.crt --key=./server.key

Create a ``Cluster`` referencing those secrets:

.. code:: bash

   kubectl apply -f - <<EOF
   apiVersion: postgresql.cnpg.io/v1
   kind: Cluster
   metadata:
     name: cluster-example
   spec:
     instances: 3
     certificates:
       serverCASecret: my-postgresql-server-ca
       serverTLSSecret: my-postgresql-server
     storage:
       storageClass: standard
       size: 1Gi
   EOF

The new cluster will use the provided server certificates for TLS
connections.

Cert-manager Example
^^^^^^^^^^^^^^^^^^^^

Here is a simple example about how to use `cert-manager <https://cert-manager.io/>`_  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

A Secret named ``my-postgres-server-cert`` is created by cert-manager,
containing 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

::

   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

deployment manifest.

Client Certificate
^^^^^^^^^^^^^^^^^^

If required, you can also provide the two client certificates,
generating them using a separate component such as `cert-manager <https://cert-manager.io/>`_  or
 `hashicorp vault <https://www.vaultproject.io/docs/secrets/pki>`_  . In order 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 that should be used to verify client certificate.

..  Note::
   The operator will still create and manage the two secrets related to server certificates.

..  Note::
   As the Cluster is not in control of the client CA secret key, client certificates can not be generated using `kubectl cnpg certificate`  anymore.

..  Note::
   If you want ConfigMaps and Secrets to be **automatically** reloaded by instances, you can add a label with key `cnpg.io/reload`  to it, otherwise you will have to reload the instances using the `kubectl cnpg reload`  subcommand.

.. _cert-manager-example-1:

Cert-manager Example
^^^^^^^^^^^^^^^^^^^^

Here a simple example about how to use `cert-manager <https://cert-manager.io/>`_  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

A Secret named ``my-postgres-client-cert`` is created by cert-manager,
containing 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:
       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

::

   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

deployment manifest.
