Certificate failure using tsl with pgbouncer and Postgres - postgresql

Hi we are running into a problem with tls between PostgreSQL 11 and pgbouncer 1.9, both on the same host in different containers.
tls enabled and is working between client and pgbouncer and between pgbouncer and PostgreSQL.
The problem is that client connet to pgbouncer with client key and certificate, and after auth pgbouncer pass the client with his/her username and password to postgreSQL and use its own pgbouncer certificate. Immediatly we got error because PostgreSQL checks the username and username in cert and they doesn't match.
What is the right way of solving this issue?
Is there a way to pass client certificate to pgbouncer and then to PostgreSQL?
Thank you
For now there is a mapping on postgres side like this
mymap pgbouncer clientuser
but this is not a viable solution

The best you can do in this case is not to use certificate authentication with PostgreSQL.
In a setup like yours, it is pgBouncer that verifies the authenticity of the incoming client connection using certificates. One this is done, you don't need any further verification.
So use the trust authentication for connections between pgBouncer and PostgreSQL, if that is a trusted network for you.

Related

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.

Amazon RDS for PostgreSQL DB with SSL Authentication?

I have a postgres SQL DB instance created on AWS RDS. I would like to connect to the postgres DB instance over ssl from my pgAdmin 4 tool which is installed on my local machine.
How do we sign the certificates a client cert against AWS's root cert so that it can be used for connection where you know the connection is secure (ssl). I could see the below config details on my AWS RDS postgres DB instance, but I couldn't download them or see a way to download those certs.
ssl_ca_file = /rdsdbdata/rds-metadata/ca-cert.pem ssl_cert_file = /rdsdbdata/rds-metadata/server-cert.pem ssl_key_file = /rdsdbdata/rds-metadata/server-key.pem
how to connect and what certificates or keys should I give in the Client Cert, Client cert key, root cert, cert revocation list locations in the attached screen shot?
Amazon PostgreSQL RDS does not support client certs. So you connect over SSL to verify the server to the client, and to get encryption, but not to verify the client/user to the server. You still use passwords (generally) to do that.

How ssl works in psql?

In AWS RDS postgresql server side ssl has been forced using below config values.
rds.force_ssl 1
ssl 1
When I am trying to connect to postgres RDS host without specifying the sslmode and sslrootcert, it is allowing the ssl connection.
psql -h hostname.us-east-1.rds.amazonaws.com -p 5432 --user=username
psql (10.10 (Ubuntu 10.10-0ubuntu0.18.04.1), server 10.6)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
username=>
Since I did not specify the sslmode, it has taken default sslmode which is prefer. I would like to know:
How is it encrypting the data in transit to the server?
How is it selecting ssl protocol, ssl cipher and compression before sending the data packets to server?
Since I am not specifying any sslrootcert, is it taking any default cert for ssl handshake with server?
Please explain.
Isn't "ECDHE-RSA-AES256-GCM-SHA384" the answer to this? If not, can you expand your question?
As far as I know, this is just outsourced to the ssl library. PostgreSQL doesn't do anything special, other than pass along the configuration options.
It will take the sslrootcert from the default location if it finds one there (in which case, the validation would probably fail, if you didn't go out of way to put something appropriate there). But if it does not find one, then you basically only get Diffie-Hellman protection. It doesn't verify that the server's cert was actually signed by the claimed CA, nor that the cert "belongs" to the server's hostname. You only get protection from eavesdroppers, not from MITM. If the client wants MITM protection, it must set sslmode to a level higher than 'require'.
There is no mechanism implemented by which the server can force the client to validate the server's cert.

How to connect to MongoDB Atlas using Robo 3T?

I'm trying to connect to MongoDB Atlas using Robo 3T.
I must be doing something wrong, cause when i'm trying to connect I get the following error message:
Failed to connect to cluster via SSL tunnel.
in details: Error: ssl connection failure: Authentication failed.
What iv'e tried so far:
Selected a "Direct connection" type.
I used my primary cluster as address (including the port number)
for Authentication I used "admin" Database, and put my username (my email) and the password of MongoDB Atlas.
I also white listed my IP address, and even set it as "allow access from anywhere", though it's not secure.
I checked "Use self-signed certificate"
Nothing I do seems to work.
Any idea what am I doing wrong?
thanks
At Atlas connections are SSL encrypted.
Go to SSL Tab in the connection settings window
Select Use SSL Protocol option
Now try connecting.
Exclude the port number in your cluster URI. :PORT. Exclude the port then use ssl and self certificate.

Parse + mongodb + SSL: "no SSL certificate provided by peer"

In the course of migrating off Parse's servers before it shuts down, I'm trying to set up a simple MongoDB instance on Digital Ocean. (I'm using that instead of mLab because my needs are very limited—-a few MB of storage, a few hundred requests per week--and for that mLab's costs are pretty high.)
I've got mongod running, and have made some progress with SSL thanks to this guide using Let's Encrypt, but now I'm stuck. Parse's migration tool says, "No reachable servers," and if I try to connect on the command line like this:
mongo --ssl -u editAdmin -p "<password-here>" --host mydb.myhost.com dbname
I get this error:
MongoDB shell version: 3.2.7
connecting to: mydb.myhost.com:27017/dbname
2016-07-24T10:31:38.814-0700 E QUERY [thread1] Error: network error while attempting to run command 'isMaster' on host 'mydb.myhost.com:27017' :
connect#src/mongo/shell/mongo.js:231:14
#(connect):1:6
exception: connect failed
The server log reports:
2016-07-24T13:32:44.357-0400 I NETWORK [initandlisten] connection accepted from 12.345.67.89:33351 #39 (1 connection now open)
2016-07-24T13:32:44.390-0400 E NETWORK [conn39] no SSL certificate provided by peer; connection rejected
2016-07-24T13:32:44.390-0400 I NETWORK [conn39] end connection 12.345.67.89:33351 (0 connections now open)
So that would suggest the client needs to provide a cert, but (a) I don't know how to provide one, and (b) Parse doesn't provide that as an option so there must be some way not to.
Thanks in advance for your help.
The key error message is this one:
no SSL certificate provided by peer; connection rejected
When you enable TLS/SSL on MongoDB, MongoDB clients can now authenticate that the MongoDB server is who it claims to be by comparing the MongoDB's TLS/SSL certificate (specified by the PEMKeyFile property in the mongod.conf file) against the public Certificate Authority certificate that you provide to the MongoDB client to indicate which Certificate Authority you trust.
But what I just described is sometimes called one-way TLS, whereas, by default, MongoDB enables two-way or mutual TLS authentication. The idea behind this is that maybe the MongoDB doesn't want to accept client requests from just anyone (the way a public website might), but wants to authenticate the clients as well.
In TLS Mutual Auth, the same Certificate Authority I mentioned above will issue client certificates and the MongoDB server will check the client's certificate to make sure it really was issued by the Certificate Authority in question and that it's valid (e.g. hasn't expired).
So this error is saying "Hey, I expect my clients to present a TLS certificate, but you're not presenting anything."
The way to fix it is described at Configure mongod and mongos for TLS/SSL:
If you want to bypass validation for clients that don’t present
certificates, include the allowConnectionsWithoutCertificates run-time
option with mongod and mongos. If the client does not present a
certificate, no validation occurs. These connections, though not
validated, are still encrypted using SSL.
Of course, you can specify this in the mongod.conf file as well: https://docs.mongodb.com/manual/reference/configuration-options/#net.ssl.allowConnectionsWithoutCertificates
My preferred solution looks like this:
net:
port: 27017
bindIp: 172.0.0.1 # Set this to whatever your private IP address is
ssl:
mode: "requireSSL"
PEMKeyFile: "/path/to/tls/private/key"
CAFile: "/path/to/ca/public/cert"
disabledProtocols: "TLS1_0,TLS1_1"
allowConnectionsWithoutCertificates: true # <-- The line to add to your config
You're command is using the SSL option (and I assume Parse is doing the same) so you are trying to connect using SSL. A client must provide a cert when using SSL. https://docs.mongodb.com/manual/tutorial/configure-ssl-clients/ this link explains how to do this and also specifically mentions your issue
Just follow this tutorial, everything is there, I know that for sure cause I was following that and now I got running parse-server without any previous knowledge... I would recommend you using the MongoDB connection without SSL certificate and allow only localhost queries to it - so only the parse-server that runs on the same machine will access this DB...