def add_permissions_to_role(role_id, resource, operations): """ Add permissions to a role. :param role_id: role identifier :type role_id: str :param resource: resource path to grant permissions to :type resource: str :param operations: list or tuple :type operations: list of allowed operations being granted :raise MissingResource: if the given role does not exist """ if role_id == SUPER_USER_ROLE: raise PulpDataException(_('super-users role cannot be changed')) role = Role.get_collection().find_one({'id': role_id}) if role is None: raise MissingResource(role_id) current_ops = role['permissions'].setdefault(resource, []) for o in operations: if o in current_ops: continue current_ops.append(o) users = factory.user_query_manager().find_users_belonging_to_role(role_id) for user in users: factory.permission_manager().grant(resource, user['login'], operations) Role.get_collection().save(role, safe=True)
def remove_user_from_role(role_id, login): """ Remove a user from a role. This has the side-effect of revoking all the permissions granted to the role from the user, unless the permissions are also granted by another role. :param role_id: role identifier :type role_id: str :param login: name of user :type login: str :raise MissingResource: if the given role or user does not exist """ role = Role.get_collection().find_one({'id': role_id}) if role is None: raise MissingResource(role_id) user = model.User.objects.get_or_404(login=login) if role_id == SUPER_USER_ROLE and user_controller.is_last_super_user(login): raise PulpDataException( _('%(role)s cannot be empty, and %(login)s is the last member') % {'role': SUPER_USER_ROLE, 'login': login}) if role_id not in user.roles: return user.roles.remove(role_id) user.save() for item in role['permissions']: other_roles = factory.role_query_manager().get_other_roles(role, user.roles) user_ops = _operations_not_granted_by_roles(item['resource'], item['permission'], other_roles) factory.permission_manager().revoke(item['resource'], login, user_ops)
def add_user_to_role(role_id, login): """ Add a user to a role. This has the side-effect of granting all the permissions granted to the role to the user. :param role_id: role identifier :type role_id: str :param login: login of user :type login: str :raise MissingResource: if the given role or user does not exist """ role = Role.get_collection().find_one({'id': role_id}) if role is None: raise MissingResource(role_id) user = User.get_collection().find_one({'login': login}) if user is None: raise MissingResource(login) if role_id in user['roles']: return user['roles'].append(role_id) User.get_collection().save(user, safe=True) for resource, operations in role['permissions'].items(): factory.permission_manager().grant(resource, login, operations)
def add_user_to_role(role_id, login): """ Add a user to a role. This has the side-effect of granting all the permissions granted to the role to the user. :param role_id: role identifier :type role_id: str :param login: login of user :type login: str :raise MissingResource: if the given role does not exist :raise InvalidValue: if some params are invalid """ role = Role.get_collection().find_one({'id': role_id}) if role is None: raise MissingResource(role_id) user = User.get_collection().find_one({'login': login}) if user is None: raise InvalidValue(['login']) if role_id in user['roles']: return user['roles'].append(role_id) User.get_collection().save(user, safe=True) for item in role['permissions']: factory.permission_manager().grant(item['resource'], login, item.get('permission', []))
def operation_to_name(operation): """ Convert an operation value to an operation name Returns None if the operation value is invalid @type operation: int @param operation: operation value @rtype: str or None @return: operation name """ if operation < factory.permission_manager().CREATE or operation > factory.permission_manager().EXECUTE: return None return factory.permission_manager().operation_names[operation]
def name_to_operation(name): """ Convert a operation name to an operation value Returns None if the name does not correspond to an operation @type name: str @param name: operation name @rtype: int or None @return: operation value """ name = name.upper() if name not in factory.permission_manager().operation_names: raise InvalidValue('operations') return factory.permission_manager().operation_names.index(name)
def test_syntactic_sugar_methods(self): """ Tests the syntactic sugar methods for retrieving specific managers. """ # Setup factory.initialize() # Test self.assertTrue(isinstance(factory.authentication_manager(), AuthenticationManager)) self.assertTrue(isinstance(factory.cert_generation_manager(), CertGenerationManager)) self.assertTrue(isinstance(factory.certificate_manager(), CertificateManager)) self.assertTrue(isinstance(factory.password_manager(), PasswordManager)) self.assertTrue(isinstance(factory.permission_manager(), PermissionManager)) self.assertTrue(isinstance(factory.permission_query_manager(), PermissionQueryManager)) self.assertTrue(isinstance(factory.role_manager(), RoleManager)) self.assertTrue(isinstance(factory.role_query_manager(), RoleQueryManager)) self.assertTrue(isinstance(factory.user_manager(), UserManager)) self.assertTrue(isinstance(factory.user_query_manager(), UserQueryManager)) self.assertTrue(isinstance(factory.repo_manager(), RepoManager)) self.assertTrue(isinstance(factory.repo_unit_association_manager(), RepoUnitAssociationManager)) self.assertTrue(isinstance(factory.repo_publish_manager(), RepoPublishManager)) self.assertTrue(isinstance(factory.repo_query_manager(), RepoQueryManager)) self.assertTrue(isinstance(factory.repo_sync_manager(), RepoSyncManager)) self.assertTrue(isinstance(factory.content_manager(), ContentManager)) self.assertTrue(isinstance(factory.content_query_manager(), ContentQueryManager)) self.assertTrue(isinstance(factory.content_upload_manager(), ContentUploadManager)) self.assertTrue(isinstance(factory.consumer_manager(), ConsumerManager)) self.assertTrue(isinstance(factory.topic_publish_manager(), TopicPublishManager))
def POST(self): # Pull all the user data user_data = self.params() login = user_data.get('login', None) password = user_data.get('password', None) name = user_data.get('name', None) # Creation manager = managers.user_manager() args = [login] kwargs = {'password': password, 'name': name} user = manager.create_user(*args, **kwargs) # Add the link to the user user_link = serialization.link.child_link_obj(login) user.update(user_link) # Grant permissions user_link = serialization.link.child_link_obj(login) permission_manager = managers.permission_manager() permission_manager.grant_automatic_permissions_for_resource(user_link['_href']) return self.created(login, user)
def get(self, request): """ List all roles. :param request: WSGI request object :type request: django.core.handlers.wsgi.WSGIRequest :return: Response containing a list of roles :rtype: django.http.HttpResponse """ role_query_manager = factory.role_query_manager() user_query_manager = factory.user_query_manager() permissions_manager = factory.permission_manager() roles = role_query_manager.find_all() for role in roles: role['users'] = [u['login'] for u in user_query_manager.find_users_belonging_to_role(role['id'])] resource_permission = {} # isolate schema change if role['permissions']: for item in role['permissions']: resource = item['resource'] operations = item.get('permission', []) resource_permission[resource] = [permissions_manager.operation_value_to_name(o) for o in operations] role['permissions'] = resource_permission link = {'_href': reverse('role_resource', kwargs={'role_id': role['id']})} role.update(link) return generate_json_response_with_pulp_encoder(roles)
def POST(self): # Params params = self.params() login = params.get('login', None) resource = params.get('resource', None) operation_names = params.get('operations', None) _check_invalid_params({'login':login, 'resource':resource, 'operation_names':operation_names}) operations = _get_operations(operation_names) # Grant permission synchronously permission_manager = managers.permission_manager() tags = [resource_tag(dispatch_constants.RESOURCE_PERMISSION_TYPE, resource), resource_tag(dispatch_constants.RESOURCE_USER_TYPE, login), action_tag('grant_permission_to_user')] call_request = CallRequest(permission_manager.grant, [resource, login, operations], tags=tags) call_request.reads_resource(dispatch_constants.RESOURCE_USER_TYPE, login) call_request.updates_resource(dispatch_constants.RESOURCE_PERMISSION_TYPE, resource) return self.ok(execution.execute_sync(call_request))
def get(self, request): """ List all roles. :param request: WSGI request object :type request: django.core.handlers.wsgi.WSGIRequest :return: Response containing a list of roles :rtype: django.http.HttpResponse """ role_query_manager = factory.role_query_manager() permissions_manager = factory.permission_manager() roles = role_query_manager.find_all() for role in roles: users = [u.login for u in user_controller.find_users_belonging_to_role(role["id"])] role["users"] = users resource_permission = {} # isolate schema change if role["permissions"]: for item in role["permissions"]: resource = item["resource"] operations = item.get("permission", []) resource_permission[resource] = [permissions_manager.operation_value_to_name(o) for o in operations] role["permissions"] = resource_permission link = {"_href": reverse("role_resource", kwargs={"role_id": role["id"]})} role.update(link) return generate_json_response_with_pulp_encoder(roles)
def GET(self): role_query_manager = managers.role_query_manager() user_query_manager = managers.user_query_manager() permissions_manager = managers.permission_manager() roles = role_query_manager.find_all() for role in roles: role['users'] = [u['login'] for u in user_query_manager.find_users_belonging_to_role(role['id'])] resource_permission = {} # isolate schema change if role['permissions']: for item in role['permissions']: resource = item['resource'] operations = item.get('permission', []) resource_permission[resource] = [permissions_manager.operation_value_to_name(o) for o in operations] role['permissions'] = resource_permission for role in roles: role.update(serialization.link.child_link_obj(role['id'])) return self.ok(roles)
def get(self, request, role_id): """ Retrieve a specific role. :param request: WSGI request object :type request: django.core.handlers.wsgi.WSGIRequest :param role_id: id for the requested role :type role_id: str :return: Response containing the role :rtype: django.http.HttpResponse :raises: MissingResource if role ID does not exist """ role = factory.role_query_manager().find_by_id(role_id) if role is None: raise pulp_exceptions.MissingResource(role_id) role["users"] = [u.login for u in user_controller.find_users_belonging_to_role(role["id"])] permissions_manager = factory.permission_manager() # isolate schema change resource_permission = {} for item in role["permissions"]: resource = item["resource"] operations = item.get("permission", []) resource_permission[resource] = [permissions_manager.operation_value_to_name(o) for o in operations] role["permissions"] = resource_permission link = {"_href": reverse("role_resource", kwargs={"role_id": role["id"]})} role.update(link) return generate_json_response_with_pulp_encoder(role)
def post(self, request): """ Grant permissions to a role. :param request: WSGI request object :type request: django.core.handlers.wsgi.WSGIRequest :return: An empty response :rtype: django.http.HttpResponse """ params = request.body_as_json role_id = params.get('role_id', None) resource = params.get('resource', None) operation_names = params.get('operations', None) _check_invalid_params({'role_id': role_id, 'resource': resource, 'operation_names': operation_names}) # Grant permission synchronously role_manager = factory.role_manager() permission_manager = factory.permission_manager() operations = permission_manager.operation_names_to_values(operation_names) add_perm = role_manager.add_permissions_to_role(role_id, resource, operations) return generate_json_response(add_perm)
def get(self, request): """ Retrieve permissions for all resources or for a particular resource. :param request: WSGI request object :type request: django.core.handlers.wsgi.WSGIRequest :return: Response containing a list of permissions for resource/s :rtype: django.http.HttpResponse """ query_params = request.GET resource = query_params.get('resource', None) permissions = [] if resource is None: permissions = factory.permission_query_manager().find_all() else: permission = factory.permission_query_manager().find_by_resource(resource) if permission is not None: permissions = [permission] for permission in permissions: # Isolate the database schema change to behind the api. This should be transparent users = {} for item in permission['users']: users[item['username']] = item['permissions'] permission['users'] = users permission_manager = factory.permission_manager() for user, ops in users.items(): users[user] = [permission_manager.operation_value_to_name(o) for o in ops] return generate_json_response_with_pulp_encoder(permissions)
def POST(self): # Pull all the user data user_data = self.params() login = user_data.get('login', None) password = user_data.get('password', None) name = user_data.get('name', None) # Creation manager = managers.user_manager() resources = {dispatch_constants.RESOURCE_USER_TYPE: {login: dispatch_constants.RESOURCE_CREATE_OPERATION}} args = [login] kwargs = {'password': password, 'name': name} weight = pulp_config.config.getint('tasks', 'create_weight') tags = [resource_tag(dispatch_constants.RESOURCE_USER_TYPE, login), action_tag('create')] call_request = CallRequest(manager.create_user, args, kwargs, resources=resources, weight=weight, tags=tags, kwarg_blacklist=['password']) user = execution.execute_sync(call_request) user_link = serialization.link.child_link_obj(login) user.update(user_link) # Grant permissions permission_manager = managers.permission_manager() permission_manager.grant_automatic_permissions_for_resource(user_link['_href']) return self.created(login, user)
def delete_user(login): """ Deletes the given user. Deletion of last superuser is not permitted. @param login: identifies the user being deleted @type login: str @raise MissingResource: if the given user does not exist @raise InvalidValue: if login value is invalid """ # Raise exception if login is invalid if login is None or invalid_type(login, basestring): raise InvalidValue(['login']) # Check whether user exists found = User.get_collection().find_one({'login': login}) if found is None: raise MissingResource(login) # Make sure user is not the last super user if factory.user_query_manager().is_last_super_user(login): raise PulpDataException(_("The last superuser [%s] cannot be deleted" % login)) # Revoke all permissions from the user permission_manager = factory.permission_manager() permission_manager.revoke_all_permissions_from_user(login) User.get_collection().remove({'login': login})
def post(self, request): """ Revoke permissions from a role. :param request: WSGI request object :type request: django.core.handlers.wsgi.WSGIRequest :return: An empty response :rtype: django.http.HttpResponse """ params = request.body_as_json role_id = params.get('role_id', None) resource = params.get('resource', None) operation_names = params.get('operations', None) _validate_params({'role_id': role_id, 'resource': resource, 'operation_names': operation_names}) role_manager = factory.role_manager() permission_manager = factory.permission_manager() operations = permission_manager.operation_names_to_values(operation_names) remove_perm = role_manager.remove_permissions_from_role(role_id, resource, operations) return generate_json_response(remove_perm)
def remove_permissions_from_role(role_id, resource, operations): """ Remove permissions from a role. :param role_id: role identifier :type role_id: str :param resource: resource path to revoke permissions from :type resource: str :param operations: list or tuple :type operations: list of allowed operations being revoked :raise InvalidValue: if some params are invalid :raise PulpDataException: if role is a superuser role """ if role_id == SUPER_USER_ROLE: raise PulpDataException(_('super-users role cannot be changed')) role = Role.get_collection().find_one({'id': role_id}) if role is None: raise InvalidValue(['role_id']) resource_permission = {} current_ops = [] for item in role['permissions']: if item['resource'] == resource: resource_permission = item current_ops = resource_permission['permission'] if not current_ops: return for o in operations: if o not in current_ops: continue current_ops.remove(o) users = factory.user_query_manager().find_users_belonging_to_role(role_id) for user in users: other_roles = factory.role_query_manager().get_other_roles(role, user['roles']) user_ops = _operations_not_granted_by_roles(resource, operations, other_roles) factory.permission_manager().revoke(resource, user['login'], user_ops) # in no more allowed operations, remove the resource if not current_ops: role['permissions'].remove(resource_permission) Role.get_collection().save(role)
def remove_permissions_from_role(role_id, resource, operations): """ Remove permissions from a role. :param role_id: role identifier :type role_id: str :param resource: resource path to revoke permissions from :type resource: str :param operations: list or tuple :type operations: list of allowed operations being revoked :raise InvalidValue: if some params are invalid :raise PulpDataException: if role is a superuser role """ if role_id == SUPER_USER_ROLE: raise PulpDataException(_('super-users role cannot be changed')) role = Role.get_collection().find_one({'id': role_id}) if role is None: raise InvalidValue(['role_id']) resource_permission = {} current_ops = [] for item in role['permissions']: if item['resource'] == resource: resource_permission = item current_ops = resource_permission['permission'] if not current_ops: return for o in operations: if o not in current_ops: continue current_ops.remove(o) users = factory.user_query_manager().find_users_belonging_to_role(role_id) for user in users: other_roles = factory.role_query_manager().get_other_roles(role, user['roles']) user_ops = _operations_not_granted_by_roles(resource, operations, other_roles) factory.permission_manager().revoke(resource, user['login'], user_ops) # in no more allowed operations, remove the resource if not current_ops: role['permissions'].remove(resource_permission) Role.get_collection().save(role, safe=True)
def add_permissions_to_role(role_id, resource, operations): """ Add permissions to a role. :param role_id: role identifier :type role_id: str :param resource: resource path to grant permissions to :type resource: str :param operations: list or tuple :type operations: list of allowed operations being granted :raise InvalidValue: if some params are invalid :raise PulpDataException: if role is a superuser role """ if role_id == SUPER_USER_ROLE: raise PulpDataException(_('super-users role cannot be changed')) role = Role.get_collection().find_one({'id': role_id}) if role is None: raise InvalidValue(['role_id']) if not role['permissions']: role['permissions'] = [] resource_permission = {} current_ops = [] for item in role['permissions']: if item['resource'] == resource: resource_permission = item current_ops = resource_permission['permission'] if not resource_permission: resource_permission = dict(resource=resource, permission=current_ops) role['permissions'].append(resource_permission) for o in operations: if o in current_ops: continue current_ops.append(o) users = factory.user_query_manager().find_users_belonging_to_role( role_id) for user in users: factory.permission_manager().grant(resource, user['login'], operations) Role.get_collection().save(role, safe=True)
def create_user(login, password=None, name=None, roles=None): """ Creates a new Pulp user and adds it to specified to roles. @param login: login name / unique identifier for the user @type login: str @param password: password for login credentials @type password: str @param name: user's full name @type name: str @param roles: list of roles user will belong to @type roles: list @raise DuplicateResource: if there is already a user with the requested login @raise InvalidValue: if any of the fields are unacceptable """ existing_user = User.get_collection().find_one({'login': login}) if existing_user is not None: raise DuplicateResource(login) invalid_values = [] if login is None or _USER_LOGIN_REGEX.match(login) is None: invalid_values.append('login') if invalid_type(name, basestring): invalid_values.append('name') if invalid_type(roles, list): invalid_values.append('roles') if invalid_values: raise InvalidValue(invalid_values) # Use the login for name of the user if one was not specified name = name or login roles = roles or None # Encode plain-text password hashed_password = None if password: hashed_password = factory.password_manager().hash_password(password) # Creation create_me = User(login=login, password=hashed_password, name=name, roles=roles) User.get_collection().save(create_me) # Grant permissions permission_manager = factory.permission_manager() permission_manager.grant_automatic_permissions_for_user(create_me['login']) # Retrieve the user to return the SON object created = User.get_collection().find_one({'login': login}) created.pop('password') return created
def remove_permissions_from_role(self, role_id, resource, operations): """ Remove permissions from a role. @type role_id: str @param role_id: role identifier @type resource: str @param resource: resource path to revoke permissions from @type operations: list of allowed operations being revoked @param operations: list or tuple @raise MissingResource: if the given role does not exist """ if role_id == self.super_user_role: raise PulpDataException(_('super-users role cannot be changed')) role = Role.get_collection().find_one({'id': role_id}) if role is None: raise MissingResource(role_id) current_ops = role['permissions'].get(resource, []) if not current_ops: return for o in operations: if o not in current_ops: continue current_ops.remove(o) users = factory.user_query_manager().find_users_belonging_to_role( role_id) for user in users: other_roles = factory.role_query_manager().get_other_roles( role, user['roles']) user_ops = _operations_not_granted_by_roles( resource, operations, other_roles) factory.permission_manager().revoke(resource, user['login'], user_ops) # in no more allowed operations, remove the resource if not current_ops: del role['permissions'][resource] Role.get_collection().save(role, safe=True)
def delete_role(role_id): """ Deletes the given role. This has the side-effect of revoking any permissions granted to the role from the users in the role, unless those permissions are also granted through another role the user is a memeber of. :param role_id: identifies the role being deleted :type role_id: str :raise InvalidValue: if any of the fields are unacceptable :raise MissingResource: if the given role does not exist :raise PulpDataException: if role is a superuser role """ # Raise exception if role id is invalid if role_id is None or not isinstance(role_id, basestring): raise InvalidValue(['role_id']) # Check whether role exists role = Role.get_collection().find_one({'id': role_id}) if role is None: raise MissingResource(role_id) # Make sure role is not a superuser role if role_id == SUPER_USER_ROLE: raise PulpDataException(_('Role %s cannot be changed') % role_id) # Remove respective roles from users users = factory.user_query_manager().find_users_belonging_to_role( role_id) for item in role['permissions']: for user in users: other_roles = factory.role_query_manager().get_other_roles( role, user['roles']) user_ops = _operations_not_granted_by_roles( item['resource'], item['permission'], other_roles) factory.permission_manager().revoke(item['resource'], user['login'], user_ops) for user in users: user['roles'].remove(role_id) factory.user_manager().update_user(user['login'], Delta(user, 'roles')) Role.get_collection().remove({'id': role_id}, safe=True)
def ensure_super_user_role(self): """ Ensure that the super user role exists. """ role = Role.get_collection().find_one({'id' : self.super_user_role}) if role is None: role = self.create_role(self.super_user_role, 'Super Users', 'Role indicates users with admin privileges') pm = factory.permission_manager() role['permissions'] = {'/':[pm.CREATE, pm.READ, pm.UPDATE, pm.DELETE, pm.EXECUTE]} Role.get_collection().save(role, safe=True)
def test_operation_name_to_value(self): pm = manager_factory.permission_manager() self.assertEqual(pm.operation_name_to_value("CREATE"), authorization.CREATE) self.assertEqual(pm.operation_name_to_value("READ"), authorization.READ) self.assertEqual(pm.operation_name_to_value("UPDATE"), authorization.UPDATE) self.assertEqual(pm.operation_name_to_value("DELETE"), authorization.DELETE) self.assertEqual(pm.operation_name_to_value("EXECUTE"), authorization.EXECUTE) self.assertRaises(exceptions.InvalidValue, pm.operation_name_to_value, "random") self.assertRaises(exceptions.InvalidValue, pm.operation_name_to_value, None) self.assertRaises(exceptions.InvalidValue, pm.operation_name_to_value, "")
def remove_user_from_role(self, role_id, login): """ Remove a user from a role. This has the side-effect of revoking all the permissions granted to the role from the user, unless the permissions are also granted by another role. @type role_id: str @param role_id: role identifier @type login: str @param login: name of user @rtype: bool @return: True on success @raise MissingResource: if the given role or user does not exist """ role = Role.get_collection().find_one({'id': role_id}) if role is None: raise MissingResource(role_id) user = User.get_collection().find_one({'login': login}) if user is None: raise MissingResource(login) if role_id == self.super_user_role and factory.user_query_manager( ).is_last_super_user(login): raise PulpDataException( _('%s cannot be empty, and %s is the last member') % (self.super_user_role, login)) if role_id not in user['roles']: return user['roles'].remove(role_id) User.get_collection().save(user, safe=True) for resource, operations in role['permissions'].items(): other_roles = factory.role_query_manager().get_other_roles( role, user['roles']) user_ops = _operations_not_granted_by_roles( resource, operations, other_roles) factory.permission_manager().revoke(resource, login, user_ops)
def test_operation_name_to_value(self): pm = manager_factory.permission_manager() self.assertEqual(pm.operation_name_to_value('CREATE'), authorization.CREATE) self.assertEqual(pm.operation_name_to_value('READ'), authorization.READ) self.assertEqual(pm.operation_name_to_value('UPDATE'), authorization.UPDATE) self.assertEqual(pm.operation_name_to_value('DELETE'), authorization.DELETE) self.assertEqual(pm.operation_name_to_value('EXECUTE'), authorization.EXECUTE) self.assertRaises(exceptions.InvalidValue, pm.operation_name_to_value, 'random') self.assertRaises(exceptions.InvalidValue, pm.operation_name_to_value, None) self.assertRaises(exceptions.InvalidValue, pm.operation_name_to_value, '')
def test_operation_value_to_name(self): pm = manager_factory.permission_manager() self.assertEqual(pm.operation_value_to_name(authorization.CREATE), 'CREATE') self.assertEqual(pm.operation_value_to_name(authorization.READ), 'READ') self.assertEqual(pm.operation_value_to_name(authorization.UPDATE), 'UPDATE') self.assertEqual(pm.operation_value_to_name(authorization.DELETE), 'DELETE') self.assertEqual(pm.operation_value_to_name(authorization.EXECUTE), 'EXECUTE') self.assertEqual(pm.operation_value_to_name('RANDOM'), None) self.assertEqual(pm.operation_value_to_name(99), None) self.assertEqual(pm.operation_value_to_name(-2), None)
def remove_permissions_from_role(self, role_id, resource, operations): """ Remove permissions from a role. @type role_id: str @param role_id: role identifier @type resource: str @param resource: resource path to revoke permissions from @type operations: list of allowed operations being revoked @param operations: list or tuple @raise MissingResource: if the given role does not exist """ if role_id == self.super_user_role: raise PulpDataException(_('super-users role cannot be changed')) role = Role.get_collection().find_one({'id' : role_id}) if role is None: raise MissingResource(role_id) current_ops = role['permissions'].get(resource, []) if not current_ops: return for o in operations: if o not in current_ops: continue current_ops.remove(o) users = factory.user_query_manager().find_users_belonging_to_role(role_id) for user in users: other_roles = factory.role_query_manager().get_other_roles(role, user['roles']) user_ops = _operations_not_granted_by_roles(resource, operations, other_roles) factory.permission_manager().revoke(resource, user['login'], user_ops) # in no more allowed operations, remove the resource if not current_ops: del role['permissions'][resource] Role.get_collection().save(role, safe=True)
def add_permissions_to_role(role_id, resource, operations): """ Add permissions to a role. :param role_id: role identifier :type role_id: str :param resource: resource path to grant permissions to :type resource: str :param operations: list or tuple :type operations: list of allowed operations being granted :raise InvalidValue: if some params are invalid :raise PulpDataException: if role is a superuser role """ if role_id == SUPER_USER_ROLE: raise PulpDataException(_('super-users role cannot be changed')) role = Role.get_collection().find_one({'id': role_id}) if role is None: raise InvalidValue(['role_id']) if not role['permissions']: role['permissions'] = [] resource_permission = {} current_ops = [] for item in role['permissions']: if item['resource'] == resource: resource_permission = item current_ops = resource_permission['permission'] if not resource_permission: resource_permission = dict(resource=resource, permission=current_ops) role['permissions'].append(resource_permission) for o in operations: if o in current_ops: continue current_ops.append(o) users = factory.user_query_manager().find_users_belonging_to_role(role_id) for user in users: factory.permission_manager().grant(resource, user['login'], operations) Role.get_collection().save(role, safe=True)
def test_operation_value_to_name(self): pm = manager_factory.permission_manager() self.assertEqual(pm.operation_value_to_name(authorization.CREATE), "CREATE") self.assertEqual(pm.operation_value_to_name(authorization.READ), "READ") self.assertEqual(pm.operation_value_to_name(authorization.UPDATE), "UPDATE") self.assertEqual(pm.operation_value_to_name(authorization.DELETE), "DELETE") self.assertEqual(pm.operation_value_to_name(authorization.EXECUTE), "EXECUTE") self.assertEqual(pm.operation_value_to_name("RANDOM"), None) self.assertEqual(pm.operation_value_to_name(99), None) self.assertEqual(pm.operation_value_to_name(-2), None)
def remove_user_from_role(role_id, login): """ Remove a user from a role. This has the side-effect of revoking all the permissions granted to the role from the user, unless the permissions are also granted by another role. :param role_id: role identifier :type role_id: str :param login: name of user :type login: str :raise MissingResource: if the given role or user does not exist """ role = Role.get_collection().find_one({'id': role_id}) if role is None: raise MissingResource(role_id) user = User.get_collection().find_one({'login': login}) if user is None: raise MissingResource(login) if role_id == SUPER_USER_ROLE and factory.user_query_manager( ).is_last_super_user(login): raise PulpDataException( _('%(role)s cannot be empty, and %(login)s is the last member') % { 'role': SUPER_USER_ROLE, 'login': login }) if role_id not in user['roles']: return user['roles'].remove(role_id) User.get_collection().save(user, safe=True) for item in role['permissions']: other_roles = factory.role_query_manager().get_other_roles( role, user['roles']) user_ops = _operations_not_granted_by_roles( item['resource'], item['permission'], other_roles) factory.permission_manager().revoke(item['resource'], login, user_ops)
def remove_user_from_role(self, role_id, login): """ Remove a user from a role. This has the side-effect of revoking all the permissions granted to the role from the user, unless the permissions are also granted by another role. @type role_id: str @param role_id: role identifier @type login: str @param login: name of user @rtype: bool @return: True on success @raise MissingResource: if the given role or user does not exist """ role = Role.get_collection().find_one({'id' : role_id}) if role is None: raise MissingResource(role_id) user = User.get_collection().find_one({'login' : login}) if user is None: raise MissingResource(login) if role_id == self.super_user_role and factory.user_query_manager().is_last_super_user(login): raise PulpDataException(_('%s cannot be empty, and %s is the last member') % (self.super_user_role, login)) if role_id not in user['roles']: return user['roles'].remove(role_id) User.get_collection().save(user, safe=True) for resource, operations in role['permissions'].items(): other_roles = factory.role_query_manager().get_other_roles(role, user['roles']) user_ops = _operations_not_granted_by_roles(resource, operations, other_roles) factory.permission_manager().revoke(resource, login, user_ops)
def setUp(self): super(AuthControllersTests, self).setUp() self.user_manager = manager_factory.user_manager() self.user_query_manager = manager_factory.user_query_manager() self.role_manager = manager_factory.role_manager() self.role_query_manager = manager_factory.role_query_manager() self.permission_manager = manager_factory.permission_manager() self.permission_query_manager = manager_factory.permission_query_manager() self.password_manager = manager_factory.password_manager() self.role_manager.ensure_super_user_role() self.user_manager.ensure_admin()
def setUp(self): super(PermissionManagerTests, self).setUp() self.alpha_num = string.letters + string.digits self.role_manager = manager_factory.role_manager() self.role_query_manager = manager_factory.role_query_manager() self.permission_manager = manager_factory.permission_manager() self.permission_query_manager = manager_factory.permission_query_manager() self.role_manager.ensure_super_user_role() manager_factory.principal_manager().clear_principal()
def setUp(self): super(RoleManagerTests, self).setUp() self.alpha_num = string.letters + string.digits self.role_manager = manager_factory.role_manager() self.role_query_manager = manager_factory.role_query_manager() self.permission_manager = manager_factory.permission_manager() self.permission_query_manager = manager_factory.permission_query_manager() self.role_manager.ensure_super_user_role() manager_factory.principal_manager().clear_principal()
def setUp(self): super(AuthControllersTests, self).setUp() self.user_manager = manager_factory.user_manager() self.user_query_manager = manager_factory.user_query_manager() self.role_manager = manager_factory.role_manager() self.role_query_manager = manager_factory.role_query_manager() self.permission_manager = manager_factory.permission_manager() self.permission_query_manager = manager_factory.permission_query_manager( ) self.password_manager = manager_factory.password_manager() self.role_manager.ensure_super_user_role() self.user_manager.ensure_admin()
def ensure_super_user_role(self): """ Ensure that the super user role exists. """ role = Role.get_collection().find_one({'id': self.super_user_role}) if role is None: role = self.create_role( self.super_user_role, 'Super Users', 'Role indicates users with admin privileges') pm = factory.permission_manager() role['permissions'] = { '/': [pm.CREATE, pm.READ, pm.UPDATE, pm.DELETE, pm.EXECUTE] } Role.get_collection().save(role, safe=True)
def test_syntactic_sugar_methods(self): """ Tests the syntactic sugar methods for retrieving specific managers. """ # Setup factory.initialize() # Test self.assertTrue( isinstance(factory.authentication_manager(), AuthenticationManager)) self.assertTrue( isinstance(factory.cert_generation_manager(), CertGenerationManager)) self.assertTrue( isinstance(factory.certificate_manager(), CertificateManager)) self.assertTrue(isinstance(factory.password_manager(), PasswordManager)) self.assertTrue( isinstance(factory.permission_manager(), PermissionManager)) self.assertTrue( isinstance(factory.permission_query_manager(), PermissionQueryManager)) self.assertTrue(isinstance(factory.role_manager(), RoleManager)) self.assertTrue( isinstance(factory.role_query_manager(), RoleQueryManager)) self.assertTrue(isinstance(factory.user_manager(), UserManager)) self.assertTrue( isinstance(factory.user_query_manager(), UserQueryManager)) self.assertTrue(isinstance(factory.repo_manager(), RepoManager)) self.assertTrue( isinstance(factory.repo_unit_association_manager(), RepoUnitAssociationManager)) self.assertTrue( isinstance(factory.repo_publish_manager(), RepoPublishManager)) self.assertTrue( isinstance(factory.repo_query_manager(), RepoQueryManager)) self.assertTrue( isinstance(factory.repo_sync_manager(), RepoSyncManager)) self.assertTrue(isinstance(factory.content_manager(), ContentManager)) self.assertTrue( isinstance(factory.content_query_manager(), ContentQueryManager)) self.assertTrue( isinstance(factory.content_upload_manager(), ContentUploadManager)) self.assertTrue(isinstance(factory.consumer_manager(), ConsumerManager)) self.assertTrue( isinstance(factory.topic_publish_manager(), TopicPublishManager))
def test_operation_names_to_values(self): pm = manager_factory.permission_manager() test1 = ['CREATE', 'delete'] test1_values = [authorization.CREATE, authorization.DELETE] test2 = ['execute'] test2_values = [authorization.EXECUTE] test3 = [] test3_values = [] test4 = ['READ', 'UPDATE', 'random'] test5 = None self.assertEqual(pm.operation_names_to_values(test1), test1_values) self.assertEqual(pm.operation_names_to_values(test2), test2_values) self.assertEqual(pm.operation_names_to_values(test3), test3_values) self.assertRaises(exceptions.InvalidValue, pm.operation_names_to_values, test4) self.assertRaises(exceptions.InvalidValue, pm.operation_names_to_values, test5)
def delete_user(login): """ Deletes the given user. Deletion of last superuser is not permitted. :param login: identifies the user being deleted :type login: str :raise pulp_exceptions.PulpDataException: if user is the last super user """ user = model.User.objects.get_or_404(login=login) if is_last_super_user(login): raise pulp_exceptions.PulpDataException( _("The last superuser [%s] cannot be deleted" % login)) # Revoke all permissions from the user permission_manager = manager_factory.permission_manager() permission_manager.revoke_all_permissions_from_user(login) user.delete()
def POST(self): # Params params = self.params() login = params.get('login', None) resource = params.get('resource', None) operation_names = params.get('operations', None) _check_invalid_params({ 'login': login, 'resource': resource, 'operation_names': operation_names }) # Grant permission synchronously permission_manager = managers.permission_manager() operations = permission_manager.operation_names_to_values( operation_names) return self.ok(permission_manager.revoke(resource, login, operations))
def GET(self, role_id): role = managers.role_query_manager().find_by_id(role_id) if role is None: raise exceptions.MissingResource(role_id) role['users'] = [ u['login'] for u in managers.user_query_manager(). find_users_belonging_to_role(role['id']) ] permissions_manager = managers.permission_manager() for resource, operations in role['permissions'].items(): role['permissions'][resource] = [ permissions_manager.operation_value_to_name(o) for o in operations ] role.update(serialization.link.current_link_obj()) return self.ok(role)
def post(self, request): """ Create a new user. :param request: WSGI request object :type request: django.core.handlers.wsgi.WSGIRequest :return: Response containing the user :rtype: django.http.HttpResponse :raises: MissingValue if login field is missing :raises: InvalidValue if some parameters are invalid """ user_data = request.body_as_json login = user_data.pop('login', None) if login is None: raise pulp_exceptions.MissingValue(['login']) password = user_data.pop('password', None) # name defaults to login name = user_data.pop('name', login) # Raise if extra data is passed if user_data: raise pulp_exceptions.InvalidValue(user_data.keys()) new_user = user_controller.create_user(login, password=password, name=name) serialized_user = model.User.SERIALIZER(new_user).data # For backwards compatability. See https://pulp.plan.io/issues/1125 serialized_user['id'] = str(serialized_user['_id']) # Grant permissions permission_manager = factory.permission_manager() permission_manager.grant_automatic_permissions_for_resource( serialized_user['_href']) response = generate_json_response_with_pulp_encoder(serialized_user) return generate_redirect_response(response, serialized_user['_href'])
def GET(self): role_query_manager = managers.role_query_manager() user_query_manager = managers.user_query_manager() permissions_manager = managers.permission_manager() roles = role_query_manager.find_all() for role in roles: role['users'] = [ u['login'] for u in user_query_manager.find_users_belonging_to_role(role['id']) ] for resource, operations in role['permissions'].items(): role['permissions'][resource] = [ permissions_manager.operation_value_to_name(o) for o in operations ] for role in roles: role.update(serialization.link.child_link_obj(role['id'])) return self.ok(roles)
def POST(self): # Params params = self.params() role_id = params.get('role_id', None) resource = params.get('resource', None) operation_names = params.get('operations', None) _check_invalid_params({ 'role_id': role_id, 'resource': resource, 'operation_names': operation_names }) # Grant permission synchronously role_manager = managers.role_manager() permission_manager = managers.permission_manager() operations = permission_manager.operation_names_to_values( operation_names) return self.ok( role_manager.remove_permissions_from_role(role_id, resource, operations))
def GET(self): query_params = web.input() resource = query_params.get('resource', None) permissions = [] if resource is None: permissions = managers.permission_query_manager().find_all() else: permission = managers.permission_query_manager().find_by_resource( resource) if permission is not None: permissions = [permission] for permission in permissions: users = permission['users'] permission_manager = managers.permission_manager() for user, ops in users.items(): users[user] = [ permission_manager.operation_value_to_name(o) for o in ops ] return self.ok(permissions)
def get(self, request): """ List all roles. :param request: WSGI request object :type request: django.core.handlers.wsgi.WSGIRequest :return: Response containing a list of roles :rtype: django.http.HttpResponse """ role_query_manager = factory.role_query_manager() permissions_manager = factory.permission_manager() roles = role_query_manager.find_all() for role in roles: users = [ u.login for u in user_controller.find_users_belonging_to_role( role['id']) ] role['users'] = users resource_permission = {} # isolate schema change if role['permissions']: for item in role['permissions']: resource = item['resource'] operations = item.get('permission', []) resource_permission[resource] = [ permissions_manager.operation_value_to_name(o) for o in operations ] role['permissions'] = resource_permission link = { '_href': reverse('role_resource', kwargs={'role_id': role['id']}) } role.update(link) return generate_json_response_with_pulp_encoder(roles)
def post(self, request): """ Create a new user. :param request: WSGI request object :type request: django.core.handlers.wsgi.WSGIRequest :return: Response containing the user :rtype: django.http.HttpResponse :raises: MissingValue if login field is missing :raises: InvalidValue if some parameters are invalid """ # Pull all the user data user_data = request.body_as_json login = user_data.pop('login', None) if login is None: raise pulp_exceptions.MissingValue(['login']) password = user_data.pop('password', None) name = user_data.pop('name', None) if user_data: raise pulp_exceptions.InvalidValue(user_data.keys()) # Creation manager = factory.user_manager() args = [login] kwargs = {'password': password, 'name': name} user = manager.create_user(*args, **kwargs) # Add the link to the user link = _add_link(user) # Grant permissions permission_manager = factory.permission_manager() permission_manager.grant_automatic_permissions_for_resource( link['_href']) response = generate_json_response_with_pulp_encoder(user) return generate_redirect_response(response, link['_href'])
def post(self, request): """ Revoke permissions from a user. :param request: WSGI request object :type request: django.core.handlers.wsgi.WSGIRequest :return: An empty response :rtype: django.http.HttpResponse """ params = request.body_as_json login = params.get('login', None) resource = params.get('resource', None) operation_names = params.get('operations', None) _validate_params({'login': login, 'resource': resource, 'operation_names': operation_names}) permission_manager = factory.permission_manager() operations = permission_manager.operation_names_to_values(operation_names) revoke_perm = permission_manager.revoke(resource, login, operations) return generate_json_response(revoke_perm)
def get(self, request, role_id): """ Retrieve a specific role. :param request: WSGI request object :type request: django.core.handlers.wsgi.WSGIRequest :param role_id: id for the requested role :type role_id: str :return: Response containing the role :rtype: django.http.HttpResponse :raises: MissingResource if role ID does not exist """ role = factory.role_query_manager().find_by_id(role_id) if role is None: raise pulp_exceptions.MissingResource(role_id) role['users'] = [ u.login for u in user_controller.find_users_belonging_to_role(role['id']) ] permissions_manager = factory.permission_manager() # isolate schema change resource_permission = {} for item in role['permissions']: resource = item['resource'] operations = item.get('permission', []) resource_permission[resource] = [ permissions_manager.operation_value_to_name(o) for o in operations ] role['permissions'] = resource_permission link = { '_href': reverse('role_resource', kwargs={'role_id': role['id']}) } role.update(link) return generate_json_response_with_pulp_encoder(role)
:type roles: list :raise DuplicateResource: if there is already a user with the requested login :raise InvalidValue: if any of the fields are unacceptable """ user = model.User(login=login, name=name, roles=roles) user.set_password(password) try: user.save() except NotUniqueError: raise pulp_exceptions.DuplicateResource(login) except ValidationError, e: raise pulp_exceptions.InvalidValue(e.to_dict().keys()) # Grant default user permissions permission_manager = manager_factory.permission_manager() permission_manager.grant_automatic_permissions_for_user(user.login) return user def update_user(login, delta): """ Updates the user with a delta dict. The delta can only contain fields that may be changed, which are name, password, and roles. :param login: identifies the user :type login: str :param delta: user attributes and their new values :type delta: dict :raise InvalidValue: if extra params are passed or params contain invalid values