Configuring TLS for Postgres for Kubernetes 4.0 on TKG 2.5 failed with "SSL error: sslv3 alert unsupported certificate"
search cancel

Configuring TLS for Postgres for Kubernetes 4.0 on TKG 2.5 failed with "SSL error: sslv3 alert unsupported certificate"

book

Article ID: 398910

calendar_today

Updated On: 05-29-2025

Products

VMware Tanzu SQL VMware Tanzu Data Suite

Issue/Introduction

The customer was trying to deploy Tanzu Postgres for Kubernetes 4.0 on their TKG 2.5, however, with HA and TLS configured. while following Configure TLS <Creating a TLS Secret Manually>, however it reported the following error: `SSL error: sslv3 alert unsupported certificate`

[pod/<podname>/pg-container] 2025-05-23 07:07:41,408 WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=0, status=None)) after connection broken by 'SSLError(1, '[SSL: SHUTDOWN_WHILE_IN_INIT] shutdown while in init (_ssl.c:2578)')': /api/v1/namespaces/postgresql/pods/<podname>
[pod/<podname>/pg-container] 2025-05-23 07:07:41,428 INFO: running post_bootstrap
[pod/<podname>/pg-container] 2025-05-23 07:07:41,428 INFO: establishing a new patroni heartbeat connection to postgres
[pod/<podname>/pg-container] 2025-05-23 07:07:41,436 ERROR: post_bootstrap
[pod/<podname>/pg-container] Traceback (most recent call last):
[pod/<podname>/pg-container]   File "/usr/local/lib/python3.10/dist-packages/patroni/postgresql/bootstrap.py", line 429, in post_bootstrap
[pod/<podname>/pg-container]     self.create_or_update_role(superuser['username'], superuser['password'], ['SUPERUSER'])
[pod/<podname>/pg-container]   File "/usr/local/lib/python3.10/dist-packages/patroni/postgresql/bootstrap.py", line 409, in create_or_update_role
[pod/<podname>/pg-container]     END;$$""".format(quote_literal(name), quote_ident(name, self._postgresql.connection()), ' '.join(options))
[pod/<podname>/pg-container]   File "/usr/local/lib/python3.10/dist-packages/patroni/postgresql/__init__.py", line 367, in connection
[pod/<podname>/pg-container]     return self._connection.get()
[pod/<podname>/pg-container]   File "/usr/local/lib/python3.10/dist-packages/patroni/postgresql/connection.py", line 55, in get
[pod/<podname>/pg-container]     self._connection = psycopg.connect(**self._conn_kwargs)
[pod/<podname>/pg-container]   File "/usr/local/lib/python3.10/dist-packages/patroni/psycopg.py", line 123, in connect
[pod/<podname>/pg-container]     ret = _connect(*args, **kwargs)
[pod/<podname>/pg-container]   File "/usr/lib/python3/dist-packages/psycopg2/__init__.py", line 122, in connect
[pod/<podname>/pg-container]     conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
[pod/<podname>/pg-container] psycopg2.OperationalError: connection to server at "localhost" (::1), port 5432 failed: SSL error: sslv3 alert unsupported certificate 

Cause

It turns out to be server.crt contains only TLS web server auth as for ExtendedKey usage which resulted in such error:

% openssl x509 -in server.crt -text -noout
...
            X509v3 Extended Key Usage:
                TLS Web Server Authentication

 

Resolution

Based on testing, the below 2 scenarios would work:

1. Exclude such Extended Key Usage

2. Include both Server and Client Authentication:

Including both serverAuth and clientAuth in a single certificate is a common practice in scenarios such as:

  • PostgreSQL with mutual TLS (mTLS)
  • Patroni clusters (where nodes function as both clients and servers)
  • TLS-based peer replication or inter-service API communication

Such certificate should look like:

            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication

 

If OpenSSL was used for certification management, we can modify this via a OpenSSL configuration file, which was also mentioned in step2 of KB398523, for example, to include both server and client Auth, we can generate the OpenSSL configuration file like the following:

% cat > openssl-san.cnf << EOF
[req]
default_bits       = 2048
prompt             = no
default_md         = sha512
distinguished_name = dn
req_extensions     = req_ext

[dn]
CN = *.postgres-sample-agent.postgres-test.svc.cluster.local

[req_ext]
subjectAltName = @alt_names
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth,clientAuth

[alt_names]
DNS.1 = *.postgres-sample-agent.postgres-test.svc.cluster.local
EOF
%

and sign the certificate using such cnf(assuming that server.csr and root.crt has been prepared), for example:

% openssl x509 -req -in server.csr -CA root.crt -CAkey root.key -CAcreateserial -out server.crt -days 365 -sha512 -extensions req_ext -extfile openssl-san.cnf

 

After that, delete the original secret and recreate it following step2 of <Creating a TLS Secret Manually>

% kubectl delete secret <some-tls-secret> -n <postgres-instance-namespace>
% kubectl create secret generic <some-tls-secret> \ 
     --type kubernetes.io/tls \
     --from-file=ca.crt=/path/to/ca.crt \
     --from-file=tls.crt=/path/to/tls.crt \
     --from-file=tls.key=/path/to/tls.key \
     --namespace <postgres-instance-namespace> 

and recreate the pod as well:

kubectl delete -f postgres.yaml
kubectl apply -f postgres.yaml