diff --git a/CHANGELOG.md b/CHANGELOG.md index cee1599cf..c4adacd3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased + - #2622, Consider any PostgreSQL authentication failure as fatal and exit immediately - @michivi + ### Fixed - #2565, Fix bad M2M embedding on RPC - @steve-chavez diff --git a/nix/tools/withTools.nix b/nix/tools/withTools.nix index 8d158d3b8..611d0af89 100644 --- a/nix/tools/withTools.nix +++ b/nix/tools/withTools.nix @@ -54,6 +54,10 @@ let export PGDATABASE export PGRST_DB_SCHEMAS + HBA_FILE="$tmpdir/pg_hba.conf" + echo "local $PGDATABASE some_protected_user password" > "$HBA_FILE" + echo "local $PGDATABASE all trust" >> "$HBA_FILE" + log "Initializing database cluster..." # We try to make the database cluster as independent as possible from the host # by specifying the timezone, locale and encoding. @@ -62,7 +66,7 @@ let log "Starting the database cluster..." # Instead of listening on a local port, we will listen on a unix domain socket. - pg_ctl -l "$tmpdir/db.log" -w start -o "-F -c listen_addresses=\"\" -k $PGHOST -c log_statement=\"all\"" \ + pg_ctl -l "$tmpdir/db.log" -w start -o "-F -c listen_addresses=\"\" -c hba_file=$HBA_FILE -k $PGHOST -c log_statement=\"all\"" \ >> "$setuplog" stop () { diff --git a/src/PostgREST/Error.hs b/src/PostgREST/Error.hs index 7259287c9..5e2150f81 100644 --- a/src/PostgREST/Error.hs +++ b/src/PostgREST/Error.hs @@ -428,7 +428,7 @@ checkIsFatal :: PgError -> Maybe Text checkIsFatal (PgError _ (SQL.ConnectionUsageError e)) | isAuthFailureMessage = Just $ toS failureMessage | otherwise = Nothing - where isAuthFailureMessage = "FATAL: password authentication failed" `isPrefixOf` failureMessage + where isAuthFailureMessage = "FATAL: password authentication failed" `isInfixOf` failureMessage failureMessage = BS.unpack $ fromMaybe mempty e checkIsFatal (PgError _ (SQL.SessionUsageError (SQL.QueryError _ _ (SQL.ResultError serverError)))) = case serverError of diff --git a/test/io/postgrest.py b/test/io/postgrest.py index ae977e3e2..2a8745f11 100644 --- a/test/io/postgrest.py +++ b/test/io/postgrest.py @@ -50,6 +50,7 @@ def run( env=None, port=None, host=None, + wait_for_readiness=True, no_pool_connection_available=False, ): "Run PostgREST and yield an endpoint that is ready for connections." @@ -88,7 +89,8 @@ def run( process.stdin.write(stdin or b"") process.stdin.close() - wait_until_ready(adminurl + "/ready") + if wait_for_readiness: + wait_until_ready(adminurl + "/ready") process.stdout.read() @@ -137,6 +139,14 @@ def freeport(): return s.getsockname()[1] +def wait_until_exit(postgrest): + "Wait for PostgREST to exit, or times out" + try: + return postgrest.process.wait(timeout=1) + except (subprocess.TimeoutExpired): + raise PostgrestTimedOut() + + def wait_until_ready(url): "Wait for the given HTTP endpoint to return a status of 200." session = requests_unixsocket.Session() diff --git a/test/io/test_io.py b/test/io/test_io.py index ebe6872ce..e5bbf443f 100644 --- a/test/io/test_io.py +++ b/test/io/test_io.py @@ -66,6 +66,15 @@ def test_read_secret_from_stdin_dbconfig(defaultenv): assert response.status_code == 200 +def test_fail_with_invalid_password(defaultenv): + "Connecting with an invalid password should fail without retries." + uri = f'postgresql://?dbname={defaultenv["PGDATABASE"]}&host={defaultenv["PGHOST"]}&user=some_protected_user&password=invalid_pass' + env = {**defaultenv, "PGRST_DB_URI": uri} + with run(env=env, wait_for_readiness=False) as postgrest: + exitCode = wait_until_exit(postgrest) + assert exitCode == 1 + + def test_connect_with_dburi(dburi, defaultenv): "Connecting with db-uri instead of LIPQ* environment variables should work." defaultenv_without_libpq = {