pull/7538/merge
Gürkan İndibay 2025-03-05 10:17:00 -08:00 committed by GitHub
commit 585e5b9b48
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 1191 additions and 98 deletions

View File

@ -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);
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);
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);
List *dependencyCommands = GetDependencyCreateDDLCommands(dependency, true);
/* create a new list with dependencies that actually created commands */
if (list_length(dependencyCommands) > 0)
@ -465,7 +466,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 +606,8 @@ GetDependencyCreateDDLCommands(const ObjectAddress *dependency)
case OCLASS_ROLE:
{
return GenerateCreateOrAlterRoleCommand(dependency->objectId);
return GenerateCreateOrAlterRoleCommand(dependency->objectId,
fetchGrantStatements);
}
case OCLASS_SCHEMA:
@ -680,15 +682,16 @@ 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;
}

View File

@ -56,6 +56,7 @@
#include "distributed/version_compat.h"
#include "distributed/worker_transaction.h"
static const char * ExtractEncryptedPassword(Oid roleOid);
static const char * CreateAlterRoleIfExistsCommand(AlterRoleStmt *stmt);
static const char * CreateAlterRoleSetIfExistsCommand(AlterRoleSetStmt *stmt);
@ -67,6 +68,9 @@ 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);
static void EnsureSequentialModeForRoleDDL(void);
@ -512,7 +516,7 @@ GenerateRoleOptionsList(HeapTuple tuple)
* the pg_authid table.
*/
List *
GenerateCreateOrAlterRoleCommand(Oid roleOid)
GenerateCreateOrAlterRoleCommand(Oid roleOid, bool fetchGrantStmts)
{
HeapTuple roleTuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleOid));
Form_pg_authid role = ((Form_pg_authid) GETSTRUCT(roleTuple));
@ -562,11 +566,10 @@ GenerateCreateOrAlterRoleCommand(Oid roleOid)
if (EnableCreateRolePropagation)
{
List *grantRoleStmts = GenerateGrantRoleStmtsOfRole(roleOid);
Node *stmt = NULL;
foreach_ptr(stmt, grantRoleStmts)
if (fetchGrantStmts)
{
completeRoleList = lappend(completeRoleList, DeparseTreeNode(stmt));
completeRoleList = list_concat(completeRoleList, GenerateGrantRoleStmtsOfRole(
roleOid));
}
/*
@ -577,7 +580,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));
@ -872,7 +875,9 @@ GenerateGrantRoleStmtsOfRole(Oid roleid)
{
Relation pgAuthMembers = table_open(AuthMemRelationId, AccessShareLock);
HeapTuple tuple = NULL;
List *stmts = NIL;
List *adminStmts = NIL;
List *otherStmts = NIL;
ScanKeyData skey[1];
@ -885,73 +890,182 @@ GenerateGrantRoleStmtsOfRole(Oid roleid)
{
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)))
GrantRoleStmt *grantRoleStmt = GetGrantRoleStmtFromAuthMemberRecord(membership);
if (grantRoleStmt == NULL)
{
/* we only need to propagate the grant if the grantor is distributed */
continue;
}
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)
if (membership->admin_option)
{
inherit_opt = makeDefElem("inherit", (Node *) makeBoolean(true), -1);
adminStmts = lappend(adminStmts, grantRoleStmt);
}
else
{
inherit_opt = makeDefElem("inherit", (Node *) makeBoolean(false), -1);
otherStmts = lappend(otherStmts, grantRoleStmt);
}
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
stmts = lappend(stmts, grantRoleStmt);
}
systable_endscan(scan);
table_close(pgAuthMembers, AccessShareLock);
return stmts;
List *allStmts = list_concat(adminStmts, otherStmts);
List *commands = NIL;
Node *stmt = NULL;
foreach_ptr(stmt, allStmts)
{
commands = lappend(commands, DeparseTreeNode(stmt));
}
return commands;
}
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);
/* 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)
{
continue;
}
if (membership->admin_option)
{
adminStmts = lappend(adminStmts, grantRoleStmt);
}
else
{
otherStmts = lappend(otherStmts, grantRoleStmt);
}
}
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 ObjectAddress *
GetRoleObjectAddressFromOid(Oid roleOid)
{
ObjectAddress *roleAddress = palloc0(sizeof(ObjectAddress));
ObjectAddressSet(*roleAddress, AuthIdRelationId, roleOid);
return roleAddress;
}
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;
}
@ -1202,7 +1316,7 @@ UnmarkRolesDistributed(List *roles)
List *
FilterDistributedRoles(List *roles)
{
List *distributedRoles = NIL;
List *validRoles = NIL;
Node *roleNode = NULL;
foreach_ptr(roleNode, roles)
{
@ -1218,12 +1332,46 @@ 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;
}
/*
* FilterDistributedRoles filters the list of AccessPrivs and returns the ones
* that are distributed.
*/
List *
FilterDistributedGrantedRoles(List *roles)
{
List *validRoles = 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);
bool isSystemRole = IsReservedName(role->priv_name);
if (IsAnyObjectDistributed(list_make1(roleAddress)) || isSystemRole)
{
validRoles = lappend(validRoles, role);
}
}
return validRoles;
}
@ -1244,17 +1392,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,
@ -1265,6 +1418,54 @@ 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.

View File

@ -5167,6 +5167,11 @@ SendDependencyCreationCommands(MetadataSyncContext *context)
List *ddlCommands = GetAllDependencyCreateDDLCommands(list_make1(dependency));
SendOrCollectCommandListToActivatedNodes(context, ddlCommands);
}
List *grantRoleCommands = GenerateGrantRoleStmts();
SendOrCollectCommandListToActivatedNodes(context, grantRoleCommands);
MemoryContextSwitchTo(oldContext);
if (!MetadataSyncCollectsCommands(context))

View File

@ -174,6 +174,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];
@ -519,7 +527,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);
@ -527,7 +535,11 @@ 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 */
extern List * PostprocessCreateSchemaStmt(Node *node, const char *queryString);

View File

@ -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;
@ -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
---------------------------------------------------------------------

View File

@ -0,0 +1,306 @@
-- 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;
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)))
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_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_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 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;

View File

@ -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;

View File

@ -1012,14 +1012,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;
@ -1033,7 +1033,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
@ -1120,7 +1128,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)

View File

@ -62,6 +62,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

View File

@ -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;

View File

@ -0,0 +1,238 @@
-- 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 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;
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;
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 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
--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"
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
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;
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 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;