目录
书接上文openGauss安全整体架构&安全认证,从安全整体架构与安全认证两方面,对高斯数据库的高安全性能进行了解读,本篇我们将从角色创建和角色管理两方面对高斯数据库的角色权限进行介绍。
3.1 角色创建
角色是拥有数据库对象和权限的实体,在不同的环境中角色可以认为是一个用户,一个组或者兼顾两者。如果在openGauss上需要创建一个角色,可以使用SQL命令CREATE ROLE,其语法为:
CREATE ROLE role_name [ [ WITH ] option [ ... ] ] [ ENCRYPTED | UNENCRYPTED ] { PASSWORD | IDENTIFIED BY } { 'password' | DISABLE };
创建角色是通过函数CreateRole实现的,其函数接口为:
void CreateRole(CreateRoleStmt* stmt)
其中,CreateRoleStmt为创建角色时所需的数据结构,具体数据结构为:
typedef struct CreateRoleStmt {
NodeTag type;
RoleStmtType stmt_type; // 将要创建的角色类型 ROLE/USER/GROUP
char* role; // 角色名
List* options; // 角色属性列表
} CreateRoleStmt;
字段stmt_type是枚举类型,如下所示:
typedef enum RoleStmtType {
ROLESTMT_ROLE, // 代表创建角色
ROLESTMT_USER, // 代表创建用户
ROLESTMT_GROUP, // 代表创建组用户
} RoleStmtType;
字段option用来存储角色的属性信息,具体的数据结构为:
typedef struct DefElem {
NodeTag type;
char* defnamespace; // 节点对应的命名空间
char* defname; // 节点对应的角色属性名
Node* arg; // 表示值或类型名
DefElemAction defaction; // SET/ADD/DROP 等其他未指定的行为
} DefElem;
有了上述的关键数据结构,完整的创建角色流程:
图1 openGauss角色创建流程
创建角色时先判断所要创建的角色类型。如果是创建用户,则设置其canlogin属性为true,因为用户默认具有登录权限。而创建角色和创建组时,若角色属性参数没有声明的话,则canlogin属性默认为false。
// 默认值可能因原始语句类型而异
switch (stmt->stmt_type) {
case ROLESTMT_ROLE:
break;
case ROLESTMT_USER:
canlogin = true;
break;
case ROLESTMT_GROUP:
break;
default:
break;
}
检查完所要创建的角色类型以后,开始循环获取角色属性options中的内容,并将其转换成对应的的角色属性值类型。
// 从node tree中获取option
foreach (option, stmt->options) {
DefElem* defel = (DefElem*)lfirst(option);
if (strcmp(defel->defname, "password") == 0 || strcmp(defel->defname, "encryptedPassword") == 0 ||
strcmp(defel->defname, "unencryptedPassword") == 0) {
if (dpassword != NULL) {
clean_role_password(dpassword);
ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options")));
}
dpassword = defel;
if (strcmp(defel->defname, "encryptedPassword") == 0)
encrypt_password = true;
else if (strcmp(defel->defname, "unencryptedPassword") == 0) {
clean_role_password(dpassword);
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("Permission denied to create role with option UNENCRYPTED.")));
}
} else if (strcmp(defel->defname, "sysid") == 0) {
ereport(NOTICE, (errmsg("SYSID can no longer be specified")));
} else if (strcmp(defel->defname, "inherit") == 0) {
if (dinherit != NULL) {
clean_role_password(dpassword);
ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options")));
}
dinherit = defel;
} else if (strcmp(defel->defname, "createrole") == 0) {
if (dcreaterole != NULL) {
clean_role_password(dpassword);
ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options")));
}
dcreaterole = defel;
} else if (strcmp(defel->defname, "createdb") == 0) {
if (dcreatedb != NULL) {
clean_role_password(dpassword);
ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options")));
}
dcreatedb = defel;
} else if (strcmp(defel->defname, "useft") == 0) {
if (duseft != NULL) {
clean_role_password(dpassword);
ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting or redundant options")));
}
duseft = defel;
……
根据对应的参数信息转换需要的角色属性值类型,如提取issuper值和createrole值等:
if (dissuper != NULL)
issuper = intVal(dissuper->arg) != 0;
if (dinherit != NULL)
inherit = intVal(dinherit->arg) != 0;
if (dcreaterole != NULL)
createrole = intVal(dcreaterole->arg) != 0;
if (dcreatedb != NULL)