Ovirt程序员

【Ovirt 笔记】权限实现分析

2017-07-17  本文已影响24人  58bc06151329

文前说明

作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

本文仅供学习交流使用,侵权必删。
不用于商业目的,转载请注明出处。

分析整理的版本为 Ovirt 3.4.5 版本。

数据库结构

字段名称 字段类型 说明
id uuid 唯一性 ID
name string 名称
description string 描述信息
role_type integer 角色类型,1 为管理员,2 为用户
app_mode integer 应用模式,1 为 gluster 分布式存储节点,255 为 virt 虚拟化节点
字段名称 字段类型 说明
role_id uuid 角色 ID
action_group_id integer 操作组 ID
字段名称 字段类型 说明
id uuid 权限 ID
role_id uuid 角色 ID
ad_element_id uuid 登录用户 ID
object_id uuid 操作对象 ID
object_type_id integer 操作对象类型

定义操作组

枚举属性 说明 用例
value 枚举值 DELETE_VM
id 唯一性 ID 1
roleType 角色类型 RoleType.USER
vdcObjectType 操作对象类型 VdcObjectType.VM

定义操作

枚举属性 说明 用例
value 枚举值 RemoveVm
intValue 唯一性 ID 1
actionGroup 操作组 ActionGroup.DELETE_VM
quotaDependency 配额 QuotaDependency.STORAGE

准备工作

---Vm Groups
INSERT INTO roles_groups(role_id,action_group_id) VALUES(v_SUPER_USER_ID,v_DELETE_VM);

权限验证事务

以删除虚拟机操作为例,执行操作 RemoveVmCommand 删除虚拟机。

@Override
public List<PermissionSubject> getPermissionCheckSubjects() {
    List<PermissionSubject> permissionList = new ArrayList<PermissionSubject>();
    permissionList.add(new PermissionSubject(getParameters().getVmId(),
            VdcObjectType.VM,
            getActionType().getActionGroup()));
    return permissionList;
}
权限对象属性 说明 用例 用例说明
objectId 操作对象 ID getParameters().getVmId() 需要删除的虚拟机对象 ID
objectType 操作对象类型 VdcObjectType.VM 虚拟机
actionGroup 操作组 getActionType().getActionGroup() 操作组权限,ActionGroup.DELETE_VM
message 无权限操作提示信息 VdcBllMessages.USER_NOT_AUTHORIZED_TO_PERFORM_ACTION 没有删除虚拟机的权限
protected boolean isUserAuthorizedToRunAction() {
    // Skip check if this is an internal action:
    if (isInternalExecution()) {
        if (log.isDebugEnabled()) {
            log.debugFormat("Permission check skipped for internal action {0}.", getActionType());
        }
        return true;
    }

    // Skip check if multilevel administration is disabled:
    if (!MultiLevelAdministrationHandler.isMultilevelAdministrationOn()) {
        if (log.isDebugEnabled()) {
            log.debugFormat("Permission check for action {0} skipped because multilevel administration is disabled.",
                    getActionType());
        }
        return true;
    }

    // Deny the permissions if there is no logged in user:
    if (getCurrentUser() == null) {
        addCanDoActionMessage(VdcBllMessages.USER_IS_NOT_LOGGED_IN);
        return false;
    }

    // Get identifiers and types of the objects whose permissions have to be
    // checked:
    final List<PermissionSubject> permSubjects = getPermissionCheckSubjects();
......
if (permSubjects == null || permSubjects.isEmpty()) {
    if (log.isDebugEnabled()) {
        log.debugFormat("The set of objects to check is null or empty for action {0}.", getActionType());
    }
    addCanDoActionMessage(VdcBllMessages.USER_NOT_AUTHORIZED_TO_PERFORM_ACTION);
    return false;
}
return checkPermissions(permSubjects);
protected boolean checkPermissions(final List<PermissionSubject> permSubjects) {
    for (PermissionSubject permSubject : permSubjects) {
        if (!checkSinglePermission(permSubject, getReturnValue().getCanDoActionMessages())) {
            return false;
        }
    }
    return true;
}
getDbFacade().getPermissionDao().getEntityPermissions(userId, actionGroup, object, type);
CREATE OR REPLACE FUNCTION get_entity_permissions(
    v_user_id uuid,
    v_action_group_id integer,
    v_object_id uuid,
    v_object_type_id integer)
  RETURNS SETOF uuid AS
$BODY$
   DECLARE
   v_everyone_object_id  UUID;
BEGIN
   v_everyone_object_id := getGlobalIds('everyone'); -- hardcoded also in MLA Handler
   RETURN QUERY
   select   id from permissions where
        -- get all roles of action
   role_id in(select role_id from roles_groups where action_group_id = v_action_group_id)
        -- get allparents of object
   and (object_id in(select id from  fn_get_entity_parents(v_object_id,v_object_type_id)))
        -- get user and his groups
   and (ad_element_id = v_everyone_object_id or
   ad_element_id = v_user_id or ad_element_id in(select * from getUserAndGroupsById(v_user_id)))   LIMIT 1;
END; $BODY$
  LANGUAGE plpgsql STABLE
  COST 100
  ROWS 1000;
ALTER FUNCTION get_entity_permissions(uuid, integer, uuid, integer)
  OWNER TO engine;
查询参数 说明 备注
v_user_id 用户 ID 系统登录用户 ID
v_action_group_id 操作组 ID ActionGroup.DELETE_VM
v_object_id 操作对象 ID 需要删除的虚拟机 ID
v_object_type_id 操作对象类型 ID VdcObjectType.VM

满足权限的条件判断(1、2 必须满足,3、4、5 满足其中一个)

role_id in(select role_id from roles_groups where action_group_id = v_action_group_id)
and (object_id in(select id from  fn_get_entity_parents(v_object_id,v_object_type_id)))
WHEN v_entity_type = 2 THEN -- VM
    -- get cluster id
    cluster_id := ( SELECT vds_group_id FROM vm_static WHERE vm_guid = v_entity_id );
    -- get data center id
    ds_id := ( SELECT storage_pool_id FROM vds_groups WHERE vds_group_id = cluster_id );

    RETURN QUERY
        SELECT system_root_id AS id
        UNION
        SELECT ds_id AS id
        UNION
        SELECT cluster_id AS id
        UNION
        SELECT v_entity_id AS id;
v_everyone_object_id := getGlobalIds('everyone'); -- hardcoded also in MLA Handler
ad_element_id = v_everyone_object_id
ad_element_id = v_user_id
ad_element_id in(select * from getUserAndGroupsById(v_user_id))
CREATE OR REPLACE FUNCTION getuserandgroupsbyid(v_id uuid)
  RETURNS SETOF iduuidtype AS
$BODY$
BEGIN
   RETURN QUERY
   select ID from ad_groups,users where users.user_id = v_id
   and ad_groups.id in(select * from fnsplitteruuid(users.group_ids))
   UNION
   select v_id
   UNION
   -- user is also member of 'Everyone'
   select 'EEE00000-0000-0000-0000-123456789EEE';
END; $BODY$
  LANGUAGE plpgsql STABLE
  COST 100
  ROWS 1000;
ALTER FUNCTION getuserandgroupsbyid(uuid)
  OWNER TO engine;

如果操作的配额非 NONE,操作对象所在数据中心的配额设置为 强制的,系统自动添加配额相关权限

if (isQuotaDependant()) {
    addQuotaPermissionSubject(permSubjects);
}
quotaPermissionList.add(new PermissionSubject(parameter.getQuotaGuid(), VdcObjectType.Quota, ActionGroup.CONSUME_QUOTA, VdcBllMessages.USER_NOT_AUTHORIZED_TO_CONSUME_QUOTA));

权限的增加与删除

Permissions permission =
        getPermissionDAO().getForRoleAndAdElementAndObject(paramPermission.getrole_id(), principalId,
                paramPermission.getObjectId());

if (permission == null) {
    paramPermission.setId(Guid.newGuid());
    paramPermission.setad_element_id(principalId);

    TransactionSupport.executeInNewTransaction(new TransactionMethod<Void>() {
        @Override
        public Void runInTransaction() {
            getPermissionDAO().save(paramPermission);
            getCompensationContext().snapshotNewEntity(paramPermission);
            getCompensationContext().stateChanged();
            return null;
        }
    });
    permission = paramPermission;
}
getPermissionDAO().remove(perms.getId());
上一篇 下一篇

猜你喜欢

热点阅读