def test_candid_disabled(self): Config.objects.set_config( "external_auth_url", "http://candid.example.com" ) Config.objects.set_config("rbac_url", "") rbac = RBACWrapper() self.assertFalse(rbac.is_enabled())
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)
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()
def _perm_pod( self, user, perm, rbac, visible_pools, view_all_pools, deploy_pools, admin_pools, obj=None, ): # `create` permissions is called without an `obj`. rbac_enabled = rbac.is_enabled() if perm == PodPermission.create: return user.is_superuser # From this point forward the `obj` must be a `ResourcePool`. if not isinstance(obj, Pod): raise ValueError( "only `PodPermission.create` can be used without an `obj`." ) if perm == PodPermission.edit: if rbac_enabled: return obj.pool_id in admin_pools return user.is_superuser elif perm == PodPermission.compose: if rbac_enabled: return obj.pool_id in admin_pools return user.is_superuser elif perm == PodPermission.dynamic_compose: if rbac_enabled: return ( obj.pool_id in deploy_pools or obj.pool_id in admin_pools ) return True elif perm == PodPermission.view: if rbac_enabled: return ( obj.pool_id in visible_pools or obj.pool_id in view_all_pools ) return True raise ValueError("unknown PodPermission value: %s" % perm)
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).')
def test_rbac_enabled(self): Config.objects.set_config('external_auth_url', '') Config.objects.set_config('rbac_url', 'http://rbac.example.com') rbac = RBACWrapper() self.assertTrue(rbac.is_enabled())
def test_local_disabled(self): Config.objects.set_config('external_auth_url', '') Config.objects.set_config('rbac_url', '') rbac = RBACWrapper() self.assertFalse(rbac.is_enabled())
def test_rbac_enabled(self): Config.objects.set_config("external_auth_url", "") Config.objects.set_config("rbac_url", "http://rbac.example.com") rbac = RBACWrapper() self.assertTrue(rbac.is_enabled())
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, admin_pools = [], [] if rbac_enabled: visible_pools = rbac.get_resource_pools( user.username, 'view').values_list( 'id', flat=True) admin_pools = rbac.get_resource_pools( user.username, 'admin-machines').values_list( 'id', flat=True) 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, admin_pools) elif perm == NodePermission.edit: can_edit = self._can_edit( rbac_enabled, user, obj, visible_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, visible_pools, admin_pools) return obj.pool_id is not None and can_edit elif perm == NodePermission.admin: return 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, 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, visible_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).')