diff --git a/pgxn/neon/control_plane_connector.c b/pgxn/neon/control_plane_connector.c index debbbce117..2546e6de5e 100644 --- a/pgxn/neon/control_plane_connector.c +++ b/pgxn/neon/control_plane_connector.c @@ -475,6 +475,12 @@ NeonXactCallback(XactEvent event, void *arg) Assert(CurrentDdlTable == &RootTable); } +static bool +RoleIsNeonSuperuser(const char *role_name) +{ + return strcmp(role_name, "neon_superuser") == 0; +} + static void HandleCreateDb(CreatedbStmt *stmt) { @@ -501,9 +507,16 @@ HandleCreateDb(CreatedbStmt *stmt) entry->type = Op_Set; if (downer && downer->arg) - entry->owner = get_role_oid(defGetString(downer), false); + { + const char *owner_name = defGetString(downer); + if (RoleIsNeonSuperuser(owner_name)) + elog(ERROR, "can't create a database with owner neon_superuser"); + entry->owner = get_role_oid(owner_name, false); + } else + { entry->owner = GetUserId(); + } } static void @@ -522,8 +535,10 @@ HandleAlterOwner(AlterOwnerStmt *stmt) if (!found) memset(entry->old_name, 0, sizeof(entry->old_name)); - - entry->owner = get_role_oid(get_rolespec_name(stmt->newowner), false); + const char *new_owner = get_rolespec_name(stmt->newowner); + if (RoleIsNeonSuperuser(new_owner)) + elog(ERROR, "can't alter owner to neon_superuser"); + entry->owner = get_role_oid(new_owner, false); entry->type = Op_Set; } @@ -617,6 +632,9 @@ HandleAlterRole(AlterRoleStmt *stmt) InitRoleTableIfNeeded(); DefElem *dpass = NULL; ListCell *option; + const char *role_name = stmt->role->rolename; + if (RoleIsNeonSuperuser(role_name)) + elog(ERROR, "can't ALTER neon_superuser"); foreach(option, stmt->options) { @@ -631,7 +649,7 @@ HandleAlterRole(AlterRoleStmt *stmt) bool found = false; RoleEntry *entry = hash_search( CurrentDdlTable->role_table, - stmt->role->rolename, + role_name, HASH_ENTER, &found); diff --git a/test_runner/regress/test_ddl_forwarding.py b/test_runner/regress/test_ddl_forwarding.py index 07ee8b405e..01aeb88bca 100644 --- a/test_runner/regress/test_ddl_forwarding.py +++ b/test_runner/regress/test_ddl_forwarding.py @@ -245,6 +245,19 @@ def test_ddl_forwarding(ddl: DdlForwardingContext): raise AssertionError("Could not count databases") assert result[0] == 0, "Database 'failure' still exists after drop" + # We don't have compute_ctl, so here, so create neon_superuser here manually + cur.execute("CREATE ROLE neon_superuser NOLOGIN CREATEDB CREATEROLE") + + with pytest.raises(psycopg2.InternalError): + cur.execute("ALTER ROLE neon_superuser LOGIN") + + with pytest.raises(psycopg2.InternalError): + cur.execute("CREATE DATABASE trololobus WITH OWNER neon_superuser") + + cur.execute("CREATE DATABASE trololobus") + with pytest.raises(psycopg2.InternalError): + cur.execute("ALTER DATABASE trololobus OWNER TO neon_superuser") + conn.close()