From 7d9ff348c70c4814713d4dee9100de60202c4e5f Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 26 Feb 2024 17:09:19 +0300 Subject: [PATCH 01/23] Moves test_atmin_role after node removal --- src/test/regress/expected/create_role_propagation.out | 2 +- src/test/regress/sql/create_role_propagation.sql | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/regress/expected/create_role_propagation.out b/src/test/regress/expected/create_role_propagation.out index 90f2690ce..3241cd846 100644 --- a/src/test/regress/expected/create_role_propagation.out +++ b/src/test/regress/expected/create_role_propagation.out @@ -196,7 +196,6 @@ SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::t (1 row) \c - - - :master_port -create role test_admin_role; -- test grants with distributed and non-distributed roles SELECT master_remove_node('localhost', :worker_2_port); master_remove_node @@ -204,6 +203,7 @@ SELECT master_remove_node('localhost', :worker_2_port); (1 row) +create role test_admin_role; CREATE ROLE dist_role_1 SUPERUSER; CREATE ROLE dist_role_2; CREATE ROLE dist_role_3; diff --git a/src/test/regress/sql/create_role_propagation.sql b/src/test/regress/sql/create_role_propagation.sql index bd2951b17..fce10595f 100644 --- a/src/test/regress/sql/create_role_propagation.sql +++ b/src/test/regress/sql/create_role_propagation.sql @@ -75,12 +75,12 @@ SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::t \c - - - :master_port -create role test_admin_role; - -- test grants with distributed and non-distributed roles SELECT master_remove_node('localhost', :worker_2_port); +create role test_admin_role; + CREATE ROLE dist_role_1 SUPERUSER; CREATE ROLE dist_role_2; CREATE ROLE dist_role_3; From 6ed8ad222ce836f0496e2f03e48789008e87965f Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 4 Mar 2024 11:55:16 +0300 Subject: [PATCH 02/23] Fixes grantor order issue --- src/backend/distributed/metadata/dependency.c | 6 + .../regress/expected/granted_by_support.out | 109 ++++++++++++++++++ src/test/regress/multi_1_schedule | 1 + src/test/regress/sql/granted_by_support.sql | 81 +++++++++++++ 4 files changed, 197 insertions(+) create mode 100644 src/test/regress/expected/granted_by_support.out create mode 100644 src/test/regress/sql/granted_by_support.sql diff --git a/src/backend/distributed/metadata/dependency.c b/src/backend/distributed/metadata/dependency.c index 01653721e..63b831075 100644 --- a/src/backend/distributed/metadata/dependency.c +++ b/src/backend/distributed/metadata/dependency.c @@ -1828,6 +1828,12 @@ ExpandRolesToGroups(Oid roleid) ObjectAddressSet(definition->data.address, AuthIdRelationId, membership->roleid); roles = lappend(roles, definition); + + DependencyDefinition *definition1 = palloc0(sizeof(DependencyDefinition)); + definition1->mode = DependencyObjectAddress; + ObjectAddressSet(definition1->data.address, AuthIdRelationId, membership->grantor); + + roles = lappend(roles, definition1); } systable_endscan(scanDescriptor); diff --git a/src/test/regress/expected/granted_by_support.out b/src/test/regress/expected/granted_by_support.out new file mode 100644 index 000000000..27d8b2e58 --- /dev/null +++ b/src/test/regress/expected/granted_by_support.out @@ -0,0 +1,109 @@ +-- Active: 1700033167033@@localhost@9700@gurkanindibay@public +--In below tests, complex role hierarchy is created and then granted by support is tested. +select 1 from citus_remove_node ('localhost',:worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +create role role1; +create role role2; +create role role3; +create role role4; +create role "role5'_test"; +grant role2 to role1 with admin option; +grant role2 to role3 with admin option granted by role1; +grant role3 to role4 with admin option; +grant role3 to "role5'_test" granted by role4; +grant role2 to "role5'_test" granted by role3; +grant role4 to "role5'_test" with admin option; +grant role4 to role1 with admin option GRANTED BY "role5'_test"; +ERROR: Citus can not handle circular dependencies between distributed objects +DETAIL: "role role1" circularly depends itself, resolve circular dependency first +grant role4 to role3 with admin option GRANTED BY role1; +ERROR: permission denied to grant privileges as role "role1" +DETAIL: The grantor must have the ADMIN option on role "role4". +grant role3 to role1 with admin option GRANTED BY role4; +ERROR: Citus can not handle circular dependencies between distributed objects +DETAIL: "role role1" circularly depends itself, resolve circular dependency first +grant "role5'_test" to role1 with admin option; +ERROR: Citus can not handle circular dependencies between distributed objects +DETAIL: "role role1" circularly depends itself, resolve circular dependency first +grant "role5'_test" to role3 with admin option GRANTED BY role1; +ERROR: permission denied to grant privileges as role "role1" +DETAIL: The grantor must have the ADMIN option on role "role5'_test". +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option, inherit_option,set_option FROM pg_auth_members pa; + role | member | grantor | admin_option | inherit_option | set_option +--------------------------------------------------------------------- + pg_read_all_settings | pg_monitor | postgres | f | t | t + pg_read_all_stats | pg_monitor | postgres | f | t | t + pg_stat_scan_tables | pg_monitor | postgres | f | t | t + role2 | role1 | postgres | t | t | t + role2 | role3 | role1 | t | t | t + role3 | role4 | postgres | t | t | t + role3 | "role5'_test" | role4 | f | t | t + role2 | "role5'_test" | role3 | f | t | t + role4 | "role5'_test" | postgres | t | t | t +(9 rows) + +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('role1','role2','role3','role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] + [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] +(2 rows) + +set citus.log_remote_commands to on; +set citus.grep_remote_commands to '%GRANT%'; +select 1 from citus_add_node ('localhost',:worker_2_port); +NOTICE: issuing CREATE SCHEMA IF NOT EXISTS public AUTHORIZATION pg_database_owner;SET ROLE pg_database_owner;GRANT USAGE ON SCHEMA public TO pg_database_owner;;GRANT CREATE ON SCHEMA public TO pg_database_owner;;RESET ROLE;SET ROLE pg_database_owner;GRANT USAGE ON SCHEMA public TO PUBLIC;;RESET ROLE +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing CREATE SCHEMA IF NOT EXISTS information_schema AUTHORIZATION postgres;SET ROLE postgres;GRANT USAGE ON SCHEMA information_schema TO postgres;;GRANT CREATE ON SCHEMA information_schema TO postgres;;RESET ROLE;SET ROLE postgres;GRANT USAGE ON SCHEMA information_schema TO PUBLIC;;RESET ROLE +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing SELECT worker_create_or_alter_role('role1', 'CREATE ROLE role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''');GRANT role2 TO role1 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY postgres; +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing SELECT worker_create_or_alter_role('role3', 'CREATE ROLE role3 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE role3 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''');GRANT role2 TO role3 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY role1; +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing SELECT worker_create_or_alter_role('role4', 'CREATE ROLE role4 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE role4 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''');GRANT role3 TO role4 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY postgres; +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing SELECT worker_create_or_alter_role('role5''_test', 'CREATE ROLE "role5''_test" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE "role5''_test" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''');GRANT role2 TO "role5'_test" WITH INHERIT TRUE GRANTED BY role3;;GRANT role3 TO "role5'_test" WITH INHERIT TRUE GRANTED BY role4;;GRANT role4 TO "role5'_test" WITH INHERIT TRUE, ADMIN OPTION GRANTED BY postgres; +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +set citus.log_remote_commands to off; +reset citus.grep_remote_commands; +--clean all resources +drop role role1,role2,role3,role4,"role5'_test"; +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('role1','role2','role3','role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + + + +(3 rows) + diff --git a/src/test/regress/multi_1_schedule b/src/test/regress/multi_1_schedule index 015f74973..878d9833f 100644 --- a/src/test/regress/multi_1_schedule +++ b/src/test/regress/multi_1_schedule @@ -63,6 +63,7 @@ test: alter_database_propagation test: citus_shards test: reassign_owned +test: granted_by_support # ---------- # multi_citus_tools tests utility functions written for citus tools diff --git a/src/test/regress/sql/granted_by_support.sql b/src/test/regress/sql/granted_by_support.sql new file mode 100644 index 000000000..c597561dc --- /dev/null +++ b/src/test/regress/sql/granted_by_support.sql @@ -0,0 +1,81 @@ +-- Active: 1700033167033@@localhost@9700@gurkanindibay@public +--In below tests, complex role hierarchy is created and then granted by support is tested. + +select 1 from citus_remove_node ('localhost',:worker_2_port); + +create role role1; + +create role role2; + +create role role3; + +create role role4; + +create role "role5'_test"; + +grant role2 to role1 with admin option; + +grant role2 to role3 with admin option granted by role1; + +grant role3 to role4 with admin option; + +grant role3 to "role5'_test" granted by role4; + +grant role2 to "role5'_test" granted by role3; + +grant role4 to "role5'_test" with admin option; + +grant role4 to role1 with admin option GRANTED BY "role5'_test"; + +grant role4 to role3 with admin option GRANTED BY role1; + +grant role3 to role1 with admin option GRANTED BY role4; + +grant "role5'_test" to role1 with admin option; + +grant "role5'_test" to role3 with admin option GRANTED BY role1; + + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option, inherit_option,set_option FROM pg_auth_members pa; + + +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('role1','role2','role3','role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + + + +set citus.log_remote_commands to on; + +set citus.grep_remote_commands to '%GRANT%'; + +select 1 from citus_add_node ('localhost',:worker_2_port); + +set citus.log_remote_commands to off; +reset citus.grep_remote_commands; + +--clean all resources + +drop role role1,role2,role3,role4,"role5'_test"; + +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('role1','role2','role3','role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); From e6e03828fa563daa4621330555221f0cf7e1ab19 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 4 Mar 2024 14:21:29 +0300 Subject: [PATCH 03/23] Removes empty lines --- .../regress/expected/granted_by_support.out | 30 ------------------- src/test/regress/sql/granted_by_support.sql | 27 ----------------- 2 files changed, 57 deletions(-) diff --git a/src/test/regress/expected/granted_by_support.out b/src/test/regress/expected/granted_by_support.out index 27d8b2e58..2687c8009 100644 --- a/src/test/regress/expected/granted_by_support.out +++ b/src/test/regress/expected/granted_by_support.out @@ -32,20 +32,6 @@ DETAIL: "role role1" circularly depends itself, resolve circular dependency fir grant "role5'_test" to role3 with admin option GRANTED BY role1; ERROR: permission denied to grant privileges as role "role1" DETAIL: The grantor must have the ADMIN option on role "role5'_test". -SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option, inherit_option,set_option FROM pg_auth_members pa; - role | member | grantor | admin_option | inherit_option | set_option ---------------------------------------------------------------------- - pg_read_all_settings | pg_monitor | postgres | f | t | t - pg_read_all_stats | pg_monitor | postgres | f | t | t - pg_stat_scan_tables | pg_monitor | postgres | f | t | t - role2 | role1 | postgres | t | t | t - role2 | role3 | role1 | t | t | t - role3 | role4 | postgres | t | t | t - role3 | "role5'_test" | role4 | f | t | t - role2 | "role5'_test" | role3 | f | t | t - role4 | "role5'_test" | postgres | t | t | t -(9 rows) - select result FROM run_command_on_all_nodes( $$ SELECT array_to_json(array_agg(row_to_json(t))) @@ -64,28 +50,12 @@ select result FROM run_command_on_all_nodes( [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] (2 rows) -set citus.log_remote_commands to on; -set citus.grep_remote_commands to '%GRANT%'; select 1 from citus_add_node ('localhost',:worker_2_port); -NOTICE: issuing CREATE SCHEMA IF NOT EXISTS public AUTHORIZATION pg_database_owner;SET ROLE pg_database_owner;GRANT USAGE ON SCHEMA public TO pg_database_owner;;GRANT CREATE ON SCHEMA public TO pg_database_owner;;RESET ROLE;SET ROLE pg_database_owner;GRANT USAGE ON SCHEMA public TO PUBLIC;;RESET ROLE -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing CREATE SCHEMA IF NOT EXISTS information_schema AUTHORIZATION postgres;SET ROLE postgres;GRANT USAGE ON SCHEMA information_schema TO postgres;;GRANT CREATE ON SCHEMA information_schema TO postgres;;RESET ROLE;SET ROLE postgres;GRANT USAGE ON SCHEMA information_schema TO PUBLIC;;RESET ROLE -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing SELECT worker_create_or_alter_role('role1', 'CREATE ROLE role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE role1 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''');GRANT role2 TO role1 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY postgres; -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing SELECT worker_create_or_alter_role('role3', 'CREATE ROLE role3 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE role3 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''');GRANT role2 TO role3 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY role1; -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing SELECT worker_create_or_alter_role('role4', 'CREATE ROLE role4 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE role4 NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''');GRANT role3 TO role4 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY postgres; -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing SELECT worker_create_or_alter_role('role5''_test', 'CREATE ROLE "role5''_test" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''', 'ALTER ROLE "role5''_test" NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT -1 PASSWORD NULL VALID UNTIL ''infinity''');GRANT role2 TO "role5'_test" WITH INHERIT TRUE GRANTED BY role3;;GRANT role3 TO "role5'_test" WITH INHERIT TRUE GRANTED BY role4;;GRANT role4 TO "role5'_test" WITH INHERIT TRUE, ADMIN OPTION GRANTED BY postgres; -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx ?column? --------------------------------------------------------------------- 1 (1 row) -set citus.log_remote_commands to off; -reset citus.grep_remote_commands; --clean all resources drop role role1,role2,role3,role4,"role5'_test"; select result FROM run_command_on_all_nodes( diff --git a/src/test/regress/sql/granted_by_support.sql b/src/test/regress/sql/granted_by_support.sql index c597561dc..2b1706f63 100644 --- a/src/test/regress/sql/granted_by_support.sql +++ b/src/test/regress/sql/granted_by_support.sql @@ -4,41 +4,24 @@ select 1 from citus_remove_node ('localhost',:worker_2_port); create role role1; - create role role2; - create role role3; - create role role4; - create role "role5'_test"; grant role2 to role1 with admin option; - grant role2 to role3 with admin option granted by role1; - grant role3 to role4 with admin option; - grant role3 to "role5'_test" granted by role4; - grant role2 to "role5'_test" granted by role3; - grant role4 to "role5'_test" with admin option; - grant role4 to role1 with admin option GRANTED BY "role5'_test"; - grant role4 to role3 with admin option GRANTED BY role1; - grant role3 to role1 with admin option GRANTED BY role4; - grant "role5'_test" to role1 with admin option; - grant "role5'_test" to role3 with admin option GRANTED BY role1; -SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option, inherit_option,set_option FROM pg_auth_members pa; - - select result FROM run_command_on_all_nodes( $$ SELECT array_to_json(array_agg(row_to_json(t))) @@ -52,19 +35,9 @@ select result FROM run_command_on_all_nodes( $$ ); - - -set citus.log_remote_commands to on; - -set citus.grep_remote_commands to '%GRANT%'; - select 1 from citus_add_node ('localhost',:worker_2_port); -set citus.log_remote_commands to off; -reset citus.grep_remote_commands; - --clean all resources - drop role role1,role2,role3,role4,"role5'_test"; select result FROM run_command_on_all_nodes( From 684f4a538667fa30b80341f776be56f2d303d2a7 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 4 Mar 2024 14:54:52 +0300 Subject: [PATCH 04/23] Fixes indentation --- src/backend/distributed/metadata/dependency.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backend/distributed/metadata/dependency.c b/src/backend/distributed/metadata/dependency.c index 63b831075..886c58a39 100644 --- a/src/backend/distributed/metadata/dependency.c +++ b/src/backend/distributed/metadata/dependency.c @@ -1831,7 +1831,8 @@ ExpandRolesToGroups(Oid roleid) DependencyDefinition *definition1 = palloc0(sizeof(DependencyDefinition)); definition1->mode = DependencyObjectAddress; - ObjectAddressSet(definition1->data.address, AuthIdRelationId, membership->grantor); + ObjectAddressSet(definition1->data.address, AuthIdRelationId, + membership->grantor); roles = lappend(roles, definition1); } From 3c16bb69d7b89450886f39eff38ffda54b4171eb Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 4 Mar 2024 21:07:56 +0300 Subject: [PATCH 05/23] Breaks the bound of grants with DDL --- .../distributed/commands/dependencies.c | 16 +- src/backend/distributed/commands/role.c | 223 ++++++++++++------ src/backend/distributed/metadata/dependency.c | 7 - .../distributed/metadata/metadata_sync.c | 5 + src/include/distributed/commands.h | 3 +- src/test/regress/sql/granted_by_support.sql | 33 +++ 6 files changed, 197 insertions(+), 90 deletions(-) diff --git a/src/backend/distributed/commands/dependencies.c b/src/backend/distributed/commands/dependencies.c index c7de5d874..acdb9aa13 100644 --- a/src/backend/distributed/commands/dependencies.c +++ b/src/backend/distributed/commands/dependencies.c @@ -44,7 +44,7 @@ static int ObjectAddressComparator(const void *a, const void *b); static void EnsureDependenciesExistOnAllNodes(const ObjectAddress *target); static void EnsureRequiredObjectSetExistOnAllNodes(const ObjectAddress *target, RequiredObjectSet requiredObjectSet); -static List * GetDependencyCreateDDLCommands(const ObjectAddress *dependency); +static List * GetDependencyCreateDDLCommands(const ObjectAddress *dependency,bool fetchGrantStatements); static bool ShouldPropagateObject(const ObjectAddress *address); static char * DropTableIfExistsCommand(Oid relationId); @@ -164,7 +164,7 @@ EnsureRequiredObjectSetExistOnAllNodes(const ObjectAddress *target, ObjectAddress *object = NULL; foreach_ptr(object, objectsToBeCreated) { - List *dependencyCommands = GetDependencyCreateDDLCommands(object); + List *dependencyCommands = GetDependencyCreateDDLCommands(object,true); ddlCommands = list_concat(ddlCommands, dependencyCommands); /* create a new list with objects that actually created commands */ @@ -432,7 +432,7 @@ GetDistributableDependenciesForObject(const ObjectAddress *target) * in nodes, but we utilize logic it follows to choose the objects that could * be distributed */ - List *dependencyCommands = GetDependencyCreateDDLCommands(dependency); + List *dependencyCommands = GetDependencyCreateDDLCommands(dependency,true); /* create a new list with dependencies that actually created commands */ if (list_length(dependencyCommands) > 0) @@ -465,7 +465,7 @@ DropTableIfExistsCommand(Oid relationId) * commands to execute on a worker to create the object. */ static List * -GetDependencyCreateDDLCommands(const ObjectAddress *dependency) +GetDependencyCreateDDLCommands(const ObjectAddress *dependency, bool fetchGrantStatements) { switch (getObjectClass(dependency)) { @@ -605,7 +605,7 @@ GetDependencyCreateDDLCommands(const ObjectAddress *dependency) case OCLASS_ROLE: { - return GenerateCreateOrAlterRoleCommand(dependency->objectId); + return GenerateCreateOrAlterRoleCommand(dependency->objectId,fetchGrantStatements); } case OCLASS_SCHEMA: @@ -680,15 +680,15 @@ GetDependencyCreateDDLCommands(const ObjectAddress *dependency) List * GetAllDependencyCreateDDLCommands(const List *dependencies) { - List *commands = NIL; + List *ddlCommands = NIL; ObjectAddress *dependency = NULL; foreach_ptr(dependency, dependencies) { - commands = list_concat(commands, GetDependencyCreateDDLCommands(dependency)); + ddlCommands = list_concat(ddlCommands, GetDependencyCreateDDLCommands(dependency,false)); } - return commands; + return ddlCommands; } diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index f2b567e6e..edadfc0ba 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -56,6 +56,12 @@ #include "distributed/version_compat.h" #include "distributed/worker_transaction.h" +typedef struct GrantRoleStmts +{ + List *adminStmts; + List *otherStmts; +} GrantRoleStmts; + static const char * ExtractEncryptedPassword(Oid roleOid); static const char * CreateAlterRoleIfExistsCommand(AlterRoleStmt *stmt); static const char * CreateAlterRoleSetIfExistsCommand(AlterRoleSetStmt *stmt); @@ -66,7 +72,7 @@ static DefElem * makeDefElemInt(char *name, int value); static DefElem * makeDefElemBool(char *name, bool value); static List * GenerateRoleOptionsList(HeapTuple tuple); static List * GenerateGrantRoleStmtsFromOptions(RoleSpec *roleSpec, List *options); -static List * GenerateGrantRoleStmtsOfRole(Oid roleid); +static GrantRoleStmts GenerateGrantRoleStmtsOfRole(Oid roleid); static List * GenerateSecLabelOnRoleStmts(Oid roleid, char *rolename); static void EnsureSequentialModeForRoleDDL(void); @@ -513,8 +519,10 @@ GenerateRoleOptionsList(HeapTuple tuple) * the pg_authid table. */ List * -GenerateCreateOrAlterRoleCommand(Oid roleOid) +GenerateCreateOrAlterRoleCommand(Oid roleOid, bool fetchGrantStmts) { + + elog(NOTICE, "Generating create or alter role command for role %u with fetchGrantStmts %s", roleOid,fetchGrantStmts ? "true" : "false"); HeapTuple roleTuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleOid)); Form_pg_authid role = ((Form_pg_authid) GETSTRUCT(roleTuple)); char *rolename = pstrdup(NameStr(role->rolname)); @@ -563,11 +571,18 @@ GenerateCreateOrAlterRoleCommand(Oid roleOid) if (EnableCreateRolePropagation) { - List *grantRoleStmts = GenerateGrantRoleStmtsOfRole(roleOid); - Node *stmt = NULL; - foreach_ptr(stmt, grantRoleStmts) - { - completeRoleList = lappend(completeRoleList, DeparseTreeNode(stmt)); + if(fetchGrantStmts){ + elog(NOTICE, "Fetching grant statements for role %s", rolename); + List *grantRoleStmtList = NIL; + GrantRoleStmts grantRoleStmts= GenerateGrantRoleStmtsOfRole(roleOid); + + grantRoleStmtList = list_concat(grantRoleStmts.adminStmts, grantRoleStmts.otherStmts); + + Node *stmt = NULL; + foreach_ptr(stmt, grantRoleStmtList) + { + completeRoleList = lappend(completeRoleList, DeparseTreeNode(stmt)); + } } /* @@ -578,7 +593,7 @@ GenerateCreateOrAlterRoleCommand(Oid roleOid) * SecLabel stmts to be run in the new node. */ List *secLabelOnRoleStmts = GenerateSecLabelOnRoleStmts(roleOid, rolename); - stmt = NULL; + Node *stmt = NULL; foreach_ptr(stmt, secLabelOnRoleStmts) { completeRoleList = lappend(completeRoleList, DeparseTreeNode(stmt)); @@ -868,91 +883,151 @@ GenerateGrantRoleStmtsFromOptions(RoleSpec *roleSpec, List *options) * GenerateGrantRoleStmtsOfRole generates the GrantRoleStmts for the memberships * of the role whose oid is roleid. */ -static List * +static GrantRoleStmts GenerateGrantRoleStmtsOfRole(Oid roleid) { - Relation pgAuthMembers = table_open(AuthMemRelationId, AccessShareLock); - HeapTuple tuple = NULL; - List *stmts = NIL; + Relation pgAuthMembers = table_open(AuthMemRelationId, AccessShareLock); + HeapTuple tuple = NULL; - ScanKeyData skey[1]; + List *adminStmts = NIL; + List *otherStmts = NIL; - ScanKeyInit(&skey[0], Anum_pg_auth_members_member, BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(roleid)); - SysScanDesc scan = systable_beginscan(pgAuthMembers, AuthMemMemRoleIndexId, true, - NULL, 1, &skey[0]); + ScanKeyData skey[1]; - while (HeapTupleIsValid(tuple = systable_getnext(scan))) - { - Form_pg_auth_members membership = (Form_pg_auth_members) GETSTRUCT(tuple); + ScanKeyInit(&skey[0], Anum_pg_auth_members_member, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(roleid)); + SysScanDesc scan = systable_beginscan(pgAuthMembers, AuthMemMemRoleIndexId, true, + NULL, 1, &skey[0]); - ObjectAddress *roleAddress = palloc0(sizeof(ObjectAddress)); - ObjectAddressSet(*roleAddress, AuthIdRelationId, membership->grantor); - if (!IsAnyObjectDistributed(list_make1(roleAddress))) - { - /* we only need to propagate the grant if the grantor is distributed */ - continue; - } + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Form_pg_auth_members membership = (Form_pg_auth_members) GETSTRUCT(tuple); - GrantRoleStmt *grantRoleStmt = makeNode(GrantRoleStmt); - grantRoleStmt->is_grant = true; + ObjectAddress *roleAddress = palloc0(sizeof(ObjectAddress)); + ObjectAddressSet(*roleAddress, AuthIdRelationId, membership->grantor); + if (!IsAnyObjectDistributed(list_make1(roleAddress))) + { + /* we only need to propagate the grant if the grantor is distributed */ + continue; + } - RoleSpec *grantedRole = makeNode(RoleSpec); - grantedRole->roletype = ROLESPEC_CSTRING; - grantedRole->location = -1; - grantedRole->rolename = GetUserNameFromId(membership->roleid, true); - grantRoleStmt->granted_roles = list_make1(grantedRole); + GrantRoleStmt *grantRoleStmt = makeNode(GrantRoleStmt); + grantRoleStmt->is_grant = true; - RoleSpec *granteeRole = makeNode(RoleSpec); - granteeRole->roletype = ROLESPEC_CSTRING; - granteeRole->location = -1; - granteeRole->rolename = GetUserNameFromId(membership->member, true); - grantRoleStmt->grantee_roles = list_make1(granteeRole); + RoleSpec *grantedRole = makeNode(RoleSpec); + grantedRole->roletype = ROLESPEC_CSTRING; + grantedRole->location = -1; + grantedRole->rolename = GetUserNameFromId(membership->roleid, true); + grantRoleStmt->granted_roles = list_make1(grantedRole); - RoleSpec *grantorRole = makeNode(RoleSpec); - grantorRole->roletype = ROLESPEC_CSTRING; - grantorRole->location = -1; - grantorRole->rolename = GetUserNameFromId(membership->grantor, false); - grantRoleStmt->grantor = grantorRole; + RoleSpec *granteeRole = makeNode(RoleSpec); + granteeRole->roletype = ROLESPEC_CSTRING; + granteeRole->location = -1; + granteeRole->rolename = GetUserNameFromId(membership->member, true); + grantRoleStmt->grantee_roles = list_make1(granteeRole); + + RoleSpec *grantorRole = makeNode(RoleSpec); + grantorRole->roletype = ROLESPEC_CSTRING; + grantorRole->location = -1; + grantorRole->rolename = GetUserNameFromId(membership->grantor, false); + grantRoleStmt->grantor = grantorRole; #if PG_VERSION_NUM >= PG_VERSION_16 + /* inherit option is always included */ + DefElem *inherit_opt; + if (membership->inherit_option) + { + inherit_opt = makeDefElem("inherit", (Node *) makeBoolean(true), -1); + } + else + { + inherit_opt = makeDefElem("inherit", (Node *) makeBoolean(false), -1); + } + grantRoleStmt->opt = list_make1(inherit_opt); - /* inherit option is always included */ - DefElem *inherit_opt; - if (membership->inherit_option) - { - inherit_opt = makeDefElem("inherit", (Node *) makeBoolean(true), -1); - } - else - { - inherit_opt = makeDefElem("inherit", (Node *) makeBoolean(false), -1); - } - grantRoleStmt->opt = list_make1(inherit_opt); + /* admin option is false by default, only include true case */ + if (membership->admin_option) + { + DefElem *admin_opt = makeDefElem("admin", (Node *) makeBoolean(true), -1); + grantRoleStmt->opt = lappend(grantRoleStmt->opt, admin_opt); + } - /* admin option is false by default, only include true case */ - if (membership->admin_option) - { - DefElem *admin_opt = makeDefElem("admin", (Node *) makeBoolean(true), -1); - grantRoleStmt->opt = lappend(grantRoleStmt->opt, admin_opt); - } - - /* set option is true by default, only include false case */ - if (!membership->set_option) - { - DefElem *set_opt = makeDefElem("set", (Node *) makeBoolean(false), -1); - grantRoleStmt->opt = lappend(grantRoleStmt->opt, set_opt); - } + /* set option is true by default, only include false case */ + if (!membership->set_option) + { + DefElem *set_opt = makeDefElem("set", (Node *) makeBoolean(false), -1); + grantRoleStmt->opt = lappend(grantRoleStmt->opt, set_opt); + } #else - grantRoleStmt->admin_opt = membership->admin_option; + grantRoleStmt->admin_opt = membership->admin_option; #endif + if (membership->admin_option) + { + adminStmts = lappend(adminStmts, grantRoleStmt); + } + else + { + otherStmts = lappend(otherStmts, grantRoleStmt); + } + } - stmts = lappend(stmts, grantRoleStmt); + systable_endscan(scan); + table_close(pgAuthMembers, AccessShareLock); + + GrantRoleStmts result; + result.adminStmts = adminStmts; + result.otherStmts = otherStmts; + + return result; +} + + +/**/ +List * GenerateGrantRoleStmts() +{ + Relation pgAuthMembers = table_open(AuthMemRelationId, AccessShareLock); + HeapTuple tuple = NULL; + List *adminStmts = NIL; + List *otherStmts = NIL; + + SysScanDesc scan = systable_beginscan(pgAuthMembers, InvalidOid, false, + NULL, 0, NULL); + + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Form_pg_auth_members membership = (Form_pg_auth_members) GETSTRUCT(tuple); + + ObjectAddress *roleAddress = palloc0(sizeof(ObjectAddress)); + ObjectAddressSet(*roleAddress, AuthIdRelationId, membership->grantor); + elog(NOTICE, "Role name: %s", GetUserNameFromId(membership->roleid, true)); + elog(NOTICE, "Member name: %s", GetUserNameFromId(membership->member, true)); + if (!IsAnyObjectDistributed(list_make1(roleAddress))) + { + /* we only need to propagate the grant if the grantor is distributed */ + continue; + } + + //log role name + elog(NOTICE, "Role name fetched: %s", GetUserNameFromId(membership->roleid, true)); + elog(NOTICE, "Member name fetched: %s", GetUserNameFromId(membership->member, true)); + GrantRoleStmts grantRoleStmts = GenerateGrantRoleStmtsOfRole(membership->roleid); + adminStmts = list_concat(adminStmts, grantRoleStmts.adminStmts); + otherStmts = list_concat(otherStmts, grantRoleStmts.otherStmts); + } + + systable_endscan(scan); + table_close(pgAuthMembers, AccessShareLock); + + List *allGrantStatements = list_concat(adminStmts, otherStmts); + + Node *stmt = NULL; + List *grantStatements = NIL; + foreach_ptr(stmt, allGrantStatements) + { + grantStatements = lappend(grantStatements, DeparseTreeNode(stmt)); } - systable_endscan(scan); - table_close(pgAuthMembers, AccessShareLock); - - return stmts; + return grantStatements; } diff --git a/src/backend/distributed/metadata/dependency.c b/src/backend/distributed/metadata/dependency.c index 886c58a39..01653721e 100644 --- a/src/backend/distributed/metadata/dependency.c +++ b/src/backend/distributed/metadata/dependency.c @@ -1828,13 +1828,6 @@ ExpandRolesToGroups(Oid roleid) ObjectAddressSet(definition->data.address, AuthIdRelationId, membership->roleid); roles = lappend(roles, definition); - - DependencyDefinition *definition1 = palloc0(sizeof(DependencyDefinition)); - definition1->mode = DependencyObjectAddress; - ObjectAddressSet(definition1->data.address, AuthIdRelationId, - membership->grantor); - - roles = lappend(roles, definition1); } systable_endscan(scanDescriptor); diff --git a/src/backend/distributed/metadata/metadata_sync.c b/src/backend/distributed/metadata/metadata_sync.c index 14f5b4624..f6d727aa7 100644 --- a/src/backend/distributed/metadata/metadata_sync.c +++ b/src/backend/distributed/metadata/metadata_sync.c @@ -5027,6 +5027,11 @@ SendDependencyCreationCommands(MetadataSyncContext *context) List *ddlCommands = GetAllDependencyCreateDDLCommands(list_make1(dependency)); SendOrCollectCommandListToActivatedNodes(context, ddlCommands); } + + List *grantRoleCommands = GenerateGrantRoleStmts(); + SendOrCollectCommandListToActivatedNodes(context, grantRoleCommands); + + MemoryContextSwitchTo(oldContext); if (!MetadataSyncCollectsCommands(context)) diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index de15553e7..8d15a1527 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -515,7 +515,7 @@ extern List * PreprocessDropRoleStmt(Node *stmt, const char *queryString, extern List * PreprocessGrantRoleStmt(Node *stmt, const char *queryString, ProcessUtilityContext processUtilityContext); extern List * PostprocessGrantRoleStmt(Node *stmt, const char *queryString); -extern List * GenerateCreateOrAlterRoleCommand(Oid roleOid); +extern List * GenerateCreateOrAlterRoleCommand(Oid roleOid,bool fetchGrantStatements); extern List * CreateRoleStmtObjectAddress(Node *stmt, bool missing_ok, bool isPostprocess); @@ -524,6 +524,7 @@ extern List * RenameRoleStmtObjectAddress(Node *stmt, bool missing_ok, bool extern void UnmarkRolesDistributed(List *roles); extern List * FilterDistributedRoles(List *roles); +extern List * GenerateGrantRoleStmts(void); /* schema.c - forward declarations */ extern List * PostprocessCreateSchemaStmt(Node *node, const char *queryString); diff --git a/src/test/regress/sql/granted_by_support.sql b/src/test/regress/sql/granted_by_support.sql index 2b1706f63..a6f133bc7 100644 --- a/src/test/regress/sql/granted_by_support.sql +++ b/src/test/regress/sql/granted_by_support.sql @@ -21,6 +21,12 @@ grant role3 to role1 with admin option GRANTED BY role4; grant "role5'_test" to role1 with admin option; grant "role5'_test" to role3 with admin option GRANTED BY role1; +SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('role1','role2','role3','role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text; + select result FROM run_command_on_all_nodes( $$ @@ -35,8 +41,14 @@ select result FROM run_command_on_all_nodes( $$ ); +set citus.log_remote_commands = on; +--set citus.grep_remote_commands = '%GRANT%'; + select 1 from citus_add_node ('localhost',:worker_2_port); +reset citus.log_remote_commands; +reset citus.grep_remote_commands; + --clean all resources drop role role1,role2,role3,role4,"role5'_test"; @@ -52,3 +64,24 @@ select result FROM run_command_on_all_nodes( ) t $$ ); + + +GRANT role2 TO role3 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY role1;; +GRANT role2 TO role3 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY role1;; +GRANT role3 TO role4 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY postgres;; x +GRANT role3 TO role4 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY postgres;; +GRANT role2 TO role3 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY role1;; x +GRANT role4 TO "role5'_test" WITH INHERIT TRUE, ADMIN OPTION GRANTED BY postgres;; x +GRANT role2 TO "role5'_test" WITH INHERIT TRUE GRANTED BY role3;; x +GRANT role3 TO "role5'_test" WITH INHERIT TRUE GRANTED BY role4 ; x + + + "role5'_test" | role2 | role3 | f x + "role5'_test" | role3 | role4 | f x + "role5'_test" | role4 | postgres | t x + role1 | "role5'_test" | postgres | t + role1 | role2 | postgres | t + role1 | role3 | role4 | t + role1 | role4 | "role5'_test" | t + role3 | role2 | role1 | t x + role4 | role3 | postgres | t x From 7a7c41f81978fb5969071c98f161359ad8217ed1 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Tue, 5 Mar 2024 01:19:46 +0300 Subject: [PATCH 06/23] Fixes granted by propagation --- .../distributed/commands/dependencies.c | 13 +- src/backend/distributed/commands/role.c | 297 +++++++++--------- src/include/distributed/commands.h | 2 +- .../regress/expected/granted_by_support.out | 55 +++- src/test/regress/sql/granted_by_support.sql | 39 +-- 5 files changed, 215 insertions(+), 191 deletions(-) diff --git a/src/backend/distributed/commands/dependencies.c b/src/backend/distributed/commands/dependencies.c index acdb9aa13..402b63adc 100644 --- a/src/backend/distributed/commands/dependencies.c +++ b/src/backend/distributed/commands/dependencies.c @@ -44,7 +44,8 @@ static int ObjectAddressComparator(const void *a, const void *b); static void EnsureDependenciesExistOnAllNodes(const ObjectAddress *target); static void EnsureRequiredObjectSetExistOnAllNodes(const ObjectAddress *target, RequiredObjectSet requiredObjectSet); -static List * GetDependencyCreateDDLCommands(const ObjectAddress *dependency,bool fetchGrantStatements); +static List * GetDependencyCreateDDLCommands(const ObjectAddress *dependency, bool + fetchGrantStatements); static bool ShouldPropagateObject(const ObjectAddress *address); static char * DropTableIfExistsCommand(Oid relationId); @@ -164,7 +165,7 @@ EnsureRequiredObjectSetExistOnAllNodes(const ObjectAddress *target, ObjectAddress *object = NULL; foreach_ptr(object, objectsToBeCreated) { - List *dependencyCommands = GetDependencyCreateDDLCommands(object,true); + List *dependencyCommands = GetDependencyCreateDDLCommands(object, true); ddlCommands = list_concat(ddlCommands, dependencyCommands); /* create a new list with objects that actually created commands */ @@ -432,7 +433,7 @@ GetDistributableDependenciesForObject(const ObjectAddress *target) * in nodes, but we utilize logic it follows to choose the objects that could * be distributed */ - List *dependencyCommands = GetDependencyCreateDDLCommands(dependency,true); + List *dependencyCommands = GetDependencyCreateDDLCommands(dependency, true); /* create a new list with dependencies that actually created commands */ if (list_length(dependencyCommands) > 0) @@ -605,7 +606,8 @@ GetDependencyCreateDDLCommands(const ObjectAddress *dependency, bool fetchGrantS case OCLASS_ROLE: { - return GenerateCreateOrAlterRoleCommand(dependency->objectId,fetchGrantStatements); + return GenerateCreateOrAlterRoleCommand(dependency->objectId, + fetchGrantStatements); } case OCLASS_SCHEMA: @@ -685,7 +687,8 @@ GetAllDependencyCreateDDLCommands(const List *dependencies) ObjectAddress *dependency = NULL; foreach_ptr(dependency, dependencies) { - ddlCommands = list_concat(ddlCommands, GetDependencyCreateDDLCommands(dependency,false)); + ddlCommands = list_concat(ddlCommands, GetDependencyCreateDDLCommands(dependency, + false)); } return ddlCommands; diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index edadfc0ba..4e6410f6d 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -56,11 +56,6 @@ #include "distributed/version_compat.h" #include "distributed/worker_transaction.h" -typedef struct GrantRoleStmts -{ - List *adminStmts; - List *otherStmts; -} GrantRoleStmts; static const char * ExtractEncryptedPassword(Oid roleOid); static const char * CreateAlterRoleIfExistsCommand(AlterRoleStmt *stmt); @@ -72,7 +67,9 @@ static DefElem * makeDefElemInt(char *name, int value); static DefElem * makeDefElemBool(char *name, bool value); static List * GenerateRoleOptionsList(HeapTuple tuple); static List * GenerateGrantRoleStmtsFromOptions(RoleSpec *roleSpec, List *options); -static GrantRoleStmts GenerateGrantRoleStmtsOfRole(Oid roleid); +static List * GenerateGrantRoleStmtsOfRole(Oid roleid); +static GrantRoleStmt * GetGrantRoleStmtFromAuthMemberRecord(Form_pg_auth_members + membership); static List * GenerateSecLabelOnRoleStmts(Oid roleid, char *rolename); static void EnsureSequentialModeForRoleDDL(void); @@ -521,8 +518,6 @@ GenerateRoleOptionsList(HeapTuple tuple) List * GenerateCreateOrAlterRoleCommand(Oid roleOid, bool fetchGrantStmts) { - - elog(NOTICE, "Generating create or alter role command for role %u with fetchGrantStmts %s", roleOid,fetchGrantStmts ? "true" : "false"); HeapTuple roleTuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleOid)); Form_pg_authid role = ((Form_pg_authid) GETSTRUCT(roleTuple)); char *rolename = pstrdup(NameStr(role->rolname)); @@ -571,18 +566,10 @@ GenerateCreateOrAlterRoleCommand(Oid roleOid, bool fetchGrantStmts) if (EnableCreateRolePropagation) { - if(fetchGrantStmts){ - elog(NOTICE, "Fetching grant statements for role %s", rolename); - List *grantRoleStmtList = NIL; - GrantRoleStmts grantRoleStmts= GenerateGrantRoleStmtsOfRole(roleOid); - - grantRoleStmtList = list_concat(grantRoleStmts.adminStmts, grantRoleStmts.otherStmts); - - Node *stmt = NULL; - foreach_ptr(stmt, grantRoleStmtList) - { - completeRoleList = lappend(completeRoleList, DeparseTreeNode(stmt)); - } + if (fetchGrantStmts) + { + completeRoleList = list_concat(completeRoleList, GenerateGrantRoleStmtsOfRole( + roleOid)); } /* @@ -883,151 +870,171 @@ GenerateGrantRoleStmtsFromOptions(RoleSpec *roleSpec, List *options) * GenerateGrantRoleStmtsOfRole generates the GrantRoleStmts for the memberships * of the role whose oid is roleid. */ -static GrantRoleStmts +static List * GenerateGrantRoleStmtsOfRole(Oid roleid) { - Relation pgAuthMembers = table_open(AuthMemRelationId, AccessShareLock); - HeapTuple tuple = NULL; + Relation pgAuthMembers = table_open(AuthMemRelationId, AccessShareLock); + HeapTuple tuple = NULL; - List *adminStmts = NIL; - List *otherStmts = NIL; + List *adminStmts = NIL; + List *otherStmts = NIL; + List *allStmts = NIL; - ScanKeyData skey[1]; + ScanKeyData skey[1]; - ScanKeyInit(&skey[0], Anum_pg_auth_members_member, BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(roleid)); - SysScanDesc scan = systable_beginscan(pgAuthMembers, AuthMemMemRoleIndexId, true, - NULL, 1, &skey[0]); + ScanKeyInit(&skey[0], Anum_pg_auth_members_member, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(roleid)); + SysScanDesc scan = systable_beginscan(pgAuthMembers, AuthMemMemRoleIndexId, true, + NULL, 1, &skey[0]); - while (HeapTupleIsValid(tuple = systable_getnext(scan))) - { - Form_pg_auth_members membership = (Form_pg_auth_members) GETSTRUCT(tuple); + while (HeapTupleIsValid(tuple = systable_getnext(scan))) + { + Form_pg_auth_members membership = (Form_pg_auth_members) GETSTRUCT(tuple); - ObjectAddress *roleAddress = palloc0(sizeof(ObjectAddress)); - ObjectAddressSet(*roleAddress, AuthIdRelationId, membership->grantor); - if (!IsAnyObjectDistributed(list_make1(roleAddress))) - { - /* we only need to propagate the grant if the grantor is distributed */ - continue; - } + GrantRoleStmt *grantRoleStmt = GetGrantRoleStmtFromAuthMemberRecord(membership); + if (grantRoleStmt == NULL) + { + continue; + } - GrantRoleStmt *grantRoleStmt = makeNode(GrantRoleStmt); - grantRoleStmt->is_grant = true; + if (membership->admin_option) + { + adminStmts = lappend(adminStmts, grantRoleStmt); + } + else + { + otherStmts = lappend(otherStmts, grantRoleStmt); + } + } - RoleSpec *grantedRole = makeNode(RoleSpec); - grantedRole->roletype = ROLESPEC_CSTRING; - grantedRole->location = -1; - grantedRole->rolename = GetUserNameFromId(membership->roleid, true); - grantRoleStmt->granted_roles = list_make1(grantedRole); + systable_endscan(scan); + table_close(pgAuthMembers, AccessShareLock); - RoleSpec *granteeRole = makeNode(RoleSpec); - granteeRole->roletype = ROLESPEC_CSTRING; - granteeRole->location = -1; - granteeRole->rolename = GetUserNameFromId(membership->member, true); - grantRoleStmt->grantee_roles = list_make1(granteeRole); + allStmts = list_concat(adminStmts, otherStmts); + List *commands = NIL; + Node *stmt = NULL; + foreach_ptr(stmt, allStmts) + { + commands = lappend(commands, DeparseTreeNode(stmt)); + } - RoleSpec *grantorRole = makeNode(RoleSpec); - grantorRole->roletype = ROLESPEC_CSTRING; - grantorRole->location = -1; - grantorRole->rolename = GetUserNameFromId(membership->grantor, false); - grantRoleStmt->grantor = grantorRole; - -#if PG_VERSION_NUM >= PG_VERSION_16 - /* inherit option is always included */ - DefElem *inherit_opt; - if (membership->inherit_option) - { - inherit_opt = makeDefElem("inherit", (Node *) makeBoolean(true), -1); - } - else - { - inherit_opt = makeDefElem("inherit", (Node *) makeBoolean(false), -1); - } - grantRoleStmt->opt = list_make1(inherit_opt); - - /* admin option is false by default, only include true case */ - if (membership->admin_option) - { - DefElem *admin_opt = makeDefElem("admin", (Node *) makeBoolean(true), -1); - grantRoleStmt->opt = lappend(grantRoleStmt->opt, admin_opt); - } - - /* set option is true by default, only include false case */ - if (!membership->set_option) - { - DefElem *set_opt = makeDefElem("set", (Node *) makeBoolean(false), -1); - grantRoleStmt->opt = lappend(grantRoleStmt->opt, set_opt); - } -#else - grantRoleStmt->admin_opt = membership->admin_option; -#endif - if (membership->admin_option) - { - adminStmts = lappend(adminStmts, grantRoleStmt); - } - else - { - otherStmts = lappend(otherStmts, grantRoleStmt); - } - } - - systable_endscan(scan); - table_close(pgAuthMembers, AccessShareLock); - - GrantRoleStmts result; - result.adminStmts = adminStmts; - result.otherStmts = otherStmts; - - return result; + return commands; } -/**/ -List * GenerateGrantRoleStmts() +List * +GenerateGrantRoleStmts() { - Relation pgAuthMembers = table_open(AuthMemRelationId, AccessShareLock); - HeapTuple tuple = NULL; - List *adminStmts = NIL; - List *otherStmts = NIL; + Relation pgAuthMembers = table_open(AuthMemRelationId, AccessShareLock); + HeapTuple tuple = NULL; + List *adminStmts = NIL; + List *otherStmts = NIL; - SysScanDesc scan = systable_beginscan(pgAuthMembers, InvalidOid, false, - NULL, 0, NULL); + SysScanDesc scan = systable_beginscan(pgAuthMembers, InvalidOid, false, + NULL, 0, NULL); - while (HeapTupleIsValid(tuple = systable_getnext(scan))) - { - Form_pg_auth_members membership = (Form_pg_auth_members) GETSTRUCT(tuple); - - ObjectAddress *roleAddress = palloc0(sizeof(ObjectAddress)); - ObjectAddressSet(*roleAddress, AuthIdRelationId, membership->grantor); - elog(NOTICE, "Role name: %s", GetUserNameFromId(membership->roleid, true)); - elog(NOTICE, "Member name: %s", GetUserNameFromId(membership->member, true)); - if (!IsAnyObjectDistributed(list_make1(roleAddress))) - { - /* we only need to propagate the grant if the grantor is distributed */ - continue; - } - - //log role name - elog(NOTICE, "Role name fetched: %s", GetUserNameFromId(membership->roleid, true)); - elog(NOTICE, "Member name fetched: %s", GetUserNameFromId(membership->member, true)); - GrantRoleStmts grantRoleStmts = GenerateGrantRoleStmtsOfRole(membership->roleid); - adminStmts = list_concat(adminStmts, grantRoleStmts.adminStmts); - otherStmts = list_concat(otherStmts, grantRoleStmts.otherStmts); - } - - systable_endscan(scan); - table_close(pgAuthMembers, AccessShareLock); - - List *allGrantStatements = list_concat(adminStmts, otherStmts); - - Node *stmt = NULL; - List *grantStatements = NIL; - foreach_ptr(stmt, allGrantStatements) + while (HeapTupleIsValid(tuple = systable_getnext(scan))) { - grantStatements = lappend(grantStatements, DeparseTreeNode(stmt)); + Form_pg_auth_members membership = (Form_pg_auth_members) GETSTRUCT(tuple); + + GrantRoleStmt *grantRoleStmt = GetGrantRoleStmtFromAuthMemberRecord(membership); + if (grantRoleStmt == NULL) + { + continue; + } + + if (membership->admin_option) + { + adminStmts = lappend(adminStmts, grantRoleStmt); + } + else + { + otherStmts = lappend(otherStmts, grantRoleStmt); + } } - return grantStatements; + systable_endscan(scan); + table_close(pgAuthMembers, AccessShareLock); + + List *allStmts = list_concat(adminStmts, otherStmts); + + /*iterate through the list of adminStmts and otherStmts */ + /*and using DeparseTreeNode to convert the GrantRoleStmt to a string */ + /*and then add the string to the list of commands */ + List *commands = NIL; + Node *stmt = NULL; + foreach_ptr(stmt, allStmts) + { + commands = lappend(commands, DeparseTreeNode(stmt)); + } + + return commands; +} + + +static GrantRoleStmt * +GetGrantRoleStmtFromAuthMemberRecord(Form_pg_auth_members membership) +{ + ObjectAddress *roleAddress = palloc0(sizeof(ObjectAddress)); + ObjectAddressSet(*roleAddress, AuthIdRelationId, membership->grantor); + if (!IsAnyObjectDistributed(list_make1(roleAddress))) + { + /* we only need to propagate the grant if the grantor is distributed */ + return NULL; + } + + GrantRoleStmt *grantRoleStmt = makeNode(GrantRoleStmt); + grantRoleStmt->is_grant = true; + + RoleSpec *grantedRole = makeNode(RoleSpec); + grantedRole->roletype = ROLESPEC_CSTRING; + grantedRole->location = -1; + grantedRole->rolename = GetUserNameFromId(membership->roleid, true); + grantRoleStmt->granted_roles = list_make1(grantedRole); + + RoleSpec *granteeRole = makeNode(RoleSpec); + granteeRole->roletype = ROLESPEC_CSTRING; + granteeRole->location = -1; + granteeRole->rolename = GetUserNameFromId(membership->member, true); + grantRoleStmt->grantee_roles = list_make1(granteeRole); + + RoleSpec *grantorRole = makeNode(RoleSpec); + grantorRole->roletype = ROLESPEC_CSTRING; + grantorRole->location = -1; + grantorRole->rolename = GetUserNameFromId(membership->grantor, false); + grantRoleStmt->grantor = grantorRole; + +#if PG_VERSION_NUM >= PG_VERSION_16 + + /* inherit option is always included */ + DefElem *inherit_opt; + if (membership->inherit_option) + { + inherit_opt = makeDefElem("inherit", (Node *) makeBoolean(true), -1); + } + else + { + inherit_opt = makeDefElem("inherit", (Node *) makeBoolean(false), -1); + } + grantRoleStmt->opt = list_make1(inherit_opt); + + /* admin option is false by default, only include true case */ + if (membership->admin_option) + { + DefElem *admin_opt = makeDefElem("admin", (Node *) makeBoolean(true), -1); + grantRoleStmt->opt = lappend(grantRoleStmt->opt, admin_opt); + } + + /* set option is true by default, only include false case */ + if (!membership->set_option) + { + DefElem *set_opt = makeDefElem("set", (Node *) makeBoolean(false), -1); + grantRoleStmt->opt = lappend(grantRoleStmt->opt, set_opt); + } +#else + grantRoleStmt->admin_opt = membership->admin_option; +#endif + return grantRoleStmt; } diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index 8d15a1527..0b005d5d2 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -515,7 +515,7 @@ extern List * PreprocessDropRoleStmt(Node *stmt, const char *queryString, extern List * PreprocessGrantRoleStmt(Node *stmt, const char *queryString, ProcessUtilityContext processUtilityContext); extern List * PostprocessGrantRoleStmt(Node *stmt, const char *queryString); -extern List * GenerateCreateOrAlterRoleCommand(Oid roleOid,bool fetchGrantStatements); +extern List * GenerateCreateOrAlterRoleCommand(Oid roleOid, bool fetchGrantStatements); extern List * CreateRoleStmtObjectAddress(Node *stmt, bool missing_ok, bool isPostprocess); diff --git a/src/test/regress/expected/granted_by_support.out b/src/test/regress/expected/granted_by_support.out index 2687c8009..976f7c7a0 100644 --- a/src/test/regress/expected/granted_by_support.out +++ b/src/test/regress/expected/granted_by_support.out @@ -18,20 +18,30 @@ grant role3 to "role5'_test" granted by role4; grant role2 to "role5'_test" granted by role3; grant role4 to "role5'_test" with admin option; grant role4 to role1 with admin option GRANTED BY "role5'_test"; -ERROR: Citus can not handle circular dependencies between distributed objects -DETAIL: "role role1" circularly depends itself, resolve circular dependency first grant role4 to role3 with admin option GRANTED BY role1; -ERROR: permission denied to grant privileges as role "role1" -DETAIL: The grantor must have the ADMIN option on role "role4". +ERROR: role "role4" is a member of role "role3" grant role3 to role1 with admin option GRANTED BY role4; -ERROR: Citus can not handle circular dependencies between distributed objects -DETAIL: "role role1" circularly depends itself, resolve circular dependency first grant "role5'_test" to role1 with admin option; -ERROR: Citus can not handle circular dependencies between distributed objects -DETAIL: "role role1" circularly depends itself, resolve circular dependency first grant "role5'_test" to role3 with admin option GRANTED BY role1; -ERROR: permission denied to grant privileges as role "role1" -DETAIL: The grantor must have the ADMIN option on role "role5'_test". +ERROR: role "role5'_test" is a member of role "role3" +SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('role1','role2','role3','role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text; + member | role | grantor | admin_option +--------------------------------------------------------------------- + "role5'_test" | role2 | role3 | f + "role5'_test" | role3 | role4 | f + "role5'_test" | role4 | postgres | t + role1 | "role5'_test" | postgres | t + role1 | role2 | postgres | t + role1 | role3 | role4 | t + role1 | role4 | "role5'_test" | t + role3 | role2 | role1 | t + role4 | role3 | postgres | t +(9 rows) + select result FROM run_command_on_all_nodes( $$ SELECT array_to_json(array_agg(row_to_json(t))) @@ -44,10 +54,10 @@ select result FROM run_command_on_all_nodes( ) t $$ ); - result + result --------------------------------------------------------------------- - [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] - [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] + [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"\"role5'_test\"","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role1","role":"role3","grantor":"role4","admin_option":true},{"member":"role1","role":"role4","grantor":"\"role5'_test\"","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] + [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"\"role5'_test\"","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role1","role":"role3","grantor":"role4","admin_option":true},{"member":"role1","role":"role4","grantor":"\"role5'_test\"","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] (2 rows) select 1 from citus_add_node ('localhost',:worker_2_port); @@ -56,6 +66,25 @@ select 1 from citus_add_node ('localhost',:worker_2_port); 1 (1 row) +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('role1','role2','role3','role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"\"role5'_test\"","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role1","role":"role3","grantor":"role4","admin_option":true},{"member":"role1","role":"role4","grantor":"\"role5'_test\"","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] + [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"\"role5'_test\"","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role1","role":"role3","grantor":"role4","admin_option":true},{"member":"role1","role":"role4","grantor":"\"role5'_test\"","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] + [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"\"role5'_test\"","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role1","role":"role3","grantor":"role4","admin_option":true},{"member":"role1","role":"role4","grantor":"\"role5'_test\"","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] +(3 rows) + --clean all resources drop role role1,role2,role3,role4,"role5'_test"; select result FROM run_command_on_all_nodes( diff --git a/src/test/regress/sql/granted_by_support.sql b/src/test/regress/sql/granted_by_support.sql index a6f133bc7..4ed7b8bd5 100644 --- a/src/test/regress/sql/granted_by_support.sql +++ b/src/test/regress/sql/granted_by_support.sql @@ -40,14 +40,20 @@ select result FROM run_command_on_all_nodes( ) t $$ ); - -set citus.log_remote_commands = on; ---set citus.grep_remote_commands = '%GRANT%'; - select 1 from citus_add_node ('localhost',:worker_2_port); -reset citus.log_remote_commands; -reset citus.grep_remote_commands; +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('role1','role2','role3','role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); --clean all resources drop role role1,role2,role3,role4,"role5'_test"; @@ -64,24 +70,3 @@ select result FROM run_command_on_all_nodes( ) t $$ ); - - -GRANT role2 TO role3 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY role1;; -GRANT role2 TO role3 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY role1;; -GRANT role3 TO role4 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY postgres;; x -GRANT role3 TO role4 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY postgres;; -GRANT role2 TO role3 WITH INHERIT TRUE, ADMIN OPTION GRANTED BY role1;; x -GRANT role4 TO "role5'_test" WITH INHERIT TRUE, ADMIN OPTION GRANTED BY postgres;; x -GRANT role2 TO "role5'_test" WITH INHERIT TRUE GRANTED BY role3;; x -GRANT role3 TO "role5'_test" WITH INHERIT TRUE GRANTED BY role4 ; x - - - "role5'_test" | role2 | role3 | f x - "role5'_test" | role3 | role4 | f x - "role5'_test" | role4 | postgres | t x - role1 | "role5'_test" | postgres | t - role1 | role2 | postgres | t - role1 | role3 | role4 | t - role1 | role4 | "role5'_test" | t - role3 | role2 | role1 | t x - role4 | role3 | postgres | t x From 580bbd5570c0cc37d8f0d5a5c1b2b3ce576c892d Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 11 Mar 2024 11:05:35 +0300 Subject: [PATCH 07/23] * Adds granted roles filter for non-distributed roles * Adds a sync filter for metadata sync --- src/backend/distributed/commands/role.c | 132 +++++++- src/include/distributed/commands.h | 3 + .../regress/expected/granted_by_support.out | 286 +++++++++++++++--- src/test/regress/sql/granted_by_support.sql | 217 +++++++++++-- 4 files changed, 565 insertions(+), 73 deletions(-) diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index 4e6410f6d..797a63a02 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -56,6 +56,13 @@ #include "distributed/version_compat.h" #include "distributed/worker_transaction.h" +typedef struct DistributedRolesInGrantRoleStmt +{ + List *distributedGrantees; + List *distributedGrantedRoles; + RoleSpec *grantor; + bool isGrantRoleStmtValid; +} DistributedRolesInGrantRoleStmt; static const char * ExtractEncryptedPassword(Oid roleOid); static const char * CreateAlterRoleIfExistsCommand(AlterRoleStmt *stmt); @@ -68,6 +75,7 @@ static DefElem * makeDefElemBool(char *name, bool value); static List * GenerateRoleOptionsList(HeapTuple tuple); static List * GenerateGrantRoleStmtsFromOptions(RoleSpec *roleSpec, List *options); static List * GenerateGrantRoleStmtsOfRole(Oid roleid); +static ObjectAddress * GetRoleObjectAddressFromOid(Oid roleOid); static GrantRoleStmt * GetGrantRoleStmtFromAuthMemberRecord(Form_pg_auth_members membership); static List * GenerateSecLabelOnRoleStmts(Oid roleid, char *rolename); @@ -937,6 +945,29 @@ GenerateGrantRoleStmts() { Form_pg_auth_members membership = (Form_pg_auth_members) GETSTRUCT(tuple); + /* we only propagate the grant if the grantor is + * member and role are distributed since all are required + * to be distributed for the grant to be propagated + */ + + + bool isAuthMemberDistributed = IsAnyObjectDistributed(list_make1( + GetRoleObjectAddressFromOid( + membership->grantor))) + && + IsAnyObjectDistributed(list_make1( + GetRoleObjectAddressFromOid( + membership->member))) + && + IsAnyObjectDistributed(list_make1( + GetRoleObjectAddressFromOid( + membership->roleid))); + if (!isAuthMemberDistributed) + { + /* we only need to propagate the grant if the grantor is distributed */ + continue; + } + GrantRoleStmt *grantRoleStmt = GetGrantRoleStmtFromAuthMemberRecord(membership); if (grantRoleStmt == NULL) { @@ -972,6 +1003,15 @@ GenerateGrantRoleStmts() } +static ObjectAddress * +GetRoleObjectAddressFromOid(Oid roleOid) +{ + ObjectAddress *roleAddress = palloc0(sizeof(ObjectAddress)); + ObjectAddressSet(*roleAddress, AuthIdRelationId, roleOid); + return roleAddress; +} + + static GrantRoleStmt * GetGrantRoleStmtFromAuthMemberRecord(Form_pg_auth_members membership) { @@ -1310,6 +1350,38 @@ FilterDistributedRoles(List *roles) } +/* + * FilterDistributedRoles filters the list of AccessPrivs and returns the ones + * that are distributed. + */ +List * +FilterDistributedGrantedRoles(List *roles) +{ + List *distributedRoles = NIL; + Node *roleNode = NULL; + foreach_ptr(roleNode, roles) + { + AccessPriv *role = castNode(AccessPriv, roleNode); + Oid roleOid = get_role_oid(role->priv_name, false); + if (roleOid == InvalidOid) + { + /* + * Non-existing roles are ignored silently here. Postgres will + * handle to give an error or not for these roles. + */ + continue; + } + ObjectAddress *roleAddress = palloc0(sizeof(ObjectAddress)); + ObjectAddressSet(*roleAddress, AuthIdRelationId, roleOid); + if (IsAnyObjectDistributed(list_make1(roleAddress))) + { + distributedRoles = lappend(distributedRoles, role); + } + } + return distributedRoles; +} + + /* * PreprocessGrantRoleStmt finds the distributed grantee roles and creates the * query to run on the workers. @@ -1327,17 +1399,22 @@ PreprocessGrantRoleStmt(Node *node, const char *queryString, GrantRoleStmt *stmt = castNode(GrantRoleStmt, node); List *allGranteeRoles = stmt->grantee_roles; + List *allGrantedRoles = stmt->granted_roles; RoleSpec *grantor = stmt->grantor; - List *distributedGranteeRoles = FilterDistributedRoles(allGranteeRoles); - if (list_length(distributedGranteeRoles) <= 0) + DistributedRolesInGrantRoleStmt *distributedRolesInGrantStmt = + ExtractDistributedRolesInGrantRoleStmt(stmt); + + if (!distributedRolesInGrantStmt->isGrantRoleStmtValid) { return NIL; } - stmt->grantee_roles = distributedGranteeRoles; + stmt->grantee_roles = distributedRolesInGrantStmt->distributedGrantees; + stmt->granted_roles = distributedRolesInGrantStmt->distributedGrantedRoles; char *sql = DeparseTreeNode((Node *) stmt); stmt->grantee_roles = allGranteeRoles; + stmt->granted_roles = allGrantedRoles; stmt->grantor = grantor; List *commands = list_make3(DISABLE_DDL_PROPAGATION, @@ -1348,6 +1425,55 @@ PreprocessGrantRoleStmt(Node *node, const char *queryString, } +DistributedRolesInGrantRoleStmt * +ExtractDistributedRolesInGrantRoleStmt(GrantRoleStmt *stmt) +{ + DistributedRolesInGrantRoleStmt *distributedRolesInGrantRoleStmt = palloc0( + sizeof(DistributedRolesInGrantRoleStmt)); + distributedRolesInGrantRoleStmt->distributedGrantees = FilterDistributedRoles( + stmt->grantee_roles); + distributedRolesInGrantRoleStmt->distributedGrantedRoles = + FilterDistributedGrantedRoles(stmt->granted_roles); + distributedRolesInGrantRoleStmt->grantor = stmt->grantor; + distributedRolesInGrantRoleStmt->isGrantRoleStmtValid = true; + + bool grantorMissingOk = false; + bool isGrantorDefined = distributedRolesInGrantRoleStmt->grantor != NULL && + get_rolespec_oid(distributedRolesInGrantRoleStmt->grantor, + grantorMissingOk) != + InvalidOid; + bool isGrantorDistributed = IsAnyObjectDistributed(RoleSpecToObjectAddress( + distributedRolesInGrantRoleStmt + ->grantor, grantorMissingOk)); + bool skipDueToGrantor = isGrantorDefined && !isGrantorDistributed; + if (list_length(distributedRolesInGrantRoleStmt->distributedGrantees) <= 0) + { + ereport(NOTICE, (errmsg("not propagating GRANT command to other nodes"), + errhint("Since no grantees are distributed, " + "the GRANT command will not be propagated to other nodes."))); + distributedRolesInGrantRoleStmt->isGrantRoleStmtValid = false; + } + + if (list_length(distributedRolesInGrantRoleStmt->distributedGrantedRoles) <= 0) + { + ereport(NOTICE, (errmsg("not propagating GRANT command to other nodes"), + errhint("Since no granted roles are distributed, " + "the GRANT command will not be propagated to other nodes."))); + distributedRolesInGrantRoleStmt->isGrantRoleStmtValid = false; + } + + if (skipDueToGrantor) + { + ereport(NOTICE, (errmsg("not propagating GRANT command to other nodes"), + errhint("Since grantor is not distributed, " + "the GRANT command will not be propagated to other nodes."))); + distributedRolesInGrantRoleStmt->isGrantRoleStmtValid = false; + } + + return distributedRolesInGrantRoleStmt; +} + + /* * PostprocessGrantRoleStmt actually creates the plan we need to execute for grant * role statement. diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index 0b005d5d2..e0b45a8a2 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -523,7 +523,10 @@ extern List * RenameRoleStmtObjectAddress(Node *stmt, bool missing_ok, bool isPostprocess); extern void UnmarkRolesDistributed(List *roles); +extern List * FilterDistributedGrantedRoles(List *roles); extern List * FilterDistributedRoles(List *roles); +extern DistributedRolesInGrantRoleStmt * ExtractDistributedRolesInGrantRoleStmt( + GrantRoleStmt *stmt); extern List * GenerateGrantRoleStmts(void); /* schema.c - forward declarations */ diff --git a/src/test/regress/expected/granted_by_support.out b/src/test/regress/expected/granted_by_support.out index 976f7c7a0..3a956bd52 100644 --- a/src/test/regress/expected/granted_by_support.out +++ b/src/test/regress/expected/granted_by_support.out @@ -1,47 +1,68 @@ -- Active: 1700033167033@@localhost@9700@gurkanindibay@public --In below tests, complex role hierarchy is created and then granted by support is tested. +--- Test 1: Tests from main database select 1 from citus_remove_node ('localhost',:worker_2_port); ?column? --------------------------------------------------------------------- 1 (1 row) -create role role1; -create role role2; -create role role3; -create role role4; -create role "role5'_test"; -grant role2 to role1 with admin option; -grant role2 to role3 with admin option granted by role1; -grant role3 to role4 with admin option; -grant role3 to "role5'_test" granted by role4; -grant role2 to "role5'_test" granted by role3; -grant role4 to "role5'_test" with admin option; -grant role4 to role1 with admin option GRANTED BY "role5'_test"; -grant role4 to role3 with admin option GRANTED BY role1; -ERROR: role "role4" is a member of role "role3" -grant role3 to role1 with admin option GRANTED BY role4; -grant "role5'_test" to role1 with admin option; -grant "role5'_test" to role3 with admin option GRANTED BY role1; -ERROR: role "role5'_test" is a member of role "role3" -SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option - FROM pg_auth_members - WHERE member::regrole::text in - ('role1','role2','role3','role4','"role5''_test"') - order by member::regrole::text, roleid::regrole::text; - member | role | grantor | admin_option +set citus.enable_create_role_propagation to off; +create role non_dist_role1; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +reset citus.enable_create_role_propagation; +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + rolname --------------------------------------------------------------------- - "role5'_test" | role2 | role3 | f - "role5'_test" | role3 | role4 | f - "role5'_test" | role4 | postgres | t - role1 | "role5'_test" | postgres | t - role1 | role2 | postgres | t - role1 | role3 | role4 | t - role1 | role4 | "role5'_test" | t - role3 | role2 | role1 | t - role4 | role3 | postgres | t -(9 rows) +(0 rows) +create role dist_role1; +create role dist_role2; +create role dist_role3; +create role dist_role4; +create role "dist_role5'_test"; +grant dist_role2 to dist_role1 with admin option; +grant dist_role2 to dist_role3 with admin option granted by dist_role1; +grant dist_role3 to dist_role4 with admin option; +-- With enable_create_role_propagation on, all grantees are propagated. +-- To test non-distributed grantor, set this option off for some roles. +set citus.enable_create_role_propagation to off; +grant non_dist_role1 to dist_role1 with admin option; +reset citus.enable_create_role_propagation; +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + rolname +--------------------------------------------------------------------- +(0 rows) + +grant dist_role2 to non_dist_role1 with admin option; +NOTICE: not propagating GRANT command to other nodes +HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. +grant dist_role3 to "dist_role5'_test" granted by dist_role4; +grant dist_role2 to "dist_role5'_test" granted by dist_role3; +grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed +NOTICE: not propagating GRANT command to other nodes +HINT: Since grantor is not distributed, the GRANT command will not be propagated to other nodes. +grant dist_role4 to "dist_role5'_test" with admin option; +--below command propagates the non_dist_role1 since non_dist_role1 is already granted to dist_role1 +--and citus sees granted roles as a dependency and citus propagates the dependent roles +grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + rolname +--------------------------------------------------------------------- + non_dist_role1 +(1 row) + +grant dist_role4 to dist_role3 with admin option GRANTED BY dist_role1; --fails since already dist_role3 granted to dist_role4 +ERROR: role "dist_role4" is a member of role "dist_role3" +grant non_dist_role1 to dist_role4 granted by dist_role1; +ERROR: permission denied to grant privileges as role "dist_role1" +DETAIL: The grantor must have the ADMIN option on role "non_dist_role1". +CONTEXT: while executing command on localhost:xxxxx +grant dist_role3 to dist_role1 with admin option GRANTED BY dist_role4; +grant "dist_role5'_test" to dist_role1 with admin option; +grant "dist_role5'_test" to dist_role3 with admin option GRANTED BY dist_role1;--fails since already dist_role3 granted to "dist_role5'_test" +ERROR: role "dist_role5'_test" is a member of role "dist_role3" select result FROM run_command_on_all_nodes( $$ SELECT array_to_json(array_agg(row_to_json(t))) @@ -49,15 +70,15 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('role1','role2','role3','role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') order by member::regrole::text, roleid::regrole::text ) t $$ ); - result + result --------------------------------------------------------------------- - [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"\"role5'_test\"","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role1","role":"role3","grantor":"role4","admin_option":true},{"member":"role1","role":"role4","grantor":"\"role5'_test\"","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] - [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"\"role5'_test\"","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role1","role":"role3","grantor":"role4","admin_option":true},{"member":"role1","role":"role4","grantor":"\"role5'_test\"","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] (2 rows) select 1 from citus_add_node ('localhost',:worker_2_port); @@ -73,20 +94,27 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('role1','role2','role3','role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') order by member::regrole::text, roleid::regrole::text ) t $$ ); - result + result --------------------------------------------------------------------- - [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"\"role5'_test\"","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role1","role":"role3","grantor":"role4","admin_option":true},{"member":"role1","role":"role4","grantor":"\"role5'_test\"","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] - [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"\"role5'_test\"","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role1","role":"role3","grantor":"role4","admin_option":true},{"member":"role1","role":"role4","grantor":"\"role5'_test\"","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] - [{"member":"\"role5'_test\"","role":"role2","grantor":"role3","admin_option":false},{"member":"\"role5'_test\"","role":"role3","grantor":"role4","admin_option":false},{"member":"\"role5'_test\"","role":"role4","grantor":"postgres","admin_option":true},{"member":"role1","role":"\"role5'_test\"","grantor":"postgres","admin_option":true},{"member":"role1","role":"role2","grantor":"postgres","admin_option":true},{"member":"role1","role":"role3","grantor":"role4","admin_option":true},{"member":"role1","role":"role4","grantor":"\"role5'_test\"","admin_option":true},{"member":"role3","role":"role2","grantor":"role1","admin_option":true},{"member":"role4","role":"role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] (3 rows) --clean all resources -drop role role1,role2,role3,role4,"role5'_test"; +drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; +drop role non_dist_role1; +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + rolname +--------------------------------------------------------------------- +(0 rows) + +reset citus.enable_create_role_propagation; select result FROM run_command_on_all_nodes( $$ SELECT array_to_json(array_agg(row_to_json(t))) @@ -94,7 +122,7 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('role1','role2','role3','role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') order by member::regrole::text, roleid::regrole::text ) t $$ @@ -106,3 +134,171 @@ select result FROM run_command_on_all_nodes( (3 rows) +--- Test 2: Tests from non-main database +set citus.enable_create_database_propagation to on; +create database test_granted_by_support; +select 1 from citus_remove_node ('localhost',:worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + rolname +--------------------------------------------------------------------- +(0 rows) + +\c test_granted_by_support +--here in below block since 'citus.enable_create_role_propagation to off ' is not effective, +--non_dist_role1 is being propagated to dist_role1 unlike main db scenario +--non_dist_role1 will be used for the test scenarios in this section +set citus.enable_create_role_propagation to off; +create role non_dist_role1; +reset citus.enable_create_role_propagation; +--dropping since it isn't non-distributed as intended +drop role non_dist_role1; +--creating non_dist_role1 again in main database +--This is actually non-distributed role +\c regression +set citus.enable_create_role_propagation to off; +create role non_dist_role1; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +reset citus.enable_create_role_propagation; +\c test_granted_by_support +create role dist_role1; +create role dist_role1; +ERROR: role "dist_role1" already exists +create role dist_role2; +create role dist_role3; +create role dist_role4; +create role "dist_role5'_test"; +\c regression - - :master_port +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + rolname +--------------------------------------------------------------------- +(0 rows) + +\c test_granted_by_support +grant dist_role2 to dist_role1 with admin option; +grant dist_role2 to dist_role3 with admin option granted by dist_role1; +grant dist_role3 to dist_role4 with admin option; +-- With enable_create_role_propagation on, all grantees are propagated. +-- To test non-distributed grantor, set this option off for some roles. +\c regression +set citus.enable_create_role_propagation to off; +grant non_dist_role1 to dist_role1 with admin option; +reset citus.enable_create_role_propagation; +\c test_granted_by_support +grant dist_role2 to non_dist_role1 with admin option; +ERROR: failure on connection marked as essential: localhost:xxxxx +CONTEXT: while executing command on localhost:xxxxx +\c test_granted_by_support - - :worker_1_port +grant dist_role3 to "dist_role5'_test" granted by dist_role4; +grant dist_role2 to "dist_role5'_test" granted by dist_role3; +grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed +ERROR: role "non_dist_role1" does not exist +\c regression - - :master_port +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + rolname +--------------------------------------------------------------------- +(0 rows) + +\c test_granted_by_support - - :worker_1_port +grant dist_role4 to "dist_role5'_test" with admin option; +\c regression - - :master_port +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + rolname +--------------------------------------------------------------------- +(0 rows) + +\c test_granted_by_support +-- Unlike maindb scenario, non-maindb scenario doesn't propagate 'create non_dist_role1' to +--workers as it doesn't create dependency objects for non-distributed roles. +grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; +\c regression - - :master_port +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + rolname +--------------------------------------------------------------------- +(0 rows) + +\c test_granted_by_support - - :worker_1_port +grant dist_role4 to dist_role3 with admin option GRANTED BY dist_role1; --fails since already dist_role3 granted to dist_role4 +ERROR: role "dist_role4" is a member of role "dist_role3" +grant non_dist_role1 to dist_role4 granted by dist_role1; +ERROR: role "non_dist_role1" does not exist +grant dist_role3 to dist_role1 with admin option GRANTED BY dist_role4; +grant "dist_role5'_test" to dist_role1 with admin option; +grant "dist_role5'_test" to dist_role3 with admin option GRANTED BY dist_role1;--fails since already dist_role3 granted to "dist_role5'_test" +ERROR: role "dist_role5'_test" is a member of role "dist_role3" +\c regression - - :master_port +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] +(2 rows) + +select 1 from citus_add_node ('localhost',:worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] +(3 rows) + +--clean all resources +set citus.enable_create_database_propagation to on; +drop database test_granted_by_support; +drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; +drop role non_dist_role1; +drop role if exists non_dist_role1; +NOTICE: role "non_dist_role1" does not exist, skipping +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + + + +(3 rows) + +reset citus.enable_create_database_propagation; diff --git a/src/test/regress/sql/granted_by_support.sql b/src/test/regress/sql/granted_by_support.sql index 4ed7b8bd5..bfc9358f0 100644 --- a/src/test/regress/sql/granted_by_support.sql +++ b/src/test/regress/sql/granted_by_support.sql @@ -1,31 +1,56 @@ -- Active: 1700033167033@@localhost@9700@gurkanindibay@public --In below tests, complex role hierarchy is created and then granted by support is tested. +--- Test 1: Tests from main database select 1 from citus_remove_node ('localhost',:worker_2_port); +set citus.enable_create_role_propagation to off; +create role non_dist_role1; +reset citus.enable_create_role_propagation; +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; -create role role1; -create role role2; -create role role3; -create role role4; -create role "role5'_test"; +create role dist_role1; +create role dist_role2; +create role dist_role3; +create role dist_role4; +create role "dist_role5'_test"; -grant role2 to role1 with admin option; -grant role2 to role3 with admin option granted by role1; -grant role3 to role4 with admin option; -grant role3 to "role5'_test" granted by role4; -grant role2 to "role5'_test" granted by role3; -grant role4 to "role5'_test" with admin option; -grant role4 to role1 with admin option GRANTED BY "role5'_test"; -grant role4 to role3 with admin option GRANTED BY role1; -grant role3 to role1 with admin option GRANTED BY role4; -grant "role5'_test" to role1 with admin option; -grant "role5'_test" to role3 with admin option GRANTED BY role1; +grant dist_role2 to dist_role1 with admin option; +grant dist_role2 to dist_role3 with admin option granted by dist_role1; +grant dist_role3 to dist_role4 with admin option; -SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option - FROM pg_auth_members - WHERE member::regrole::text in - ('role1','role2','role3','role4','"role5''_test"') - order by member::regrole::text, roleid::regrole::text; +-- With enable_create_role_propagation on, all grantees are propagated. +-- To test non-distributed grantor, set this option off for some roles. +set citus.enable_create_role_propagation to off; +grant non_dist_role1 to dist_role1 with admin option; +reset citus.enable_create_role_propagation; + +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + + + +grant dist_role2 to non_dist_role1 with admin option; + +grant dist_role3 to "dist_role5'_test" granted by dist_role4; +grant dist_role2 to "dist_role5'_test" granted by dist_role3; +grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed + + +grant dist_role4 to "dist_role5'_test" with admin option; + +--below command propagates the non_dist_role1 since non_dist_role1 is already granted to dist_role1 +--and citus sees granted roles as a dependency and citus propagates the dependent roles +grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; + +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + +grant dist_role4 to dist_role3 with admin option GRANTED BY dist_role1; --fails since already dist_role3 granted to dist_role4 + +grant non_dist_role1 to dist_role4 granted by dist_role1; + + +grant dist_role3 to dist_role1 with admin option GRANTED BY dist_role4; +grant "dist_role5'_test" to dist_role1 with admin option; +grant "dist_role5'_test" to dist_role3 with admin option GRANTED BY dist_role1;--fails since already dist_role3 granted to "dist_role5'_test" select result FROM run_command_on_all_nodes( @@ -35,7 +60,139 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('role1','role2','role3','role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + +select 1 from citus_add_node ('localhost',:worker_2_port); + +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + +--clean all resources +drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; +drop role non_dist_role1; + +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; +reset citus.enable_create_role_propagation; + +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + +--- Test 2: Tests from non-main database +set citus.enable_create_database_propagation to on; +create database test_granted_by_support; + +select 1 from citus_remove_node ('localhost',:worker_2_port); + +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + +\c test_granted_by_support +--here in below block since 'citus.enable_create_role_propagation to off ' is not effective, +--non_dist_role1 is being propagated to dist_role1 unlike main db scenario +--non_dist_role1 will be used for the test scenarios in this section +set citus.enable_create_role_propagation to off; +create role non_dist_role1; +reset citus.enable_create_role_propagation; + +--dropping since it isn't non-distributed as intended +drop role non_dist_role1; + +--creating non_dist_role1 again in main database +--This is actually non-distributed role +\c regression +set citus.enable_create_role_propagation to off; +create role non_dist_role1; +reset citus.enable_create_role_propagation; + +\c test_granted_by_support +create role dist_role1; +create role dist_role1; +create role dist_role2; +create role dist_role3; +create role dist_role4; +create role "dist_role5'_test"; +\c regression - - :master_port +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + + +\c test_granted_by_support +grant dist_role2 to dist_role1 with admin option; +grant dist_role2 to dist_role3 with admin option granted by dist_role1; +grant dist_role3 to dist_role4 with admin option; + +-- With enable_create_role_propagation on, all grantees are propagated. +-- To test non-distributed grantor, set this option off for some roles. + +\c regression +set citus.enable_create_role_propagation to off; +grant non_dist_role1 to dist_role1 with admin option; +reset citus.enable_create_role_propagation; + +\c test_granted_by_support +grant dist_role2 to non_dist_role1 with admin option; + +\c test_granted_by_support - - :worker_1_port +grant dist_role3 to "dist_role5'_test" granted by dist_role4; +grant dist_role2 to "dist_role5'_test" granted by dist_role3; +grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed +\c regression - - :master_port +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; +\c test_granted_by_support - - :worker_1_port +grant dist_role4 to "dist_role5'_test" with admin option; + +\c regression - - :master_port +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + +\c test_granted_by_support + +-- Unlike maindb scenario, non-maindb scenario doesn't propagate 'create non_dist_role1' to +--workers as it doesn't create dependency objects for non-distributed roles. +grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; + +\c regression - - :master_port +select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; + + +\c test_granted_by_support - - :worker_1_port +grant dist_role4 to dist_role3 with admin option GRANTED BY dist_role1; --fails since already dist_role3 granted to dist_role4 +grant non_dist_role1 to dist_role4 granted by dist_role1; +grant dist_role3 to dist_role1 with admin option GRANTED BY dist_role4; +grant "dist_role5'_test" to dist_role1 with admin option; +grant "dist_role5'_test" to dist_role3 with admin option GRANTED BY dist_role1;--fails since already dist_role3 granted to "dist_role5'_test" + +\c regression - - :master_port + +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') order by member::regrole::text, roleid::regrole::text ) t $$ @@ -49,14 +206,23 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('role1','role2','role3','role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') order by member::regrole::text, roleid::regrole::text ) t $$ ); --clean all resources -drop role role1,role2,role3,role4,"role5'_test"; + +set citus.enable_create_database_propagation to on; +drop database test_granted_by_support; +drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; +drop role non_dist_role1; +drop role if exists non_dist_role1; + + + + select result FROM run_command_on_all_nodes( $$ @@ -65,8 +231,9 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('role1','role2','role3','role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') order by member::regrole::text, roleid::regrole::text ) t $$ ); +reset citus.enable_create_database_propagation; From 93c140a91367560777f6ad7781ad8b4325deef36 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 11 Mar 2024 11:35:07 +0300 Subject: [PATCH 08/23] Fixes compile error --- src/backend/distributed/commands/role.c | 10 +--------- src/include/distributed/commands.h | 8 ++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index 797a63a02..2604aa5bb 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -56,13 +56,6 @@ #include "distributed/version_compat.h" #include "distributed/worker_transaction.h" -typedef struct DistributedRolesInGrantRoleStmt -{ - List *distributedGrantees; - List *distributedGrantedRoles; - RoleSpec *grantor; - bool isGrantRoleStmtValid; -} DistributedRolesInGrantRoleStmt; static const char * ExtractEncryptedPassword(Oid roleOid); static const char * CreateAlterRoleIfExistsCommand(AlterRoleStmt *stmt); @@ -1440,8 +1433,7 @@ ExtractDistributedRolesInGrantRoleStmt(GrantRoleStmt *stmt) bool grantorMissingOk = false; bool isGrantorDefined = distributedRolesInGrantRoleStmt->grantor != NULL && get_rolespec_oid(distributedRolesInGrantRoleStmt->grantor, - grantorMissingOk) != - InvalidOid; + grantorMissingOk) != InvalidOid; bool isGrantorDistributed = IsAnyObjectDistributed(RoleSpecToObjectAddress( distributedRolesInGrantRoleStmt ->grantor, grantorMissingOk)); diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index e0b45a8a2..d2dd3566a 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -170,6 +170,14 @@ typedef enum TenantOperation TENANT_SET_SCHEMA, } TenantOperation; +typedef struct DistributedRolesInGrantRoleStmt +{ + List *distributedGrantees; + List *distributedGrantedRoles; + RoleSpec *grantor; + bool isGrantRoleStmtValid; +} DistributedRolesInGrantRoleStmt; + #define TOTAL_TENANT_OPERATION 5 extern const char *TenantOperationNames[TOTAL_TENANT_OPERATION]; From 154dfeed490ad2ad0d9c97bf5b1b5ea76c2c1c67 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 11 Mar 2024 12:17:57 +0300 Subject: [PATCH 09/23] Fixes create_role_propagation --- .../expected/create_role_propagation.out | 44 +++++++++++++------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/src/test/regress/expected/create_role_propagation.out b/src/test/regress/expected/create_role_propagation.out index 3241cd846..9e6e1a737 100644 --- a/src/test/regress/expected/create_role_propagation.out +++ b/src/test/regress/expected/create_role_propagation.out @@ -225,6 +225,10 @@ SET citus.enable_create_role_propagation TO ON; grant dist_role_3,dist_role_1 to test_admin_role with admin option; SET ROLE dist_role_1; GRANT non_dist_role_1 TO non_dist_role_2; +NOTICE: not propagating GRANT command to other nodes +HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. +NOTICE: not propagating GRANT command to other nodes +HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. SET citus.enable_create_role_propagation TO OFF; grant dist_role_1 to non_dist_role_1 with admin option; SET ROLE non_dist_role_1; @@ -232,7 +236,11 @@ GRANT dist_role_1 TO dist_role_2 granted by non_dist_role_1; RESET ROLE; SET citus.enable_create_role_propagation TO ON; GRANT dist_role_3 TO non_dist_role_3 granted by test_admin_role; +NOTICE: not propagating GRANT command to other nodes +HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. GRANT non_dist_role_4 TO dist_role_4; +NOTICE: not propagating GRANT command to other nodes +HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. GRANT dist_role_3 TO dist_role_4 granted by test_admin_role; SELECT 1 FROM master_add_node('localhost', :worker_2_port); ?column? @@ -300,6 +308,8 @@ SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid':: (5 rows) REVOKE dist_role_3 from non_dist_role_3 granted by test_admin_role cascade; +NOTICE: not propagating GRANT command to other nodes +HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. SELECT result FROM run_command_on_all_nodes( $$ SELECT json_agg(q.* ORDER BY member) FROM ( @@ -320,10 +330,9 @@ revoke dist_role_3,dist_role_1 from test_admin_role cascade; drop role test_admin_role; \c - - - :worker_1_port SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_%' ORDER BY 1, 2; - role | member | grantor | admin_option + role | member | grantor | admin_option --------------------------------------------------------------------- - non_dist_role_4 | dist_role_4 | postgres | f -(1 row) +(0 rows) SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_%' ORDER BY 1; rolname @@ -435,15 +444,13 @@ SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid':: \c - - - :worker_1_port SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1, 2; - role | member | grantor | admin_option + role | member | grantor | admin_option --------------------------------------------------------------------- - dist_mixed_1 | dist_mixed_3 | postgres | f - dist_mixed_1 | dist_mixed_4 | postgres | f - dist_mixed_2 | dist_mixed_3 | postgres | f - dist_mixed_2 | dist_mixed_4 | postgres | f - nondist_mixed_1 | dist_mixed_3 | postgres | f - nondist_mixed_1 | dist_mixed_4 | postgres | f -(6 rows) + dist_mixed_1 | dist_mixed_3 | postgres | f + dist_mixed_1 | dist_mixed_4 | postgres | f + dist_mixed_2 | dist_mixed_3 | postgres | f + dist_mixed_2 | dist_mixed_4 | postgres | f +(4 rows) SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; rolname @@ -571,7 +578,15 @@ HINT: Connect to other nodes directly to manually create all necessary users an SET citus.enable_create_role_propagation TO ON; CREATE ROLE dist_cascade; GRANT nondist_cascade_1 TO nondist_cascade_2; +NOTICE: not propagating GRANT command to other nodes +HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. +NOTICE: not propagating GRANT command to other nodes +HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. GRANT nondist_cascade_2 TO nondist_cascade_3; +NOTICE: not propagating GRANT command to other nodes +HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. +NOTICE: not propagating GRANT command to other nodes +HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%cascade%' ORDER BY 1; objid --------------------------------------------------------------------- @@ -605,6 +620,8 @@ SELECT master_remove_node('localhost', :worker_2_port); (1 row) GRANT nondist_cascade_3 TO dist_cascade; +NOTICE: not propagating GRANT command to other nodes +HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. SELECT 1 FROM master_add_node('localhost', :worker_2_port); ?column? --------------------------------------------------------------------- @@ -643,8 +660,7 @@ SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::t --------------------------------------------------------------------- nondist_cascade_1 | nondist_cascade_2 | postgres | f nondist_cascade_2 | nondist_cascade_3 | postgres | f - nondist_cascade_3 | dist_cascade | postgres | f -(3 rows) +(2 rows) \c - - - :worker_2_port SELECT rolname FROM pg_authid WHERE rolname LIKE '%cascade%' ORDER BY 1; @@ -675,7 +691,7 @@ SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::t (0 rows) GRANT existing_role_1, nonexisting_role_1 TO existing_role_2, nonexisting_role_2; -ERROR: role "nonexisting_role_2" does not exist +ERROR: role "nonexisting_role_1" does not exist SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%existing%' ORDER BY 1, 2; role | member | grantor | admin_option --------------------------------------------------------------------- From 77f0e4be8656698b94dd618b6f846a30050e1f8b Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 11 Mar 2024 12:19:04 +0300 Subject: [PATCH 10/23] Removes useless parameter --- src/backend/distributed/commands/role.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index 2604aa5bb..ea2486d96 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -879,7 +879,6 @@ GenerateGrantRoleStmtsOfRole(Oid roleid) List *adminStmts = NIL; List *otherStmts = NIL; - List *allStmts = NIL; ScanKeyData skey[1]; @@ -911,7 +910,7 @@ GenerateGrantRoleStmtsOfRole(Oid roleid) systable_endscan(scan); table_close(pgAuthMembers, AccessShareLock); - allStmts = list_concat(adminStmts, otherStmts); + List *allStmts = list_concat(adminStmts, otherStmts); List *commands = NIL; Node *stmt = NULL; foreach_ptr(stmt, allStmts) From 6ba4ee036c4c8a47d6aaac9b491484445d295401 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 11 Mar 2024 12:42:36 +0300 Subject: [PATCH 11/23] Changes dist_object check --- .../regress/expected/granted_by_support.out | 36 +++++++++---------- src/test/regress/sql/granted_by_support.sql | 18 +++++----- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/test/regress/expected/granted_by_support.out b/src/test/regress/expected/granted_by_support.out index 3a956bd52..4e44b4c7d 100644 --- a/src/test/regress/expected/granted_by_support.out +++ b/src/test/regress/expected/granted_by_support.out @@ -12,8 +12,8 @@ create role non_dist_role1; NOTICE: not propagating CREATE ROLE/USER commands to other nodes HINT: Connect to other nodes directly to manually create all necessary users and roles. reset citus.enable_create_role_propagation; -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; - rolname +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid --------------------------------------------------------------------- (0 rows) @@ -30,8 +30,8 @@ grant dist_role3 to dist_role4 with admin option; set citus.enable_create_role_propagation to off; grant non_dist_role1 to dist_role1 with admin option; reset citus.enable_create_role_propagation; -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; - rolname +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid --------------------------------------------------------------------- (0 rows) @@ -47,8 +47,8 @@ grant dist_role4 to "dist_role5'_test" with admin option; --below command propagates the non_dist_role1 since non_dist_role1 is already granted to dist_role1 --and citus sees granted roles as a dependency and citus propagates the dependent roles grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; - rolname +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid --------------------------------------------------------------------- non_dist_role1 (1 row) @@ -109,8 +109,8 @@ select result FROM run_command_on_all_nodes( --clean all resources drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; drop role non_dist_role1; -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; - rolname +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid --------------------------------------------------------------------- (0 rows) @@ -143,8 +143,8 @@ select 1 from citus_remove_node ('localhost',:worker_2_port); 1 (1 row) -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; - rolname +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid --------------------------------------------------------------------- (0 rows) @@ -174,8 +174,8 @@ create role dist_role3; create role dist_role4; create role "dist_role5'_test"; \c regression - - :master_port -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; - rolname +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid --------------------------------------------------------------------- (0 rows) @@ -199,16 +199,16 @@ grant dist_role2 to "dist_role5'_test" granted by dist_role3; grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed ERROR: role "non_dist_role1" does not exist \c regression - - :master_port -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; - rolname +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid --------------------------------------------------------------------- (0 rows) \c test_granted_by_support - - :worker_1_port grant dist_role4 to "dist_role5'_test" with admin option; \c regression - - :master_port -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; - rolname +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid --------------------------------------------------------------------- (0 rows) @@ -217,8 +217,8 @@ select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid whe --workers as it doesn't create dependency objects for non-distributed roles. grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; \c regression - - :master_port -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; - rolname +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid --------------------------------------------------------------------- (0 rows) diff --git a/src/test/regress/sql/granted_by_support.sql b/src/test/regress/sql/granted_by_support.sql index bfc9358f0..fcec183c5 100644 --- a/src/test/regress/sql/granted_by_support.sql +++ b/src/test/regress/sql/granted_by_support.sql @@ -6,7 +6,7 @@ select 1 from citus_remove_node ('localhost',:worker_2_port); set citus.enable_create_role_propagation to off; create role non_dist_role1; reset citus.enable_create_role_propagation; -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; create role dist_role1; create role dist_role2; @@ -24,7 +24,7 @@ set citus.enable_create_role_propagation to off; grant non_dist_role1 to dist_role1 with admin option; reset citus.enable_create_role_propagation; -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; @@ -41,7 +41,7 @@ grant dist_role4 to "dist_role5'_test" with admin option; --and citus sees granted roles as a dependency and citus propagates the dependent roles grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; grant dist_role4 to dist_role3 with admin option GRANTED BY dist_role1; --fails since already dist_role3 granted to dist_role4 @@ -85,7 +85,7 @@ select result FROM run_command_on_all_nodes( drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; drop role non_dist_role1; -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; reset citus.enable_create_role_propagation; select result FROM run_command_on_all_nodes( @@ -107,7 +107,7 @@ create database test_granted_by_support; select 1 from citus_remove_node ('localhost',:worker_2_port); -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; \c test_granted_by_support --here in below block since 'citus.enable_create_role_propagation to off ' is not effective, @@ -135,7 +135,7 @@ create role dist_role3; create role dist_role4; create role "dist_role5'_test"; \c regression - - :master_port -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; \c test_granted_by_support @@ -159,12 +159,12 @@ grant dist_role3 to "dist_role5'_test" granted by dist_role4; grant dist_role2 to "dist_role5'_test" granted by dist_role3; grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed \c regression - - :master_port -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; \c test_granted_by_support - - :worker_1_port grant dist_role4 to "dist_role5'_test" with admin option; \c regression - - :master_port -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; \c test_granted_by_support @@ -173,7 +173,7 @@ select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid whe grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; \c regression - - :master_port -select r.rolname from pg_roles r inner join pg_dist_object o on r.oid= objid where r.rolname = 'non_dist_role1'; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; \c test_granted_by_support - - :worker_1_port From b151c41a1338c7a0663774dde777c3aee3f1f3a9 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 11 Mar 2024 15:09:05 +0300 Subject: [PATCH 12/23] Fixes system role filters --- src/backend/distributed/commands/role.c | 18 ++++++++++-------- .../regress/expected/granted_by_support.out | 2 ++ src/test/regress/sql/granted_by_support.sql | 7 +++---- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index ea2486d96..fde986dc2 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -1317,7 +1317,7 @@ UnmarkRolesDistributed(List *roles) List * FilterDistributedRoles(List *roles) { - List *distributedRoles = NIL; + List *validRoles = NIL; Node *roleNode = NULL; foreach_ptr(roleNode, roles) { @@ -1333,12 +1333,13 @@ FilterDistributedRoles(List *roles) } ObjectAddress *roleAddress = palloc0(sizeof(ObjectAddress)); ObjectAddressSet(*roleAddress, AuthIdRelationId, roleOid); - if (IsAnyObjectDistributed(list_make1(roleAddress))) + bool isSystemRole = IsReservedName(role->rolename); + if (IsAnyObjectDistributed(list_make1(roleAddress)) || isSystemRole) { - distributedRoles = lappend(distributedRoles, role); + validRoles = lappend(validRoles, role); } } - return distributedRoles; + return validRoles; } @@ -1349,7 +1350,7 @@ FilterDistributedRoles(List *roles) List * FilterDistributedGrantedRoles(List *roles) { - List *distributedRoles = NIL; + List *validRoles = NIL; Node *roleNode = NULL; foreach_ptr(roleNode, roles) { @@ -1365,12 +1366,13 @@ FilterDistributedGrantedRoles(List *roles) } ObjectAddress *roleAddress = palloc0(sizeof(ObjectAddress)); ObjectAddressSet(*roleAddress, AuthIdRelationId, roleOid); - if (IsAnyObjectDistributed(list_make1(roleAddress))) + bool isSystemRole = IsReservedName(role->priv_name); + if (IsAnyObjectDistributed(list_make1(roleAddress)) || isSystemRole) { - distributedRoles = lappend(distributedRoles, role); + validRoles = lappend(validRoles, role); } } - return distributedRoles; + return validRoles; } diff --git a/src/test/regress/expected/granted_by_support.out b/src/test/regress/expected/granted_by_support.out index 4e44b4c7d..4928f5516 100644 --- a/src/test/regress/expected/granted_by_support.out +++ b/src/test/regress/expected/granted_by_support.out @@ -55,6 +55,8 @@ SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid':: grant dist_role4 to dist_role3 with admin option GRANTED BY dist_role1; --fails since already dist_role3 granted to dist_role4 ERROR: role "dist_role4" is a member of role "dist_role3" +--Below command will not be successful since non_dist_role1 is propagated with the dependency resolution above +--however, ADMIN OPTION is not propagated for non_dist_role1 to worker 1 because the citus.enable_create_role_propagation is off grant non_dist_role1 to dist_role4 granted by dist_role1; ERROR: permission denied to grant privileges as role "dist_role1" DETAIL: The grantor must have the ADMIN option on role "non_dist_role1". diff --git a/src/test/regress/sql/granted_by_support.sql b/src/test/regress/sql/granted_by_support.sql index fcec183c5..1261e78d4 100644 --- a/src/test/regress/sql/granted_by_support.sql +++ b/src/test/regress/sql/granted_by_support.sql @@ -45,9 +45,10 @@ SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid':: grant dist_role4 to dist_role3 with admin option GRANTED BY dist_role1; --fails since already dist_role3 granted to dist_role4 +--Below command will not be successful since non_dist_role1 is propagated with the dependency resolution above +--however, ADMIN OPTION is not propagated for non_dist_role1 to worker 1 because the citus.enable_create_role_propagation is off grant non_dist_role1 to dist_role4 granted by dist_role1; - grant dist_role3 to dist_role1 with admin option GRANTED BY dist_role4; grant "dist_role5'_test" to dist_role1 with admin option; grant "dist_role5'_test" to dist_role3 with admin option GRANTED BY dist_role1;--fails since already dist_role3 granted to "dist_role5'_test" @@ -218,12 +219,10 @@ set citus.enable_create_database_propagation to on; drop database test_granted_by_support; drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; drop role non_dist_role1; + drop role if exists non_dist_role1; - - - select result FROM run_command_on_all_nodes( $$ SELECT array_to_json(array_agg(row_to_json(t))) From e8fb4c694cf9c4a05b0e3451ba827c48458c0e85 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 11 Mar 2024 16:08:56 +0300 Subject: [PATCH 13/23] Fixes pg14 and pg15 outputs --- .../regress/expected/granted_by_support_0.out | 303 ++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 src/test/regress/expected/granted_by_support_0.out diff --git a/src/test/regress/expected/granted_by_support_0.out b/src/test/regress/expected/granted_by_support_0.out new file mode 100644 index 000000000..3de13a622 --- /dev/null +++ b/src/test/regress/expected/granted_by_support_0.out @@ -0,0 +1,303 @@ +-- Active: 1700033167033@@localhost@9700@gurkanindibay@public +--In below tests, complex role hierarchy is created and then granted by support is tested. +--- Test 1: Tests from main database +select 1 from citus_remove_node ('localhost',:worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +set citus.enable_create_role_propagation to off; +create role non_dist_role1; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +reset citus.enable_create_role_propagation; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid +--------------------------------------------------------------------- +(0 rows) + +create role dist_role1; +create role dist_role2; +create role dist_role3; +create role dist_role4; +create role "dist_role5'_test"; +grant dist_role2 to dist_role1 with admin option; +grant dist_role2 to dist_role3 with admin option granted by dist_role1; +grant dist_role3 to dist_role4 with admin option; +-- With enable_create_role_propagation on, all grantees are propagated. +-- To test non-distributed grantor, set this option off for some roles. +set citus.enable_create_role_propagation to off; +grant non_dist_role1 to dist_role1 with admin option; +reset citus.enable_create_role_propagation; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid +--------------------------------------------------------------------- +(0 rows) + +grant dist_role2 to non_dist_role1 with admin option; +NOTICE: not propagating GRANT command to other nodes +HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. +grant dist_role3 to "dist_role5'_test" granted by dist_role4; +grant dist_role2 to "dist_role5'_test" granted by dist_role3; +grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed +NOTICE: not propagating GRANT command to other nodes +HINT: Since grantor is not distributed, the GRANT command will not be propagated to other nodes. +grant dist_role4 to "dist_role5'_test" with admin option; +--below command propagates the non_dist_role1 since non_dist_role1 is already granted to dist_role1 +--and citus sees granted roles as a dependency and citus propagates the dependent roles +grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid +--------------------------------------------------------------------- + non_dist_role1 +(1 row) + +grant dist_role4 to dist_role3 with admin option GRANTED BY dist_role1; --fails since already dist_role3 granted to dist_role4 +ERROR: role "dist_role4" is a member of role "dist_role3" +--Below command will not be successful since non_dist_role1 is propagated with the dependency resolution above +--however, ADMIN OPTION is not propagated for non_dist_role1 to worker 1 because the citus.enable_create_role_propagation is off +grant non_dist_role1 to dist_role4 granted by dist_role1; +grant dist_role3 to dist_role1 with admin option GRANTED BY dist_role4; +grant "dist_role5'_test" to dist_role1 with admin option; +grant "dist_role5'_test" to dist_role3 with admin option GRANTED BY dist_role1;--fails since already dist_role3 granted to "dist_role5'_test" +ERROR: role "dist_role5'_test" is a member of role "dist_role3" +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false}] +(2 rows) + +select 1 from citus_add_node ('localhost',:worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false}] +(3 rows) + +--clean all resources +drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; +drop role non_dist_role1; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid +--------------------------------------------------------------------- +(0 rows) + +reset citus.enable_create_role_propagation; +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + + + +(3 rows) + +--- Test 2: Tests from non-main database +set citus.enable_create_database_propagation to on; +create database test_granted_by_support; +select 1 from citus_remove_node ('localhost',:worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid +--------------------------------------------------------------------- +(0 rows) + +\c test_granted_by_support +--here in below block since 'citus.enable_create_role_propagation to off ' is not effective, +--non_dist_role1 is being propagated to dist_role1 unlike main db scenario +--non_dist_role1 will be used for the test scenarios in this section +set citus.enable_create_role_propagation to off; +create role non_dist_role1; +reset citus.enable_create_role_propagation; +--dropping since it isn't non-distributed as intended +drop role non_dist_role1; +--creating non_dist_role1 again in main database +--This is actually non-distributed role +\c regression +set citus.enable_create_role_propagation to off; +create role non_dist_role1; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +reset citus.enable_create_role_propagation; +\c test_granted_by_support +create role dist_role1; +create role dist_role1; +ERROR: role "dist_role1" already exists +create role dist_role2; +create role dist_role3; +create role dist_role4; +create role "dist_role5'_test"; +\c regression - - :master_port +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid +--------------------------------------------------------------------- +(0 rows) + +\c test_granted_by_support +grant dist_role2 to dist_role1 with admin option; +grant dist_role2 to dist_role3 with admin option granted by dist_role1; +grant dist_role3 to dist_role4 with admin option; +-- With enable_create_role_propagation on, all grantees are propagated. +-- To test non-distributed grantor, set this option off for some roles. +\c regression +set citus.enable_create_role_propagation to off; +grant non_dist_role1 to dist_role1 with admin option; +reset citus.enable_create_role_propagation; +\c test_granted_by_support +grant dist_role2 to non_dist_role1 with admin option; +ERROR: failure on connection marked as essential: localhost:xxxxx +CONTEXT: while executing command on localhost:xxxxx +\c test_granted_by_support - - :worker_1_port +grant dist_role3 to "dist_role5'_test" granted by dist_role4; +grant dist_role2 to "dist_role5'_test" granted by dist_role3; +grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed +ERROR: role "non_dist_role1" does not exist +\c regression - - :master_port +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid +--------------------------------------------------------------------- +(0 rows) + +\c test_granted_by_support - - :worker_1_port +grant dist_role4 to "dist_role5'_test" with admin option; +\c regression - - :master_port +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid +--------------------------------------------------------------------- +(0 rows) + +\c test_granted_by_support +-- Unlike maindb scenario, non-maindb scenario doesn't propagate 'create non_dist_role1' to +--workers as it doesn't create dependency objects for non-distributed roles. +grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; +\c regression - - :master_port +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid +--------------------------------------------------------------------- +(0 rows) + +\c test_granted_by_support - - :worker_1_port +grant dist_role4 to dist_role3 with admin option GRANTED BY dist_role1; --fails since already dist_role3 granted to dist_role4 +ERROR: role "dist_role4" is a member of role "dist_role3" +grant non_dist_role1 to dist_role4 granted by dist_role1; +ERROR: role "non_dist_role1" does not exist +grant dist_role3 to dist_role1 with admin option GRANTED BY dist_role4; +grant "dist_role5'_test" to dist_role1 with admin option; +grant "dist_role5'_test" to dist_role3 with admin option GRANTED BY dist_role1;--fails since already dist_role3 granted to "dist_role5'_test" +ERROR: role "dist_role5'_test" is a member of role "dist_role3" +\c regression - - :master_port +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] +(2 rows) + +select 1 from citus_add_node ('localhost',:worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] +(3 rows) + +--clean all resources +set citus.enable_create_database_propagation to on; +drop database test_granted_by_support; +drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; +drop role non_dist_role1; +drop role if exists non_dist_role1; +NOTICE: role "non_dist_role1" does not exist, skipping +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + + + +(3 rows) + +reset citus.enable_create_database_propagation; From e0cc004c7e0da3cd5119c3b0eff75266f3f99d9f Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 11 Mar 2024 16:12:26 +0300 Subject: [PATCH 14/23] Fixes pg16 output --- src/test/regress/expected/pg16.out | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/test/regress/expected/pg16.out b/src/test/regress/expected/pg16.out index a035fcfc4..40e671db6 100644 --- a/src/test/regress/expected/pg16.out +++ b/src/test/regress/expected/pg16.out @@ -1032,14 +1032,14 @@ WHERE roleid::regrole::text = 'role1' ORDER BY 1, 2; -- Set GUCs to log remote commands and filter on REVOKE commands SET citus.log_remote_commands TO on; SET citus.grep_remote_commands = '%REVOKE%'; - -- test REVOKES as well - GRANT role1 TO role2; - REVOKE SET OPTION FOR role1 FROM role2; +-- test REVOKES as well +GRANT role1 TO role2; +REVOKE SET OPTION FOR role1 FROM role2; NOTICE: issuing REVOKE SET OPTION FOR role1 FROM role2 RESTRICT; DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing REVOKE SET OPTION FOR role1 FROM role2 RESTRICT; DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx - REVOKE INHERIT OPTION FOR role1 FROM role2; +REVOKE INHERIT OPTION FOR role1 FROM role2; NOTICE: issuing REVOKE INHERIT OPTION FOR role1 FROM role2 RESTRICT; DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing REVOKE INHERIT OPTION FOR role1 FROM role2 RESTRICT; @@ -1053,7 +1053,15 @@ CREATE ROLE role5; RESET citus.enable_ddl_propagation; -- by default, admin option is false, inherit is true, set is true GRANT role3 TO role4; +NOTICE: not propagating GRANT command to other nodes +HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. +NOTICE: not propagating GRANT command to other nodes +HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. GRANT role3 TO role5 WITH ADMIN TRUE, INHERIT FALSE, SET FALSE; +NOTICE: not propagating GRANT command to other nodes +HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. +NOTICE: not propagating GRANT command to other nodes +HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. SELECT roleid::regrole::text AS role, member::regrole::text, admin_option, inherit_option, set_option FROM pg_auth_members WHERE roleid::regrole::text = 'role3' ORDER BY 1, 2; role | member | admin_option | inherit_option | set_option @@ -1140,7 +1148,7 @@ DROP ROLE role6, role7, role8, role9, role10, role11, role12, -- when adding a new node. -- First, we need to remove the node: SELECT 1 FROM citus_remove_node('localhost', :worker_2_port); -?column? + ?column? --------------------------------------------------------------------- 1 (1 row) From 029b0e16974377a0c0b8d0a96cf1504df9f452d6 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Wed, 13 Mar 2024 11:28:15 +0300 Subject: [PATCH 15/23] Removes all filters for roles --- src/backend/distributed/commands/role.c | 43 ---- .../regress/expected/granted_by_support.out | 18 +- src/test/regress/sql/granted_by_support.sql | 191 +++++------------- 3 files changed, 59 insertions(+), 193 deletions(-) diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index fde986dc2..ec7e1430b 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -937,28 +937,6 @@ GenerateGrantRoleStmts() { Form_pg_auth_members membership = (Form_pg_auth_members) GETSTRUCT(tuple); - /* we only propagate the grant if the grantor is - * member and role are distributed since all are required - * to be distributed for the grant to be propagated - */ - - - bool isAuthMemberDistributed = IsAnyObjectDistributed(list_make1( - GetRoleObjectAddressFromOid( - membership->grantor))) - && - IsAnyObjectDistributed(list_make1( - GetRoleObjectAddressFromOid( - membership->member))) - && - IsAnyObjectDistributed(list_make1( - GetRoleObjectAddressFromOid( - membership->roleid))); - if (!isAuthMemberDistributed) - { - /* we only need to propagate the grant if the grantor is distributed */ - continue; - } GrantRoleStmt *grantRoleStmt = GetGrantRoleStmtFromAuthMemberRecord(membership); if (grantRoleStmt == NULL) @@ -1009,11 +987,6 @@ GetGrantRoleStmtFromAuthMemberRecord(Form_pg_auth_members membership) { ObjectAddress *roleAddress = palloc0(sizeof(ObjectAddress)); ObjectAddressSet(*roleAddress, AuthIdRelationId, membership->grantor); - if (!IsAnyObjectDistributed(list_make1(roleAddress))) - { - /* we only need to propagate the grant if the grantor is distributed */ - return NULL; - } GrantRoleStmt *grantRoleStmt = makeNode(GrantRoleStmt); grantRoleStmt->is_grant = true; @@ -1392,24 +1365,8 @@ PreprocessGrantRoleStmt(Node *node, const char *queryString, EnsurePropagationToCoordinator(); GrantRoleStmt *stmt = castNode(GrantRoleStmt, node); - List *allGranteeRoles = stmt->grantee_roles; - List *allGrantedRoles = stmt->granted_roles; - RoleSpec *grantor = stmt->grantor; - DistributedRolesInGrantRoleStmt *distributedRolesInGrantStmt = - ExtractDistributedRolesInGrantRoleStmt(stmt); - - if (!distributedRolesInGrantStmt->isGrantRoleStmtValid) - { - return NIL; - } - - stmt->grantee_roles = distributedRolesInGrantStmt->distributedGrantees; - stmt->granted_roles = distributedRolesInGrantStmt->distributedGrantedRoles; char *sql = DeparseTreeNode((Node *) stmt); - stmt->grantee_roles = allGranteeRoles; - stmt->granted_roles = allGrantedRoles; - stmt->grantor = grantor; List *commands = list_make3(DISABLE_DDL_PROPAGATION, sql, diff --git a/src/test/regress/expected/granted_by_support.out b/src/test/regress/expected/granted_by_support.out index 4928f5516..2ab0e6c7b 100644 --- a/src/test/regress/expected/granted_by_support.out +++ b/src/test/regress/expected/granted_by_support.out @@ -36,13 +36,13 @@ SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid':: (0 rows) grant dist_role2 to non_dist_role1 with admin option; -NOTICE: not propagating GRANT command to other nodes -HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. +ERROR: role "non_dist_role1" does not exist +CONTEXT: while executing command on localhost:xxxxx grant dist_role3 to "dist_role5'_test" granted by dist_role4; grant dist_role2 to "dist_role5'_test" granted by dist_role3; grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed -NOTICE: not propagating GRANT command to other nodes -HINT: Since grantor is not distributed, the GRANT command will not be propagated to other nodes. +ERROR: permission denied to grant privileges as role "non_dist_role1" +DETAIL: The grantor must have the ADMIN option on role "dist_role2". grant dist_role4 to "dist_role5'_test" with admin option; --below command propagates the non_dist_role1 since non_dist_role1 is already granted to dist_role1 --and citus sees granted roles as a dependency and citus propagates the dependent roles @@ -77,9 +77,9 @@ select result FROM run_command_on_all_nodes( ) t $$ ); - result + result --------------------------------------------------------------------- - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] (2 rows) @@ -101,11 +101,11 @@ select result FROM run_command_on_all_nodes( ) t $$ ); - result + result --------------------------------------------------------------------- - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] (3 rows) --clean all resources diff --git a/src/test/regress/sql/granted_by_support.sql b/src/test/regress/sql/granted_by_support.sql index 1261e78d4..afd3e416c 100644 --- a/src/test/regress/sql/granted_by_support.sql +++ b/src/test/regress/sql/granted_by_support.sql @@ -22,23 +22,52 @@ grant dist_role3 to dist_role4 with admin option; -- To test non-distributed grantor, set this option off for some roles. set citus.enable_create_role_propagation to off; grant non_dist_role1 to dist_role1 with admin option; +grant dist_role2 to non_dist_role1 with admin option; +grant dist_role2 to dist_role4 granted by non_dist_role1 ; reset citus.enable_create_role_propagation; -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; +grant dist_role2 to "dist_role5'_test" granted by non_dist_role1;--will fail since non_dist_role1 does not exist on worker_1 - -grant dist_role2 to non_dist_role1 with admin option; - +\c - - - :master_port grant dist_role3 to "dist_role5'_test" granted by dist_role4; grant dist_role2 to "dist_role5'_test" granted by dist_role3; -grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed + + +--will fail since non_dist_role2 does not exist in worker_1 +grant dist_role2 to non_dist_role2 with admin option; +grant dist_role2 to dist_role4 granted by non_dist_role2 ; +grant non_dist_role2 to "dist_role5'_test"; + + +\c - - - :worker_1_port +create role non_dist_role2; + +\c - - - :master_port +--will be successful since non_dist_role has been created on worker_1 +grant dist_role2 to non_dist_role2 with admin option; +grant dist_role2 to dist_role4 granted by non_dist_role2 ; +grant non_dist_role2 to "dist_role5'_test"; grant dist_role4 to "dist_role5'_test" with admin option; +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','non_dist_role1') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + --below command propagates the non_dist_role1 since non_dist_role1 is already granted to dist_role1 --and citus sees granted roles as a dependency and citus propagates the dependent roles + grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; @@ -54,6 +83,18 @@ grant "dist_role5'_test" to dist_role1 with admin option; grant "dist_role5'_test" to dist_role3 with admin option GRANTED BY dist_role1;--fails since already dist_role3 granted to "dist_role5'_test" + + +set citus.enable_create_role_propagation to off; +create role non_dist_role_for_mds; + +grant dist_role3 to non_dist_role_for_mds with admin option; +grant non_dist_role_for_mds to dist_role1 with admin option; + +grant dist_role3 to dist_role4 with admin option GRANTED BY non_dist_role_for_mds; +reset citus.enable_create_role_propagation; + + select result FROM run_command_on_all_nodes( $$ SELECT array_to_json(array_agg(row_to_json(t))) @@ -61,7 +102,7 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"', 'non_dist_role_for_mds','non_dist_role1','non_dist_role2') order by member::regrole::text, roleid::regrole::text ) t $$ @@ -76,7 +117,7 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"','non_dist_role_for_mds','non_dist_role1','non_dist_role2') order by member::regrole::text, roleid::regrole::text ) t $$ @@ -84,7 +125,7 @@ select result FROM run_command_on_all_nodes( --clean all resources drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; -drop role non_dist_role1; +drop role non_dist_role1,non_dist_role2,non_dist_role_for_mds; SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; reset citus.enable_create_role_propagation; @@ -96,143 +137,11 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"','non_dist_role_for_mds','non_dist_role1','non_dist_role2') order by member::regrole::text, roleid::regrole::text ) t $$ ); ---- Test 2: Tests from non-main database -set citus.enable_create_database_propagation to on; -create database test_granted_by_support; - -select 1 from citus_remove_node ('localhost',:worker_2_port); - -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - -\c test_granted_by_support ---here in below block since 'citus.enable_create_role_propagation to off ' is not effective, ---non_dist_role1 is being propagated to dist_role1 unlike main db scenario ---non_dist_role1 will be used for the test scenarios in this section -set citus.enable_create_role_propagation to off; -create role non_dist_role1; -reset citus.enable_create_role_propagation; - ---dropping since it isn't non-distributed as intended -drop role non_dist_role1; - ---creating non_dist_role1 again in main database ---This is actually non-distributed role -\c regression -set citus.enable_create_role_propagation to off; -create role non_dist_role1; -reset citus.enable_create_role_propagation; - -\c test_granted_by_support -create role dist_role1; -create role dist_role1; -create role dist_role2; -create role dist_role3; -create role dist_role4; -create role "dist_role5'_test"; -\c regression - - :master_port -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; -\c test_granted_by_support -grant dist_role2 to dist_role1 with admin option; -grant dist_role2 to dist_role3 with admin option granted by dist_role1; -grant dist_role3 to dist_role4 with admin option; - --- With enable_create_role_propagation on, all grantees are propagated. --- To test non-distributed grantor, set this option off for some roles. - -\c regression -set citus.enable_create_role_propagation to off; -grant non_dist_role1 to dist_role1 with admin option; -reset citus.enable_create_role_propagation; - -\c test_granted_by_support -grant dist_role2 to non_dist_role1 with admin option; - -\c test_granted_by_support - - :worker_1_port -grant dist_role3 to "dist_role5'_test" granted by dist_role4; -grant dist_role2 to "dist_role5'_test" granted by dist_role3; -grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed -\c regression - - :master_port -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; -\c test_granted_by_support - - :worker_1_port -grant dist_role4 to "dist_role5'_test" with admin option; - -\c regression - - :master_port -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - -\c test_granted_by_support - --- Unlike maindb scenario, non-maindb scenario doesn't propagate 'create non_dist_role1' to ---workers as it doesn't create dependency objects for non-distributed roles. -grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; - -\c regression - - :master_port -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - - -\c test_granted_by_support - - :worker_1_port -grant dist_role4 to dist_role3 with admin option GRANTED BY dist_role1; --fails since already dist_role3 granted to dist_role4 -grant non_dist_role1 to dist_role4 granted by dist_role1; -grant dist_role3 to dist_role1 with admin option GRANTED BY dist_role4; -grant "dist_role5'_test" to dist_role1 with admin option; -grant "dist_role5'_test" to dist_role3 with admin option GRANTED BY dist_role1;--fails since already dist_role3 granted to "dist_role5'_test" - -\c regression - - :master_port - -select result FROM run_command_on_all_nodes( - $$ - SELECT array_to_json(array_agg(row_to_json(t))) - FROM ( - SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option - FROM pg_auth_members - WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') - order by member::regrole::text, roleid::regrole::text - ) t - $$ -); -select 1 from citus_add_node ('localhost',:worker_2_port); - -select result FROM run_command_on_all_nodes( - $$ - SELECT array_to_json(array_agg(row_to_json(t))) - FROM ( - SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option - FROM pg_auth_members - WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') - order by member::regrole::text, roleid::regrole::text - ) t - $$ -); - ---clean all resources - -set citus.enable_create_database_propagation to on; -drop database test_granted_by_support; -drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; -drop role non_dist_role1; - -drop role if exists non_dist_role1; - - -select result FROM run_command_on_all_nodes( - $$ - SELECT array_to_json(array_agg(row_to_json(t))) - FROM ( - SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option - FROM pg_auth_members - WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') - order by member::regrole::text, roleid::regrole::text - ) t - $$ -); -reset citus.enable_create_database_propagation; From 632a8613c8d34f5f256ecda22c635a179c2c81dc Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Wed, 13 Mar 2024 12:15:13 +0300 Subject: [PATCH 16/23] Fixes test outputs --- .../expected/create_role_propagation.out | 199 ++++++++---------- src/test/regress/expected/pg16.out | 18 +- .../regress/sql/create_role_propagation.sql | 7 + src/test/regress/sql/granted_by_support.sql | 21 ++ 4 files changed, 118 insertions(+), 127 deletions(-) diff --git a/src/test/regress/expected/create_role_propagation.out b/src/test/regress/expected/create_role_propagation.out index 9e6e1a737..5bdbf5826 100644 --- a/src/test/regress/expected/create_role_propagation.out +++ b/src/test/regress/expected/create_role_propagation.out @@ -225,10 +225,7 @@ SET citus.enable_create_role_propagation TO ON; grant dist_role_3,dist_role_1 to test_admin_role with admin option; SET ROLE dist_role_1; GRANT non_dist_role_1 TO non_dist_role_2; -NOTICE: not propagating GRANT command to other nodes -HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. -NOTICE: not propagating GRANT command to other nodes -HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. +ERROR: connection to the remote node dist_role_1@localhost:xxxxx failed with the following error: FATAL: role "dist_role_1" is not permitted to log in SET citus.enable_create_role_propagation TO OFF; grant dist_role_1 to non_dist_role_1 with admin option; SET ROLE non_dist_role_1; @@ -236,12 +233,17 @@ GRANT dist_role_1 TO dist_role_2 granted by non_dist_role_1; RESET ROLE; SET citus.enable_create_role_propagation TO ON; GRANT dist_role_3 TO non_dist_role_3 granted by test_admin_role; -NOTICE: not propagating GRANT command to other nodes -HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. +ERROR: role "non_dist_role_3" does not exist +CONTEXT: while executing command on localhost:xxxxx GRANT non_dist_role_4 TO dist_role_4; -NOTICE: not propagating GRANT command to other nodes -HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. GRANT dist_role_3 TO dist_role_4 granted by test_admin_role; +SELECT 1 FROM master_add_node('localhost', :worker_2_port); +WARNING: role "non_dist_role_1" does not exist +CONTEXT: while executing command on localhost:xxxxx +ERROR: failure on connection marked as essential: localhost:xxxxx +\c - - - :worker_2_port +create role non_dist_role_1; +\c - - - :master_port SELECT 1 FROM master_add_node('localhost', :worker_2_port); ?column? --------------------------------------------------------------------- @@ -256,14 +258,13 @@ SELECT result FROM run_command_on_all_nodes( ) q; $$ ); - result + result --------------------------------------------------------------------- - [{"member":"dist_role_4","role":"dist_role_3","grantor":"test_admin_role","admin_option":false}, + - {"member":"non_dist_role_3","role":"dist_role_3","grantor":"test_admin_role","admin_option":false}, + + [{"member":"dist_role_4","role":"dist_role_3","grantor":"test_admin_role","admin_option":false}, + {"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] - [{"member":"dist_role_4","role":"dist_role_3","grantor":"test_admin_role","admin_option":false}, + + [{"member":"dist_role_4","role":"dist_role_3","grantor":"test_admin_role","admin_option":false}, + {"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] - [{"member":"dist_role_4","role":"dist_role_3","grantor":"test_admin_role","admin_option":false}, + + [{"member":"dist_role_4","role":"dist_role_3","grantor":"test_admin_role","admin_option":false}, + {"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] (3 rows) @@ -277,10 +278,9 @@ SELECT result FROM run_command_on_all_nodes( ) q; $$ ); - result + result --------------------------------------------------------------------- - [{"member":"non_dist_role_3","role":"dist_role_3","grantor":"test_admin_role","admin_option":false}, + - {"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] + [{"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] [{"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] [{"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] (3 rows) @@ -291,11 +291,9 @@ SELECT roleid::regrole::text AS role, member::regrole::text, (grantor::regrole:: dist_role_1 | dist_role_2 | t | f dist_role_1 | non_dist_role_1 | t | t dist_role_1 | test_admin_role | t | t - dist_role_3 | non_dist_role_3 | t | f dist_role_3 | test_admin_role | t | t - non_dist_role_1 | non_dist_role_2 | t | f non_dist_role_4 | dist_role_4 | t | f -(7 rows) +(5 rows) SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist\_%' ORDER BY 1; objid @@ -304,12 +302,14 @@ SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid':: dist_role_2 dist_role_3 dist_role_4 + non_dist_role_1 non_dist_role_4 -(5 rows) +(6 rows) REVOKE dist_role_3 from non_dist_role_3 granted by test_admin_role cascade; -NOTICE: not propagating GRANT command to other nodes -HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. +WARNING: role "non_dist_role_3" has not been granted membership in role "dist_role_3" by role "test_admin_role" +ERROR: role "non_dist_role_3" does not exist +CONTEXT: while executing command on localhost:xxxxx SELECT result FROM run_command_on_all_nodes( $$ SELECT json_agg(q.* ORDER BY member) FROM ( @@ -329,22 +329,6 @@ SELECT result FROM run_command_on_all_nodes( revoke dist_role_3,dist_role_1 from test_admin_role cascade; drop role test_admin_role; \c - - - :worker_1_port -SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_%' ORDER BY 1, 2; - role | member | grantor | admin_option ---------------------------------------------------------------------- -(0 rows) - -SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_%' ORDER BY 1; - rolname ---------------------------------------------------------------------- - dist_role_1 - dist_role_2 - dist_role_3 - dist_role_4 - non_dist_role_4 -(5 rows) - -\c - - - :worker_2_port SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_%' ORDER BY 1, 2; role | member | grantor | admin_option --------------------------------------------------------------------- @@ -358,8 +342,29 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_%' ORDER BY 1; dist_role_2 dist_role_3 dist_role_4 + non_dist_role_1 non_dist_role_4 -(5 rows) +(6 rows) + +\c - - - :worker_2_port +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + dist_role_1 | dist_role_2 | non_dist_role_1 | f + dist_role_1 | non_dist_role_1 | postgres | t + non_dist_role_4 | dist_role_4 | postgres | f +(3 rows) + +SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + dist_role_1 + dist_role_2 + dist_role_3 + dist_role_4 + non_dist_role_1 + non_dist_role_4 +(6 rows) \c - - - :master_port DROP ROLE dist_role_3, non_dist_role_3, dist_role_4, non_dist_role_4; @@ -412,6 +417,8 @@ SELECT master_remove_node('localhost', :worker_2_port); (1 row) GRANT dist_mixed_1, dist_mixed_2, nondist_mixed_1 TO dist_mixed_3, dist_mixed_4, nondist_mixed_2; +ERROR: role "nondist_mixed_2" does not exist +CONTEXT: while executing command on localhost:xxxxx SELECT 1 FROM master_add_node('localhost', :worker_2_port); ?column? --------------------------------------------------------------------- @@ -419,38 +426,24 @@ SELECT 1 FROM master_add_node('localhost', :worker_2_port); (1 row) SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1, 2; - role | member | grantor | admin_option + role | member | grantor | admin_option --------------------------------------------------------------------- - dist_mixed_1 | dist_mixed_3 | postgres | f - dist_mixed_1 | dist_mixed_4 | postgres | f - dist_mixed_1 | nondist_mixed_2 | postgres | f - dist_mixed_2 | dist_mixed_3 | postgres | f - dist_mixed_2 | dist_mixed_4 | postgres | f - dist_mixed_2 | nondist_mixed_2 | postgres | f - nondist_mixed_1 | dist_mixed_3 | postgres | f - nondist_mixed_1 | dist_mixed_4 | postgres | f - nondist_mixed_1 | nondist_mixed_2 | postgres | f -(9 rows) +(0 rows) SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1; - objid + objid --------------------------------------------------------------------- dist_mixed_1 dist_mixed_2 dist_mixed_3 dist_mixed_4 - nondist_mixed_1 -(5 rows) +(4 rows) \c - - - :worker_1_port SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1, 2; - role | member | grantor | admin_option + role | member | grantor | admin_option --------------------------------------------------------------------- - dist_mixed_1 | dist_mixed_3 | postgres | f - dist_mixed_1 | dist_mixed_4 | postgres | f - dist_mixed_2 | dist_mixed_3 | postgres | f - dist_mixed_2 | dist_mixed_4 | postgres | f -(4 rows) +(0 rows) SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; rolname @@ -464,35 +457,29 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; \c - - - :worker_2_port SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1, 2; - role | member | grantor | admin_option + role | member | grantor | admin_option --------------------------------------------------------------------- - dist_mixed_1 | dist_mixed_3 | postgres | f - dist_mixed_1 | dist_mixed_4 | postgres | f - dist_mixed_2 | dist_mixed_3 | postgres | f - dist_mixed_2 | dist_mixed_4 | postgres | f - nondist_mixed_1 | dist_mixed_3 | postgres | f - nondist_mixed_1 | dist_mixed_4 | postgres | f -(6 rows) +(0 rows) SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; - rolname + rolname --------------------------------------------------------------------- dist_mixed_1 dist_mixed_2 dist_mixed_3 dist_mixed_4 - nondist_mixed_1 -(5 rows) +(4 rows) \c - - - :master_port DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4, nondist_mixed_1, nondist_mixed_2; -- test drop multiple roles with non-distributed roles SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist%' ORDER BY 1; - objid + objid --------------------------------------------------------------------- dist_role_1 dist_role_2 -(2 rows) + non_dist_role_1 +(3 rows) SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; rolname @@ -505,11 +492,13 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; \c - - - :worker_1_port SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; - rolname + rolname --------------------------------------------------------------------- dist_role_1 dist_role_2 -(2 rows) + non_dist_role_1 + nondist_mixed_1 +(4 rows) \c - - - :master_port DROP ROLE dist_role_1, non_dist_role_1, dist_role_2, non_dist_role_2; @@ -525,9 +514,10 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; \c - - - :worker_1_port SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; - rolname + rolname --------------------------------------------------------------------- -(0 rows) + nondist_mixed_1 +(1 row) \c - - - :master_port -- test alter part of create or alter role @@ -578,15 +568,11 @@ HINT: Connect to other nodes directly to manually create all necessary users an SET citus.enable_create_role_propagation TO ON; CREATE ROLE dist_cascade; GRANT nondist_cascade_1 TO nondist_cascade_2; -NOTICE: not propagating GRANT command to other nodes -HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. -NOTICE: not propagating GRANT command to other nodes -HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. +ERROR: role "nondist_cascade_2" does not exist +CONTEXT: while executing command on localhost:xxxxx GRANT nondist_cascade_2 TO nondist_cascade_3; -NOTICE: not propagating GRANT command to other nodes -HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. -NOTICE: not propagating GRANT command to other nodes -HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. +ERROR: role "nondist_cascade_3" does not exist +CONTEXT: while executing command on localhost:xxxxx SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%cascade%' ORDER BY 1; objid --------------------------------------------------------------------- @@ -594,11 +580,9 @@ SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid':: (1 row) SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%cascade%' ORDER BY 1, 2; - role | member | grantor | admin_option + role | member | grantor | admin_option --------------------------------------------------------------------- - nondist_cascade_1 | nondist_cascade_2 | postgres | f - nondist_cascade_2 | nondist_cascade_3 | postgres | f -(2 rows) +(0 rows) \c - - - :worker_1_port SELECT rolname FROM pg_authid WHERE rolname LIKE '%cascade%' ORDER BY 1; @@ -620,8 +604,6 @@ SELECT master_remove_node('localhost', :worker_2_port); (1 row) GRANT nondist_cascade_3 TO dist_cascade; -NOTICE: not propagating GRANT command to other nodes -HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. SELECT 1 FROM master_add_node('localhost', :worker_2_port); ?column? --------------------------------------------------------------------- @@ -631,54 +613,43 @@ SELECT 1 FROM master_add_node('localhost', :worker_2_port); SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%cascade%' ORDER BY 1; objid --------------------------------------------------------------------- - nondist_cascade_1 - nondist_cascade_2 nondist_cascade_3 dist_cascade -(4 rows) +(2 rows) SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%cascade%' ORDER BY 1, 2; - role | member | grantor | admin_option + role | member | grantor | admin_option --------------------------------------------------------------------- - nondist_cascade_1 | nondist_cascade_2 | postgres | f - nondist_cascade_2 | nondist_cascade_3 | postgres | f - nondist_cascade_3 | dist_cascade | postgres | f -(3 rows) + nondist_cascade_3 | dist_cascade | postgres | f +(1 row) \c - - - :worker_1_port SELECT rolname FROM pg_authid WHERE rolname LIKE '%cascade%' ORDER BY 1; rolname --------------------------------------------------------------------- dist_cascade - nondist_cascade_1 - nondist_cascade_2 nondist_cascade_3 -(4 rows) +(2 rows) SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%cascade%' ORDER BY 1, 2; - role | member | grantor | admin_option + role | member | grantor | admin_option --------------------------------------------------------------------- - nondist_cascade_1 | nondist_cascade_2 | postgres | f - nondist_cascade_2 | nondist_cascade_3 | postgres | f -(2 rows) + nondist_cascade_3 | dist_cascade | postgres | f +(1 row) \c - - - :worker_2_port SELECT rolname FROM pg_authid WHERE rolname LIKE '%cascade%' ORDER BY 1; rolname --------------------------------------------------------------------- dist_cascade - nondist_cascade_1 - nondist_cascade_2 nondist_cascade_3 -(4 rows) +(2 rows) SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%cascade%' ORDER BY 1, 2; - role | member | grantor | admin_option + role | member | grantor | admin_option --------------------------------------------------------------------- - nondist_cascade_1 | nondist_cascade_2 | postgres | f - nondist_cascade_2 | nondist_cascade_3 | postgres | f - nondist_cascade_3 | dist_cascade | postgres | f -(3 rows) + nondist_cascade_3 | dist_cascade | postgres | f +(1 row) \c - - - :master_port DROP ROLE create_role, create_role_2, create_group, create_group_2, create_user, create_user_2, create_role_with_nothing, create_role_sysid, "create_role'edge", "create_role""edge"; @@ -691,7 +662,7 @@ SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::t (0 rows) GRANT existing_role_1, nonexisting_role_1 TO existing_role_2, nonexisting_role_2; -ERROR: role "nonexisting_role_1" does not exist +ERROR: role "nonexisting_role_2" does not exist SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%existing%' ORDER BY 1, 2; role | member | grantor | admin_option --------------------------------------------------------------------- diff --git a/src/test/regress/expected/pg16.out b/src/test/regress/expected/pg16.out index 40e671db6..a035fcfc4 100644 --- a/src/test/regress/expected/pg16.out +++ b/src/test/regress/expected/pg16.out @@ -1032,14 +1032,14 @@ WHERE roleid::regrole::text = 'role1' ORDER BY 1, 2; -- Set GUCs to log remote commands and filter on REVOKE commands SET citus.log_remote_commands TO on; SET citus.grep_remote_commands = '%REVOKE%'; --- test REVOKES as well -GRANT role1 TO role2; -REVOKE SET OPTION FOR role1 FROM role2; + -- test REVOKES as well + GRANT role1 TO role2; + REVOKE SET OPTION FOR role1 FROM role2; NOTICE: issuing REVOKE SET OPTION FOR role1 FROM role2 RESTRICT; DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing REVOKE SET OPTION FOR role1 FROM role2 RESTRICT; DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -REVOKE INHERIT OPTION FOR role1 FROM role2; + REVOKE INHERIT OPTION FOR role1 FROM role2; NOTICE: issuing REVOKE INHERIT OPTION FOR role1 FROM role2 RESTRICT; DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing REVOKE INHERIT OPTION FOR role1 FROM role2 RESTRICT; @@ -1053,15 +1053,7 @@ CREATE ROLE role5; RESET citus.enable_ddl_propagation; -- by default, admin option is false, inherit is true, set is true GRANT role3 TO role4; -NOTICE: not propagating GRANT command to other nodes -HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. -NOTICE: not propagating GRANT command to other nodes -HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. GRANT role3 TO role5 WITH ADMIN TRUE, INHERIT FALSE, SET FALSE; -NOTICE: not propagating GRANT command to other nodes -HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. -NOTICE: not propagating GRANT command to other nodes -HINT: Since no granted roles are distributed, the GRANT command will not be propagated to other nodes. SELECT roleid::regrole::text AS role, member::regrole::text, admin_option, inherit_option, set_option FROM pg_auth_members WHERE roleid::regrole::text = 'role3' ORDER BY 1, 2; role | member | admin_option | inherit_option | set_option @@ -1148,7 +1140,7 @@ DROP ROLE role6, role7, role8, role9, role10, role11, role12, -- when adding a new node. -- First, we need to remove the node: SELECT 1 FROM citus_remove_node('localhost', :worker_2_port); - ?column? +?column? --------------------------------------------------------------------- 1 (1 row) diff --git a/src/test/regress/sql/create_role_propagation.sql b/src/test/regress/sql/create_role_propagation.sql index fce10595f..5e615413f 100644 --- a/src/test/regress/sql/create_role_propagation.sql +++ b/src/test/regress/sql/create_role_propagation.sql @@ -121,6 +121,13 @@ GRANT non_dist_role_4 TO dist_role_4; GRANT dist_role_3 TO dist_role_4 granted by test_admin_role; +SELECT 1 FROM master_add_node('localhost', :worker_2_port); + +\c - - - :worker_2_port +create role non_dist_role_1; + +\c - - - :master_port + SELECT 1 FROM master_add_node('localhost', :worker_2_port); SELECT result FROM run_command_on_all_nodes( diff --git a/src/test/regress/sql/granted_by_support.sql b/src/test/regress/sql/granted_by_support.sql index afd3e416c..d111feeb9 100644 --- a/src/test/regress/sql/granted_by_support.sql +++ b/src/test/regress/sql/granted_by_support.sql @@ -94,6 +94,8 @@ grant non_dist_role_for_mds to dist_role1 with admin option; grant dist_role3 to dist_role4 with admin option GRANTED BY non_dist_role_for_mds; reset citus.enable_create_role_propagation; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role_for_mds' ORDER BY 1; + select result FROM run_command_on_all_nodes( $$ @@ -108,6 +110,24 @@ select result FROM run_command_on_all_nodes( $$ ); + +set citus.enable_create_role_propagation to off; +create role non_dist_role_mds_fail; + +grant dist_role2 to non_dist_role_mds_fail with admin option; +grant dist_role2 to non_dist_role_for_mds GRANTED BY non_dist_role_mds_fail; + + +reset citus.enable_create_role_propagation; + +--will fail since non_dist_role_for_mds is not in dependency resolution +select 1 from citus_add_node ('localhost',:worker_2_port); + +--this grant statement will add non_dist_role_mds_fail to dist_role3 dependencies +grant non_dist_role_mds_fail to dist_role3; + +--will be successful since non_dist_role_mds_fail is in dependency resolution of dist_role3 +-- and will be created in metadata sync phase select 1 from citus_add_node ('localhost',:worker_2_port); select result FROM run_command_on_all_nodes( @@ -123,6 +143,7 @@ select result FROM run_command_on_all_nodes( $$ ); + --clean all resources drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; drop role non_dist_role1,non_dist_role2,non_dist_role_for_mds; From f9091b612ea1d286b75a9f067606524464073f66 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Wed, 13 Mar 2024 13:01:03 +0300 Subject: [PATCH 17/23] Adds new tests --- .../expected/create_role_propagation.out | 47 +++++++++++++++++++ .../regress/sql/create_role_propagation.sql | 16 ++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/test/regress/expected/create_role_propagation.out b/src/test/regress/expected/create_role_propagation.out index 5bdbf5826..97aaa5e6c 100644 --- a/src/test/regress/expected/create_role_propagation.out +++ b/src/test/regress/expected/create_role_propagation.out @@ -244,12 +244,24 @@ ERROR: failure on connection marked as essential: localhost:xxxxx \c - - - :worker_2_port create role non_dist_role_1; \c - - - :master_port +--will be successful since non_dist_role_1 is created on worker_2 SELECT 1 FROM master_add_node('localhost', :worker_2_port); ?column? --------------------------------------------------------------------- 1 (1 row) +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist\_%' ORDER BY 1; + objid +--------------------------------------------------------------------- + dist_role_1 + dist_role_2 + dist_role_3 + dist_role_4 + non_dist_role_1 + non_dist_role_4 +(6 rows) + SELECT result FROM run_command_on_all_nodes( $$ SELECT json_agg(q.* ORDER BY member) FROM ( @@ -471,7 +483,33 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; (4 rows) \c - - - :master_port +set citus.log_remote_commands to on; DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4, nondist_mixed_1, nondist_mixed_2; +NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx'); +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx'); +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing SET citus.enable_ddl_propagation TO 'off' +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4 +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing SET citus.enable_ddl_propagation TO 'off' +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4 +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing SET citus.enable_ddl_propagation TO 'on' +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing SET citus.enable_ddl_propagation TO 'on' +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing PREPARE TRANSACTION 'citus_xx_xx_xx_xx' +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing PREPARE TRANSACTION 'citus_xx_xx_xx_xx' +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing COMMIT PREPARED 'citus_xx_xx_xx_xx' +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing COMMIT PREPARED 'citus_xx_xx_xx_xx' +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +reset citus.log_remote_commands; -- test drop multiple roles with non-distributed roles SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist%' ORDER BY 1; objid @@ -519,6 +557,12 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; nondist_mixed_1 (1 row) +\c - - - :worker_2_port +SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; + rolname +--------------------------------------------------------------------- +(0 rows) + \c - - - :master_port -- test alter part of create or alter role SELECT master_remove_node('localhost', :worker_2_port); @@ -738,3 +782,6 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%existing%' ORDER BY 1; \c - - - :master_port DROP ROLE nondist_cascade_1, nondist_cascade_2, nondist_cascade_3, dist_cascade; +\c - - - :worker_2_port +drop role non_dist_role_1; +ERROR: role "non_dist_role_1" does not exist diff --git a/src/test/regress/sql/create_role_propagation.sql b/src/test/regress/sql/create_role_propagation.sql index 5e615413f..4b88dfa7d 100644 --- a/src/test/regress/sql/create_role_propagation.sql +++ b/src/test/regress/sql/create_role_propagation.sql @@ -127,9 +127,13 @@ SELECT 1 FROM master_add_node('localhost', :worker_2_port); create role non_dist_role_1; \c - - - :master_port - +--will be successful since non_dist_role_1 is created on worker_2 SELECT 1 FROM master_add_node('localhost', :worker_2_port); +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist\_%' ORDER BY 1; + + + SELECT result FROM run_command_on_all_nodes( $$ SELECT json_agg(q.* ORDER BY member) FROM ( @@ -213,8 +217,12 @@ SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::t SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; \c - - - :master_port +set citus.log_remote_commands to on; DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4, nondist_mixed_1, nondist_mixed_2; +reset citus.log_remote_commands; + + -- test drop multiple roles with non-distributed roles SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist%' ORDER BY 1; @@ -231,6 +239,9 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; \c - - - :worker_1_port SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; + +\c - - - :worker_2_port +SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; \c - - - :master_port -- test alter part of create or alter role @@ -328,3 +339,6 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%existing%' ORDER BY 1; \c - - - :master_port DROP ROLE nondist_cascade_1, nondist_cascade_2, nondist_cascade_3, dist_cascade; + +\c - - - :worker_2_port +drop role non_dist_role_1; From f944925cdf2f4a91d09294351c6b58244c72707c Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Wed, 13 Mar 2024 13:02:15 +0300 Subject: [PATCH 18/23] Adds new output --- src/test/regress/expected/create_role_propagation.out | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/regress/expected/create_role_propagation.out b/src/test/regress/expected/create_role_propagation.out index 97aaa5e6c..e244be290 100644 --- a/src/test/regress/expected/create_role_propagation.out +++ b/src/test/regress/expected/create_role_propagation.out @@ -491,12 +491,12 @@ NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_ DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing SET citus.enable_ddl_propagation TO 'off' DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4 -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing SET citus.enable_ddl_propagation TO 'off' DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4 DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4 +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing SET citus.enable_ddl_propagation TO 'on' DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing SET citus.enable_ddl_propagation TO 'on' From 6699da07da2e48374f5e1b99fdf4969bf654f077 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Wed, 13 Mar 2024 13:31:48 +0300 Subject: [PATCH 19/23] Fixes create role propagation --- .../expected/create_role_propagation.out | 95 +++++++++++-------- .../regress/sql/create_role_propagation.sql | 11 ++- 2 files changed, 62 insertions(+), 44 deletions(-) diff --git a/src/test/regress/expected/create_role_propagation.out b/src/test/regress/expected/create_role_propagation.out index e244be290..cf05b1cb8 100644 --- a/src/test/regress/expected/create_role_propagation.out +++ b/src/test/regress/expected/create_role_propagation.out @@ -431,6 +431,10 @@ SELECT master_remove_node('localhost', :worker_2_port); GRANT dist_mixed_1, dist_mixed_2, nondist_mixed_1 TO dist_mixed_3, dist_mixed_4, nondist_mixed_2; ERROR: role "nondist_mixed_2" does not exist CONTEXT: while executing command on localhost:xxxxx +\c - - - :worker_1_port +create role nondist_mixed_2; +\c - - - :master_port +GRANT dist_mixed_1, dist_mixed_2, nondist_mixed_1 TO dist_mixed_3, dist_mixed_4, nondist_mixed_2; SELECT 1 FROM master_add_node('localhost', :worker_2_port); ?column? --------------------------------------------------------------------- @@ -438,24 +442,44 @@ SELECT 1 FROM master_add_node('localhost', :worker_2_port); (1 row) SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1, 2; - role | member | grantor | admin_option + role | member | grantor | admin_option --------------------------------------------------------------------- -(0 rows) + dist_mixed_1 | dist_mixed_3 | postgres | f + dist_mixed_1 | dist_mixed_4 | postgres | f + dist_mixed_1 | nondist_mixed_2 | postgres | f + dist_mixed_2 | dist_mixed_3 | postgres | f + dist_mixed_2 | dist_mixed_4 | postgres | f + dist_mixed_2 | nondist_mixed_2 | postgres | f + nondist_mixed_1 | dist_mixed_3 | postgres | f + nondist_mixed_1 | dist_mixed_4 | postgres | f + nondist_mixed_1 | nondist_mixed_2 | postgres | f +(9 rows) SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1; - objid + objid --------------------------------------------------------------------- dist_mixed_1 dist_mixed_2 dist_mixed_3 dist_mixed_4 -(4 rows) + nondist_mixed_1 + nondist_mixed_2 +(6 rows) \c - - - :worker_1_port SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1, 2; - role | member | grantor | admin_option + role | member | grantor | admin_option --------------------------------------------------------------------- -(0 rows) + dist_mixed_1 | dist_mixed_3 | postgres | f + dist_mixed_1 | dist_mixed_4 | postgres | f + dist_mixed_1 | nondist_mixed_2 | postgres | f + dist_mixed_2 | dist_mixed_3 | postgres | f + dist_mixed_2 | dist_mixed_4 | postgres | f + dist_mixed_2 | nondist_mixed_2 | postgres | f + nondist_mixed_1 | dist_mixed_3 | postgres | f + nondist_mixed_1 | dist_mixed_4 | postgres | f + nondist_mixed_1 | nondist_mixed_2 | postgres | f +(9 rows) SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; rolname @@ -465,50 +489,44 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; dist_mixed_3 dist_mixed_4 nondist_mixed_1 -(5 rows) + nondist_mixed_2 +(6 rows) \c - - - :worker_2_port SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1, 2; - role | member | grantor | admin_option + role | member | grantor | admin_option --------------------------------------------------------------------- -(0 rows) + dist_mixed_1 | dist_mixed_3 | postgres | f + dist_mixed_1 | dist_mixed_4 | postgres | f + dist_mixed_1 | nondist_mixed_2 | postgres | f + dist_mixed_2 | dist_mixed_3 | postgres | f + dist_mixed_2 | dist_mixed_4 | postgres | f + dist_mixed_2 | nondist_mixed_2 | postgres | f + nondist_mixed_1 | dist_mixed_3 | postgres | f + nondist_mixed_1 | dist_mixed_4 | postgres | f + nondist_mixed_1 | nondist_mixed_2 | postgres | f +(9 rows) SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; - rolname + rolname --------------------------------------------------------------------- dist_mixed_1 dist_mixed_2 dist_mixed_3 dist_mixed_4 -(4 rows) + nondist_mixed_1 + nondist_mixed_2 +(6 rows) \c - - - :master_port set citus.log_remote_commands to on; +set citus.grep_remote_commands to '%DROP%'; DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4, nondist_mixed_1, nondist_mixed_2; -NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx'); +NOTICE: issuing DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4, nondist_mixed_1, nondist_mixed_2 DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx'); -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing SET citus.enable_ddl_propagation TO 'off' -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing SET citus.enable_ddl_propagation TO 'off' -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4 -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4 -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing SET citus.enable_ddl_propagation TO 'on' -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing SET citus.enable_ddl_propagation TO 'on' -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing PREPARE TRANSACTION 'citus_xx_xx_xx_xx' -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing PREPARE TRANSACTION 'citus_xx_xx_xx_xx' -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing COMMIT PREPARED 'citus_xx_xx_xx_xx' -DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -NOTICE: issuing COMMIT PREPARED 'citus_xx_xx_xx_xx' +NOTICE: issuing DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4, nondist_mixed_1, nondist_mixed_2 DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +set citus.grep_remote_commands to '%DROP%'; reset citus.log_remote_commands; -- test drop multiple roles with non-distributed roles SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist%' ORDER BY 1; @@ -535,8 +553,7 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; dist_role_1 dist_role_2 non_dist_role_1 - nondist_mixed_1 -(4 rows) +(3 rows) \c - - - :master_port DROP ROLE dist_role_1, non_dist_role_1, dist_role_2, non_dist_role_2; @@ -552,10 +569,9 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; \c - - - :worker_1_port SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; - rolname + rolname --------------------------------------------------------------------- - nondist_mixed_1 -(1 row) +(0 rows) \c - - - :worker_2_port SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; @@ -782,6 +798,3 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%existing%' ORDER BY 1; \c - - - :master_port DROP ROLE nondist_cascade_1, nondist_cascade_2, nondist_cascade_3, dist_cascade; -\c - - - :worker_2_port -drop role non_dist_role_1; -ERROR: role "non_dist_role_1" does not exist diff --git a/src/test/regress/sql/create_role_propagation.sql b/src/test/regress/sql/create_role_propagation.sql index 4b88dfa7d..d5cdb8ec9 100644 --- a/src/test/regress/sql/create_role_propagation.sql +++ b/src/test/regress/sql/create_role_propagation.sql @@ -205,6 +205,12 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; SELECT master_remove_node('localhost', :worker_2_port); GRANT dist_mixed_1, dist_mixed_2, nondist_mixed_1 TO dist_mixed_3, dist_mixed_4, nondist_mixed_2; + +\c - - - :worker_1_port +create role nondist_mixed_2; + +\c - - - :master_port +GRANT dist_mixed_1, dist_mixed_2, nondist_mixed_1 TO dist_mixed_3, dist_mixed_4, nondist_mixed_2; SELECT 1 FROM master_add_node('localhost', :worker_2_port); SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1, 2; @@ -218,8 +224,9 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; \c - - - :master_port set citus.log_remote_commands to on; +set citus.grep_remote_commands to '%DROP%'; DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4, nondist_mixed_1, nondist_mixed_2; - +set citus.grep_remote_commands to '%DROP%'; reset citus.log_remote_commands; @@ -340,5 +347,3 @@ SELECT rolname FROM pg_authid WHERE rolname LIKE '%existing%' ORDER BY 1; DROP ROLE nondist_cascade_1, nondist_cascade_2, nondist_cascade_3, dist_cascade; -\c - - - :worker_2_port -drop role non_dist_role_1; From e89d48ef7faca891c8b4751b13db93633a2b19a8 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Wed, 13 Mar 2024 13:35:37 +0300 Subject: [PATCH 20/23] Removes unused code --- src/backend/distributed/commands/role.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index ec7e1430b..b6dffc0de 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -68,7 +68,6 @@ static DefElem * makeDefElemBool(char *name, bool value); static List * GenerateRoleOptionsList(HeapTuple tuple); static List * GenerateGrantRoleStmtsFromOptions(RoleSpec *roleSpec, List *options); static List * GenerateGrantRoleStmtsOfRole(Oid roleid); -static ObjectAddress * GetRoleObjectAddressFromOid(Oid roleOid); static GrantRoleStmt * GetGrantRoleStmtFromAuthMemberRecord(Form_pg_auth_members membership); static List * GenerateSecLabelOnRoleStmts(Oid roleid, char *rolename); @@ -973,15 +972,6 @@ GenerateGrantRoleStmts() } -static ObjectAddress * -GetRoleObjectAddressFromOid(Oid roleOid) -{ - ObjectAddress *roleAddress = palloc0(sizeof(ObjectAddress)); - ObjectAddressSet(*roleAddress, AuthIdRelationId, roleOid); - return roleAddress; -} - - static GrantRoleStmt * GetGrantRoleStmtFromAuthMemberRecord(Form_pg_auth_members membership) { From 70f0bc041b775e91249d2b7c057f77676d04fa56 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Wed, 13 Mar 2024 13:48:51 +0300 Subject: [PATCH 21/23] Fixes granted by support tests --- .../regress/expected/granted_by_support.out | 260 +++++------------- src/test/regress/sql/granted_by_support.sql | 2 +- 2 files changed, 75 insertions(+), 187 deletions(-) diff --git a/src/test/regress/expected/granted_by_support.out b/src/test/regress/expected/granted_by_support.out index 2ab0e6c7b..9c76c88fe 100644 --- a/src/test/regress/expected/granted_by_support.out +++ b/src/test/regress/expected/granted_by_support.out @@ -29,21 +29,48 @@ grant dist_role3 to dist_role4 with admin option; -- To test non-distributed grantor, set this option off for some roles. set citus.enable_create_role_propagation to off; grant non_dist_role1 to dist_role1 with admin option; -reset citus.enable_create_role_propagation; -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - objid ---------------------------------------------------------------------- -(0 rows) - grant dist_role2 to non_dist_role1 with admin option; +grant dist_role2 to dist_role4 granted by non_dist_role1 ; +reset citus.enable_create_role_propagation; +grant dist_role2 to "dist_role5'_test" granted by non_dist_role1;--will fail since non_dist_role1 does not exist on worker_1 ERROR: role "non_dist_role1" does not exist CONTEXT: while executing command on localhost:xxxxx +\c - - - :master_port grant dist_role3 to "dist_role5'_test" granted by dist_role4; grant dist_role2 to "dist_role5'_test" granted by dist_role3; -grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed -ERROR: permission denied to grant privileges as role "non_dist_role1" -DETAIL: The grantor must have the ADMIN option on role "dist_role2". +--will fail since non_dist_role2 does not exist in worker_1 +grant dist_role2 to non_dist_role2 with admin option; +ERROR: role "non_dist_role2" does not exist +grant dist_role2 to dist_role4 granted by non_dist_role2 ; +ERROR: role "non_dist_role2" does not exist +grant non_dist_role2 to "dist_role5'_test"; +ERROR: role "non_dist_role2" does not exist +\c - - - :worker_1_port +create role non_dist_role2; +\c - - - :master_port +--will be successful since non_dist_role has been created on worker_1 +grant dist_role2 to non_dist_role2 with admin option; +grant dist_role2 to dist_role4 granted by non_dist_role2 ; +grant non_dist_role2 to "dist_role5'_test"; grant dist_role4 to "dist_role5'_test" with admin option; +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','non_dist_role1') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + [{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"non_dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true}] +(2 rows) + --below command propagates the non_dist_role1 since non_dist_role1 is already granted to dist_role1 --and citus sees granted roles as a dependency and citus propagates the dependent roles grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; @@ -65,175 +92,19 @@ grant dist_role3 to dist_role1 with admin option GRANTED BY dist_role4; grant "dist_role5'_test" to dist_role1 with admin option; grant "dist_role5'_test" to dist_role3 with admin option GRANTED BY dist_role1;--fails since already dist_role3 granted to "dist_role5'_test" ERROR: role "dist_role5'_test" is a member of role "dist_role3" -select result FROM run_command_on_all_nodes( - $$ - SELECT array_to_json(array_agg(row_to_json(t))) - FROM ( - SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option - FROM pg_auth_members - WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') - order by member::regrole::text, roleid::regrole::text - ) t - $$ -); - result ---------------------------------------------------------------------- - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] -(2 rows) - -select 1 from citus_add_node ('localhost',:worker_2_port); - ?column? ---------------------------------------------------------------------- - 1 -(1 row) - -select result FROM run_command_on_all_nodes( - $$ - SELECT array_to_json(array_agg(row_to_json(t))) - FROM ( - SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option - FROM pg_auth_members - WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') - order by member::regrole::text, roleid::regrole::text - ) t - $$ -); - result ---------------------------------------------------------------------- - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] -(3 rows) - ---clean all resources -drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; -drop role non_dist_role1; -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - objid ---------------------------------------------------------------------- -(0 rows) - -reset citus.enable_create_role_propagation; -select result FROM run_command_on_all_nodes( - $$ - SELECT array_to_json(array_agg(row_to_json(t))) - FROM ( - SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option - FROM pg_auth_members - WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') - order by member::regrole::text, roleid::regrole::text - ) t - $$ -); - result ---------------------------------------------------------------------- - - - -(3 rows) - ---- Test 2: Tests from non-main database -set citus.enable_create_database_propagation to on; -create database test_granted_by_support; -select 1 from citus_remove_node ('localhost',:worker_2_port); - ?column? ---------------------------------------------------------------------- - 1 -(1 row) - -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - objid ---------------------------------------------------------------------- -(0 rows) - -\c test_granted_by_support ---here in below block since 'citus.enable_create_role_propagation to off ' is not effective, ---non_dist_role1 is being propagated to dist_role1 unlike main db scenario ---non_dist_role1 will be used for the test scenarios in this section set citus.enable_create_role_propagation to off; -create role non_dist_role1; -reset citus.enable_create_role_propagation; ---dropping since it isn't non-distributed as intended -drop role non_dist_role1; ---creating non_dist_role1 again in main database ---This is actually non-distributed role -\c regression -set citus.enable_create_role_propagation to off; -create role non_dist_role1; +create role non_dist_role_for_mds; NOTICE: not propagating CREATE ROLE/USER commands to other nodes HINT: Connect to other nodes directly to manually create all necessary users and roles. +grant dist_role3 to non_dist_role_for_mds with admin option; +grant non_dist_role_for_mds to dist_role1 with admin option; +grant dist_role3 to dist_role4 with admin option GRANTED BY non_dist_role_for_mds; reset citus.enable_create_role_propagation; -\c test_granted_by_support -create role dist_role1; -create role dist_role1; -ERROR: role "dist_role1" already exists -create role dist_role2; -create role dist_role3; -create role dist_role4; -create role "dist_role5'_test"; -\c regression - - :master_port -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role_for_mds' ORDER BY 1; objid --------------------------------------------------------------------- (0 rows) -\c test_granted_by_support -grant dist_role2 to dist_role1 with admin option; -grant dist_role2 to dist_role3 with admin option granted by dist_role1; -grant dist_role3 to dist_role4 with admin option; --- With enable_create_role_propagation on, all grantees are propagated. --- To test non-distributed grantor, set this option off for some roles. -\c regression -set citus.enable_create_role_propagation to off; -grant non_dist_role1 to dist_role1 with admin option; -reset citus.enable_create_role_propagation; -\c test_granted_by_support -grant dist_role2 to non_dist_role1 with admin option; -ERROR: failure on connection marked as essential: localhost:xxxxx -CONTEXT: while executing command on localhost:xxxxx -\c test_granted_by_support - - :worker_1_port -grant dist_role3 to "dist_role5'_test" granted by dist_role4; -grant dist_role2 to "dist_role5'_test" granted by dist_role3; -grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed -ERROR: role "non_dist_role1" does not exist -\c regression - - :master_port -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - objid ---------------------------------------------------------------------- -(0 rows) - -\c test_granted_by_support - - :worker_1_port -grant dist_role4 to "dist_role5'_test" with admin option; -\c regression - - :master_port -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - objid ---------------------------------------------------------------------- -(0 rows) - -\c test_granted_by_support --- Unlike maindb scenario, non-maindb scenario doesn't propagate 'create non_dist_role1' to ---workers as it doesn't create dependency objects for non-distributed roles. -grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; -\c regression - - :master_port -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - objid ---------------------------------------------------------------------- -(0 rows) - -\c test_granted_by_support - - :worker_1_port -grant dist_role4 to dist_role3 with admin option GRANTED BY dist_role1; --fails since already dist_role3 granted to dist_role4 -ERROR: role "dist_role4" is a member of role "dist_role3" -grant non_dist_role1 to dist_role4 granted by dist_role1; -ERROR: role "non_dist_role1" does not exist -grant dist_role3 to dist_role1 with admin option GRANTED BY dist_role4; -grant "dist_role5'_test" to dist_role1 with admin option; -grant "dist_role5'_test" to dist_role3 with admin option GRANTED BY dist_role1;--fails since already dist_role3 granted to "dist_role5'_test" -ERROR: role "dist_role5'_test" is a member of role "dist_role3" -\c regression - - :master_port select result FROM run_command_on_all_nodes( $$ SELECT array_to_json(array_agg(row_to_json(t))) @@ -241,17 +112,33 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"', 'non_dist_role_for_mds','non_dist_role1','non_dist_role2') order by member::regrole::text, roleid::regrole::text ) t $$ ); - result + result --------------------------------------------------------------------- - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"non_dist_role_for_mds","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role2","admin_option":false},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"non_dist_role_for_mds","admin_option":true},{"member":"non_dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role2","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role_for_mds","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role2","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"non_dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role2","role":"dist_role2","grantor":"postgres","admin_option":true}] (2 rows) +set citus.enable_create_role_propagation to off; +create role non_dist_role_mds_fail; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +grant dist_role2 to non_dist_role_mds_fail with admin option; +grant dist_role2 to non_dist_role_for_mds GRANTED BY non_dist_role_mds_fail; +reset citus.enable_create_role_propagation; +--will fail since non_dist_role_for_mds is not in dependency resolution +select 1 from citus_add_node ('localhost',:worker_2_port); +WARNING: role "non_dist_role_mds_fail" does not exist +CONTEXT: while executing command on localhost:xxxxx +ERROR: failure on connection marked as essential: localhost:xxxxx +--this grant statement will add non_dist_role_mds_fail to dist_role3 dependencies +grant non_dist_role_mds_fail to dist_role3; +--will be successful since non_dist_role_mds_fail is in dependency resolution of dist_role3 +-- and will be created in metadata sync phase select 1 from citus_add_node ('localhost',:worker_2_port); ?column? --------------------------------------------------------------------- @@ -265,25 +152,27 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"','non_dist_role_for_mds','non_dist_role1','non_dist_role2') order by member::regrole::text, roleid::regrole::text ) t $$ ); - result + result --------------------------------------------------------------------- - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"non_dist_role_for_mds","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role3","role":"non_dist_role_mds_fail","grantor":"postgres","admin_option":false},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role2","admin_option":false},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"non_dist_role_for_mds","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"non_dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role2","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role_for_mds","role":"dist_role2","grantor":"non_dist_role_mds_fail","admin_option":false},{"member":"non_dist_role_for_mds","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role3","role":"non_dist_role_mds_fail","grantor":"postgres","admin_option":false},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role2","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"non_dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role2","role":"dist_role2","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"non_dist_role_for_mds","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role3","role":"non_dist_role_mds_fail","grantor":"postgres","admin_option":false},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role2","admin_option":false},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"non_dist_role_for_mds","admin_option":true},{"member":"non_dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role2","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role_for_mds","role":"dist_role2","grantor":"non_dist_role_mds_fail","admin_option":false},{"member":"non_dist_role_for_mds","role":"dist_role3","grantor":"postgres","admin_option":true}] (3 rows) --clean all resources -set citus.enable_create_database_propagation to on; -drop database test_granted_by_support; drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; -drop role non_dist_role1; -drop role if exists non_dist_role1; -NOTICE: role "non_dist_role1" does not exist, skipping +drop role non_dist_role1,non_dist_role2,non_dist_role_for_mds,non_dist_role_mds_fail; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid +--------------------------------------------------------------------- +(0 rows) + +reset citus.enable_create_role_propagation; select result FROM run_command_on_all_nodes( $$ SELECT array_to_json(array_agg(row_to_json(t))) @@ -291,7 +180,7 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"','non_dist_role_for_mds','non_dist_role1','non_dist_role2') order by member::regrole::text, roleid::regrole::text ) t $$ @@ -303,4 +192,3 @@ select result FROM run_command_on_all_nodes( (3 rows) -reset citus.enable_create_database_propagation; diff --git a/src/test/regress/sql/granted_by_support.sql b/src/test/regress/sql/granted_by_support.sql index d111feeb9..e0d742a3e 100644 --- a/src/test/regress/sql/granted_by_support.sql +++ b/src/test/regress/sql/granted_by_support.sql @@ -146,7 +146,7 @@ select result FROM run_command_on_all_nodes( --clean all resources drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; -drop role non_dist_role1,non_dist_role2,non_dist_role_for_mds; +drop role non_dist_role1,non_dist_role2,non_dist_role_for_mds,non_dist_role_mds_fail; SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; reset citus.enable_create_role_propagation; From 42a5149ece525bf589ed8700a58cd67d82c97536 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Wed, 13 Mar 2024 14:37:21 +0300 Subject: [PATCH 22/23] Fixes test errors --- src/backend/distributed/commands/role.c | 4 +- .../expected/create_role_propagation_0.out | 800 ++++++++++++++++++ .../regress/expected/granted_by_support_0.out | 266 ++---- 3 files changed, 880 insertions(+), 190 deletions(-) create mode 100644 src/test/regress/expected/create_role_propagation_0.out diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index b6dffc0de..b5fab1e3b 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -891,7 +891,7 @@ GenerateGrantRoleStmtsOfRole(Oid roleid) Form_pg_auth_members membership = (Form_pg_auth_members) GETSTRUCT(tuple); GrantRoleStmt *grantRoleStmt = GetGrantRoleStmtFromAuthMemberRecord(membership); - if (grantRoleStmt == NULL) + if (grantRoleStmt == NULL ||IsReservedName(GetUserNameFromId(membership->roleid, true))) { continue; } @@ -938,7 +938,7 @@ GenerateGrantRoleStmts() GrantRoleStmt *grantRoleStmt = GetGrantRoleStmtFromAuthMemberRecord(membership); - if (grantRoleStmt == NULL) + if (grantRoleStmt == NULL || IsReservedName(GetUserNameFromId(membership->roleid, true))) { continue; } diff --git a/src/test/regress/expected/create_role_propagation_0.out b/src/test/regress/expected/create_role_propagation_0.out new file mode 100644 index 000000000..9a70ca88c --- /dev/null +++ b/src/test/regress/expected/create_role_propagation_0.out @@ -0,0 +1,800 @@ +SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname LIKE 'create\_%' ORDER BY rolname; + rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil +--------------------------------------------------------------------- +(0 rows) + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE 'create\_%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- +(0 rows) + +\c - - - :worker_1_port +SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname LIKE 'create\_%' ORDER BY rolname; + rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil +--------------------------------------------------------------------- +(0 rows) + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE 'create\_%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- +(0 rows) + +\c - - - :master_port +CREATE ROLE create_role; +CREATE ROLE create_role_2; +CREATE USER create_user; +CREATE USER create_user_2; +CREATE GROUP create_group; +CREATE GROUP create_group_2; +-- show that create role fails if sysid option is given as non-int +CREATE ROLE create_role_sysid SYSID "123"; +ERROR: syntax error at or near ""123"" +-- show that create role accepts sysid option as int +CREATE ROLE create_role_sysid SYSID 123; +NOTICE: SYSID can no longer be specified +SELECT master_remove_node('localhost', :worker_2_port); + master_remove_node +--------------------------------------------------------------------- + +(1 row) + +CREATE ROLE create_role_with_everything SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN REPLICATION BYPASSRLS CONNECTION LIMIT 105 PASSWORD 'strong_password123^' VALID UNTIL '2045-05-05 00:00:00.00+00' IN ROLE create_role, create_group ROLE create_user, create_group_2 ADMIN create_role_2, create_user_2; +CREATE ROLE create_role_with_nothing NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOLOGIN NOREPLICATION NOBYPASSRLS CONNECTION LIMIT 3 PASSWORD 'weakpassword' VALID UNTIL '2015-05-05 00:00:00.00+00'; +-- show that creating role from worker node is allowed +\c - - - :worker_1_port +CREATE ROLE role_on_worker; +DROP ROLE role_on_worker; +\c - - - :master_port +-- edge case role names +CREATE ROLE "create_role'edge"; +CREATE ROLE "create_role""edge"; +-- test grant role +GRANT create_group TO create_role; +GRANT create_group TO create_role_2 WITH ADMIN OPTION; +SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, (rolpassword != '') as pass_not_empty, rolvaliduntil FROM pg_authid WHERE rolname LIKE 'create\_%' ORDER BY rolname; + rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | pass_not_empty | rolvaliduntil +--------------------------------------------------------------------- + create_group | f | t | f | f | f | f | f | -1 | | + create_group_2 | f | t | f | f | f | f | f | -1 | | + create_role | f | t | f | f | f | f | f | -1 | | + create_role"edge | f | t | f | f | f | f | f | -1 | | + create_role'edge | f | t | f | f | f | f | f | -1 | | + create_role_2 | f | t | f | f | f | f | f | -1 | | + create_role_sysid | f | t | f | f | f | f | f | -1 | | + create_role_with_everything | t | t | t | t | t | t | t | 105 | t | Thu May 04 17:00:00 2045 PDT + create_role_with_nothing | f | f | f | f | f | f | f | 3 | t | Mon May 04 17:00:00 2015 PDT + create_user | f | t | f | f | t | f | f | -1 | | + create_user_2 | f | t | f | f | t | f | f | -1 | | +(11 rows) + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE 'create\_%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + create_group | create_role | postgres | f + create_group | create_role_2 | postgres | t + create_group | create_role_with_everything | postgres | f + create_role | create_role_with_everything | postgres | f + create_role_with_everything | create_group_2 | postgres | f + create_role_with_everything | create_role_2 | postgres | t + create_role_with_everything | create_user | postgres | f + create_role_with_everything | create_user_2 | postgres | t +(8 rows) + +\c - - - :worker_1_port +SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, (rolpassword != '') as pass_not_empty, rolvaliduntil FROM pg_authid WHERE rolname LIKE 'create\_%' ORDER BY rolname; + rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | pass_not_empty | rolvaliduntil +--------------------------------------------------------------------- + create_group | f | t | f | f | f | f | f | -1 | | + create_group_2 | f | t | f | f | f | f | f | -1 | | + create_role | f | t | f | f | f | f | f | -1 | | + create_role"edge | f | t | f | f | f | f | f | -1 | | + create_role'edge | f | t | f | f | f | f | f | -1 | | + create_role_2 | f | t | f | f | f | f | f | -1 | | + create_role_sysid | f | t | f | f | f | f | f | -1 | | + create_role_with_everything | t | t | t | t | t | t | t | 105 | t | Thu May 04 17:00:00 2045 PDT + create_role_with_nothing | f | f | f | f | f | f | f | 3 | t | Mon May 04 17:00:00 2015 PDT + create_user | f | t | f | f | t | f | f | -1 | | + create_user_2 | f | t | f | f | t | f | f | -1 | | +(11 rows) + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE 'create\_%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + create_group | create_role | postgres | f + create_group | create_role_2 | postgres | t + create_group | create_role_with_everything | postgres | f + create_role | create_role_with_everything | postgres | f + create_role_with_everything | create_group_2 | postgres | f + create_role_with_everything | create_role_2 | postgres | t + create_role_with_everything | create_user | postgres | f + create_role_with_everything | create_user_2 | postgres | t +(8 rows) + +\c - - - :master_port +SELECT 1 FROM master_add_node('localhost', :worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +\c - - - :worker_2_port +SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, (rolpassword != '') as pass_not_empty, rolvaliduntil FROM pg_authid WHERE rolname LIKE 'create\_%' ORDER BY rolname; + rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | pass_not_empty | rolvaliduntil +--------------------------------------------------------------------- + create_group | f | t | f | f | f | f | f | -1 | | infinity + create_group_2 | f | t | f | f | f | f | f | -1 | | infinity + create_role | f | t | f | f | f | f | f | -1 | | infinity + create_role"edge | f | t | f | f | f | f | f | -1 | | infinity + create_role'edge | f | t | f | f | f | f | f | -1 | | infinity + create_role_2 | f | t | f | f | f | f | f | -1 | | infinity + create_role_sysid | f | t | f | f | f | f | f | -1 | | infinity + create_role_with_everything | t | t | t | t | t | t | t | 105 | t | Thu May 04 17:00:00 2045 PDT + create_role_with_nothing | f | f | f | f | f | f | f | 3 | t | Mon May 04 17:00:00 2015 PDT + create_user | f | t | f | f | t | f | f | -1 | | infinity + create_user_2 | f | t | f | f | t | f | f | -1 | | infinity +(11 rows) + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE 'create\_%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + create_group | create_role | postgres | f + create_group | create_role_2 | postgres | t + create_group | create_role_with_everything | postgres | f + create_role | create_role_with_everything | postgres | f + create_role_with_everything | create_group_2 | postgres | f + create_role_with_everything | create_role_2 | postgres | t + create_role_with_everything | create_user | postgres | f + create_role_with_everything | create_user_2 | postgres | t +(8 rows) + +\c - - - :master_port +DROP ROLE create_role_with_everything; +REVOKE create_group FROM create_role; +REVOKE ADMIN OPTION FOR create_group FROM create_role_2; +\c - - - :master_port +SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, (rolpassword != '') as pass_not_empty, rolvaliduntil FROM pg_authid WHERE rolname LIKE 'create\_%' ORDER BY rolname; + rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | pass_not_empty | rolvaliduntil +--------------------------------------------------------------------- + create_group | f | t | f | f | f | f | f | -1 | | + create_group_2 | f | t | f | f | f | f | f | -1 | | + create_role | f | t | f | f | f | f | f | -1 | | + create_role"edge | f | t | f | f | f | f | f | -1 | | + create_role'edge | f | t | f | f | f | f | f | -1 | | + create_role_2 | f | t | f | f | f | f | f | -1 | | + create_role_sysid | f | t | f | f | f | f | f | -1 | | + create_role_with_nothing | f | f | f | f | f | f | f | 3 | t | Mon May 04 17:00:00 2015 PDT + create_user | f | t | f | f | t | f | f | -1 | | + create_user_2 | f | t | f | f | t | f | f | -1 | | +(10 rows) + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE 'create\_%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + create_group | create_role_2 | postgres | f +(1 row) + +\c - - - :worker_1_port +SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, (rolpassword != '') as pass_not_empty, rolvaliduntil FROM pg_authid WHERE rolname LIKE 'create\_%' ORDER BY rolname; + rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | pass_not_empty | rolvaliduntil +--------------------------------------------------------------------- + create_group | f | t | f | f | f | f | f | -1 | | + create_group_2 | f | t | f | f | f | f | f | -1 | | + create_role | f | t | f | f | f | f | f | -1 | | + create_role"edge | f | t | f | f | f | f | f | -1 | | + create_role'edge | f | t | f | f | f | f | f | -1 | | + create_role_2 | f | t | f | f | f | f | f | -1 | | + create_role_sysid | f | t | f | f | f | f | f | -1 | | + create_role_with_nothing | f | f | f | f | f | f | f | 3 | t | Mon May 04 17:00:00 2015 PDT + create_user | f | t | f | f | t | f | f | -1 | | + create_user_2 | f | t | f | f | t | f | f | -1 | | +(10 rows) + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE 'create\_%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + create_group | create_role_2 | postgres | f +(1 row) + +\c - - - :master_port +-- test grants with distributed and non-distributed roles +SELECT master_remove_node('localhost', :worker_2_port); + master_remove_node +--------------------------------------------------------------------- + +(1 row) + +create role test_admin_role; +CREATE ROLE dist_role_1 SUPERUSER; +CREATE ROLE dist_role_2; +CREATE ROLE dist_role_3; +CREATE ROLE dist_role_4; +SET citus.enable_create_role_propagation TO OFF; +CREATE ROLE non_dist_role_1 SUPERUSER; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +CREATE ROLE non_dist_role_2; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +CREATE ROLE non_dist_role_3; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +CREATE ROLE non_dist_role_4; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +SET citus.enable_create_role_propagation TO ON; +grant dist_role_3,dist_role_1 to test_admin_role with admin option; +SET ROLE dist_role_1; +GRANT non_dist_role_1 TO non_dist_role_2; +ERROR: connection to the remote node dist_role_1@localhost:xxxxx failed with the following error: FATAL: role "dist_role_1" is not permitted to log in +SET citus.enable_create_role_propagation TO OFF; +grant dist_role_1 to non_dist_role_1 with admin option; +SET ROLE non_dist_role_1; +GRANT dist_role_1 TO dist_role_2 granted by non_dist_role_1; +RESET ROLE; +SET citus.enable_create_role_propagation TO ON; +GRANT dist_role_3 TO non_dist_role_3 granted by test_admin_role; +ERROR: role "non_dist_role_3" does not exist +CONTEXT: while executing command on localhost:xxxxx +GRANT non_dist_role_4 TO dist_role_4; +GRANT dist_role_3 TO dist_role_4 granted by test_admin_role; +SELECT 1 FROM master_add_node('localhost', :worker_2_port); +WARNING: role "non_dist_role_1" does not exist +CONTEXT: while executing command on localhost:xxxxx +ERROR: failure on connection marked as essential: localhost:xxxxx +\c - - - :worker_2_port +create role non_dist_role_1; +\c - - - :master_port +--will be successful since non_dist_role_1 is created on worker_2 +SELECT 1 FROM master_add_node('localhost', :worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist\_%' ORDER BY 1; + objid +--------------------------------------------------------------------- + dist_role_1 + dist_role_2 + dist_role_3 + dist_role_4 + non_dist_role_1 + non_dist_role_4 +(6 rows) + +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT json_agg(q.* ORDER BY member) FROM ( + SELECT member::regrole::text, roleid::regrole::text AS role, grantor::regrole::text, admin_option + FROM pg_auth_members WHERE roleid::regrole::text = 'dist_role_3' + ) q; + $$ +); + result +--------------------------------------------------------------------- + [{"member":"dist_role_4","role":"dist_role_3","grantor":"test_admin_role","admin_option":false}, + + {"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role_4","role":"dist_role_3","grantor":"test_admin_role","admin_option":false}, + + {"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role_4","role":"dist_role_3","grantor":"test_admin_role","admin_option":false}, + + {"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] +(3 rows) + +REVOKE dist_role_3 from dist_role_4 granted by test_admin_role cascade; +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT json_agg(q.* ORDER BY member) FROM ( + SELECT member::regrole::text, roleid::regrole::text AS role, grantor::regrole::text, admin_option + FROM pg_auth_members WHERE roleid::regrole::text = 'dist_role_3' + order by member::regrole::text + ) q; + $$ +); + result +--------------------------------------------------------------------- + [{"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] + [{"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] + [{"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] +(3 rows) + +SELECT roleid::regrole::text AS role, member::regrole::text, (grantor::regrole::text IN ('postgres', 'non_dist_role_1', 'dist_role_1','test_admin_role')) AS grantor, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + dist_role_1 | dist_role_2 | t | f + dist_role_1 | non_dist_role_1 | t | t + dist_role_1 | test_admin_role | t | t + dist_role_3 | test_admin_role | t | t + non_dist_role_4 | dist_role_4 | t | f +(5 rows) + +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist\_%' ORDER BY 1; + objid +--------------------------------------------------------------------- + dist_role_1 + dist_role_2 + dist_role_3 + dist_role_4 + non_dist_role_1 + non_dist_role_4 +(6 rows) + +REVOKE dist_role_3 from non_dist_role_3 granted by test_admin_role cascade; +WARNING: role "non_dist_role_3" is not a member of role "dist_role_3" +ERROR: role "non_dist_role_3" does not exist +CONTEXT: while executing command on localhost:xxxxx +SELECT result FROM run_command_on_all_nodes( + $$ + SELECT json_agg(q.* ORDER BY member) FROM ( + SELECT member::regrole::text, roleid::regrole::text AS role, grantor::regrole::text, admin_option + FROM pg_auth_members WHERE roleid::regrole::text = 'dist_role_3' + order by member::regrole::text + ) q; + $$ +); + result +--------------------------------------------------------------------- + [{"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] + [{"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] + [{"member":"test_admin_role","role":"dist_role_3","grantor":"postgres","admin_option":true}] +(3 rows) + +revoke dist_role_3,dist_role_1 from test_admin_role cascade; +drop role test_admin_role; +\c - - - :worker_1_port +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + non_dist_role_4 | dist_role_4 | postgres | f +(1 row) + +SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + dist_role_1 + dist_role_2 + dist_role_3 + dist_role_4 + non_dist_role_1 + non_dist_role_4 +(6 rows) + +\c - - - :worker_2_port +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + dist_role_1 | dist_role_2 | non_dist_role_1 | f + dist_role_1 | non_dist_role_1 | dist_role_1 | t + non_dist_role_4 | dist_role_4 | postgres | f +(3 rows) + +SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + dist_role_1 + dist_role_2 + dist_role_3 + dist_role_4 + non_dist_role_1 + non_dist_role_4 +(6 rows) + +\c - - - :master_port +DROP ROLE dist_role_3, non_dist_role_3, dist_role_4, non_dist_role_4; +-- test grant with multiple mixed roles +CREATE ROLE dist_mixed_1; +CREATE ROLE dist_mixed_2; +CREATE ROLE dist_mixed_3; +CREATE ROLE dist_mixed_4; +SET citus.enable_create_role_propagation TO OFF; +CREATE ROLE nondist_mixed_1; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +CREATE ROLE nondist_mixed_2; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- +(0 rows) + +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1; + objid +--------------------------------------------------------------------- + dist_mixed_1 + dist_mixed_2 + dist_mixed_3 + dist_mixed_4 +(4 rows) + +\c - - - :worker_1_port +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- +(0 rows) + +SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + dist_mixed_1 + dist_mixed_2 + dist_mixed_3 + dist_mixed_4 +(4 rows) + +\c - - - :master_port +SELECT master_remove_node('localhost', :worker_2_port); + master_remove_node +--------------------------------------------------------------------- + +(1 row) + +GRANT dist_mixed_1, dist_mixed_2, nondist_mixed_1 TO dist_mixed_3, dist_mixed_4, nondist_mixed_2; +ERROR: role "nondist_mixed_2" does not exist +CONTEXT: while executing command on localhost:xxxxx +\c - - - :worker_1_port +create role nondist_mixed_2; +\c - - - :master_port +GRANT dist_mixed_1, dist_mixed_2, nondist_mixed_1 TO dist_mixed_3, dist_mixed_4, nondist_mixed_2; +SELECT 1 FROM master_add_node('localhost', :worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + dist_mixed_1 | dist_mixed_3 | postgres | f + dist_mixed_1 | dist_mixed_4 | postgres | f + dist_mixed_1 | nondist_mixed_2 | postgres | f + dist_mixed_2 | dist_mixed_3 | postgres | f + dist_mixed_2 | dist_mixed_4 | postgres | f + dist_mixed_2 | nondist_mixed_2 | postgres | f + nondist_mixed_1 | dist_mixed_3 | postgres | f + nondist_mixed_1 | dist_mixed_4 | postgres | f + nondist_mixed_1 | nondist_mixed_2 | postgres | f +(9 rows) + +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1; + objid +--------------------------------------------------------------------- + dist_mixed_1 + dist_mixed_2 + dist_mixed_3 + dist_mixed_4 + nondist_mixed_1 + nondist_mixed_2 +(6 rows) + +\c - - - :worker_1_port +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + dist_mixed_1 | dist_mixed_3 | postgres | f + dist_mixed_1 | dist_mixed_4 | postgres | f + dist_mixed_1 | nondist_mixed_2 | postgres | f + dist_mixed_2 | dist_mixed_3 | postgres | f + dist_mixed_2 | dist_mixed_4 | postgres | f + dist_mixed_2 | nondist_mixed_2 | postgres | f + nondist_mixed_1 | dist_mixed_3 | postgres | f + nondist_mixed_1 | dist_mixed_4 | postgres | f + nondist_mixed_1 | nondist_mixed_2 | postgres | f +(9 rows) + +SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + dist_mixed_1 + dist_mixed_2 + dist_mixed_3 + dist_mixed_4 + nondist_mixed_1 + nondist_mixed_2 +(6 rows) + +\c - - - :worker_2_port +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%dist\_mixed%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + dist_mixed_1 | dist_mixed_3 | postgres | f + dist_mixed_1 | dist_mixed_4 | postgres | f + dist_mixed_1 | nondist_mixed_2 | postgres | f + dist_mixed_2 | dist_mixed_3 | postgres | f + dist_mixed_2 | dist_mixed_4 | postgres | f + dist_mixed_2 | nondist_mixed_2 | postgres | f + nondist_mixed_1 | dist_mixed_3 | postgres | f + nondist_mixed_1 | dist_mixed_4 | postgres | f + nondist_mixed_1 | nondist_mixed_2 | postgres | f +(9 rows) + +SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist\_mixed%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + dist_mixed_1 + dist_mixed_2 + dist_mixed_3 + dist_mixed_4 + nondist_mixed_1 + nondist_mixed_2 +(6 rows) + +\c - - - :master_port +set citus.log_remote_commands to on; +set citus.grep_remote_commands to '%DROP%'; +DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4, nondist_mixed_1, nondist_mixed_2; +NOTICE: issuing DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4, nondist_mixed_1, nondist_mixed_2 +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +NOTICE: issuing DROP ROLE dist_mixed_1, dist_mixed_2, dist_mixed_3, dist_mixed_4, nondist_mixed_1, nondist_mixed_2 +DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx +set citus.grep_remote_commands to '%DROP%'; +reset citus.log_remote_commands; +-- test drop multiple roles with non-distributed roles +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist%' ORDER BY 1; + objid +--------------------------------------------------------------------- + dist_role_1 + dist_role_2 + non_dist_role_1 +(3 rows) + +SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + dist_role_1 + dist_role_2 + non_dist_role_1 + non_dist_role_2 +(4 rows) + +\c - - - :worker_1_port +SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + dist_role_1 + dist_role_2 + non_dist_role_1 +(3 rows) + +\c - - - :master_port +DROP ROLE dist_role_1, non_dist_role_1, dist_role_2, non_dist_role_2; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%dist%' ORDER BY 1; + objid +--------------------------------------------------------------------- +(0 rows) + +SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; + rolname +--------------------------------------------------------------------- +(0 rows) + +\c - - - :worker_1_port +SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; + rolname +--------------------------------------------------------------------- +(0 rows) + +\c - - - :worker_2_port +SELECT rolname FROM pg_authid WHERE rolname LIKE '%dist%' ORDER BY 1; + rolname +--------------------------------------------------------------------- +(0 rows) + +\c - - - :master_port +-- test alter part of create or alter role +SELECT master_remove_node('localhost', :worker_2_port); + master_remove_node +--------------------------------------------------------------------- + +(1 row) + +DROP ROLE create_role, create_role_2; +\c - - - :worker_2_port +SELECT rolname, rolcanlogin FROM pg_authid WHERE rolname = 'create_role' OR rolname = 'create_role_2' ORDER BY rolname; + rolname | rolcanlogin +--------------------------------------------------------------------- + create_role | f + create_role_2 | f +(2 rows) + +\c - - - :master_port +CREATE ROLE create_role LOGIN; +SELECT 1 FROM master_add_node('localhost', :worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +CREATE ROLE create_role_2 LOGIN; +\c - - - :worker_2_port +SELECT rolname, rolcanlogin FROM pg_authid WHERE rolname = 'create_role' OR rolname = 'create_role_2' ORDER BY rolname; + rolname | rolcanlogin +--------------------------------------------------------------------- + create_role | t + create_role_2 | t +(2 rows) + +\c - - - :master_port +-- test cascading grants +SET citus.enable_create_role_propagation TO OFF; +CREATE ROLE nondist_cascade_1; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +CREATE ROLE nondist_cascade_2; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +CREATE ROLE nondist_cascade_3; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +SET citus.enable_create_role_propagation TO ON; +CREATE ROLE dist_cascade; +GRANT nondist_cascade_1 TO nondist_cascade_2; +ERROR: role "nondist_cascade_2" does not exist +CONTEXT: while executing command on localhost:xxxxx +GRANT nondist_cascade_2 TO nondist_cascade_3; +ERROR: role "nondist_cascade_3" does not exist +CONTEXT: while executing command on localhost:xxxxx +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%cascade%' ORDER BY 1; + objid +--------------------------------------------------------------------- + dist_cascade +(1 row) + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%cascade%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- +(0 rows) + +\c - - - :worker_1_port +SELECT rolname FROM pg_authid WHERE rolname LIKE '%cascade%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + dist_cascade +(1 row) + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%cascade%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- +(0 rows) + +\c - - - :master_port +SELECT master_remove_node('localhost', :worker_2_port); + master_remove_node +--------------------------------------------------------------------- + +(1 row) + +GRANT nondist_cascade_3 TO dist_cascade; +SELECT 1 FROM master_add_node('localhost', :worker_2_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%cascade%' ORDER BY 1; + objid +--------------------------------------------------------------------- + nondist_cascade_3 + dist_cascade +(2 rows) + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%cascade%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + nondist_cascade_3 | dist_cascade | postgres | f +(1 row) + +\c - - - :worker_1_port +SELECT rolname FROM pg_authid WHERE rolname LIKE '%cascade%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + dist_cascade + nondist_cascade_3 +(2 rows) + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%cascade%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + nondist_cascade_3 | dist_cascade | postgres | f +(1 row) + +\c - - - :worker_2_port +SELECT rolname FROM pg_authid WHERE rolname LIKE '%cascade%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + dist_cascade + nondist_cascade_3 +(2 rows) + +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%cascade%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- + nondist_cascade_3 | dist_cascade | postgres | f +(1 row) + +\c - - - :master_port +DROP ROLE create_role, create_role_2, create_group, create_group_2, create_user, create_user_2, create_role_with_nothing, create_role_sysid, "create_role'edge", "create_role""edge"; +-- test grant non-existing roles +CREATE ROLE existing_role_1; +CREATE ROLE existing_role_2; +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%existing%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- +(0 rows) + +GRANT existing_role_1, nonexisting_role_1 TO existing_role_2, nonexisting_role_2; +ERROR: role "nonexisting_role_2" does not exist +SELECT roleid::regrole::text AS role, member::regrole::text, grantor::regrole::text, admin_option FROM pg_auth_members WHERE roleid::regrole::text LIKE '%existing%' ORDER BY 1, 2; + role | member | grantor | admin_option +--------------------------------------------------------------------- +(0 rows) + +-- test drop non-existing roles +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%existing%' ORDER BY 1; + objid +--------------------------------------------------------------------- + existing_role_1 + existing_role_2 +(2 rows) + +SELECT rolname FROM pg_authid WHERE rolname LIKE '%existing%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + existing_role_1 + existing_role_2 +(2 rows) + +\c - - - :worker_1_port +SELECT rolname FROM pg_authid WHERE rolname LIKE '%existing%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + existing_role_1 + existing_role_2 +(2 rows) + +\c - - - :master_port +DROP ROLE existing_role_1, existing_role_2, nonexisting_role_1, nonexisting_role_2; +ERROR: role "nonexisting_role_1" does not exist +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%existing%' ORDER BY 1; + objid +--------------------------------------------------------------------- + existing_role_1 + existing_role_2 +(2 rows) + +SELECT rolname FROM pg_authid WHERE rolname LIKE '%existing%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + existing_role_1 + existing_role_2 +(2 rows) + +\c - - - :worker_1_port +SELECT rolname FROM pg_authid WHERE rolname LIKE '%existing%' ORDER BY 1; + rolname +--------------------------------------------------------------------- + existing_role_1 + existing_role_2 +(2 rows) + +\c - - - :master_port +DROP ROLE IF EXISTS existing_role_1, existing_role_2, nonexisting_role_1, nonexisting_role_2; +NOTICE: role "nonexisting_role_1" does not exist, skipping +NOTICE: role "nonexisting_role_2" does not exist, skipping +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text LIKE '%existing%' ORDER BY 1; + objid +--------------------------------------------------------------------- +(0 rows) + +SELECT rolname FROM pg_authid WHERE rolname LIKE '%existing%' ORDER BY 1; + rolname +--------------------------------------------------------------------- +(0 rows) + +\c - - - :worker_1_port +SELECT rolname FROM pg_authid WHERE rolname LIKE '%existing%' ORDER BY 1; + rolname +--------------------------------------------------------------------- +(0 rows) + +\c - - - :master_port +DROP ROLE nondist_cascade_1, nondist_cascade_2, nondist_cascade_3, dist_cascade; diff --git a/src/test/regress/expected/granted_by_support_0.out b/src/test/regress/expected/granted_by_support_0.out index 3de13a622..e850214a8 100644 --- a/src/test/regress/expected/granted_by_support_0.out +++ b/src/test/regress/expected/granted_by_support_0.out @@ -29,21 +29,49 @@ grant dist_role3 to dist_role4 with admin option; -- To test non-distributed grantor, set this option off for some roles. set citus.enable_create_role_propagation to off; grant non_dist_role1 to dist_role1 with admin option; -reset citus.enable_create_role_propagation; -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - objid ---------------------------------------------------------------------- -(0 rows) - grant dist_role2 to non_dist_role1 with admin option; -NOTICE: not propagating GRANT command to other nodes -HINT: Since no grantees are distributed, the GRANT command will not be propagated to other nodes. +grant dist_role2 to dist_role4 granted by non_dist_role1 ; +reset citus.enable_create_role_propagation; +grant dist_role2 to "dist_role5'_test" granted by non_dist_role1;--will fail since non_dist_role1 does not exist on worker_1 +ERROR: role "non_dist_role1" does not exist +CONTEXT: while executing command on localhost:xxxxx +\c - - - :master_port grant dist_role3 to "dist_role5'_test" granted by dist_role4; grant dist_role2 to "dist_role5'_test" granted by dist_role3; -grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed -NOTICE: not propagating GRANT command to other nodes -HINT: Since grantor is not distributed, the GRANT command will not be propagated to other nodes. +--will fail since non_dist_role2 does not exist in worker_1 +grant dist_role2 to non_dist_role2 with admin option; +ERROR: role "non_dist_role2" does not exist +grant dist_role2 to dist_role4 granted by non_dist_role2 ; +ERROR: role "non_dist_role2" does not exist +grant non_dist_role2 to "dist_role5'_test"; +ERROR: role "non_dist_role2" does not exist +\c - - - :worker_1_port +create role non_dist_role2; +\c - - - :master_port +--will be successful since non_dist_role has been created on worker_1 +grant dist_role2 to non_dist_role2 with admin option; +grant dist_role2 to dist_role4 granted by non_dist_role2 ; +NOTICE: role "dist_role4" is already a member of role "dist_role2" +grant non_dist_role2 to "dist_role5'_test"; grant dist_role4 to "dist_role5'_test" with admin option; +select result FROM run_command_on_all_nodes( + $$ + SELECT array_to_json(array_agg(row_to_json(t))) + FROM ( + SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option + FROM pg_auth_members + WHERE member::regrole::text in + ('dist_role1','non_dist_role1') + order by member::regrole::text, roleid::regrole::text + ) t + $$ +); + result +--------------------------------------------------------------------- + [{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"non_dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true}] +(2 rows) + --below command propagates the non_dist_role1 since non_dist_role1 is already granted to dist_role1 --and citus sees granted roles as a dependency and citus propagates the dependent roles grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; @@ -62,175 +90,20 @@ grant dist_role3 to dist_role1 with admin option GRANTED BY dist_role4; grant "dist_role5'_test" to dist_role1 with admin option; grant "dist_role5'_test" to dist_role3 with admin option GRANTED BY dist_role1;--fails since already dist_role3 granted to "dist_role5'_test" ERROR: role "dist_role5'_test" is a member of role "dist_role3" -select result FROM run_command_on_all_nodes( - $$ - SELECT array_to_json(array_agg(row_to_json(t))) - FROM ( - SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option - FROM pg_auth_members - WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') - order by member::regrole::text, roleid::regrole::text - ) t - $$ -); - result ---------------------------------------------------------------------- - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false}] - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false}] -(2 rows) - -select 1 from citus_add_node ('localhost',:worker_2_port); - ?column? ---------------------------------------------------------------------- - 1 -(1 row) - -select result FROM run_command_on_all_nodes( - $$ - SELECT array_to_json(array_agg(row_to_json(t))) - FROM ( - SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option - FROM pg_auth_members - WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') - order by member::regrole::text, roleid::regrole::text - ) t - $$ -); - result ---------------------------------------------------------------------- - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false}] - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false}] - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false}] -(3 rows) - ---clean all resources -drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; -drop role non_dist_role1; -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - objid ---------------------------------------------------------------------- -(0 rows) - -reset citus.enable_create_role_propagation; -select result FROM run_command_on_all_nodes( - $$ - SELECT array_to_json(array_agg(row_to_json(t))) - FROM ( - SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option - FROM pg_auth_members - WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') - order by member::regrole::text, roleid::regrole::text - ) t - $$ -); - result ---------------------------------------------------------------------- - - - -(3 rows) - ---- Test 2: Tests from non-main database -set citus.enable_create_database_propagation to on; -create database test_granted_by_support; -select 1 from citus_remove_node ('localhost',:worker_2_port); - ?column? ---------------------------------------------------------------------- - 1 -(1 row) - -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - objid ---------------------------------------------------------------------- -(0 rows) - -\c test_granted_by_support ---here in below block since 'citus.enable_create_role_propagation to off ' is not effective, ---non_dist_role1 is being propagated to dist_role1 unlike main db scenario ---non_dist_role1 will be used for the test scenarios in this section set citus.enable_create_role_propagation to off; -create role non_dist_role1; -reset citus.enable_create_role_propagation; ---dropping since it isn't non-distributed as intended -drop role non_dist_role1; ---creating non_dist_role1 again in main database ---This is actually non-distributed role -\c regression -set citus.enable_create_role_propagation to off; -create role non_dist_role1; +create role non_dist_role_for_mds; NOTICE: not propagating CREATE ROLE/USER commands to other nodes HINT: Connect to other nodes directly to manually create all necessary users and roles. +grant dist_role3 to non_dist_role_for_mds with admin option; +grant non_dist_role_for_mds to dist_role1 with admin option; +grant dist_role3 to dist_role4 with admin option GRANTED BY non_dist_role_for_mds; +NOTICE: role "dist_role4" is already a member of role "dist_role3" reset citus.enable_create_role_propagation; -\c test_granted_by_support -create role dist_role1; -create role dist_role1; -ERROR: role "dist_role1" already exists -create role dist_role2; -create role dist_role3; -create role dist_role4; -create role "dist_role5'_test"; -\c regression - - :master_port -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role_for_mds' ORDER BY 1; objid --------------------------------------------------------------------- (0 rows) -\c test_granted_by_support -grant dist_role2 to dist_role1 with admin option; -grant dist_role2 to dist_role3 with admin option granted by dist_role1; -grant dist_role3 to dist_role4 with admin option; --- With enable_create_role_propagation on, all grantees are propagated. --- To test non-distributed grantor, set this option off for some roles. -\c regression -set citus.enable_create_role_propagation to off; -grant non_dist_role1 to dist_role1 with admin option; -reset citus.enable_create_role_propagation; -\c test_granted_by_support -grant dist_role2 to non_dist_role1 with admin option; -ERROR: failure on connection marked as essential: localhost:xxxxx -CONTEXT: while executing command on localhost:xxxxx -\c test_granted_by_support - - :worker_1_port -grant dist_role3 to "dist_role5'_test" granted by dist_role4; -grant dist_role2 to "dist_role5'_test" granted by dist_role3; -grant dist_role2 to dist_role4 granted by non_dist_role1 ;--will not be propagated since grantor is non-distributed -ERROR: role "non_dist_role1" does not exist -\c regression - - :master_port -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - objid ---------------------------------------------------------------------- -(0 rows) - -\c test_granted_by_support - - :worker_1_port -grant dist_role4 to "dist_role5'_test" with admin option; -\c regression - - :master_port -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - objid ---------------------------------------------------------------------- -(0 rows) - -\c test_granted_by_support --- Unlike maindb scenario, non-maindb scenario doesn't propagate 'create non_dist_role1' to ---workers as it doesn't create dependency objects for non-distributed roles. -grant dist_role4 to dist_role1 with admin option GRANTED BY "dist_role5'_test"; -\c regression - - :master_port -SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; - objid ---------------------------------------------------------------------- -(0 rows) - -\c test_granted_by_support - - :worker_1_port -grant dist_role4 to dist_role3 with admin option GRANTED BY dist_role1; --fails since already dist_role3 granted to dist_role4 -ERROR: role "dist_role4" is a member of role "dist_role3" -grant non_dist_role1 to dist_role4 granted by dist_role1; -ERROR: role "non_dist_role1" does not exist -grant dist_role3 to dist_role1 with admin option GRANTED BY dist_role4; -grant "dist_role5'_test" to dist_role1 with admin option; -grant "dist_role5'_test" to dist_role3 with admin option GRANTED BY dist_role1;--fails since already dist_role3 granted to "dist_role5'_test" -ERROR: role "dist_role5'_test" is a member of role "dist_role3" -\c regression - - :master_port select result FROM run_command_on_all_nodes( $$ SELECT array_to_json(array_agg(row_to_json(t))) @@ -238,17 +111,33 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"', 'non_dist_role_for_mds','non_dist_role1','non_dist_role2') order by member::regrole::text, roleid::regrole::text ) t $$ ); - result + result --------------------------------------------------------------------- - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"non_dist_role_for_mds","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false},{"member":"non_dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role2","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role_for_mds","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role2","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false},{"member":"non_dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role2","role":"dist_role2","grantor":"postgres","admin_option":true}] (2 rows) +set citus.enable_create_role_propagation to off; +create role non_dist_role_mds_fail; +NOTICE: not propagating CREATE ROLE/USER commands to other nodes +HINT: Connect to other nodes directly to manually create all necessary users and roles. +grant dist_role2 to non_dist_role_mds_fail with admin option; +grant dist_role2 to non_dist_role_for_mds GRANTED BY non_dist_role_mds_fail; +reset citus.enable_create_role_propagation; +--will fail since non_dist_role_for_mds is not in dependency resolution +select 1 from citus_add_node ('localhost',:worker_2_port); +WARNING: role "non_dist_role_mds_fail" does not exist +CONTEXT: while executing command on localhost:xxxxx +ERROR: failure on connection marked as essential: localhost:xxxxx +--this grant statement will add non_dist_role_mds_fail to dist_role3 dependencies +grant non_dist_role_mds_fail to dist_role3; +--will be successful since non_dist_role_mds_fail is in dependency resolution of dist_role3 +-- and will be created in metadata sync phase select 1 from citus_add_node ('localhost',:worker_2_port); ?column? --------------------------------------------------------------------- @@ -262,25 +151,27 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"','non_dist_role_for_mds','non_dist_role1','non_dist_role2') order by member::regrole::text, roleid::regrole::text ) t $$ ); - result + result --------------------------------------------------------------------- - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] - [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"non_dist_role_for_mds","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role3","role":"non_dist_role_mds_fail","grantor":"postgres","admin_option":false},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false},{"member":"non_dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role2","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role_for_mds","role":"dist_role2","grantor":"non_dist_role_mds_fail","admin_option":false},{"member":"non_dist_role_for_mds","role":"dist_role3","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role3","role":"non_dist_role_mds_fail","grantor":"postgres","admin_option":false},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role2","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false},{"member":"non_dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role2","role":"dist_role2","grantor":"postgres","admin_option":true}] + [{"member":"dist_role1","role":"\"dist_role5'_test\"","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"dist_role3","grantor":"dist_role4","admin_option":true},{"member":"dist_role1","role":"dist_role4","grantor":"\"dist_role5'_test\"","admin_option":true},{"member":"dist_role1","role":"non_dist_role1","grantor":"postgres","admin_option":true},{"member":"dist_role1","role":"non_dist_role_for_mds","grantor":"postgres","admin_option":true},{"member":"dist_role3","role":"dist_role2","grantor":"dist_role1","admin_option":true},{"member":"dist_role3","role":"non_dist_role_mds_fail","grantor":"postgres","admin_option":false},{"member":"dist_role4","role":"dist_role2","grantor":"non_dist_role1","admin_option":false},{"member":"dist_role4","role":"dist_role3","grantor":"postgres","admin_option":true},{"member":"dist_role4","role":"non_dist_role1","grantor":"dist_role1","admin_option":false},{"member":"non_dist_role1","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role2","role":"dist_role2","grantor":"postgres","admin_option":true},{"member":"non_dist_role_for_mds","role":"dist_role2","grantor":"non_dist_role_mds_fail","admin_option":false},{"member":"non_dist_role_for_mds","role":"dist_role3","grantor":"postgres","admin_option":true}] (3 rows) --clean all resources -set citus.enable_create_database_propagation to on; -drop database test_granted_by_support; drop role dist_role1,dist_role2,dist_role3,dist_role4,"dist_role5'_test"; -drop role non_dist_role1; -drop role if exists non_dist_role1; -NOTICE: role "non_dist_role1" does not exist, skipping +drop role non_dist_role1,non_dist_role2,non_dist_role_for_mds,non_dist_role_mds_fail; +SELECT objid::regrole FROM pg_catalog.pg_dist_object WHERE classid='pg_authid'::regclass::oid AND objid::regrole::text= 'non_dist_role1' ORDER BY 1; + objid +--------------------------------------------------------------------- +(0 rows) + +reset citus.enable_create_role_propagation; select result FROM run_command_on_all_nodes( $$ SELECT array_to_json(array_agg(row_to_json(t))) @@ -288,7 +179,7 @@ select result FROM run_command_on_all_nodes( SELECT member::regrole, roleid::regrole as role, grantor::regrole, admin_option FROM pg_auth_members WHERE member::regrole::text in - ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"') + ('dist_role1','dist_role2','dist_role3','dist_role4','"role5''_test"','non_dist_role_for_mds','non_dist_role1','non_dist_role2') order by member::regrole::text, roleid::regrole::text ) t $$ @@ -300,4 +191,3 @@ select result FROM run_command_on_all_nodes( (3 rows) -reset citus.enable_create_database_propagation; From 9874a074f6a200fd7a99f1e8c1318598c7f51099 Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Wed, 13 Mar 2024 14:58:52 +0300 Subject: [PATCH 23/23] Fixes test output for pg16 --- src/backend/distributed/commands/role.c | 6 ++++-- src/test/regress/expected/pg16.out | 20 +++++++++++--------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index b5fab1e3b..c195fe3f2 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -891,7 +891,8 @@ GenerateGrantRoleStmtsOfRole(Oid roleid) Form_pg_auth_members membership = (Form_pg_auth_members) GETSTRUCT(tuple); GrantRoleStmt *grantRoleStmt = GetGrantRoleStmtFromAuthMemberRecord(membership); - if (grantRoleStmt == NULL ||IsReservedName(GetUserNameFromId(membership->roleid, true))) + if (grantRoleStmt == NULL || IsReservedName(GetUserNameFromId(membership->roleid, + true))) { continue; } @@ -938,7 +939,8 @@ GenerateGrantRoleStmts() GrantRoleStmt *grantRoleStmt = GetGrantRoleStmtFromAuthMemberRecord(membership); - if (grantRoleStmt == NULL || IsReservedName(GetUserNameFromId(membership->roleid, true))) + if (grantRoleStmt == NULL || IsReservedName(GetUserNameFromId(membership->roleid, + true))) { continue; } diff --git a/src/test/regress/expected/pg16.out b/src/test/regress/expected/pg16.out index a035fcfc4..1974f2eb1 100644 --- a/src/test/regress/expected/pg16.out +++ b/src/test/regress/expected/pg16.out @@ -1032,14 +1032,14 @@ WHERE roleid::regrole::text = 'role1' ORDER BY 1, 2; -- Set GUCs to log remote commands and filter on REVOKE commands SET citus.log_remote_commands TO on; SET citus.grep_remote_commands = '%REVOKE%'; - -- test REVOKES as well - GRANT role1 TO role2; - REVOKE SET OPTION FOR role1 FROM role2; +-- test REVOKES as well +GRANT role1 TO role2; +REVOKE SET OPTION FOR role1 FROM role2; NOTICE: issuing REVOKE SET OPTION FOR role1 FROM role2 RESTRICT; DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing REVOKE SET OPTION FOR role1 FROM role2 RESTRICT; DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx - REVOKE INHERIT OPTION FOR role1 FROM role2; +REVOKE INHERIT OPTION FOR role1 FROM role2; NOTICE: issuing REVOKE INHERIT OPTION FOR role1 FROM role2 RESTRICT; DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing REVOKE INHERIT OPTION FOR role1 FROM role2 RESTRICT; @@ -1053,14 +1053,16 @@ CREATE ROLE role5; RESET citus.enable_ddl_propagation; -- by default, admin option is false, inherit is true, set is true GRANT role3 TO role4; +ERROR: role "role4" does not exist +CONTEXT: while executing command on localhost:xxxxx GRANT role3 TO role5 WITH ADMIN TRUE, INHERIT FALSE, SET FALSE; +ERROR: role "role5" does not exist +CONTEXT: while executing command on localhost:xxxxx SELECT roleid::regrole::text AS role, member::regrole::text, admin_option, inherit_option, set_option FROM pg_auth_members WHERE roleid::regrole::text = 'role3' ORDER BY 1, 2; - role | member | admin_option | inherit_option | set_option + role | member | admin_option | inherit_option | set_option --------------------------------------------------------------------- - role3 | role4 | f | t | t - role3 | role5 | t | f | f -(2 rows) +(0 rows) DROP ROLE role3, role4, role5; -- Test that everything works fine for roles that are propagated @@ -1140,7 +1142,7 @@ DROP ROLE role6, role7, role8, role9, role10, role11, role12, -- when adding a new node. -- First, we need to remove the node: SELECT 1 FROM citus_remove_node('localhost', :worker_2_port); -?column? + ?column? --------------------------------------------------------------------- 1 (1 row)