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;