Skip to content

Commit

Permalink
feat: PG16 support
Browse files Browse the repository at this point in the history
  • Loading branch information
soedirgo committed Apr 30, 2024
1 parent 7a546bd commit 77f5f18
Show file tree
Hide file tree
Showing 14 changed files with 408 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
pg-version: ['13', '14', '15']
pg-version: ['13', '14', '15', '16']

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
matrix:
extension_name:
- supautils
postgres: [13, 14, 15]
postgres: [13, 14, 15, 16]
box:
- { runner: ubuntu-20.04, arch: amd64 }
- { runner: arm-runner, arch: arm64 }
Expand Down
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ endif
MODULE_big = supautils
OBJS = src/supautils.o src/privileged_extensions.o src/constrained_extensions.o src/extensions_parameter_overrides.o src/policy_grants.o src/utils.o

PG_VERSION = $(strip $(shell $(PG_CONFIG) --version | $(GREP) -oP '(?<=PostgreSQL )[0-9]+'))
PG_GE16 = $(shell test $(PG_VERSION) -ge 16; echo $$?)
SYSTEM = $(shell uname -s)

TESTS := $(wildcard test/sql/*.sql)
ifneq ($(SYSTEM), Linux)
TESTS = $(filter-out test/sql/ge13_%.sql, $(wildcard test/sql/*.sql))
TESTS := $(filter-out test/sql/linux_%.sql, $(TESTS))
endif
ifneq ($(PG_GE16), 0)
TESTS := $(filter-out test/sql/ge16_%.sql, $(TESTS))
else
TESTS = $(wildcard test/sql/*.sql)
TESTS := $(filter-out test/sql/lt16_%.sql, $(TESTS))
endif

REGRESS = $(patsubst test/sql/%.sql,%,$(TESTS))
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Supautils is an extension that secures a PostgreSQL cluster on a cloud environme

It doesn't require creating database objects. It's a shared library that modifies PostgreSQL behavior through "hooks", not through tables or functions.

It's tested to work on PostgreSQL 13, 14 and 15.
It's tested to work on PostgreSQL 13, 14, 15, and 16.

## Installation

Expand Down
14 changes: 14 additions & 0 deletions src/supautils.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,19 @@ supautils_hook(PROCESS_UTILITY_PARAMS)
if (hasrolemembers)
confirm_reserved_memberships(created_role);

// We don't want to switch to superuser on PG16+ because the
// creating role is implicitly granted ADMIN on the new
// role:
// https://www.postgresql.org/docs/16/runtime-config-client.html#GUC-CREATEROLE-SELF-GRANT
//
// This ADMIN will be missing if we switch to superuser
// since the creating role becomes the superuser.
//
// We also no longer need superuser to grant BYPASSRLS &
// REPLICATION anyway.
#if PG16_GTE
run_process_utility_hook(prev_hook);
#else
if (is_current_role_privileged()) {
bool already_switched_to_superuser = false;

Expand All @@ -478,6 +491,7 @@ supautils_hook(PROCESS_UTILITY_PARAMS)
} else {
run_process_utility_hook(prev_hook);
}
#endif

return;
}
Expand Down
205 changes: 205 additions & 0 deletions test/expected/ge16_privileged_role.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
-- non-superuser privileged role
set role privileged_role;
\echo

-- can set privileged_role_allowed_configs
set session_replication_role to 'replica';
begin;
set local session_replication_role to 'origin';
commit;
reset session_replication_role;
\echo

-- non-superuser non-privileged role cannot set privileged_role_allowed_configs
set role rolecreator;
set session_replication_role to 'replica';
ERROR: permission denied to set parameter "session_replication_role"
begin;
set local session_replication_role to 'origin';
ERROR: permission denied to set parameter "session_replication_role"
commit;
reset session_replication_role;
ERROR: permission denied to set parameter "session_replication_role"
set role privileged_role;
\echo

-- superuser can set privileged_role_allowed_configs
set role postgres;
set session_replication_role to 'replica';
begin;
set local session_replication_role to 'origin';
commit;
reset session_replication_role;
set role privileged_role;
\echo

-- can set privileged_role_allowed_configs for a role
create role r;
alter role r set session_replication_role to 'replica';
drop role r;
\echo

-- can manage bypassrls role attribute
create role r bypassrls;
select rolbypassrls from pg_roles where rolname = 'r';
rolbypassrls
--------------
t
(1 row)

alter role r nobypassrls;
select rolbypassrls from pg_roles where rolname = 'r';
rolbypassrls
--------------
f
(1 row)

alter role r bypassrls;
select rolbypassrls from pg_roles where rolname = 'r';
rolbypassrls
--------------
t
(1 row)

drop role r;
\echo

-- can manage replication role attribute
create role r replication;
select rolreplication from pg_roles where rolname = 'r';
rolreplication
----------------
t
(1 row)

alter role r noreplication;
select rolreplication from pg_roles where rolname = 'r';
rolreplication
----------------
f
(1 row)

alter role r replication;
select rolreplication from pg_roles where rolname = 'r';
rolreplication
----------------
t
(1 row)

drop role r;
\echo

-- can manage foreign data wrappers
create extension postgres_fdw;
create foreign data wrapper new_fdw
handler postgres_fdw_handler
validator postgres_fdw_validator;
drop extension postgres_fdw cascade;
NOTICE: drop cascades to foreign-data wrapper new_fdw
\echo

-- non-superuser non-privileged role cannot manage bypassrls role attribute
set role rolecreator;
\echo

-- the error message changed in PG14
do $$
begin
create role r bypassrls;
exception when insufficient_privilege then null;
end;
$$ language plpgsql;
create role r;
alter role r nobypassrls;
ERROR: permission denied to alter role
DETAIL: Only roles with the BYPASSRLS attribute may change the BYPASSRLS attribute.
alter role r bypassrls;
ERROR: permission denied to alter role
DETAIL: Only roles with the BYPASSRLS attribute may change the BYPASSRLS attribute.
drop role r;
set role privileged_role;
\echo

-- superuser can manage bypassrls role attribute
set role postgres;
create role r bypassrls;
select rolbypassrls from pg_roles where rolname = 'r';
rolbypassrls
--------------
t
(1 row)

alter role r nobypassrls;
select rolbypassrls from pg_roles where rolname = 'r';
rolbypassrls
--------------
f
(1 row)

alter role r bypassrls;
select rolbypassrls from pg_roles where rolname = 'r';
rolbypassrls
--------------
t
(1 row)

drop role r;
set role privileged_role;
\echo

-- regression: https://github.com/supabase/supautils/issues/34
create role tmp;
alter role tmp;
\echo

-- privileged_role can modify reserved roles GUCs
set role privileged_role;
alter role authenticator set search_path to public;
alter role authenticator set statement_timeout = '15s';
\echo

-- privileged_role can do GRANT <role> to <reserved_role>
grant testme to authenticator;
\echo

-- privileged_role can set wildcard privileged_role_allowed_configs
alter role authenticator set pgrst.db_plan_enabled to true;
alter role authenticator set pgrst.db_prepared_statements to false;
alter role authenticator set other.nested.foo to true;
alter role authenticator set other.nested.bar to true;
\echo

-- privileged_role cannot drop, rename or nologin reserved role
drop role authenticator;
ERROR: "authenticator" is a reserved role, only superusers can modify it
alter role authenticator rename to authorized;
ERROR: "authenticator" is a reserved role, only superusers can modify it
alter role authenticator nologin;
ERROR: "authenticator" is a reserved role, only superusers can modify it
\echo

-- privileged_role cannot manage [no]superuser attribute
create role r superuser;
ERROR: permission denied to create role
DETAIL: Only roles with the SUPERUSER attribute may create roles with the SUPERUSER attribute.
create role r;
alter role r superuser;
ERROR: permission denied to alter role
DETAIL: Only roles with the SUPERUSER attribute may alter roles with the SUPERUSER attribute.
alter role postgres nosuperuser;
ERROR: permission denied to alter role
DETAIL: Only superusers can alter privileged roles.
drop role r;
\echo

-- member of privileged_role can do privileged role stuff
set role privileged_role_member;
grant testme to authenticator;
NOTICE: role "authenticator" has already been granted membership in role "testme" by role "privileged_role"
set role privileged_role;
\echo

-- privileged_role can manage publications
create publication p for all tables;
drop publication p;
-- not testing `create publication ... for tables in schema ...` because it's PG15+
File renamed without changes.
11 changes: 7 additions & 4 deletions test/expected/reserved_roles.out
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ set role rolecreator;
\echo

-- cannot rename an existing role to a reserved role
alter role fake rename to reserved_but_not_yet_created;
create role r;
alter role r rename to reserved_but_not_yet_created;
ERROR: "reserved_but_not_yet_created" is a reserved role, only superusers can modify it
drop role r;
\echo

-- cannot rename a reserved role
Expand Down Expand Up @@ -56,9 +58,10 @@ ERROR: "reserved_but_not_yet_created" is a reserved role, only superusers can m
create role anon;
ERROR: role "anon" already exists
-- ensure our hooks don't mess regular non-reserved roles functionality
alter role fake rename to new_fake;
alter role new_fake createrole createdb;
drop role new_fake;
create role r;
alter role r rename to new_r;
alter role new_r createrole createdb;
drop role new_r;
create role non_reserved;
\echo

Expand Down
11 changes: 8 additions & 3 deletions test/fixtures.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ create role supabase_storage_admin noinherit;
create role anon noinherit;

-- login role
create user rolecreator createrole noinherit nosuperuser;
grant anon to rolecreator;
create user rolecreator createrole createdb noinherit nosuperuser;
grant anon to rolecreator with admin option;
grant pg_monitor to rolecreator with admin option;
grant pg_read_all_settings to rolecreator with admin option;
grant pg_read_all_stats to rolecreator with admin option;
grant supabase_storage_admin to rolecreator;

-- other roles
create role fake noinherit;
create role privileged_role login createrole;
create role privileged_role login createrole bypassrls replication;
create role privileged_role_member login createrole in role privileged_role;
create role testme noinherit;
grant testme to privileged_role with admin option;
create role authenticator login noinherit;
grant authenticator to privileged_role with admin option;
grant all on database postgres to privileged_role;
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 77f5f18

Please sign in to comment.