openGauss源码解析(197)

openGauss源码解析:安全管理源码解析(8)

2. 删除角色

如果要删除一个角色,可以使用SQL命令DROP ROLE。角色的删除是通过调用DropRole函数来实现的,该函数只有一个类型为DropRoleStmt结构的参数。相关代码如下:

typedef struct DropRoleStmt {

NodeTagtype;

List*roles; /* 要删除的角色列表 */

boolmissing_ok; /* 判断角色是否存在 */

boolis_user; /* 要删除的是角色还是用户 */

boolinherit_from_parent; /* 是否继承自父角色*/

DropBehavior behavior; /* 是否级联删除依赖对象 */

} DropRoleStmt;

删除角色的流程如图9-16所示。

图9-16 openGauss角色删除流程图

角色删除的执行流程为:首先判断当前操作者是否有权限执行该操作,若没有则报错退出;然后检查待删除的角色是否存在,若不存在,则根据missing_ok选择返回ERROR或NOTICE提示信息;再通过扫描系统表pg_authid和pg_auth_members,删除所有涉及待删除角色的元组执行;若behavior取值DROP_CASCADE,则级联删除该角色所拥有的所有数据库对象;最后删除该角色在系统表pg_auth_history和pg_user_status中对应的信息。具体的实现过程代码如下:

void DropRole(DropRoleStmt* stmt)

{

. . .

/* 检查执行者是否有权限删除角色 */

if (!have_createrole_privilege())

ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Permission denied to drop role.")));

/* 循环处理要删除的角色 */

foreach (item, stmt->roles) {

. . .

/* 检查要删除的角色是否存在,若不存在则提示报错 */

HeapTuple tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(role));

if (!HeapTupleIsValid(tuple)) {

if (!stmt->missing_ok) {

ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("role \"%s\" does not exist", role)));

} else {

ereport(NOTICE, (errmsg("role \"%s\" does not exist, skipping", role)));

}

continue;

}

. . .

/* 当前用户不允许删除 */

if (roleid == GetUserId())

ereport(ERROR, (errcode(ERRCODE_OBJECT_IN_USE), errmsg("current user cannot be dropped")));

if (roleid == GetOuterUserId())

ereport(ERROR, (errcode(ERRCODE_OBJECT_IN_USE), errmsg("current user cannot be dropped")));

if (roleid == GetSessionUserId())

ereport(ERROR, (errcode(ERRCODE_OBJECT_IN_USE), errmsg("session user cannot be dropped")));

/* 校验执行者和被删除角色的权限,如系统管理员才有权限删除其他系统管理员 */

if((((Form_pg_authid)GETSTRUCT(tuple))->rolsuper|| ((Form_pg_authid)GETSTRUCT(tuple))->rolsystemadmin) &&

!isRelSuperuser())

ereport(ERROR,(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Permission denied.")));

if ((((Form_pg_authid)GETSTRUCT(tuple))->rolauditadmin) &&

g_instance.attr.attr_security.enablePrivilegesSeparate && !isRelSuperuser())

ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("Permission denied.")));

. . .

/* 针对CASCADE(级联)的情况,删除该角色拥有的对象 */

if (stmt->behavior == DROP_CASCADE) {

char* user = NULL;

CancelQuery(role);

user = (char*)palloc(sizeof(char) * strlen(role) + 1);

errno_t errorno = strncpy_s(user, strlen(role) + 1, role, strlen(role));

securec_check(errorno, "\0", "\0");

drop_objectstmt.behavior = stmt->behavior;

drop_objectstmt.type = T_DropOwnedStmt;

drop_objectstmt.roles = list_make1(makeString(user));

DropOwnedObjects(&drop_objectstmt);

list_free_deep(drop_objectstmt.roles);

}

/* 检查是否有对象依赖于该角色,若还存在依赖,则提示报错 */

if (checkSharedDependencies(AuthIdRelationId, roleid, &detail, &detail_log))

ereport(ERROR,

(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),

errmsg("role \"%s\" cannot be dropped because some objects depend on it", role),

errdetail_internal("%s", detail),

errdetail_log("%s", detail_log)));

/* 从相关系统表中删除涉及待删除角色的元组 */

simple_heap_delete(pg_authid_rel, &tuple->t_self);

. . .

while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan))) {

simple_heap_delete(pg_auth_members_rel, &tmp_tuple->t_self);

}

systable_endscan(sscan);

DropAuthHistory(roleid);

DropUserStatus(roleid);

DeleteSharedComments(roleid, AuthIdRelationId);

DeleteSharedSecurityLabel(roleid, AuthIdRelationId);

DropSetting(InvalidOid, roleid);

. . .

heap_close(pg_auth_members_rel, NoLock);

heap_close(pg_authid_rel, NoLock);

}

posted @ 2024-05-07 09:25  openGauss-bot  阅读(5)  评论(0编辑  收藏  举报