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.
Overview of Procedures
The procedures to enable MTLS communication are listed below:
Create a self signed certificate as CA
Create Configmap to store CA certificate
Create a password for protecting FEP Server private key (optional)
Create FEP Server private key
Create FEP Server certificate signing request
Create FEP Server certificate signed by CA
Create TLS Secret to store FEP Server certificate and key
Create private key for Patroni
Create certificate signing request for Patroni
Create certificate signed by CA for Patroni
Create TLS secret to store Patroni certificate and key
Create private key for "postgres" user client certificate
Create certificate signing request for "postgres" user client certificate
Create client certificate for "postgres" user
Create TLS secret to store "postgres" certificate and key
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
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
oc create configmap cacert --from-file=ca.crt=myca.pem -n my-namespaceoc create secret generic mydb-fep-private-key-password --from-literal=keypassword=abcdefghijk -n my-namespaceCreating a Server Certificate
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
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.
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
oc create secret generic mydb-fep-cert --from-file=tls.crt=fep.pem --from-file=tls.key=fep.key -n my-namespaceAt 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)
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.
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
oc create secret tls mydb-patroni-cert --cert=patroni.pem --key=patroni.key -n my-namespaceCreating a User 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)
openssl req -new -key postgres.key -out postgres.csr -subj "/CN=postgres"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
oc create secret tls mydb-postgres-cert --cert=postgres.pem --key=postgres.key -n my-namespaceThere 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.
oc create namespace cert-manager
oc apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.0/cert-manager.yaml
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
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.
cat << EOF | oc apply -f -
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: ca-issuer
namespace: my-namespace
spec:
ca:
secretName: cacert
EOF
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
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
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
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
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
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
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
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
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
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-----
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 |
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 |
The above setting will foce FEP server to perform md5 authentication as well as verifying the authenticity of client certificate.