Certificates v1

EDB Postgres Distributed for Kubernetes was designed to natively support TLS certificates. To set up an PGD cluster, each PGD node requires:

  • Server certificates configuration.
  • Client certificates configuration.
Note

You can find all the secrets used by each PGD node and the expiry dates in the cluster (PGD node) status.

Server certificates configuration

The server certificate configuration is handled in the spec.connectivity.tls.serverCert section of the PGDGroup custom resource. This configuration requires a server CA secret and a cert-manager template to generate the TLS certificates needed for the underlying Postgres instance to terminate TLS connections.

The following assumptions must be met for this section to function correctly:

  1. Cert-manager must be installed.
  2. An issuer specified spec.connectivity.tls.serverCert.certManager.issuerRef is available for the domain specified in spec.connectivity.dns.domain and any additional domains listed in spec.connectivity.tls.serverCert.certManager.spec.dnsNames.
  3. A server CA secret containing the public certificate of the CA used by the issuer must be created.
Note

The server CA secret specified by spec.connectivity.tls.clientCert.serverCA will be referenced as serverCASecret in the underlying CNP nodes. The public part, ca.crt, validates the server certificate and is included as sslrootcert into client connection strings. The private part, ca.key, is used to automatically sign the server SSL certificate, if a self-signed certificate is employed.

Note

The server TLS secret generated by PGD group will be specified as the value of serverTLSSecret in the underlying CNP nodes. For more information, refer to server certificates.

DNS names

The operator will add the following altDnsNames to the server TLS certificate:

${nodeName}${hostSuffix}.${domain}
${groupName}${hostSuffix}.${domain}
${proxyName}${hostSuffix}.${domain}
${nodeName}${additionalHostSuffix}.${additionalDomain}
${groupName}${additionalHostSuffix}.${additionalDomain}
${proxyName}${additionalHostSuffix}.${additionalDomain}

Users are responsible for including any necessary names in spec.connectivity.tls.serverCert.certManager.spec.dnsNames, based on their underlying networking architecture (e.g. any load balancers to access the nodes).

For example, consider a PGD Group configured as follows:

apiVersion: pgd.k8s.enterprisedb.io/v1beta1
kind: PGDGroup
metadata:
  name: region-a
spec:
  instances: 3
  ...
  connectivity:
    dns:
      # we need to configure the domain for the group so it could be resolved
      domain: enterprisedb.network
      additional:
        - domain: alternate.network
          hostSuffix: -dc1

All of the following Subject Alternative Names (SANs) will be added to the server TLS certificate:

region-a-1-node.domain.enterprisedb.network
region-a-group.domain.enterprisedb.network
region-a-proxy.domain.enterprisedb.network
region-a-1-node-dc1.alternate.network
region-a-group-dc1.alternate.network
region-a-proxy-dc1.alternate.network

Client certificates configuration

The client certificates configuration is managed under the spec.connectivity.tls.clientCert section of the PGDGroup custom resource. This configuration requires a client CA secret and a client cert-manager template to generate the client streaming replication certificate for the streaming_replica Postgres user.

The following assumptions must be met for this section to function properly:

  1. Cert-manager must be installed.
  2. An issuer specified in spec.connectivity.tls.clientCert.certManager.issuerRef is available; this issuer will be used to sign a certificate with the common name streaming_replica.
  3. A client CA secret must be present. It contains the public certificate of the CA used by the issuer.

The operator will use the configuration under spec.connectivity.tls.clientCert.certManager to create a certificate request for the streaming_replica Postgres user. The resulting certificate will be used to secure communication between the nodes.

Note

The client CA secret specified by spec.connectivity.tls.clientCert.clientCA will be used as the value of clientCASecret in the underlying CNP nodes. The public part, ca.crt, will be provided as ssl_ca_file to all the instances, allowing them to verify client certificates they have signed. The private part, ca.key, is optional and can be used to sign client certificate generated by the kubectl cnp plugin.

Client pre-provisioned replication certificate

Alternatively, you can specify a secret containing the pre-provisioned client certificate for the streaming_replica user using the spec.connectivity.tls.clientCert.preProvisioned.streamingReplica.secretRef option. In this case, the certificate lifecycle is managed entirely by a third party (manually or automatically), by simply updating the content of the secret.

Note

Regardless of how the client streaming replication certificate is provided, it will be used as the value of replicationTLSSecret in the underlying CNP nodes. For more information, refer to the section on Client certificate.

TLS mode

You can configure the TLS mode, which determines how the server certificates are verified during communication between nodes, using spec.connectivity.tls.mode. Its default value is verify-ca. Note that the TLS mode cannot be changed once the PGD Group is set up. The mode accepts the following values, as documented in SSL Support in the PostgreSQL documentation:

  • verify-full
  • verify-ca
  • required

Self-signed example

This example demonstrates how to use cert-manager to setup a self-signed CA and generated required certificates.

First, we need to generate the server and client CA certificates. We will create two self-signed issuers, server-ca-issuer and client-ca-issuer, in the target namespace.

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: selfsigned-issuer
spec:
  selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: server-ca-issuer
spec:
  ca:
    secretName: server-ca-key-pair
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: client-ca-issuer
spec:
  ca:
    secretName: client-ca-key-pair

With the following Certificate object, we can generate the private key and a signed certificate from the issuer. The private key and signed certificate will be stored in the secrets named server-ca-key-pair and client-ca-key-pair.

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: 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

We can now configure the PGD group. The server-ca-key-pair and client-ca-key-pair will be used as the server CA secret and client CA secret, respectively. The cert-manager template can be set up to reference the corresponding issuer to automatically generate the server TLS certificate and client replication certificate.

apiVersion: pgd.k8s.enterprisedb.io/v1beta1
kind: PGDGroup
metadata:
  name: region-a
spec:
  ...
  connectivity:
    tls:
      mode: verify-ca
      clientCert:
        caCertSecret: client-ca-key-pair
        certManager:
          spec:
            issuerRef:
              name: client-ca-issuer
              kind: Issuer
              group: cert-manager.io
      serverCert:
        caCertSecret: server-ca-key-pair
        certManager:
          spec:
            issuerRef:
              name: server-ca-issuer
              kind: Issuer
              group: cert-manager.io

For more information about how certificate works, see the EDB Postgres for Kubernetes documentation.