Skip to content

Commit

Permalink
maint: enable SCRAM support (#193)
Browse files Browse the repository at this point in the history
* maint: enable SCRAM support

In order to support SCRAM support for the new Heroku Postgres
"Essential" plans, we need to shift from MD5 hashed passwords in
`auth_file` to plain text. This does not materially change the threat
model, as anyone with dyno access can read the passwords from the
environment just as well as the file.

See: https://www.pgbouncer.org/config.html#authentication-file-format
for more.

This commit switches the `auth_type` to `scram-sha-256` and also pushes
`server_tls_sslmode` up to `require` over `prefer`.

Why not use a method like `auth_query`? Exposing something like
`pg_authid` or `pg_shadow` in a safe way via a `SECURITY DEFINER`
function is extremely challenging in a multi-tenant environment. This
may change in the future.

Fixes #155.

Ref: https://gus.my.salesforce.com/a07EE00001rjvVBYAY

* update tests

* add updates from feedback
  • Loading branch information
mble-sfdc authored May 23, 2024
1 parent 723459e commit c93b9ee
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 9 deletions.
4 changes: 4 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
## Unreleased
* Support SCRAM authentication, use plain passwords in auth_file
* Add PGBOUNCER_AUTH_TYPE config and update default to scram-sha-256
* Add PGBOUNCER_SERVER_TLS_SSLMODE config and update default to require
* Update server_tls_sslmode to require (from prefer)

## v0.14.0 (May 20, 2024)
* Converted our remaining CircleCI tests to Github Actions
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ your leader as a read-only replica, potentially doubling your connection count.
Some settings are configurable through app config vars at runtime. Refer to the appropriate documentation for
[pgbouncer](https://pgbouncer.github.io/config.html) configurations to see what settings are right for you.

- `PGBOUNCER_AUTH_TYPE` Default is `scram-sha-256`. Can be changed to `md5` or `plain` depending on server support.
- `PGBOUNCER_SERVER_TLS_SSLMODE` Default is `require`.
- `PGBOUNCER_POOL_MODE` Default is transaction
- `PGBOUNCER_MAX_CLIENT_CONN` Default is 100
- `PGBOUNCER_DEFAULT_POOL_SIZE` Default is 1
Expand Down
8 changes: 3 additions & 5 deletions bin/gen-pgbouncer-conf.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ cat >> "$CONFIG_DIR/pgbouncer.ini" << EOFEOF
[pgbouncer]
listen_addr = 127.0.0.1
listen_port = 6000
auth_type = md5
auth_type = ${PGBOUNCER_AUTH_TYPE:-scram-sha-256}
auth_file = $CONFIG_DIR/users.txt
server_tls_sslmode = prefer
server_tls_sslmode = ${PGBOUNCER_SERVER_TLS_SSLMODE:-require}
server_tls_protocols = secure
server_tls_ciphers = HIGH:!ADH:!AECDH:!LOW:!EXP:!MD5:!3DES:!SRP:!PSK:@STRENGTH
Expand Down Expand Up @@ -72,8 +72,6 @@ do
fi
done

DB_MD5_PASS="md5"$(echo -n "${DB_PASS}""${DB_USER}" | md5sum | awk '{print $1}')

CLIENT_DB_NAME="db${n}"

echo "Setting ${POSTGRES_URL}_PGBOUNCER config var"
Expand All @@ -86,7 +84,7 @@ do
fi

cat >> "$CONFIG_DIR/users.txt" << EOFEOF
"$DB_USER" "$DB_MD5_PASS"
"$DB_USER" "$DB_PASS"
EOFEOF

cat >> "$CONFIG_DIR/pgbouncer.ini" << EOFEOF
Expand Down
27 changes: 23 additions & 4 deletions test/gen-pgbouncer-conf.bats
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,34 @@ teardown_file() {

@test "successfully writes the config" {
export DATABASE_URL="postgres://user:pass@host:5432/name?query"
export DATABASE_2_URL="postgresql://user2:pass@host2:7777/dbname"
export DATABASE_2_URL="postgresql://user2:pass2@host2:7777/dbname"
export PGBOUNCER_URLS="DATABASE_URL DATABASE_2_URL"
run bash bin/gen-pgbouncer-conf.sh
assert_success
cat "$PGBOUNCER_CONFIG_DIR/pgbouncer.ini"
assert_line 'Setting DATABASE_URL_PGBOUNCER config var'
assert grep "server_tls_sslmode = prefer" "$PGBOUNCER_CONFIG_DIR/pgbouncer.ini"
assert grep "auth_type = scram-sha-256" "$PGBOUNCER_CONFIG_DIR/pgbouncer.ini"
assert grep "server_tls_sslmode = require" "$PGBOUNCER_CONFIG_DIR/pgbouncer.ini"
assert grep "db1= host=host dbname=name?query port=5432" "$PGBOUNCER_CONFIG_DIR/pgbouncer.ini"
assert grep "db2= host=host2 dbname=dbname port=7777" "$PGBOUNCER_CONFIG_DIR/pgbouncer.ini"
assert grep "user" "$PGBOUNCER_CONFIG_DIR/users.txt"
assert grep "user2" "$PGBOUNCER_CONFIG_DIR/users.txt"
assert grep "\"user\" \"pass\"" "$PGBOUNCER_CONFIG_DIR/users.txt"
assert grep "\"user2\" \"pass2\"" "$PGBOUNCER_CONFIG_DIR/users.txt"
}

@test "successfully allows changing of auth_type" {
export DATABASE_URL="postgres://user:pass@host:5432/name?query"
export PGBOUNCER_AUTH_TYPE="md5"
run bash bin/gen-pgbouncer-conf.sh
assert_success
cat "$PGBOUNCER_CONFIG_DIR/pgbouncer.ini"
assert grep "auth_type = md5" "$PGBOUNCER_CONFIG_DIR/pgbouncer.ini"
}

@test "successfully allows changing of server_tls_sslmode" {
export DATABASE_URL="postgres://user:pass@host:5432/name?query"
export PGBOUNCER_SERVER_TLS_SSLMODE="prefer"
run bash bin/gen-pgbouncer-conf.sh
assert_success
cat "$PGBOUNCER_CONFIG_DIR/pgbouncer.ini"
assert grep "server_tls_sslmode = prefer" "$PGBOUNCER_CONFIG_DIR/pgbouncer.ini"
}

0 comments on commit c93b9ee

Please sign in to comment.