From 6ed8ad222ce836f0496e2f03e48789008e87965f Mon Sep 17 00:00:00 2001 From: gurkanindibay Date: Mon, 4 Mar 2024 11:55:16 +0300 Subject: [PATCH] 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 + $$ +);