Top
Enterprise Postgres 18 for Kubernetes User's Guide

4.8.2 When Using Your Own Certificate

Here, we provide two methods to create certificates for securing the TLS connection and provide mutual authentication. The first method is to create and renew certificate manually. The second method is to use CertManager to create an automatically renew certificate.

Note

The following considerations apply to client connections to a database cluster in an MTLS configuration:.

  • Distribute the Root certificate for server (validation) that you specified when you created the MTLS database cluster to the client machines.

  • Create and use a new client certificate.

  • If the server root certificate and the client root certificate are different, a server-side configuration update is required.

4.8.2.1 Manual Certificate Management

Overview of Procedures

The procedures to enable MTLS communication are listed below:

  1. Create a self signed certificate as CA

  2. Create Configmap to store CA certificate

  3. Create a password for protecting FEP Server private key (optional)

  4. Create FEP Server private key

  5. Create FEP Server certificate signing request

  6. Create FEP Server certificate signed by CA

  7. Create TLS Secret to store FEP Server certificate and key

  8. Create private key for Patroni

  9. Create certificate signing request for Patroni

  10. Create certificate signed by CA for Patroni

  11. Create TLS secret to store Patroni certificate and key

  12. Create private key for "postgres" user client certificate

  13. Create certificate signing request for "postgres" user client certificate

  14. Create client certificate for "postgres" user

  15. Create TLS secret to store "postgres" certificate and key

  16. Repeat step 12-15 for "repluser" and "rewinduser"

Note

  • The information in the manual is only an example, and in operation, use a certificate signed by a certificate authority (CA) that the user can trust.

  • When working on a Kubernetes cluster, replace the oc command with the kubectl command.


Creating a CA Certificate

1. Create a self signed certificate as CA
openssl genrsa -aes256 -out myca.key 4096
Generating RSA private key, 4096 bit long modulus (2 primes) ........................++++ ........................................................++++ e is 65537 (0x010001) Enter pass phrase for myca.key: 0okm9ijn8uhb7ygv Verifying - Enter pass phrase for myca.key: 0okm9ijn8uhb7ygv cat << EOF > ca.cnf
[req]

distinguished_name=req_distinguished_name

x509_extensions=v3_ca

[v3_ca]

basicConstraints = critical, CA:true

keyUsage=critical,keyCertSign,digitalSignature,cRLSign

[req_distinguished_name]

commonName=Common Name

EOF


openssl req -x509 -new -nodes -key myca.key -days 3650 -out myca.pem -subj "/O=My Organization/OU=CA
/CN=My Organization Certificate Authority" -config ca.cnf Enter pass phrase for myca.key: 0okm9ijn8uhb7ygv

2. Create Configmap to store CA certificate
oc create configmap cacert --from-file=ca.crt=myca.pem -n my-namespace

3. Create a password for protecting FEP Server private key (optional)
oc create secret generic mydb-fep-private-key-password --from-literal=keypassword=abcdefghijk -n my-namespace

Creating a Server Certificate

4. Create FEP Server private key
openssl genrsa -aes256 -out fep.key 2048
Generating RSA private key, 2048 bit long modulus ................................................+++ .......+++ e is 65537 (0x10001) Enter pass phrase for fep.key: abcdefghijk Verifying - Enter pass phrase for fep.key: abcdefghijk

5. Create FEP Server certificate signing request
cat << EOF > san.cnf
[SAN]

subjectAltName = @alt_names

[alt_names]

DNS.1 = *.my-namespace.pod

DNS.2 = *.my-namespace.pod.cluster.local

DNS.3 = mydb-primary-svc

DNS.4 = mydb-primary-svc.my-namespace

DNS.5 = mydb-primary-svc.my-namespace.svc

DNS.6 = mydb-primary-svc.my-namespace.svc.cluster.local

DNS.7 = mydb-replica-svc

DNS.8 = mydb-replica-svc.my-namespace

DNS.9 = mydb-replica-svc.my-namespace.svc

DNS.10 = mydb-replica-svc.my-namespace.svc.cluster.local

EOF


openssl req -new -key fep.key -out fep.csr -subj "/CN=mydb-headless-svc" -reqexts SAN -config <(cat /etc/pki/tls/openssl.cnf <(cat san.cnf))

Enter pass phrase for fep.key: abcdefghijk


Note

The cluster name and namespace must be changed appropriately.

If you are connecting from outside the OCP cluster, you must also include the host name used for that connection.


6. Create FEP Server certificate signed by CA
openssl x509 -req -in fep.csr -CA myca.pem -CAkey myca.key -out fep.pem -days 365 -extfile <(cat /etc/pki/tls/openssl.cnf <(cat san.cnf)) -extensions SAN -CAcreateserial  # all in one line
Signature ok
subject=/CN=mydb-headless-svc
Getting CA Private Key
Enter pass phrase for myca.key: 0okm9ijn8uhb7ygv

7. Create TLS Secret to store FEP Server certificate and key
oc create secret generic mydb-fep-cert --from-file=tls.crt=fep.pem --from-file=tls.key=fep.key -n my-namespace

8. Create private key for Patroni

At the moment, FEP container does not support password protected private key for Patroni.

openssl genrsa -out patroni.key 2048
Generating RSA private key, 2048 bit long modulus ...............................................+++ .......+++ e is 65537 (0x10001)

9. Create certificate signing request for Patroni
cat << EOF > san.cnf
[SAN]

subjectAltName = @alt_names

[alt_names]

DNS.1 = *.my-namespace.pod

DNS.2 = *.my-namespace.pod.cluster.local

DNS.3 = mydb-primary-svc

DNS.4 = mydb-primary-svc.my-namespace

DNS.5 = mydb-replica-svc

DNS.6 = mydb-replica-svc.my-namespace

DNS.7 = mydb-headless-svc

DNS.8 = mydb-headless-svc.my-namespace

EOF


openssl req -new -key patroni.key -out patroni.csr -subj "/CN=mydb-headless-svc" -reqexts SAN -config <(cat /etc/pki/tls/openssl.cnf <(cat san.cnf)) # all in one line


Note

The cluster name and namespace must be changed appropriately.

If you are connecting from outside the OCP cluster, you must also include the host name used for that connection.


10. Create certificate signed by CA for Patroni
openssl x509 -req -in patroni.csr -CA myca.pem -CAkey myca.key -out patroni.pem -days 365 -extfile <(cat /etc/pki/tls/openssl.cnf <(cat san.cnf)) -extensions SAN -CAcreateserial  # all in one line
Signature ok subject=/CN=mydb-headless-svc Getting CA Private Key Enter pass phrase for myca.key: 0okm9ijn8uhb7ygv

11. Create TLS secret to store Patroni certificate and key
oc create secret tls mydb-patroni-cert --cert=patroni.pem --key=patroni.key -n my-namespace

Creating a User Certificate

12. Create private key for "postgres" user client certificate

At the moment, SQL client inside FEP server container does not support password protected certificate.

openssl genrsa -out postgres.key 2048
Generating RSA private key, 2048 bit long modulus ...............................................+++ .......+++ e is 65537 (0x10001)

13. Create certificate signing request for "postgres" user client certificate
openssl req -new -key postgres.key -out postgres.csr -subj "/CN=postgres"

14. Create client certificate for "postgres" user
openssl x509 -req -in postgres.csr -CA myca.pem -CAkey myca.key -out postgres.pem -days 365
Signature ok

subject=CN = postgres

Getting CA Private Key

Enter pass phrase for myca.key: 0okm9ijn8uhb7ygv


15. Create TLS secret to store "postgres" certificate and key
oc create secret tls mydb-postgres-cert --cert=postgres.pem --key=postgres.key -n my-namespace

16. Repeat step 12-15 for "repluser" and "rewinduser"

4.8.2.2 Automatic Certificate Management

There are many Certificate Management tools available in the public. In this example, we will use cert-manager for the purpose.

Note

  • Note that certificates created in this example are not password protected.

  • When working on a Kubernetes cluster, replace the oc command with the kubectl command.


Install cert-manager
oc create namespace cert-manager

oc apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.0/cert-manager.yaml


Create a Self Signed Issuer (This can be namespace specific or cluster wise)

This example creates an Issuer, that can create self signed certificate, in namespace my-namespace.

cat << EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: selfsigned-issuer
  namespace: my-namespace
spec:
  selfSigned: {}
EOF

Create a Self Signed CA certificate using selfsigned-issuer
cat << EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: cacert
  namespace: my-namespace
spec:
  subject:
    organizations:
      - My Organization
    organizationalUnits:
      - CA
  commonName: "My Organization Certificate Authority"
  duration: 87600h
  isCA: true
  secretName: cacert
  issuerRef:
    name: selfsigned-issuer
EOF

The above command will create a self signed Root certificate and private key stored in the Kubernetes secret "cacert" in namespace my-namespace.


Create a CA Issuer with above certificate
cat << EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: ca-issuer
  namespace: my-namespace
spec:
  ca:
    secretName: cacert
EOF

Create FEP Server certificate using above CA Issuer

Assuming FEPCluster name is mydb in namespace my-namespace.

cat << EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: mydb-fep-cert
  namespace: my-namespace
spec:
  subject:
  commonName: "mydb-headless-svc"
  dnsNames:
  - "*.my-namespace.pod"
  - "*.my-namespace.pod.cluster.local"
  - "mydb-primary-svc"
  - "mydb-primary-svc.my-namespace"
  - "mydb-primary-svc.my-namespace.svc"
  - "mydb-primary-svc.my-namespace.svc.cluster.local"
  - "mydb-replica-svc"
  - "mydb-replica-svc.my-namespace"
  - "mydb-replica-svc.my-namespace.svc"
  - "mydb-replica-svc.my-namespace.svc.cluster.local"
  duration: 8760h
  usages:
  - server auth
  secretName: mydb-fep-cert
  issuerRef:
    name: ca-issuer
EOF

Create Patroni certificate using above CA Issuer

Assuming FEPCluster name is mydb in namespace my-namespace.

cat << EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: mydb-patroni-cert
  namespace: my-namespace
spec:
  subject:
  commonName: "mydb-headless-svc"
  dnsNames:
  - "*.my-namespace.pod"
  - "*.my-namespace.pod.cluster.local"
  - "*.mydb-primary-svc"
  - "*.mydb-primary-svc.my-namespace"
  - "*.mydb-replica-svc "
  - "*.mydb-replica-svc.my-namespace"
  duration: 8760h
  usages:
  - server auth
  secretName: mydb-patroni-cert
  issuerRef:
    name: ca-issuer
EOF

Create postgres user client certificate
cat << EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: mydb-postgres-cert
  namespace: my-namespace
spec:
  subject:
  commonName: "postgres"
  duration: 8760h
  usages:
  - client auth
  secretName: mydb-postgres-cert
  issuerRef:
    name: ca-issuer
EOF

Create repluser user client certificate
cat << EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: mydb-repluser-cert
  namespace: my-namespace
spec:
  subject:
  commonName: "repluser"
  duration: 8760h
  usages:
  - client auth
  secretName: mydb-repluser-cert
  issuerRef:
    name: ca-issuer
EOF

Create FEPLogging(Fluentd) server certificate using above CA Issuer

Assuming FEPLogging name is nfl in namespace feplogging-dev.

cat << EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: fluentd-cert
  namespace: feplogging-dev
spec:
  subject:
  commonName: "nfl-fluentd-headless-service"
  dnsNames:
  - 'nfl-fluentd-headless-service'
  - 'nfl-fluentd-headless-service.feplogging-dev'
  - 'nfl-fluentd-headless-service.feplogging-dev.svc'
  - 'nfl-fluentd-headless-service.feplogging-dev.svc.cluster.local'
  duration: 8760h
  usages:
  - server auth
  secretName: fluentd-cert
  issuerRef:
    name: ca-issuer
EOF

Create FEPLogging client(prometheus) certificate
cat << EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: prometheus-cert
  namespace: feplogging-dev
spec:
  subject:
  commonName: "prometheus"
  duration: 8760h
  usages:
  - client auth
  secretName: prometheus-cert
  issuerRef:
    name: ca-issuer
EOF

Create FEPLogging client(fluentbit) certificate
cat << EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: fluentbit-cert
  namespace: feplogging-dev
spec:
  subject:
  commonName: "fluentbit"
  duration: 8760h
  usages:
  - client auth
  secretName: fluentbit-cert
  issuerRef:
    name: ca-issuer
EOF

Create FEPExporter certificate using above CA Issuer

Assuming FEP Exporter name is exp1 in namespace my-namespace.

cat << EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: fepexporter-cert
  namespace: my-namespace
spec:
  subject:
  commonName: "exp1-service"
  dnsNames:
  - 'exp1-service'
  - 'exp1-service.fepexporter-dev'
  - 'exp1-service.fepexporter-dev.svc'
  - 'exp1-service.fepexporter-dev.svc.cluster.local'
  duration: 8760h
  usages:
  - server auth
  secretName: fepexporter-cert
  issuerRef:
    name: ca-issuer
EOF

Create FEPExporter user client(prometheus) certificate
cat << EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: prometheus-cert
  namespace: my-namespace
spec:
  subject:
  commonName: "prometheus"
  duration: 8760h
  usages:
  - client auth
  secretName: prometheus-cert
  issuerRef:
    name: ca-issuer
EOF

4.8.2.3 Deploy FEPCluster with MTLS support

Deploy FEPCluster with manual certificate management

Use the following yaml as an example to deploy a FEPCluster with Manual Certificate Management. MTLS related parameters are highlighted in Red.

apiVersion: fep.fujitsu.io/v2
kind: FEPCluster
metadata:
  name: mydb
  namespace: my-namespace
spec:
  fep:
    usePodName: true
patroni:

tls:

certificateName: mydb-patroni-cert

caName: cacert

postgres:

tls:

certificateName: mydb-fep-cert

caName: cacert

privateKeyPassword: mydb-fep-private-key-password
forceSsl: true podAntiAffinity: false mcSpec: limits: cpu: 500m memory: 700Mi requests: cpu: 200m memory: 512Mi customAnnotations: allDeployments: {} servicePort: 27500 image: image: 'quay.io/fujitsu/fujitsu-enterprise-postgres-18-server:ubi9-18-1.0' pullPolicy: IfNotPresent sysExtraLogging: false podDisruptionBudget: false instances: 3 syncMode: 'on' fepChildCrVal: customPgAudit: | # define pg audit custom params here to override defaults. # if log volume is not defined, log_directory should be # changed to '/database/userdata/data/log' [output] logger = 'auditlog' log_directory = '/database/log/audit' [rule] customPgHba: | # define pg_hba custom rules here to be merged with default rules. # TYPE DATABASE USER ADDRESS METHOD hostssl all all 0.0.0.0/0 cert
hostssl replication all 0.0.0.0/0 cert
customPgParams: >+ # define custom postgresql.conf parameters below to override defaults. # Current values are as per default FEP deployment shared_preload_libraries='pgx_datamasking,pgaudit,pg_prewarm' session_preload_libraries='pg_prewarm' max_prepared_transactions = 100 max_worker_processes = 30 max_connections = 100 work_mem = 1MB maintenance_work_mem = 12MB shared_buffers = 128MB effective_cache_size = 384MB checkpoint_completion_target = 0.8 # tcp parameters tcp_keepalives_idle = 30 tcp_keepalives_interval = 10 tcp_keepalives_count = 3 # logging parameters in default fep installation # if log volume is not defined, log_directory should be # changed to '/database/userdata/data/log' log_directory = '/database/log' log_filename = 'logfile-%a.log' log_file_mode = 0600 log_truncate_on_rotation = on log_rotation_age = 1d log_rotation_size = 0 log_checkpoints = on log_line_prefix = '%e %t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h' log_lock_waits = on log_autovacuum_min_duration = 60s logging_collector = on pgaudit.config_file='/opt/app-root/src/pgaudit-cfg/pgaudit.conf' log_replication_commands = on log_min_messages = WARNING log_destination = stderr # wal_archive parameters in default fep installation archive_mode = on archive_command = '/bin/true' wal_level = replica max_wal_senders = 12 wal_keep_segments = 64 storage: dataVol: size: 2Gi storageClass: nfs-client walVol: size: 1200Mi storageClass: nfs-client logVol: size: 1Gi storageClass: nfs-client sysUsers: pgAdminPassword: admin-password pgdb: mydb pgpassword: mydbpassword pguser: mydbuser pgrepluser: repluser pgreplpassword: repluserpwd pgRewindUser: rewinduser pgRewindPassword: rewinduserpwd pgAdminTls:
certificateName: mydb-postgres-cert

caName: cacert

sslMode: prefer


pgrepluserTls:

certificateName: mydb-repluser-cert

caName: cacert

sslMode: prefer


pgRewindUserTls:

certificateName: mydb-rewinduser-cert

caName: cacert

sslMode: prefer

tdepassphrase: tde-passphrase systemCertificates: key: |- -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA0DFkImha8CIJiVcwXbBPlL+/DmS9/ipRhQQHxfO5x7jSOnse IHdFd6+Qx2GX8KAiAhVykf6kfacwBYTATU1xDgwWTm82KVRPh+kZDIj2wPcJr14m mTP6I6a2mavUgDhezHc9F8/dchYj3cw81X0kU6xamqrKQYlxQH48NkI0qcwhO6sK AHF4eWfCr8Ot44xADIA1JcU2CS1RKSZEtURZ+30Py+j907Enjp1YR33ZKUHw30pU 9dpIneyfXBN/pT6cX3MetYwtgmpV/pHqY8pbxqGfoyRhgQDsSRCl4dtlecaZeZ4j uTOotcPkZELHP6eu8gaLtycG9lpbAMQl5w0r8QIDAQABAoIBACq213qPuoimExrQ fqXaNJmqNYK4fJqXCB6oUwf0F1u4ubkx5V532hLSPHwLs+a0lAWlbNozSoBVOu8G 64VwrA9bv3/cJVqZZ6/UzUTbHPU+Ogh24qhwF5QU8kXZEUI1To3YsPoftalgjX9G Ff0fLcLVC8nL3K9RiaDXxXbEYpWrYu39M3FCpAXAzV2PrNxsP9PKyNWHnBPc08z5 tFj45/bHn+j31AVVvgWtqz0pLks57hc4Q7yW/2RoRYq2md1KI709OLNwtkWEOVqb qnraorh2TwGnNaOB5oX5/lJvKtlq778fw96jGqykBr0+DKozj9rlr1OGgYOKDwlD nsZJPAECgYEA+Oqf/fxtPdsNGiaL2Z/heewvtaxjw/WoEVBFECb6/y4Ro7aux9nB 16FcVi79Cwfp0UTJ7cnZvYSmBk5GWEObEIAeo61lvm/QeltM5+usAPd5/TcHXLYe 92OnXmq7h3F4UXEkMayak8Lpu/TdmR5uOaL+m4aEu+XMY5tlxqDCnyECgYEA1h4X jCPi7Ja5CHK7a2Ud4TL2DNpIBE6GSK9iQ+0xFL6TsiK2Sfu6n8mx2sh+Jm0KHTiE /gWHdHQZSSWiuULfHoYEq3Rq8S6Av3GsGtRSpO03j7BE8C20Vpt0FnNTjZmdzf2/ YZxc5KuYLh9qeY7Y7ceOsWA8JckDgMHPYzyLAtECgYBALD0TPgDr8Y1vMIDdmlqH FF04eTk/TBYIYKltgJ81KqthibeFzp4q+W7UyUhzj5a4XQOySlfYhFpJReTc3JEd r+o2SH3ymuEkqmUpZZjyptrMbWN4g3t4TDjaHqo6QQbD+GdcZyNy9M1Np9N5pl7E fUEm14dg6d3H0Ehs7QVAAQKBgQDRUx3mLXc9oKRINBIyDerGLJILQqLBQxtYl81T ZuFizGWL8w+PCIAMkpxDrVpWqqcGpiiuRi2ElbPapOaOg2epaY/LJscd/j5z6uc8 W3JoNljpKoRa4fO578Pv5tM6TYHOzlF5Veoiy/a8sI3hRNuiqkM/+TsUHY5FJDRh aeDk4QKBgCOHIevvR+MWuwakzD6lNCbb8H6fvZ3WRAT8BYYz3wW9YfnV4J4uh/Bl moWYgIK2UpkrhA8scMUC790FoybQeParQ35x7Jl91bmTKkCqsX63fyqqYhx3SXRl JSktmH4E2cGmosZisjB7COKHR32w0J5JCgaGInQxjldbGrwhZQpn -----END RSA PRIVATE KEY----- crt: |- -----BEGIN CERTIFICATE----- MIID2DCCAsCgAwIBAgIQDfFYteD4kZj4Sko2iy1IJTANBgkqhkiG9w0BAQsFADBX MRgwFgYDVQQKEw9NeSBPcmdhbml6YXRpb24xCzAJBgNVBAsTAkNBMS4wLAYDVQQD EyVNeSBPcmdhbml6YXRpb24gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTIxMDQy MDAwMDQ1OVoXDTIxMDQyMDAxMDQ1OVowGDEWMBQGA1UEAwwNKi5jaGctcHRjLnBv ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAxZCJoWvAiCYlXMF2w T5S/vw5kvf4qUYUEB8Xzuce40jp7HiB3RXevkMdhl/CgIgIVcpH+pH2nMAWEwE1N cQ4MFk5vNilUT4fpGQyI9sD3Ca9eJpkz+iOmtpmr1IA4Xsx3PRfP3XIWI93MPNV9 JFOsWpqqykGJcUB+PDZCNKnMITurCgBxeHlnwq/DreOMQAyANSXFNgktUSkmRLVE Wft9D8vo/dOxJ46dWEd92SlB8N9KVPXaSJ3sn1wTf6U+nF9zHrWMLYJqVf6R6mPK W8ahn6MkYYEA7EkQpeHbZXnGmXmeI7kzqLXD5GRCxz+nrvIGi7cnBvZaWwDEJecN K/ECAwEAAaOB3jCB2zATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAA MIG1BgNVHREEga0wgaqCCWxvY2FsaG9zdIIbKi5jaGctcHRjLnBvZC5jbHVzdGVy LmxvY2FsghMqLm15ZGItaGVhZGxlc3Mtc3ZjghsqLm15ZGItaGVhZGxlc3Mtc3Zj LmNoZy1wdGOCHyoubXlkYi1oZWFkbGVzcy1zdmMuY2hnLXB0Yy5zdmOCLSoubXlk Yi1oZWFkbGVzcy1zdmMuY2hnLXB0Yy5zdmMuY2x1c3Rlci5sb2NhbDANBgkqhkiG 9w0BAQsFAAOCAQEALnhliDflu+BHp5conq4dXBwD/Ti2YR5TWQixM/0a6OD4KecZ MmaLl0T+OJJvA/j2IufZpc7dzEx5mZDkR2CRmoq10qZXqCRTrBZSXm6ARQWoYpeg 9c0l4f8roxrkMGUKVPTKUwAvbnNYhD2l6PlBPwMpkMUfqFaSEXMaPyQKhrtQxdpH WjuS54OP0lm0peYu/yiaD98LtrTXnb6jch84SKf6Vii4HAVQyMeJaW+dpkqcI2+V Q4fkwWYSJy8BNcmXCwvHDLDy+s4EXWvHafhusuUhcp4HyMb1A6hd5hJhgFSnEvLy kLA0L9LaScxee6V756Vt9TN1NGjwmwyQDOhnQQ== -----END CERTIFICATE----- cacrt: |- -----BEGIN CERTIFICATE----- MIIDXDCCAkSgAwIBAgIRAMPzF3BNFxT9HWE+NXlFQjQwDQYJKoZIhvcNAQELBQAw VzEYMBYGA1UEChMPTXkgT3JnYW5pemF0aW9uMQswCQYDVQQLEwJDQTEuMCwGA1UE AxMlTXkgT3JnYW5pemF0aW9uIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0yMTA0 MTkwNDQ0MjNaFw0zMTA0MTcwNDQ0MjNaMFcxGDAWBgNVBAoTD015IE9yZ2FuaXph dGlvbjELMAkGA1UECxMCQ0ExLjAsBgNVBAMTJU15IE9yZ2FuaXphdGlvbiBDZXJ0 aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQC5t6CS23Glk65YMw5e4i4xHldyxkCZS67w/6LWqeIlYKmFAaEl83WWy8MHUpOb 4mahtUafEzDEOX6+URf72J8m0voldQ5FYr1AyUOyX8U90wGFqhbEgKRqt7vZEwIe 2961fwqHh6917zI4xmt5W6ZJ5dBQVtkhzB+Pf7O6KBYjHoCnBBkfNVzsfZQ/1hnR 0UzimfAc7Ze+UNwhXJhinFRJ3YuR+xiOTpPkl1GXPhLgFSQhekz4KepcbQEQKejb jg0dum1oBYIXZTSSbiO9rNmfUVLB5DcV0vZbSrGxLjWLBt5U8N2xf2d1bvkQW+bw Kklf9OG26bAi27tujurzN3r3AgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNV HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAM0CN3n5C/KOT4uZ4ewwKK rHmANBPVM9u6MJBO8U62HcqLeoCuDFeU8zmUjLHjsQaPX64mJZlR7T5y52gEKO5A 0qsBz3pg/vJ5DJTv0698+1Q1hB9k3smQdksAim19FZqysB7J4zK/+8aJ/q2kIFvs Jk3ekwQdQ3xfggklBQVuf76gr1v0uYlPtfPffPlfcGZ06Im6mqbajenXoR1PxPB0 +zyCS8DkgPtDulplruwvXCFMYw9TPbzXKlt7tlsqRXogYLnxWJDzM1nOYCnD+rDm qxenV9Ir8RqZ0XSYuUyzRka5N4dhIhrzTAiNdeU5gzynXOz67u/Iefz1iK9ZcdE3 -----END CERTIFICATE-----

Deploy FEPCluster with automatic certificate management

Use the following yaml as an example to deploy a FEPCluster with Automatic Certificate Management. MTLS related parameters are highlighted in Red.

apiVersion: fep.fujitsu.io/v2
kind: FEPCluster
metadata:
  name: mydb
  namespace: my-namespace
spec:
  fep:
    usePodName: true
patroni:

tls:

certificateName: mydb-patroni-cert

postgres:

tls:

certificateName: mydb-fep-cert

forceSsl: true podAntiAffinity: false mcSpec: limits: cpu: 500m memory: 700Mi requests: cpu: 200m memory: 512Mi customAnnotations: allDeployments: {} servicePort: 27500 image: image: 'quay.io/fujitsu/fujitsu-enterprise-postgres-18-server:ubi9-18-1.0' pullPolicy: IfNotPresent sysExtraLogging: false podDisruptionBudget: false instances: '3' syncMode: 'on' fepChildCrVal: customPgAudit: | # define pg audit custom params here to override defaults. # if log volume is not defined, log_directory should be # changed to '/database/userdata/data/log' [output] logger = 'auditlog' log_directory = '/database/log/audit' [rule] customPgHba: | # define pg_hba custom rules here to be merged with default rules. # TYPE DATABASE USER ADDRESS METHOD hostssl all all 0.0.0.0/0 cert
hostssl replication all 0.0.0.0/0 cert customPgParams: >+ # define custom postgresql.conf parameters below to override defaults. # Current values are as per default FEP deployment shared_preload_libraries='pgx_datamasking,pgaudit,pg_prewarm' session_preload_libraries='pg_prewarm' max_prepared_transactions = 100 max_worker_processes = 30 max_connections = 100 work_mem = 1MB maintenance_work_mem = 12MB shared_buffers = 128MB effective_cache_size = 384MB checkpoint_completion_target = 0.8 # tcp parameters tcp_keepalives_idle = 30 tcp_keepalives_interval = 10 tcp_keepalives_count = 3 # logging parameters in default fep installation # if log volume is not defined, log_directory should be # changed to '/database/userdata/data/log' log_directory = '/database/log' log_filename = 'logfile-%a.log' log_file_mode = 0600 log_truncate_on_rotation = on log_rotation_age = 1d log_rotation_size = 0 log_checkpoints = on log_line_prefix = '%e %t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h' log_lock_waits = on log_autovacuum_min_duration = 60s logging_collector = on pgaudit.config_file='/opt/app-root/src/pgaudit-cfg/pgaudit.conf' log_replication_commands = on log_min_messages = WARNING log_destination = stderr # wal_archive parameters in default fep installation archive_mode = on archive_command = '/bin/true' wal_level = replica max_wal_senders = 12 wal_keep_segments = 64 storage: dataVol: size: 2Gi storageClass: nfs-client walVol: size: 1200Mi storageClass: nfs-client logVol: size: 1Gi storageClass: nfs-client sysUsers: pgAdminPassword: admin-password pgdb: mydb pgpassword: mydbpassword pguser: mydbuser pgrepluser: repluser pgreplpassword: repluserpwd pgRewindUser: rewinduser pgRewindPassword: rewinduserpwd pgAdminTls: certificateName: mydb-postgres-cert
sslMode: verify-full

pgrepluserTls:
certificateName: mydb-repluser-cert

sslMode: verify-full


pgRewindUserTls:

certificateName: mydb-rewinduser-cert

sslMode: verify-full

tdepassphrase: tde-passphrase systemCertificates: key: |- -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA0DFkImha8CIJiVcwXbBPlL+/DmS9/ipRhQQHxfO5x7jSOnse IHdFd6+Qx2GX8KAiAhVykf6kfacwBYTATU1xDgwWTm82KVRPh+kZDIj2wPcJr14m mTP6I6a2mavUgDhezHc9F8/dchYj3cw81X0kU6xamqrKQYlxQH48NkI0qcwhO6sK AHF4eWfCr8Ot44xADIA1JcU2CS1RKSZEtURZ+30Py+j907Enjp1YR33ZKUHw30pU 9dpIneyfXBN/pT6cX3MetYwtgmpV/pHqY8pbxqGfoyRhgQDsSRCl4dtlecaZeZ4j uTOotcPkZELHP6eu8gaLtycG9lpbAMQl5w0r8QIDAQABAoIBACq213qPuoimExrQ fqXaNJmqNYK4fJqXCB6oUwf0F1u4ubkx5V532hLSPHwLs+a0lAWlbNozSoBVOu8G 64VwrA9bv3/cJVqZZ6/UzUTbHPU+Ogh24qhwF5QU8kXZEUI1To3YsPoftalgjX9G Ff0fLcLVC8nL3K9RiaDXxXbEYpWrYu39M3FCpAXAzV2PrNxsP9PKyNWHnBPc08z5 tFj45/bHn+j31AVVvgWtqz0pLks57hc4Q7yW/2RoRYq2md1KI709OLNwtkWEOVqb qnraorh2TwGnNaOB5oX5/lJvKtlq778fw96jGqykBr0+DKozj9rlr1OGgYOKDwlD nsZJPAECgYEA+Oqf/fxtPdsNGiaL2Z/heewvtaxjw/WoEVBFECb6/y4Ro7aux9nB 16FcVi79Cwfp0UTJ7cnZvYSmBk5GWEObEIAeo61lvm/QeltM5+usAPd5/TcHXLYe 92OnXmq7h3F4UXEkMayak8Lpu/TdmR5uOaL+m4aEu+XMY5tlxqDCnyECgYEA1h4X jCPi7Ja5CHK7a2Ud4TL2DNpIBE6GSK9iQ+0xFL6TsiK2Sfu6n8mx2sh+Jm0KHTiE /gWHdHQZSSWiuULfHoYEq3Rq8S6Av3GsGtRSpO03j7BE8C20Vpt0FnNTjZmdzf2/ YZxc5KuYLh9qeY7Y7ceOsWA8JckDgMHPYzyLAtECgYBALD0TPgDr8Y1vMIDdmlqH FF04eTk/TBYIYKltgJ81KqthibeFzp4q+W7UyUhzj5a4XQOySlfYhFpJReTc3JEd r+o2SH3ymuEkqmUpZZjyptrMbWN4g3t4TDjaHqo6QQbD+GdcZyNy9M1Np9N5pl7E fUEm14dg6d3H0Ehs7QVAAQKBgQDRUx3mLXc9oKRINBIyDerGLJILQqLBQxtYl81T ZuFizGWL8w+PCIAMkpxDrVpWqqcGpiiuRi2ElbPapOaOg2epaY/LJscd/j5z6uc8 W3JoNljpKoRa4fO578Pv5tM6TYHOzlF5Veoiy/a8sI3hRNuiqkM/+TsUHY5FJDRh aeDk4QKBgCOHIevvR+MWuwakzD6lNCbb8H6fvZ3WRAT8BYYz3wW9YfnV4J4uh/Bl moWYgIK2UpkrhA8scMUC790FoybQeParQ35x7Jl91bmTKkCqsX63fyqqYhx3SXRl JSktmH4E2cGmosZisjB7COKHR32w0J5JCgaGInQxjldbGrwhZQpn -----END RSA PRIVATE KEY----- crt: |- -----BEGIN CERTIFICATE----- MIID2DCCAsCgAwIBAgIQDfFYteD4kZj4Sko2iy1IJTANBgkqhkiG9w0BAQsFADBX MRgwFgYDVQQKEw9NeSBPcmdhbml6YXRpb24xCzAJBgNVBAsTAkNBMS4wLAYDVQQD EyVNeSBPcmdhbml6YXRpb24gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTIxMDQy MDAwMDQ1OVoXDTIxMDQyMDAxMDQ1OVowGDEWMBQGA1UEAwwNKi5jaGctcHRjLnBv ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAxZCJoWvAiCYlXMF2w T5S/vw5kvf4qUYUEB8Xzuce40jp7HiB3RXevkMdhl/CgIgIVcpH+pH2nMAWEwE1N cQ4MFk5vNilUT4fpGQyI9sD3Ca9eJpkz+iOmtpmr1IA4Xsx3PRfP3XIWI93MPNV9 JFOsWpqqykGJcUB+PDZCNKnMITurCgBxeHlnwq/DreOMQAyANSXFNgktUSkmRLVE Wft9D8vo/dOxJ46dWEd92SlB8N9KVPXaSJ3sn1wTf6U+nF9zHrWMLYJqVf6R6mPK W8ahn6MkYYEA7EkQpeHbZXnGmXmeI7kzqLXD5GRCxz+nrvIGi7cnBvZaWwDEJecN K/ECAwEAAaOB3jCB2zATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAA MIG1BgNVHREEga0wgaqCCWxvY2FsaG9zdIIbKi5jaGctcHRjLnBvZC5jbHVzdGVy LmxvY2FsghMqLm15ZGItaGVhZGxlc3Mtc3ZjghsqLm15ZGItaGVhZGxlc3Mtc3Zj LmNoZy1wdGOCHyoubXlkYi1oZWFkbGVzcy1zdmMuY2hnLXB0Yy5zdmOCLSoubXlk Yi1oZWFkbGVzcy1zdmMuY2hnLXB0Yy5zdmMuY2x1c3Rlci5sb2NhbDANBgkqhkiG 9w0BAQsFAAOCAQEALnhliDflu+BHp5conq4dXBwD/Ti2YR5TWQixM/0a6OD4KecZ MmaLl0T+OJJvA/j2IufZpc7dzEx5mZDkR2CRmoq10qZXqCRTrBZSXm6ARQWoYpeg 9c0l4f8roxrkMGUKVPTKUwAvbnNYhD2l6PlBPwMpkMUfqFaSEXMaPyQKhrtQxdpH WjuS54OP0lm0peYu/yiaD98LtrTXnb6jch84SKf6Vii4HAVQyMeJaW+dpkqcI2+V Q4fkwWYSJy8BNcmXCwvHDLDy+s4EXWvHafhusuUhcp4HyMb1A6hd5hJhgFSnEvLy kLA0L9LaScxee6V756Vt9TN1NGjwmwyQDOhnQQ== -----END CERTIFICATE----- cacrt: |- -----BEGIN CERTIFICATE----- MIIDXDCCAkSgAwIBAgIRAMPzF3BNFxT9HWE+NXlFQjQwDQYJKoZIhvcNAQELBQAw VzEYMBYGA1UEChMPTXkgT3JnYW5pemF0aW9uMQswCQYDVQQLEwJDQTEuMCwGA1UE AxMlTXkgT3JnYW5pemF0aW9uIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0yMTA0 MTkwNDQ0MjNaFw0zMTA0MTcwNDQ0MjNaMFcxGDAWBgNVBAoTD015IE9yZ2FuaXph dGlvbjELMAkGA1UECxMCQ0ExLjAsBgNVBAMTJU15IE9yZ2FuaXphdGlvbiBDZXJ0 aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQC5t6CS23Glk65YMw5e4i4xHldyxkCZS67w/6LWqeIlYKmFAaEl83WWy8MHUpOb 4mahtUafEzDEOX6+URf72J8m0voldQ5FYr1AyUOyX8U90wGFqhbEgKRqt7vZEwIe 2961fwqHh6917zI4xmt5W6ZJ5dBQVtkhzB+Pf7O6KBYjHoCnBBkfNVzsfZQ/1hnR 0UzimfAc7Ze+UNwhXJhinFRJ3YuR+xiOTpPkl1GXPhLgFSQhekz4KepcbQEQKejb jg0dum1oBYIXZTSSbiO9rNmfUVLB5DcV0vZbSrGxLjWLBt5U8N2xf2d1bvkQW+bw Kklf9OG26bAi27tujurzN3r3AgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNV HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAM0CN3n5C/KOT4uZ4ewwKK rHmANBPVM9u6MJBO8U62HcqLeoCuDFeU8zmUjLHjsQaPX64mJZlR7T5y52gEKO5A 0qsBz3pg/vJ5DJTv0698+1Q1hB9k3smQdksAim19FZqysB7J4zK/+8aJ/q2kIFvs Jk3ekwQdQ3xfggklBQVuf76gr1v0uYlPtfPffPlfcGZ06Im6mqbajenXoR1PxPB0 +zyCS8DkgPtDulplruwvXCFMYw9TPbzXKlt7tlsqRXogYLnxWJDzM1nOYCnD+rDm qxenV9Ir8RqZ0XSYuUyzRka5N4dhIhrzTAiNdeU5gzynXOz67u/Iefz1iK9ZcdE3 -----END CERTIFICATE-----

4.8.2.4 Configurable Parameters

To enable MTLS, make changes to the following parameters.

Key

Value

Details

spec.fep.usePodName

True

For MTLS, this key must be defined and set to true. For TLS connection without MTLS, it can be omitted. However, it is recommended to set this to true as well.

spec.fep.patroni.tls.certificateName

<secret-name>

Name of Kubernetes secret that contains the certificate in tls.crt and private key in tls.key for Patroni REST API. For MTLS Patroni REST API communication, this key must be defined. The private key cannot be password protected. When using cert-manager, the secret also contains the CA bundle in ca.crt.

spec.fep.patroni.tls.caName

<configmap-name>

Name of Kubernetes configmap that contains the CA bundle. If using cert-manager, the ca.crt is already included in the secret above. In this situation, this key can be omitted.

spec.fep.postgres.tls.certificateName

<secret-name>

Name of Kubernetes secret that contains the certificate in tls.crt and private key in tls.key for Postgres server. For MTLS Postgres communication, this key must be defined. The private key can be password protected. When using cert-manager, the secret also contains the CA bundle in ca.crt.

spec.fep.postgres.tls.caName

<configmap-name>

Name of Kubernetes configmap that contains the CA bundle. If using cert-manager, the ca.crt is already included in the secret above. In this situation, this key can be omitted.

spec.fep.postgres.tls.privateKeyPassword

<secret-name>

Name of Kubernetes secret that contains the password for the private key for Postgres Server.

spec.fepChildCrVal.sysUsers.pgAdminTls.certificateName

<secret-name>

Name of Kubernetes secret that contains the certificate in tls.crt and private key in tls.key for "postgres" user. For MTLS Postgres communication, this key must be defined. The private key cannot be password protected. When using cert-manager, the secret also contains the CA bundle in ca.crt.

spec.fepChildCrVal.sysUsers.pgAdminTls.caName

<configmap-name>

Name of Kubernetes configmap that contains the CA bundle. If using cert-manager, the ca.crt is already included in the secret above. In this situation, this key can be omitted.

spec.fepChildCrVal.sysUsers.pgAdminTls.sslMode

verify-full

For MTLS, this value must be set to verify-full. If only TLS is required, this can be set to verify-ca or prefer.

spec.fepChildCrVal.sysUsers.pgrepluserTls.certificateName

<secret-name>

Name of Kubernetes secret that contains the certificate in tls.crt and private key in tls.key for "repluser" user. For MTLS Postgres communication, this key must be defined. The private key cannot be password protected. When using cert-manager, the secret also contains the CA bundle in ca.crt.

spec.fepChildCrVal.sysUsers.pgrepluserTls.caName

<configmap-name>

Name of Kubernetes configmap that contains the CA bundle. If using cert-manager, the ca.crt is already included in the secret above. In this situation, this key can be omitted.

spec.fepChildCrVal.sysUsers.pgrepluserTls.sslMode

verify-full

For MTLS, this value must be set to verify-full. If only TLS is required, this can be set to verify-ca or prefer.

spec.fepChildCrVal.sysUsers.pgRewindUserTls.certificateName

<secret-name>

Name of Kubernetes secret that contains the certificate in tls.crt and private key in tls.key for "rewinduser" user. For MTLS Postgres communication, this key must be defined. The private key cannot be password protected. When using cert-manager, the secret also contains the CA bundle in ca.crt.

spec.fepChildCrVal.sysUsers.pgRewindUserTls.caName

<configmap-name>

Name of Kubernetes configmap that contains the CA bundle. If using cert-manager, the ca.crt is already included in the secret above. In this situation, this key can be omitted.

spec.fepChildCrVal.sysUsers.pgRewindUserTls.sslMode

verify-full

For MTLS, this value must be set to verify-full. If only TLS is required, this can be set to verify-ca or prefer.


It is also required to customize pg_hba.conf to perform MTLS. Below are two possible settings.

spec.fep.customPgHba

hostssl all all 0.0.0.0/0 cert
hostssl replication all 0.0.0.0/0 cert


The above setting will force FEP server to perform certification authentication. At the same time verify the authenticity of client certificate.

spec.fep.customPgHba

hostssl all all 0.0.0.0/0 md5 clientcert=verify-full
hostssl replication repluser 0.0.0.0/0 md5 clientcert=verify-full


The above setting will foce FEP server to perform md5 authentication as well as verifying the authenticity of client certificate.