示例#1
0
    def _perm_resource_pool(
            self, user, perm, rbac, visible_pools, obj=None):
        # `create` permissions is called without an `obj`.
        rbac_enabled = rbac.is_enabled()
        if perm == ResourcePoolPermission.create:
            if rbac_enabled:
                return rbac.can_create_resource_pool(user.username)
            return user.is_superuser

        # From this point forward the `obj` must be a `ResourcePool`.
        if not isinstance(obj, ResourcePool):
            raise ValueError(
                'only `ResourcePoolPermission.create` can be used '
                'without an `obj`.')

        if perm == ResourcePoolPermission.edit:
            if rbac_enabled:
                return obj.id in rbac.get_resource_pool_ids(
                    user.username, 'edit')
            return user.is_superuser
        elif perm == ResourcePoolPermission.view:
            if rbac_enabled:
                return obj.id in visible_pools
            return True

        raise ValueError(
            'unknown ResourcePoolPermission value: %s' % perm)
示例#2
0
    def get_resource_pools(self, user):
        """Fetch `ResourcePool`'s on which the User_ has the given permission.

        :param user: The user that should be used in the permission check.
        :type user: User_

        .. _User: https://
           docs.djangoproject.com/en/dev/topics/auth/
           #django.contrib.auth.models.User

        """
        # Circular imports.
        from maasserver.rbac import rbac
        if rbac.is_enabled():
            return self.filter(
                id__in=rbac.get_resource_pool_ids(user.username, 'view'))
        return self.all()
示例#3
0
    def has_perm(self, user, perm, obj=None):
        if not user.is_active:
            # Deactivated users, and in particular the node-init user,
            # are prohibited from accessing maasserver services.
            return False

        from maasserver.rbac import rbac
        rbac_enabled = rbac.is_enabled()
        visible_pools, view_all_pools = [], []
        deploy_pools, admin_pools = [], []
        if rbac_enabled:
            visible_pools = rbac.get_resource_pool_ids(
                user.username, 'view')
            view_all_pools = rbac.get_resource_pool_ids(
                user.username, 'view-all')
            deploy_pools = rbac.get_resource_pool_ids(
                user.username, 'deploy-machines')
            admin_pools = rbac.get_resource_pool_ids(
                user.username, 'admin-machines')

        # Sanity check that a `ResourcePool` is being checked against
        # `ResourcePoolPermission`.
        if (obj is not None and isinstance(obj, ResourcePool) and
                not isinstance(perm, ResourcePoolPermission)):
            raise TypeError(
                'obj type of ResourcePool must be checked '
                'against a `ResourcePoolPermission`.')

        # Handle node permissions without objects.
        if perm == NodePermission.admin and obj is None:
            # User wants to admin writes to all nodes (aka. create a node),
            # must be superuser for those permissions.
            return user.is_superuser
        elif perm == NodePermission.view and obj is None:
            # XXX 2018-11-20 blake_r: View permission without an obj is used
            # for device create as a standard user. Currently there is no
            # specific DevicePermission and no way for this code path to know
            # its for a device. So it is represented using this path.
            #
            # View is only used for the create action, modifying a created
            # device uses the appropriate `NodePermission.edit` scoped to the
            # device being editted.
            if rbac_enabled:
                # User must either be global admin or have access to deploy
                # or admin some machines.
                return (
                    user.is_superuser or
                    (len(deploy_pools) > 0 or len(admin_pools) > 0))
            return True

        # ResourcePool permissions are handled specifically.
        if isinstance(perm, ResourcePoolPermission):
            return self._perm_resource_pool(
                user, perm, rbac, visible_pools, obj)

        if isinstance(obj, (Node, BlockDevice, FilesystemGroup)):
            if isinstance(obj, BlockDevice):
                obj = obj.node
            elif isinstance(obj, FilesystemGroup):
                obj = obj.get_node()
            if perm == NodePermission.view:
                return self._can_view(
                    rbac_enabled, user, obj,
                    visible_pools, view_all_pools,
                    deploy_pools, admin_pools)
            elif perm == NodePermission.edit:
                can_edit = self._can_edit(
                    rbac_enabled, user, obj, deploy_pools, admin_pools)
                return not obj.locked and can_edit
            elif perm == NodePermission.lock:
                # only machines can be locked
                can_edit = self._can_edit(
                    rbac_enabled, user, obj, deploy_pools, admin_pools)
                return obj.pool_id is not None and can_edit
            elif perm == NodePermission.admin:
                return not obj.locked and self._can_admin(
                    rbac_enabled, user, obj, admin_pools)
            else:
                raise NotImplementedError(
                    'Invalid permission check (invalid permission name: %s).' %
                    perm)
        elif isinstance(obj, Interface):
            node = obj.get_node()
            if node is None:
                # Doesn't matter the permission level if the interface doesn't
                # have a node, the user must be a global admin.
                return user.is_superuser
            if perm == NodePermission.view:
                return self._can_view(
                    rbac_enabled, user, node,
                    visible_pools, view_all_pools,
                    deploy_pools, admin_pools)
            elif perm == NodePermission.edit:
                # Machine interface can only be modified by an administrator
                # of the machine. Even the owner of the machine cannot modify
                # the interfaces on that machine, unless they have
                # administrator rights.
                if node.node_type == NODE_TYPE.MACHINE:
                    return self._can_admin(
                        rbac_enabled, user, node, admin_pools)
                # Other node types must be editable by the user.
                return self._can_edit(
                    rbac_enabled, user, node, deploy_pools, admin_pools)
            elif perm == NodePermission.admin:
                # Admin permission is solely granted to superusers.
                return self._can_admin(
                    rbac_enabled, user, node, admin_pools)
            else:
                raise NotImplementedError(
                    'Invalid permission check (invalid permission name: %s).' %
                    perm)
        elif is_instance_or_subclass(obj, UNRESTRICTED_READ_MODELS):
            # This model is classified under 'unrestricted read' for any
            # logged-in user; so everyone can view, but only an admin can
            # do anything else.
            if perm == NodePermission.view:
                return True
            elif perm in ADMIN_PERMISSIONS:
                # Admin permission is solely granted to superusers.
                return user.is_superuser
            else:
                raise NotImplementedError(
                    'Invalid permission check (invalid permission name: %s).' %
                    perm)
        elif is_instance_or_subclass(obj, ADMIN_RESTRICTED_MODELS):
            # Only administrators are allowed to read/write these objects.
            if perm in ADMIN_PERMISSIONS:
                return user.is_superuser
            else:
                raise NotImplementedError(
                    'Invalid permission check (invalid permission name: %s).' %
                    perm)
        else:
            raise NotImplementedError(
                'Invalid permission check (invalid object type).')