Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow an 'auth_query' so passwords for pools can be loaded from database servers #253

Closed
magec opened this issue Dec 13, 2022 · 7 comments
Closed

Comments

@magec
Copy link
Collaborator

magec commented Dec 13, 2022

Is your feature request related to a problem? Please describe.

We currently use PgBouncer with md5 password method using auth_query so we do not need to change its configuration when password changes etc. Also it allows us not to have to set passwords in three places, application -> DB connection pooler -> Database server.

It would be nice to have a feature like PgBouncer/Odyssey have that allows md5 authentication using passwords stored on server backends by means of a query to the target server. This way we only have to tell PgCat one password, the one used to connect to the server for looking up the password. The rest of passwords are obtained from the DB.

Describe the solution you'd like
I find Pgbouncer neat.

In the case of PGCat It would be something like:


auth_query string

Enable remote user authentication.

Whenever a new client connection is opened and MD5 auth is used, use 'auth_query' against target server (using auth_user and auth_password) to obtain user password.

auth_query "SELECT usename, passwd FROM pg_shadow WHERE usename=$1"
auth_user ""
auth_password ""

This is usually done using a function so you can use an unprivileged user that have access to just this table (see this)

Disabled by default.


Also, to ease deployment in containerized environments It would be nice to be able to overwrite auth_query_password using an environment variable like (PGCAT_AUTH_QUERY_PASSWORD) , this way, if also admin password can be overridden by an Env var, config file will be password-less which improves security and simplifies deployment in containerized environments.

NOTE: I currently have some bandwidth to implement this.

@levkk
Copy link
Contributor

levkk commented Dec 13, 2022

Postgres 14 switched to SCRAM, will this still work?

@magec
Copy link
Collaborator Author

magec commented Dec 13, 2022

MD5 is still available (and widely used), not an expert on the new scram method, will investigate a bit further.

@magec
Copy link
Collaborator Author

magec commented Dec 13, 2022

Uhmm, from pgbouncer docu:

SCRAM secrets can only be used for logging into a server if the client authentication also uses SCRAM, the PgBouncer database definition does not specify a user name, and the SCRAM secrets are identical in PgBouncer and the PostgreSQL server (same salt and iterations, not merely the same password). This is due to an inherent security property of SCRAM: The stored SCRAM secret cannot by itself be used for deriving login credentials.

The authentication file can be written by hand, but it's also useful to generate it from some other list of users and passwords. See ./etc/mkauth.py for a sample script to generate the authentication file from the pg_shadow system table. Alternatively, use auth_query instead of auth_file to avoid having to maintain a separate authentication file.

It seems that username definition should be drop from pool config, well also the password which is the point of this. I don't see why not this could also be used for scram. Will dig deeper tomorrow, when I have some time.

@magec
Copy link
Collaborator Author

magec commented Dec 16, 2022

Well, the whole scram thing can't be easily implemented given the way the pool works. For "pass-through" authentication to work in scram, PgCat should talk to clients for opening new server connections and currently this is decoupled, server connections are started by PgCat on demand with the client not intervening at all.

I have a working proof of concept for MD5, mainly because knowing server hash (by using auth_query) you can construct the salted hash without even knowing the password, but for scram this is not possible, which is the whole point of the protocol in the end.

So, even though we could "easily" set up Client -> PgCat scram auth using server hashes obtained by the auth_query method, we still need the client to open server connections. I see some 'possible' solutions:

  • A "clean" solution could be using existing client connections to establish new server connections, but I don't see any way of requesting a 're-auth' to clients in Postgres protocol. If such thing could be generated, we could establish new server connections by requesting auth messages to the client that wants to use a server connection.

  • Use new client connections to open server connections and keep them opened. This is suboptimal, because we will not be pooling until we reach the pool_size.

@levkk
Copy link
Contributor

levkk commented Dec 18, 2022

We could try to do what we do for our config validation: fetch all information at boot and store it in a HashMap or similar. When a user attempts to login, we compare their md5 hash with what we fetched from pg_shadow on boot. It won't be real time, e.g. when a new user is added, this mapping has to be refetched, but that can be implemented as part of RELOAD.

@magec
Copy link
Collaborator Author

magec commented Dec 19, 2022

Yep, that would do. Still, are you ok on implementing only cleartext/md5 with auth_query.

@levkk
Copy link
Contributor

levkk commented Dec 19, 2022

Yeah sure, it's a great feature to have, and as you said there are many installations still using md5. Maybe we'll be able to figure out SCRAM later too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants