Skip to content

Commit

Permalink
feat: allow privileged_role to create ALL TABLES publication
Browse files Browse the repository at this point in the history
  • Loading branch information
soedirgo committed Aug 28, 2023
1 parent da58877 commit 5a8cf2e
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 1 deletion.
2 changes: 1 addition & 1 deletion shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ let
PGTZ=UTC initdb --no-locale --encoding=UTF8 --nosync -U "$PGUSER"
options="-F -c listen_addresses=\"\" -k $PGDATA -c shared_preload_libraries=\"pg_tle, supautils\""
options="-F -c listen_addresses=\"\" -k $PGDATA -c shared_preload_libraries=\"pg_tle, supautils\" -c wal_level=logical"
reserved_roles="supabase_storage_admin, anon, reserved_but_not_yet_created, authenticator*"
reserved_memberships="pg_read_server_files, pg_write_server_files, pg_execute_server_program, role_with_reserved_membership"
Expand Down
78 changes: 78 additions & 0 deletions src/supautils.c
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,84 @@ supautils_hook(PROCESS_UTILITY_PARAMS)
return;
}

/**
* CREATE PUBLICATION
*/
case T_CreatePublicationStmt:
{
const Oid current_user_id = GetUserId();

if (superuser()) {
break;
}
if (!is_privileged_role()) {
break;
}

switch_to_superuser(privileged_extensions_superuser);

run_process_utility_hook(prev_hook);

// Change publication owner to the current role (which is a privileged role)
{
CreatePublicationStmt *stmt = (CreatePublicationStmt *)utility_stmt;

const char *current_role_name = GetUserNameFromId(current_user_id, false);
const char *current_role_name_ident = quote_identifier(current_role_name);
const char *publication_name_ident = quote_identifier(stmt->pubname);
const char *sql_template = "alter publication %s owner to %s;\n";
size_t sql_len = strlen(sql_template)
+ strlen(publication_name_ident)
+ strlen(current_role_name_ident);
char *sql = (char *)palloc(sql_len);
int rc;

snprintf(sql,
sql_len,
sql_template,
publication_name_ident,
current_role_name_ident);

PushActiveSnapshot(GetTransactionSnapshot());
SPI_connect();

rc = SPI_execute(sql, false, 0);
if (rc != SPI_OK_UTILITY) {
elog(ERROR, "SPI_execute failed with error code %d", rc);
}

pfree(sql);

SPI_finish();
PopActiveSnapshot();
}

switch_to_original_role();

return;
}

/**
* ALTER PUBLICATION <name> ADD TABLES IN SCHEMA ...
*/
case T_AlterPublicationStmt:
{
if (superuser()) {
break;
}
if (!is_privileged_role()) {
break;
}

switch_to_superuser(privileged_extensions_superuser);

run_process_utility_hook(prev_hook);

switch_to_original_role();

return;
}

case T_DropStmt:
{
DropStmt *stmt = (DropStmt *)utility_stmt;
Expand Down
6 changes: 6 additions & 0 deletions test/expected/privileged_role.out
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,9 @@ set role privileged_role_member;
grant testme to authenticator;
NOTICE: role "authenticator" is already a member of role "testme"
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+
1 change: 1 addition & 0 deletions test/fixtures.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ create role privileged_role login createrole;
create role privileged_role_member login createrole in role privileged_role;
create role testme noinherit;
create role authenticator login noinherit;
grant all on database postgres to privileged_role;
6 changes: 6 additions & 0 deletions test/sql/privileged_role.sql
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,9 @@ set role privileged_role_member;
grant testme to authenticator;

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+

0 comments on commit 5a8cf2e

Please sign in to comment.