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

Fixed connection with unknown stats_users or admin_users which throws… #817

Merged
merged 8 commits into from May 16, 2023

Conversation

wwoytenko
Copy link
Contributor

Description

This PR contains a bug fix for not existed stats or admin users when auth_query is turned on

This fixes #314

Clarification

I have found in my environment unexpected behavior when some user is trying to connect to pgbouncer. As a result pgbouncer instance crashed with error @src/objects.c:316 in function put_in_order(): put_in_order: found existing elem

Debug setting verbose=2 shows me that some that this user is stats.

2023-03-22 11:49:13.588 EET [162420] NOISE C-0x55e9e01f3360: (nodb)/(nouser)@[::1]:33504 read pkt='!' len=82
2023-03-22 11:49:13.588 EET [162420] DEBUG C-0x55e9e01f3360: (nodb)/(nouser)@[::1]:33504 got var: user=stats
2023-03-22 11:49:13.588 EET [162420] DEBUG C-0x55e9e01f3360: (nodb)/(nouser)@[::1]:33504 got var: database=pgbouncer
2023-03-22 11:49:13.588 EET [162420] DEBUG C-0x55e9e01f3360: (nodb)/(nouser)@[::1]:33504 using application_name: psql - [::1]:33504
2023-03-22 11:49:13.588 EET [162420] DEBUG C-0x55e9e01f3360: (nodb)/(nouser)@[::1]:33504 got var: client_encoding=UTF8
2023-03-22 11:49:13.588 EET [162420] FATAL @src/objects.c:334 in function put_in_order(): put_in_order: found existing elem

The psql call is
psql "host=localhost port=6432 dbname=pgbouncer user=stats sslmode=disable"

I looked through pgbouncer.ini and userlixt.txt and found that the stats user was set in pgbouncer.ini with the setting stats_users = stats but it was not in the userlixt.txt file.

So the original behavior (in this case) is:

  • Get creds from userlist.txt
  • Get cred from auth_query
  • Reject the connection if cred was not found or mismatch

It is right when we are connecting to the real database (not admin) or auth_dbname was defined and set up in the [databases] section. But due to we are connecting to the admin DB we are using it as an auth_dbname by default and the source code does not contain any checks about the admin flag. Eventually, before the login query we are adding existing db into the pool and it throws @src/objects.c:316 in function put_in_order(): put_in_order: found existing elem

To repeat this problem use config

pgbouncer.ini

[databases]
;; postgres = host=127.0.0.1 port=5432 dbname=postgres
* = host=127.0.0.1 port=5432

[pgbouncer]
auth_query = SELECT usename, passwd FROM pg_shadow where usename = $1
auth_user = pgbouncer
stats_users = stats
listen_addr = localhost
verbose = 2
admin_users = pgbouncer
auth_file = ./etc/userlist.txt
;; auth_dbname = postgres

userlist.txt

"pgbouncer" "1234"

@JelteF
Copy link
Member

JelteF commented Mar 22, 2023

Thanks for the contribution. Could you add a regression test for this as well?

@wwoytenko
Copy link
Contributor Author

@JelteF Surely I'll do this in a few days

@wwoytenko
Copy link
Contributor Author

I found another case when we set up auth_dbname = pgbouncer we are still able to crash the pgbouncer instance. Going to add additional checks

@wwoytenko wwoytenko force-pushed the fix_admin_user_auth branch 2 times, most recently from daf5804 to 9f97bfa Compare March 22, 2023 17:20
…in_users which throws '@src/objects.c:316 in function put_in_order(): put_in_order: found existing elem'

Fixes a bug introduced by pgbouncer#314
@wwoytenko wwoytenko force-pushed the fix_admin_user_auth branch 3 times, most recently from 4448ae3 to 335197e Compare March 22, 2023 20:23
@wwoytenko
Copy link
Contributor Author

@JelteF We have done all regression tests and are ready for review

@wwoytenko
Copy link
Contributor Author

I found another case when we set up auth_dbname = pgbouncer we are still able to crash the pgbouncer instance. Going to add additional checks

The check has been moved to start_auth_query() level - it covers both cases.

src/client.c Outdated Show resolved Hide resolved
test/test_auth.py Outdated Show resolved Hide resolved
test/test_auth.py Outdated Show resolved Hide resolved
test/test_auth.py Outdated Show resolved Hide resolved
test/test_auth.py Outdated Show resolved Hide resolved
test/utils.py Outdated Show resolved Hide resolved
* Moved checks within the prepare_auth_database function
* Added additional check for [databases] section which prevents explicit usage of auth_dbname=pgbouncer

Tests:
* Fixed bug in "run_with_config" context manager
* Added "stats" user creation in conftest.py
* Added query parameter with default value "select 1" for functions test, atest, psql_test in Pgbouncer class
* Refactored tests, now it covers the next cases:
 1. Checking broken connection to pgbouncer using auth_dbname from client target DB
 2. Checking broken connection to pgbouncer using auth_dbname from fallback DB definition
 3. Checking reloading error using auth_dbname from DB definition
 4. Checking broken connection to pgbouncer using global auth_dbname
 5. Checking successful connection using auth_dbname from client DB, DB definition, and global setting
@wwoytenko wwoytenko requested a review from goksgie March 29, 2023 05:41
@wwoytenko
Copy link
Contributor Author

Going to add additional checks and tests soon:

  1. Check for cf_auth_dbname
  2. Check for autodb that it does not contain param auth_dbname check with "pgbouncer" value

* Implemented `cf_set_authdb` function for parsing auth_dbname in [pgbouncer] section
* Added auth_dbname check for `cf_autodb_connstr`
* Added warning message in prepare_auth_database

Tests:
* Adapted tests for cases when we are explicitly set auth_dbname (
  * in [pgbouncer] section
  * in [databases] section:
    * for all explicitly defined databases
    * for autodb
@wwoytenko
Copy link
Contributor Author

@goksgie The PR is ready to review. All fixes mentioned above were added in the last commit.

I should mention that this issue we can meet in any version higher that 1.14, even though I didn’t try to perform the same tests with versions not from master branch. But I almost sure that the root cause is the same.

src/loader.c Outdated Show resolved Hide resolved
src/util.c Outdated Show resolved Hide resolved
src/util.c Outdated Show resolved Hide resolved
src/client.c Outdated Show resolved Hide resolved
src/client.c Outdated Show resolved Hide resolved
test/test_auth.py Outdated Show resolved Hide resolved
test/test_auth.py Outdated Show resolved Hide resolved
Copy link
Contributor

@goksgie goksgie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think mostly looks good. Though, I think we should remove the added loop in the "cf_autodb_connstr" parser, set_autodb.

Edit: I think I left the review incorrectly 😢 , please check the comments

… explicitly setting the PostgreSQL version, such as postgrsql@15

* Fixed python linters errors
* Refactored python tests
* Fixes according to reviewer request
@wwoytenko
Copy link
Contributor Author

Seems that this MR is ready for review.
I have simplified the code changes as much as possible and resolved all the requested threads.
Now pgbouncer checks:

  • [pgbouncer] auth_dbname setting during config reloading and does not allow to apply config with reserved auth_dbname
  • During auth stage pgbouncer determines the auth_dbname and closes the connection with an error if it is an attempt to connect using auth_dbname=pgbouncer
  • Slightly refactored tests. Now we've got only three that cover - global setting reloading, connection with wrong auth_dbname (non-global), and positive cases

@wwoytenko wwoytenko requested review from goksgie and JelteF May 15, 2023 13:48
test/utils.py Outdated Show resolved Hide resolved
Copy link
Member

@JelteF JelteF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is very close to merging. Some final feedback. Once that is adressed I think this is good.

test/test_auth.py Outdated Show resolved Hide resolved
test/test_auth.py Outdated Show resolved Hide resolved
@wwoytenko
Copy link
Contributor Author

Total notes about the last changes:

  • Fixed doubled test cases with their description
  • Added a few checks for the test_auth_dbname_works_fine test
  • Reverted changes in QueryBuilder in utils.py

@wwoytenko wwoytenko requested a review from JelteF May 15, 2023 19:28
@JelteF JelteF merged commit e5c46b1 into pgbouncer:master May 16, 2023
23 checks passed
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

Successfully merging this pull request may close these issues.

pgbouncer crashes when user is equal to auth_user in database config
3 participants