DNS names in certificate terminate with an dot - violates standard
I installed the operator and created a cluster named 'master' with basically default configuration:
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
name: master
namespace: persistence
spec:
config:
postgresVersion: 16
instances:
- name: instance1
replicas: 2
...
When I do a port-forward to localhost:5432 and try to connect with a Go application I get the following error
Error connecting to database: tls: failed to parse certificate from server: x509: SAN dNSName is malformed
I took a look in the the secret master-server-cert and then the tls.crt and found this:
X509v3 Subject Alternative Name:
DNS:master-primary.persistence.svc.cluster.local., DNS:master-primary.persistence.svc, DNS:master-primary.persistence, DNS:master-primary, DNS:master-replicas.persistence.svc.cluster.local., DNS:master-replicas.persistence.svc, DNS:master-replicas.persistence, DNS:master-replicas
All the names that terminate with a dot are illegal according to X.509 standard. It looks like the go client library does not like the certificate. Is this a bug or do I see this wrong?
Additionally: Is there an easy way to add hosts like "localhost" or "db.example.com" (for a TCPRoute) to the certificate?
Fun fact: I am able to access the database remotely (either port-forward or TCPRoute) from the Database-Client in Golang which is Java-based. Obviously Java is more relaxed than Go regarding the certificate.
I found a workaround by creating a custom certificate like (my database is called master)
# Create key and certificate for our CA
openssl genrsa -out ca.key 2048
# Create CSR data with our custom domain names, including the external ones
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt \
-subj "/CN=PGO-Custom-CA"
cat <<EOF > csr.conf
[req]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
[dn]
CN = master-primary.persistence.svc.cluster.local
[req_ext]
subjectAltName = @alt_names
[alt_names]
DNS.1 = db.example.com
DNS.2 = master-primary.persistence.svc.cluster.local
DNS.3 = master-primary.persistence.svc
DNS.4 = master-primary.persistence
DNS.5 = master-primary
DNS.6 = master-replicas.persistence.svc.cluster.local
DNS.7 = master-replicas.persistence.svc
DNS.8 = master-replicas.persistence
DNS.9 = master-replicas
DNS.10 = localhost
EOF
# Create key for the certificate
openssl genrsa -out server.key 2048
# Create CSR
openssl req -new -key server.key -out server.csr -config csr.conf
# Sign our CSR with the CA
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 365 -sha256 -extfile csr.conf -extensions req_ext
# Create a secret in Kubernetes with ca.crt, tls.key and tls.crt
kubectl -n persistence create secret generic master-custom-cert --from-file=ca.crt --from-file=tls.key=server.key --from-file=tls.crt=server.crt
The I add this configuration to the PostgresCluster
spec:
customTLSSecret:
name: master-custom-cert
customReplicationTLSSecret:
name: master-custom-cert
I know, the replication secret should be a dedicated one, but I was lazy for now
Now I can connect to the server with sslmode=require. sslmode=verify-full works with a local copy of ca.crt.
This is likely related to https://github.com/golang/go/issues/75828
Thanks @pat-s! This indeed due to the Go issue you reference (https://github.com/golang/go/issues/75828).
Fortunately it looks like this issue is going to be addressed in the next minor releases of Go v1.24 and v1.25, which per this comment should be released soon.
So we're hoping that patch lands soon to avoid any further issues with the PGO-generated certs (such as the issue described in this thread).
Wouldn't it make more sense to remove the SAN entries with trailing dots from the generated certificate?