Skip to content

Commit d2de7b4

Browse files
committed
fix: search path and migration grants
search_path not set on pgbouncer.get_auth and later migrations don't apply permissions correctly.
1 parent 7009932 commit d2de7b4

File tree

9 files changed

+78
-11
lines changed

9 files changed

+78
-11
lines changed

ansible/files/pgbouncer_config/pgbouncer_auth_schema.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ BEGIN
1414
SELECT usename::TEXT, passwd::TEXT FROM pg_catalog.pg_shadow
1515
WHERE usename = p_usename;
1616
END;
17-
$$ LANGUAGE plpgsql SECURITY DEFINER;
17+
$$ LANGUAGE plpgsql
18+
SET search_path = ''
19+
SECURITY DEFINER;
1820

1921
REVOKE ALL ON FUNCTION pgbouncer.get_auth(p_usename TEXT) FROM PUBLIC;
2022
GRANT EXECUTE ON FUNCTION pgbouncer.get_auth(p_usename TEXT) TO pgbouncer;

ansible/vars.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ postgres_major:
1010

1111
# Full version strings for each major version
1212
postgres_release:
13-
postgresorioledb-17: "17.6.0.010-orioledb"
14-
postgres17: "17.6.1.053"
15-
postgres15: "15.14.1.053"
13+
postgresorioledb-17: "17.6.0.011-orioledb"
14+
postgres17: "17.6.1.054"
15+
postgres15: "15.14.1.054"
1616

1717
# Non Postgres Extensions
1818
pgbouncer_release: 1.19.0
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
-- migrate:up
2+
3+
create or replace function pgbouncer.get_auth(p_usename text) returns table (username text, password text)
4+
language plpgsql
5+
set search_path = ''
6+
security definer
7+
as $$
8+
begin
9+
raise debug 'PgBouncer auth request: %', p_usename;
10+
11+
return query
12+
select
13+
rolname::text,
14+
case when rolvaliduntil < now()
15+
then null
16+
else rolpassword::text
17+
end
18+
from pg_authid
19+
where rolname=$1 and rolcanlogin;
20+
end;
21+
$$;
22+
23+
revoke execute on function pgbouncer.get_auth(text) from public;
24+
grant execute on function pgbouncer.get_auth(text) to pgbouncer;
25+
-- migrate:down
26+

migrations/schema-15.sql

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,9 @@ COMMENT ON FUNCTION extensions.set_graphql_placeholder() IS 'Reintroduces placeh
477477
--
478478

479479
CREATE FUNCTION pgbouncer.get_auth(p_usename text) RETURNS TABLE(username text, password text)
480-
LANGUAGE plpgsql SECURITY DEFINER
480+
LANGUAGE plpgsql
481+
SET search_path = ''
482+
SECURITY DEFINER
481483
AS $_$
482484
begin
483485
raise debug 'PgBouncer auth request: %', p_usename;
@@ -494,6 +496,8 @@ begin
494496
end;
495497
$_$;
496498

499+
REVOKE ALL ON FUNCTION pgbouncer.get_auth(p_usename TEXT) FROM PUBLIC;
500+
GRANT EXECUTE ON FUNCTION pgbouncer.get_auth(p_usename TEXT) TO pgbouncer;
497501

498502
--
499503
-- Name: extension(text); Type: FUNCTION; Schema: storage; Owner: -

migrations/schema-17.sql

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,9 @@ COMMENT ON FUNCTION extensions.set_graphql_placeholder() IS 'Reintroduces placeh
478478
--
479479

480480
CREATE FUNCTION pgbouncer.get_auth(p_usename text) RETURNS TABLE(username text, password text)
481-
LANGUAGE plpgsql SECURITY DEFINER
481+
LANGUAGE plpgsql
482+
SET search_path = ''
483+
SECURITY DEFINER
482484
AS $_$
483485
begin
484486
raise debug 'PgBouncer auth request: %', p_usename;
@@ -495,7 +497,8 @@ begin
495497
end;
496498
$_$;
497499

498-
500+
REVOKE ALL ON FUNCTION pgbouncer.get_auth(p_usename TEXT) FROM PUBLIC;
501+
GRANT EXECUTE ON FUNCTION pgbouncer.get_auth(p_usename TEXT) TO pgbouncer;
499502
--
500503
-- Name: extension(text); Type: FUNCTION; Schema: storage; Owner: -
501504
--

migrations/schema-orioledb-17.sql

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,9 @@ COMMENT ON FUNCTION extensions.set_graphql_placeholder() IS 'Reintroduces placeh
492492
--
493493

494494
CREATE FUNCTION pgbouncer.get_auth(p_usename text) RETURNS TABLE(username text, password text)
495-
LANGUAGE plpgsql SECURITY DEFINER
495+
LANGUAGE plpgsql
496+
SET search_path = ''
497+
SECURITY DEFINER
496498
AS $_$
497499
begin
498500
raise debug 'PgBouncer auth request: %', p_usename;
@@ -509,7 +511,8 @@ begin
509511
end;
510512
$_$;
511513

512-
514+
REVOKE ALL ON FUNCTION pgbouncer.get_auth(p_usename TEXT) FROM PUBLIC;
515+
GRANT EXECUTE ON FUNCTION pgbouncer.get_auth(p_usename TEXT) TO pgbouncer;
513516
--
514517
-- Name: extension(text); Type: FUNCTION; Schema: storage; Owner: -
515518
--

migrations/schema.sql

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,9 @@ COMMENT ON FUNCTION extensions.set_graphql_placeholder() IS 'Reintroduces placeh
474474
--
475475

476476
CREATE FUNCTION pgbouncer.get_auth(p_usename text) RETURNS TABLE(username text, password text)
477-
LANGUAGE plpgsql SECURITY DEFINER
477+
LANGUAGE plpgsql
478+
SET search_path = ''
479+
SECURITY DEFINER
478480
AS $$
479481
BEGIN
480482
RAISE WARNING 'PgBouncer auth request: %', p_usename;
@@ -485,7 +487,8 @@ BEGIN
485487
END;
486488
$$;
487489

488-
490+
REVOKE ALL ON FUNCTION pgbouncer.get_auth(p_usename TEXT) FROM PUBLIC;
491+
GRANT EXECUTE ON FUNCTION pgbouncer.get_auth(p_usename TEXT) TO pgbouncer;
489492
--
490493
-- Name: extension(text); Type: FUNCTION; Schema: storage; Owner: -
491494
--

nix/tests/expected/pgbouncer.out

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,21 @@ select pgbouncer.get_auth('test_valid_user_password');
8383
(test_valid_user_password,SCRAM-SHA-256$4096:testsaltbase64$storedkeybase64$serverkeybase64)
8484
(1 row)
8585

86+
87+
-- Test pgbouncer.get_auth is executable by the pgbouncer user
88+
set role pgbouncer;
89+
select pgbouncer.get_auth('test_expired_user_password');
90+
get_auth
91+
-------------------------------
92+
(test_expired_user_password,)
93+
(1 row)
94+
reset role;
95+
96+
-- and not other non-superusers
97+
set role postgres;
98+
select pgbouncer.get_auth('test_expired_user_password');
99+
ERROR: permission denied for function get_auth
100+
reset role;
101+
86102
drop role test_expired_user_password;
87103
drop role test_valid_user_password;

nix/tests/sql/pgbouncer.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,15 @@ select pgbouncer.get_auth('test_expired_user_password');
6262

6363
select pgbouncer.get_auth('test_valid_user_password');
6464

65+
-- Test pgbouncer.get_auth is executable by the pgbouncer user
66+
set role pgbouncer;
67+
select pgbouncer.get_auth('test_expired_user_password');
68+
reset role;
69+
70+
-- and not other non-superusers
71+
set role postgres;
72+
select pgbouncer.get_auth('test_expired_user_password');
73+
reset role;
74+
6575
drop role test_expired_user_password;
6676
drop role test_valid_user_password;

0 commit comments

Comments
 (0)