Issuing a new client certificate
kubectl cnp certificate --help
This command create a new Kubernetes secret containing the crypto-material
needed to configure TLS with Certificate authentication access for an application to
connect to the PostgreSQL cluster.
Usage:
kubectl cnp certificate [secretName] [flags]
Flags:
--cnp-cluster string The name of the PostgreSQL cluster
--cnp-user string The name of the PostgreSQL user
--dry-run If specified the secret is not created
-h, --help help for certificate
-o, --output string Output format. One of json|yaml
A real life example
apiVersion: postgresql.k8s.enterprisedb.io/v1
kind: Cluster
metadata:
name: cluster-example
spec:
instances: 3
storage:
size: 1Gi
bootstrap:
initdb:
owner: appuser
postgresql:
pg_hba:
- hostssl all all all cert
Step 1: issue a new certificate for app user
Note that this feature is available for any custom user you might want to configure in the cluster.
kubectl cnp certificate cluster-appuser --cnp-cluster cluster-example --cnp-user appuser
secret/cluster-appuser created
Step 2: fetch the new TLS client certificate
kubectl get secret cluster-appuser
Output:
NAME TYPE DATA AGE
cluster-cert kubernetes.io/tls 2 73s
kubectl get secret cluster-appuser -o json | jq -r '.data | map(@base64d) | .[]'
-----BEGIN CERTIFICATE-----
MIIBbTCCARSgAwIBAgIRALeyJdCG4GfoVVdFydd5sgMwCgYIKoZIzj0EAwIwLDEQ
MA4GA1UECxMHZGVmYXVsdDEYMBYGA1UEAxMPcG9zdGdyZXNxbC1jZXJ0MB4XDTIx
MDMwMzEwMzEwOFoXDTIyMDMwMzEwMzEwOFowDjEMMAoGA1UEAxMDYXBwMFkwEwYH
KoZIzj0CAQYIKoZIzj0DAQcDQgAEX/mnSV57RH35CRxRxp/FZddTBEMRh2OqSGp0
loRTiEywBzyqe02MbRwLiigzPHwaW4o+7anLgNCo96J/Oi7ZMqM1MDMwDgYDVR0P
AQH/BAQDAgOIMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwCgYI
KoZIzj0EAwIDRwAwRAIgcF9TZetuD0MDlSyQUaauYbrfYRDWk4kyuFAct7DKT/sC
ICgniN49e7qyDaBZ18+1V8N1EloqWM1CQupI1Fo6eXWv
-----END CERTIFICATE-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIHJFrapxgT6w/CXVY0vZR/elT4gNXL00vnBlRYtU7LigoAoGCCqGSM49
AwEHoUQDQgAEX/mnSV57RH35CRxRxp/FZddTBEMRh2OqSGp0loRTiEywBzyqe02M
bRwLiigzPHwaW4o+7anLgNCo96J/Oi7ZMg==
-----END EC PRIVATE KEY----
kubectl get secret cluster-appuser -o jsonpath="{.data['tls\.crt']}" | base64 -d | openssl x509 -text -noout | head -n 11
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
5d:e1:72:8a:39:9f:ce:51:19:9d:21:ff:1e:4b:24:5d
Signature Algorithm: ecdsa-with-SHA256
Issuer: OU = default, CN = cluster-example
Validity
Not Before: Mar 22 10:22:14 2021 GMT
Not After : Mar 22 10:22:14 2022 GMT
Subject: CN = appuser
Step 3: connect to a Postgres cluster using a TLS certificate
$ cat > cert-test.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: cert-test
spec:
replicas: 1
selector:
matchLabels:
app: webtest
template:
metadata:
labels:
app: webtest
spec:
containers:
- image: leonardoce/webtest:1.0.0
name: cert-test
volumeMounts:
- name: secret-volume-root-ca
mountPath: /etc/secrets/ca
- name: secret-volume-appuser
mountPath: /etc/secrets/appuser
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
value: >
sslkey=/etc/secrets/appuser/tls.key
sslcert=/etc/secrets/appuser/tls.crt
sslrootcert=/etc/secrets/ca/ca.crt
host=cluster-example-rw.default.svc
dbname=app
user=appuser
sslmode=verify-full
- name: SQL_QUERY
value: SELECT 1
readinessProbe:
httpGet:
port: 8080
path: /tx
volumes:
- name: secret-volume-root-ca
secret:
secretName: cluster-example-ca
defaultMode: 0600
- name: secret-volume-appuser
secret:
secretName: cluster-appuser
defaultMode: 0600
This Pod will mount secrets managed by the EDB Postgres for Kubernetes operator that contain the TLS client certificate, the TLS client certificate private key and the TLS Certification Authority certificate. They will be used to create the default resources that psql (and other libpq based applications like pgbench) requires to establish a TLS encrypted connection to the Postgres database.
The content of the above files is gathered from the secrets that were previously created by using the “cnp” plugin for kubectl.
kubectl create -f cert-test.yaml
deployment.apps/cert-test created
kubectl get pods
NAME READY STATUS RESTARTS AGE
cert-test-6dbcdbdcfd-c2l5l 1/1 Running 0 2m19s
cluster-example-1 1/1 Running 0 4m38s
cluster-example-2 1/1 Running 0 4m24s
cluster-example-3 1/1 Running 0 4m5s
kubectl exec -it cert-test-6dbcdbdcfd-c2l5l -- bash -c "psql 'sslkey=/etc/secrets/appuser/tls.key sslcert=/etc/secrets/appuser/tls.crt sslrootcert=/etc/secrets/ca/ca.crt host=cluster-example-rw.default.svc dbname=app user=appuser sslmode=verify-full' -c 'select version();'"
version
--------------------------------------------------------------------------------------------------------
PostgreSQL 13.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.3.1 20191121 (Red Hat 8.3.1-5), 64-bit
(1 row)
Additional information about the sslmode option can be found in the official PostgreSQL documentation.