Reputation: 1205
I am trying to connect to my PostgreSQL server but psql is complaining that I don't have a valid client certificate. Here is how I create my certificates:
Self-signed server certificate:
openssl req -new -text -nodes -keyout server.key -out server.csr -subj '/C=US/ST=California/L=Fremont/O=Example/OU=CoreDev/CN=192.168.0.100' # CN is the server's IP address
openssl req -x509 -text -in server.csr -key server.key -out server.crt
cp server.crt root.crt
rm server.csr
chmod og-rwx server.key
Client certificate:
openssl req -new -nodes -keyout client.key -out client.csr -subj '/C=US/ST=California/L=Fremont/O=Example/OU=CoreDev/CN=postgres' # postgres is the database user name
openssl x509 -req -CAcreateserial -in client.csr -CA root.crt -CAkey server.key -out client.crt
rm client.csr
After copying the necessary files (client.crt, client.key, root.crt) onto the client machine and changing permission (i.e., chmod og-rwx client.key), I do the following:
psql 'host=192.168.0.100 port=5432 dbname=postgres user=postgres sslmode=verify-full sslcert=client.crt sslkey=client.key sslrootcert=root.crt'
and then I get:
psql: FATAL: connection requires a valid client certificate
Am I doing the client certificate signing process wrong?
I tried:
openssl verify -CAfile root.crt -purpose sslclient client.crt
and I get:
client.crt: OK
Using Wireshark, here is the capture I got for the communication between the client (192.168.0.103) and the server (192.168.0.100):
Why does this happen?
It seems like the server does not send the CertificateRequest message to the client.. as you can see below:
but this is weird because in pg_hba.conf, I have:
hostssl all postgres 192.168.0.103/32 cert
Upvotes: 26
Views: 40831
Reputation: 305
Just adding another answer here for someone else. I was getting this same error when connecting from a jdbc using the org.postgresql.driver. The issue is that the format for the key I was passing for the sslkey parameter was a pem format. This link explains it.
https://jdbc.postgresql.org/documentation/head/connect.html#:~:text=keyfile.-,sslkey,-%3D%20String
Note: The key file must be in PKCS-12 or in PKCS-8 DER format. A PEM key can be converted to DER format using the openssl command:
openssl pkcs8 -topk8 -inform PEM -in postgresql.key -outform DER -out postgresql.pk8 -v1 PBE-MD5-DES
Upvotes: 2
Reputation: 325141
In this situation I tend to pull out Wireshark and snoop the SSL negotiation to make sure the client certificate is really being offered by the client.
I suggest using openssl to verify the client->root signing link, too.
openssl verify -CAfile root.crt -purpose sslclient client.crt
Edit: It's necessary to specify clientcert=1
even when cert
authentication is chosen. Yes, that's weird.
Upvotes: 13