Esempio n. 1
0
    def validate_perms_rbac(self, request, obj_uuid, mode=PERMS_R,
                            perms2=None, obj_owner_for_delete=None):
        user, roles = self.get_user_roles(request)
        if has_role(self.cloud_admin_role, roles):
            return (True, 'RWX')
        if has_role(self.global_read_only_role, roles) and mode == PERMS_R:
            return (True, 'R')

        # Get request scope
        env = request.headers.environ
        domain_id = env.get('HTTP_X_DOMAIN_ID')
        domain_name = env.get('HTTP_X_DOMAIN_NAME')
        project_id = env.get('HTTP_X_PROJECT_ID')
        project_name = env.get('HTTP_X_PROJECT_NAME')

        # retrieve object permissions if missing
        if not perms2:
            try:
                perms2 = self._server_mgr._db_conn.uuid_to_obj_perms2(obj_uuid)
            except NoIdError:
                return True, ''

        owner = perms2['owner'].replace('-','')
        perms = perms2['owner_access'] << 6
        perms |= perms2['global_access']

        # build perms
        mask = 07
        if project_id == owner:
            mask |= 0700

        share_items = perms2['share']
        shares = [item['tenant'] for item in share_items]
        for item in share_items:
            # item['tenant'] => [share-type, uuid]
            # allow access if domain or project from token matches configured
            # sharing information
            share_type, share_uuid = shareinfo_from_perms2_tenant(item['tenant'])
            share_uuid = share_uuid.replace('-','')
            if ((share_type == 'tenant' and project_id == share_uuid) or
                    (share_type == 'domain' and domain_id == share_uuid)):
                perms = perms | item['tenant_access'] << 3
                mask |= 0070
                break

        mode_mask = mode | mode << 3 | mode << 6
        ok = (mask & perms & mode_mask)
        if (ok and obj_owner_for_delete):
            obj_owner_for_delete = obj_owner_for_delete.replace('-','')
            ok = (project_id == obj_owner_for_delete)

        granted = ok & 07 | (ok >> 3) & 07 | (ok >> 6) & 07

        msg = ("RBAC: %s (%s:%s) mode=%03o mask=%03o perms=%03o, "
               "(user=%s(%s)/owner=%s/shares=%s)" %
               ('+++' if ok else '---', self.mode_str[mode], obj_uuid,
                mode_mask, mask, perms, project_id, project_name, owner,
                shares))
        self._server_mgr.config_log(msg, level=SandeshLevel.SYS_DEBUG)
        if not ok:
            msg = ("RBAC: %s doesn't have %s permission in project '%s'" %
                   (user, self.mode_str2[mode], owner))
            self._server_mgr.config_log(msg, level=SandeshLevel.SYS_NOTICE)

        err_msg = ("Permission Denied for %s to %s operation in domain '%s' "
                   "and project '%s'" %
                   (roles, self.mode_str2[mode], domain_name, project_name))
        if ok:
            return True, self.mode_str[granted]
        else:
            return False, (403, err_msg)
    def validate_perms_rbac(self,
                            request,
                            obj_uuid,
                            mode=PERMS_R,
                            perms2=None,
                            obj_owner_for_delete=None):
        user, roles = self.get_user_roles(request)
        if has_role(self.cloud_admin_role, roles):
            return (True, 'RWX')
        if has_role(self.global_read_only_role, roles) and mode == PERMS_R:
            return (True, 'R')

        # Get request scope
        env = request.headers.environ
        domain_id = env.get('HTTP_X_DOMAIN_ID')
        domain_name = env.get('HTTP_X_DOMAIN_NAME')
        project_id = env.get('HTTP_X_PROJECT_ID')
        project_name = env.get('HTTP_X_PROJECT_NAME')

        # retrieve object permissions if missing
        if not perms2:
            try:
                perms2 = self._server_mgr._db_conn.uuid_to_obj_perms2(obj_uuid)
            except NoIdError:
                return True, ''

        owner = perms2['owner'].replace('-', '')
        perms = perms2['owner_access'] << 6
        perms |= perms2['global_access']

        # build perms
        mask = 07
        if project_id == owner:
            mask |= 0700

        share_items = perms2['share']
        shares = [item['tenant'] for item in share_items]
        for item in share_items:
            # item['tenant'] => [share-type, uuid]
            # allow access if domain or project from token matches configured
            # sharing information
            share_type, share_uuid = shareinfo_from_perms2_tenant(
                item['tenant'])
            share_uuid = share_uuid.replace('-', '')
            if ((share_type == 'tenant' and project_id == share_uuid)
                    or (share_type == 'domain' and domain_id == share_uuid)):
                perms = perms | item['tenant_access'] << 3
                mask |= 0070
                break

        mode_mask = mode | mode << 3 | mode << 6
        ok = (mask & perms & mode_mask)
        if (ok and obj_owner_for_delete):
            obj_owner_for_delete = obj_owner_for_delete.replace('-', '')
            ok = (project_id == obj_owner_for_delete)

        granted = ok & 07 | (ok >> 3) & 07 | (ok >> 6) & 07

        msg = (
            "RBAC: %s (%s:%s) mode=%03o mask=%03o perms=%03o, "
            "(user=%s(%s)/owner=%s/shares=%s)" %
            ('+++' if ok else '---', self.mode_str[mode], obj_uuid, mode_mask,
             mask, perms, project_id, project_name, owner, shares))
        self._server_mgr.config_log(msg, level=SandeshLevel.SYS_DEBUG)
        if not ok:
            msg = ("RBAC: %s doesn't have %s permission in project '%s'" %
                   (user, self.mode_str2[mode], owner))
            self._server_mgr.config_log(msg, level=SandeshLevel.SYS_NOTICE)

        err_msg = ("Permission Denied for %s to %s operation in domain '%s' "
                   "and project '%s'" %
                   (roles, self.mode_str2[mode], domain_name, project_name))
        if ok:
            return True, self.mode_str[granted]
        else:
            return False, (403, err_msg)