diff --git a/CHANGELOG.md b/CHANGELOG.md index 689c8a65f..12290bb8c 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 + ### Added - #1414, Add related orders - @steve-chavez diff --git a/nix/tools/withTools.nix b/nix/tools/withTools.nix index 042140d0c..0d6e8ad57 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" # shellcheck disable=SC2317 diff --git a/src/PostgREST/Error.hs b/src/PostgREST/Error.hs index 45c4ae8a7..aa59e02c5 100644 --- a/src/PostgREST/Error.hs +++ b/src/PostgREST/Error.hs @@ -450,7 +450,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 = {