PostgreSQL SSL doesn't work in cmd and java - postgresql

Please help with the following problem ...
OS - Windows.
I want to configure SSL on Postgresql 12.
Then my Java application will add entries to the database, delete, etc.
I created certificates: CA, server, client.
CA and server are located in the directory C:\Program Files\PostgreSQL\12\data
The client is located in C:\Users\User\AppData\postgresql
Then I added CA certificate to trusted in Windows.
Configs:
pg_hba:
hostnossl all all 0.0.0.0/0 reject
hostssl all all 0.0.0.0/0 cert clientcert=1
postgresql.conf:
ssl = on
ssl_ca_file = 'root.crt'
I can connect server throw pgAdmin with my certificates, but there are some errors in cmd (and java)
Thant's what I tried to do in cmd
psql.exe -U postgres -h 127.0.0.1
Result:
SSL: certificate verify failed
FATAL: pg_hba.conf rejects connection for host "127.0.0.1", user "postgres", database "prod", SSL off
Logs:
tlsv1 alert unknown ca
FATAL: pg_hba.conf rejects connection for host "127.0.0.1", user "postgres", database "prod", SSL off
Please, tell me what's can be wrong and how can I fix it...
Also I did not find information, how to transfer my certificates to the database from Java application. Maybe, anybody can help me with that problem))
Thanks!

use this in your connection string and it will work:
ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory

Then I added CA certificate to trusted in Windows.
psql does not integrate with the Windows certificate manager. The CA to be used by the client needs to go in %APPDATA%\postgresql\root.crt, or if elsewhere its location must be specified by a connection parameter (sslrootcert) or environment variable (PGSSLROOTCERT). These must be files, I don't think there is way to say "go get it from the cert manager".
I think jdbc is the same way, it does not integrate with the Windows cert manager either, for how to specify the locations see https://jdbc.postgresql.org/documentation/head/ssl-client.html
SSL: certificate verify failed FATAL: pg_hba.conf rejects connection for host "127.0.0.1", user "postgres", database "prod", SSL off
Maybe you already know this, but first it tried using SSL and failed to verify the cert (it does not make it clear which side failed, the client cert or the server cert), then it tried to fall back to no SSL and got rejected by the pg_hba. If you had set the client's sslmode to "require" or higher, it would not have tried to fall back to the no SSL, it would have stopped at the first error.

Related

PostgreSQL: Secure LDAP (LDAPS) to AD with LDAPTLS and LDAPSCHEME not working

I am trying to establish secure LDAP (LDAPS) connection for postgresql.
Currently, LDAP authentication method is established and working.
dockerized PostgreSQL v.14
LDAP connection to Active Directory. AD is setup by IT dept
I tried several options like LDAPTLS and LDAPSCHEME but nothing working.
LDAPTLS:
modified pg_hba.conf file by adding following rule
host all all 0.0.0.0/0 ldap ldapserver=test.ldapserver.com ldapport=389 ldaptls=1 ldapbasedn="DC=test,DC=ldapserver,DC=com" ldapbinddn="CN=test-user,OU=dept,DC=test,DC=ldapserver,DC=com" ldapbindpasswd="ldappassword" ldapsearchfilter="(&(memberOf=CN=subgroup,OU=dept,OU=special,DC=test,DC=ldapserver,DC=com)(cn=$username))"
IT dept provided only root-ca and sub-ca certificates. Server.key and server.crt not provided.
adding the root-ca cert and modified the postgresql.conf
ssl = on
ssl_ca_file = '/etc/ssl/certs/root-ca.crt'
FATAL: could not load server certificate file "server.crt": No such file or directory
After I commented the ssl and ssl_ca_file then the server starts but throw error
LOG: could not start LDAP TLS session: Connect error
DETAIL: LDAP diagnostics: (unknown error code)
FATAL: LDAP authentication failed for user "user"
How to get the server.key and server.crt if root-ca.crt is provided?
LDAPSCHEME:
updated pg_hba.conf file as following
host all all 0.0.0.0/0 ldap ldapserver=test.ldapserver.com ldapscheme=ldaps ldapbasedn="DC=test,DC=ldapserver,DC=com" ldapbinddn="CN=test-user,OU=dept,DC=test,DC=ldapserver,DC=com" ldapbindpasswd="ldappassword" ldapsearchfilter="(&(memberOf=CN=subgroup,OU=dept,OU=special,DC=test,DC=ldapserver,DC=com)(cn=$username))"
LOG: could not perform initial LDAP bind for ldapbinddn="CN=test-user,OU=dept,DC=test,DC=ldapserver,DC=com" on server "test.ldapserver.com": Can't contact LDAP server
DETAIL: LDAP diagnostics: (unknown error code)
FATAL: LDAP authentication failed for user "user"
Also added ldapport=636 and ldaptls=0, but the error remain the same.
What is missing here? Because LDAP can bind without adding ldapscheme
I also tried with ldapurl, but here seems the url doesn't work correctly
host all all 0.0.0.0/0 ldap ldapscheme=ldaps ldapurl="ldaps://test.ldapserver.com:636/DC=test,DC=ldapserver,DC=com?sub?memberOf=CN=subgroup,OU=dept,OU=special,DC=test,DC=ldapserver,DC=com" ldapbinddn="CN=test-user,OU=dept,DC=test,DC=ldapserver,DC=com" ldapbindpasswd="ldappassword
Is this the correct way to use ldapurl?
You are confusing the use of SSL to secure communication between the client and the PostgreSQL server, and the use of SSL to secure communication between the PostgreSQL server and the LDAP server. All those setting you mention (server.key, server.crt, ssl, ssl_ca_file) are for the first of those, not the second.
For the second topic, those certs are not configured through PostgreSQL as far as I know. PostgreSQL just outsources that to whatever your LDAP library is, and it would be configured through that package. Like, for example, /etc/ldap/ldap.conf.

could not initiate GSSAPI security context on Postgres 14 logical replication

I am following this post to enable ssl on Postgres 14 for logical replication. Then try to make connection on client:
CREATE SUBSCRIPTION my-sub
CONNECTION 'host=my-domain.com dbname=my-db user=my-username password=xxxxxx'
PUBLICATION my-pub;
It throws error:
2022-05-12 13:51:36.047 PDT [37340] ERROR: could not connect to the publisher: connection to server at "my_domain.com" (xxx.xxx.xxx.141), port 5432 failed: could not initiate GSSAPI security context: The operation or option is not available: Credential for asked mech-type mech not found in the credential handle
connection to server at "my_domain.com" (xxx.xxx.xxx.141), port 5432 failed: FATAL: connection requires a valid client certificate
connection to server at "my-domain.com" (xxx.xxx.xxx.141), port 5432 failed: FATAL: no pg_hba.conf entry for host "xxx.xxx.xxx.199", user "my-username", database "my-db", no encryption
On my-pub server, one line was added to pg_hba.conf:
hostssl all all 0.0.0.0/0 scram-sha-256 clientcert=verify-full
On sub client, the ca file is setup as below:
ssl_ca_file = '/usr/local/var/postgres/root.crt'. //<<==client cert copied from pub server.
Mostly people just use serve certs. Using client certs is unusual, I would say especially in the case of a logical replication subscriber. But if you do actually want the publisher to demand client certs, it is not configured incorrectly to that purpose (or at least, not that we can tell from the current data). The publisher is demanding a client cert, but the subscriber is not offering one. The configuration problem is on the subscriber.
Note that in this case the subscriber will be acting as the client to connect to the publisher, not acting in the role of a server. It uses the libpq client library to do that, and so the configuration of it is not based on the contents of postgresql.conf. In particular, ssl_ca_file is a server configuration option, not client configuration.
So the way to do this would be for the CONNECTION to look something like
'host=my-domain.com dbname=my-db user=my-username password=xxxxxx sslcert=/foobar/my-username.crt sslkey=/foobar/my-username.key'
But for this to work, the cert and key would need to be on the subscriber computer, readable to whomever owns the postgres process. Which already renders any security benefit dubious.

Talend Connection to PostgreSQL Database fails

I'm trying to make a connection to a PostgreSQL database which is located in a remote server using Talend Open Studio for Big Data v7.3.1
the problem is that the server requires SSL certificates. I tried many ways but It still fails.
Here are the connection strings that I tried and the log errors in TOS BD
1)With ssl mode disable jdbc:postgresql://xx.xx.xx.xx:5432/dbName?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory&sslmode=disable
Exception in component tDBConnection_1 (DB_Connection)
org.postgresql.util.PSQLException: FATAL: pg_hba.conf rejects connection for host "my.ip.address.here", user "user", database "databasename", SSL off
2)Without specifying ssl mode (it means it takes the default mode) jdbc:postgresql://xx.xx.xx.xx:5432/dbName?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory
org.postgresql.ssl.PGjdbcHostnameVerifier verify
GRAVE: Server name validation failed: hostname xx.xx.xx.xx does not match common name xxxxx
Exception in component tDBConnection_1 (DB_Connection)
org.postgresql.util.PSQLException: The hostname xx.xx.xx.xx could not be verified by
hostnameverifier PgjdbcHostnameVerifier
3)If I omit SSL parameters part in the connection like this jdbc:postgresql://xx.xx.xx.xx:5432/dbName? it asks for a valid client certificate.
NB:I can connect to the database using the pgadmin the problem is with Talend open Studio
The solution is to put the certificates locations in the connection string with specifying the ssl mode :
ssl=true&sslmode=prefer&sslcert=DirectoryToSslCertificates/client.crt&sslkey=DirectoryToSslCertificates/clientkey.pk8&sslrootcert=DirectoryToSslCertificates/root.crt
(dont forget to change the certificates formats with openssl commands,I had .pem files)

How to Configure postgresql User with SSL connection only?

My steps I did (psql v. 9.3):
create psql user with password
give him access to relevant databases
allow connection from the outside (psql conf)
and put "hostssl all all 0.0.0.0/0 trust" in pg_hba.conf
Do I need to create a key now to be able to connect?
How can I test that key if it works?
Thanks for help.
Read the documentation.
If you didn't do that already, you'll have to configure the PostgreSQL server for SSL: create server.crt and server.key in the PostgreSQL data directory, set ssl = on in postgresql.conf and restart the server.
You don't need a client certificate or key to connect to the server.
To test if your setup works, just connect with psql.
If SSL is used, it will look as follows:
$ psql -d test -h 127.0.0.1
psql (9.3.13)
SSL connection (cipher: DHE-RSA-AES256-GCM-SHA384, bits: 256)
Type "help" for help.
test=#
Change the trust to md5 (EXTREMELY IMPORTANT)
try to connect over psql from another system using different ssl settings (see the psql man page for this).
If you want to require a cert, then there are additional steps to do, but that's not specified in your question. And cert authentication is possible but an advanced topic.

SSL error when connection pgAdmin3 to Heroku postgreSQL DB

When trying to connect to Heroku PostgresSQL DB using pgAdmin3 I'm getting the following error:
Error connecting to the server: SSL error: certificate verify failed
The connection is based on pg:credentials output and defined as below:
[Properties]:
Host: <host>
Port: 5432
Service: [blank]
Maintenance DB: <database>
Username: <user>
[SSL]:
SSL: require
Server Root Certificate File: [blank]
Server Certificate Revocation List: [blank]
Client Certificate File: [blank]
Client Key File: [blank]
SSL compression: on
[SSH Tunnel] and [Advanced] left default
so as per Heroku guidelines SSL is enabled (set to: [**require**]).
Any ideas how to provide/fix the certificate referred by the error message?
It's likely that pgAdmin is picking up a bundle of CA certificates that has been configured on your system, in which case require would try to verify the server certificate against that bundle.
Typically, this would be a root.crt file located in %APPDATA%\postgresql\ (C:\Users\YourUserName\AppData\Roaming\postgresql\) under Windows, or in ~/.postgresql/ under Linux.
If there is such a file, try to move it out of the way temporarily to check if it works better.
The problem with moving it out of the way is that you are then no longer verifying any remote PostgreSQL certificates against anything but it still works (with require, it would fail with verify-full).
You can solve this by putting the root.crt file in the right place and adding the server certificate to the list of trusted certificates.
It can be bit tricky to find a remote PostgreSQL certificate, but this simple Python application should let you do it (replace hostname and port as required):
import socket
import ssl
import struct
hostname = '...'
port = 5432
sock = socket.socket()
sock.connect((hostname, port))
# We first connect without encryption and tell the server
# we want to upgrade to SSL/TLS.
initiate_ssl_command = struct.Struct('!ii').pack(8, 80877103)
sock.sendall(initiate_ssl_command)
resp = sock.recv(1)
print "Response should be S: %s" % (resp,)
# We then initiate an SSL/TLS connection on this socket.
ssl_sock = ssl.wrap_socket(sock, cert_reqs=ssl.CERT_NONE)
ssl_sock.do_handshake()
peer_cert = ssl_sock.getpeercert(True)
print ssl.DER_cert_to_PEM_cert(peer_cert)
ssl_sock.close()
(For details about what this code does, see the PostgreSQL protocol documentation, in particular the "SSL Session Encryption" section and the SSLRequest message, which is similar to what STARTTLS does in other protocols such as SMTP.)
Security warning: Here, you're just hoping that this particular connection has not been attacked and returns the genuine certificate the first time. It's what you'll use as a trust anchor for subsequent connections. (It's very similar to accepting an SSH server key for the first connection, it will flag changes to the certificate if it changes.)
It's also worth noting that the certificate Subject DN might not match that of the server you're connecting to, therefore you might not be able to use PostgreSQL's verify-full mode (which is the only really secure mode, since it also verifies the host name as well as the trust anchor).
Ideally, Heroku (or whoever provides this service) should give you that certificate by another secure means, and make sure that the Subject DN in that certificate matches the host name they give you. (I'm not sure if this is the case at the moment, perhaps it is available from the administration interface.)