def setUp(self): self.distro = data_setup.create_distro() self.distro_tree1 = data_setup.create_distro_tree(distro=self.distro, arch='x86_64') self.distro_tree2 = data_setup.create_distro_tree(distro=self.distro, arch='i386') self.distro_tree1.activity.append(DistroTreeActivity( user=User.by_user_name(data_setup.ADMIN_USER), service=u'testdata', field_name=u'Nonesente', old_value=u'sdfas', new_value=u'sdfa', action='Added')) self.distro_tree2.activity.append(DistroTreeActivity( user=User.by_user_name(data_setup.ADMIN_USER), service=u'testdata', field_name=u'Noneseonce', old_value=u'bsdf', new_value=u'sdfas', action='Added')) self.distro.activity.append(DistroActivity( user=User.by_user_name(data_setup.ADMIN_USER), service=u'testdata', action=u'Nothing', field_name=u'Nonsense', old_value=u'asdf', new_value=u'omgwtfbbq')) self.system = data_setup.create_system() self.system.activity.append(SystemActivity( user=User.by_user_name(data_setup.ADMIN_USER), service=u'testdata', action=u'Nothing', field_name=u'Nonsense', old_value=u'asdf', new_value=u'omgwtfbbq')) self.group2 = data_setup.create_group() self.group = data_setup.create_group() self.group.activity.append(GroupActivity( user=User.by_user_name(data_setup.ADMIN_USER), service=u'testdata', action=u'Nothing', field_name=u'Nonsense', old_value=u'asdf', new_value=u'omgwtfbbq')) self.browser = self.get_browser()
def remove_account(self, username, newowner=None): """ Removes a Beaker user account. When the account is removed: * it is removed from all groups and access policies * any running jobs owned by the account are cancelled * any systems reserved by or loaned to the account are returned * any systems and system pools owned by the account are transferred to the admin running this command, or some other user if specified using the *newowner* parameter * the account is disabled for further login :param username: An existing username :param newowner: An optional username to assign all systems to. :type username: string """ kwargs = {} try: user = User.by_user_name(username) except InvalidRequestError: raise BX(_('Invalid User %s ' % username)) if newowner: owner = User.by_user_name(newowner) if owner is None: raise BX(_('Invalid user name for owner %s' % newowner)) kwargs['newowner'] = owner if user.removed: raise BX(_('User already removed %s' % username)) _remove(user=user, method='XMLRPC', **kwargs)
def login_password(self, username, password, proxy_user=None): """ Authenticates the current session using the given username and password. The caller may act as a proxy on behalf of another user by passing the *proxy_user* argument. This requires that the caller has 'proxy_auth' permission. :param proxy_user: username on whose behalf the caller is proxying :type proxy_user: string or None """ user = User.by_user_name(username) if user is None: raise LoginException(_(u'Invalid username or password')) if not user.can_log_in(): raise LoginException(_(u'Invalid username or password')) if not user.check_password(password): raise LoginException(_(u'Invalid username or password')) if proxy_user: if not user.has_permission(u'proxy_auth'): raise LoginException(_(u'%s does not have proxy_auth permission') % user.user_name) proxied_user = User.by_user_name(proxy_user) if proxied_user is None: raise LoginException(_(u'Proxy user %s does not exist') % proxy_user) identity.set_authentication(proxied_user, proxied_by=user) else: identity.set_authentication(user) return user.user_name
def test_system_pool_activity(self): with session.begin(): pool1 = data_setup.create_system_pool() act1 = pool1.record_activity(service=u'testdata', user=User.by_user_name(data_setup.ADMIN_USER), action=u'Nothing', field=u'Nonsense', old=u'asdf', new=u'omgwtfbbq') pool2 = data_setup.create_system_pool() act2 = pool2.record_activity(service=u'testdata', user=User.by_user_name(data_setup.ADMIN_USER), action=u'Nothing', field=u'Nonsense', old=u'asdf', new=u'lollercopter') b = self.browser b.get(get_server_base() + 'activity/pool') b.find_element_by_class_name('search-query').send_keys( 'pool.name:%s' % pool1.name) b.find_element_by_class_name('grid-filter').submit() check_activity_search_results(b, present=[act1], absent=[act2]) # search by pool owner b.get(get_server_base() + 'activity/pool') b.find_element_by_class_name('search-query').send_keys( 'pool.owner.user_name:%s' % pool2.owner.user_name) b.find_element_by_class_name('grid-filter').submit() check_activity_search_results(b, present=[act2], absent=[act1]) with session.begin(): pool1.owning_user = None pool1.owning_group = data_setup.create_group() b.get(get_server_base() + 'activity/pool') b.find_element_by_class_name('search-query').send_keys( 'pool.owner.group_name:%s' % pool1.owner.group_name) b.find_element_by_class_name('grid-filter').submit() check_activity_search_results(b, present=[act1], absent=[act2])
def remove_account(self, username, newowner=None): """ Remove a user account. Removing a user account cancels any running job(s), returns all the systems in use by the user, modifies the ownership of the systems owned to the admin closing the account, and disables the account for further login. :param username: An existing username :param newowner: An optional username to assign all systems to. :type username: string """ kwargs = {} try: user = User.by_user_name(username) except InvalidRequestError: raise BX(_('Invalid User %s ' % username)) if newowner: owner = User.by_user_name(newowner) if owner is None: raise BX(_('Invalid user name for owner %s' % newowner)) kwargs['newowner'] = owner if user.removed: raise BX(_('User already removed %s' % username)) self._remove(user=user, method='XMLRPC', **kwargs)
def check_authentication(): """ Checks the current request for: * REMOTE_USER in the WSGI environment, indicating that the container has already authenticated the request for us; or * a valid signed token, indicating that the user has authenticated to us successfully on a previous request. Sets up the "current identity" state according to what's found. """ from bkr.server.model import User if 'REMOTE_USER' in flask.request.environ: # strip realm if present user_name, _, realm = flask.request.environ['REMOTE_USER'].partition('@') user = User.by_user_name(user_name.decode('utf8')) if user is None and config.get('identity.autocreate', True): # handle automatic user creation if possible user = _try_autocreate(user_name) if user is None: log.debug('REMOTE_USER %r does not exist', user_name) return proxied_by_user = None elif _token_cookie_name in flask.request.cookies: token = flask.request.cookies[_token_cookie_name] if token == 'deleted': return token_value = _check_token(token) if not token_value or 'user_name' not in token_value: return user_name = token_value['user_name'] user = User.by_user_name(user_name.decode('utf8')) if user is None: log.warning('Token claimed to be for non-existent user %r', user_name) return # handle "proxy authentication" support proxied_by_user_name = token_value.get('proxied_by_user_name', None) if proxied_by_user_name: proxied_by_user = User.by_user_name(proxied_by_user_name.decode('utf8')) if proxied_by_user is None: log.warning('Token for %r claimed to be proxied by non-existent user %r', user_name, proxied_by_user_name) return if not proxied_by_user.can_log_in(): log.debug('Denying login for %r proxied by disabled user %r', user_name, proxied_by_user_name) return else: proxied_by_user = None else: return if not user.can_log_in(): log.debug('Denying login for disabled user %s', user) return flask.g._beaker_validated_user = user flask.g._beaker_proxied_by_user = proxied_by_user
def login_krbV(self, krb_request, proxy_user=None): """ Authenticates the current session using Kerberos. The caller may act as a proxy on behalf of another user by passing the *proxy_user* argument. This requires that the caller has 'proxy_auth' permission. :param krb_request: KRB_AP_REQ message containing client credentials, as produced by :c:func:`krb5_mk_req` :type krb_request: base64-encoded string :param proxy_user: username on whose behalf the caller is proxying :type proxy_user: string or None This method is also available under the alias :meth:`auth.login_krbv`, for compatibility with `Kobo`_. """ import krbV import base64 context = krbV.default_context() server_principal = krbV.Principal(name=self.KRB_AUTH_PRINCIPAL, context=context) server_keytab = krbV.Keytab(name=self.KRB_AUTH_KEYTAB, context=context) auth_context = krbV.AuthContext(context=context) auth_context.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME auth_context.addrs = (socket.gethostbyname(cherrypy.request.remote_host), 0, cherrypy.request.remote_addr, 0) # decode and read the authentication request decoded_request = base64.decodestring(krb_request) auth_context, opts, server_principal, cache_credentials = context.rd_req(decoded_request, server=server_principal, keytab=server_keytab, auth_context=auth_context, options=krbV.AP_OPTS_MUTUAL_REQUIRED) cprinc = cache_credentials[2] # remove @REALM username = cprinc.name.split("@")[0] user = User.by_user_name(username) if user is None: raise LoginException(_(u'Invalid username')) if not user.can_log_in(): raise LoginException(_(u'Invalid username')) if proxy_user: if not user.has_permission(u'proxy_auth'): raise LoginException(_(u'%s does not have proxy_auth permission') % user.user_name) proxied_user = User.by_user_name(proxy_user) if proxied_user is None: raise LoginException(_(u'Proxy user %s does not exist') % proxy_user) identity.set_authentication(proxied_user, proxied_by=user) else: identity.set_authentication(user) return username
def test_release_system(self): with session.begin(): system = data_setup.create_system( owner=User.by_user_name(data_setup.ADMIN_USER), status=u'Manual', shared=True) user = data_setup.create_user(password=u'password') system.reserve_manually(service=u'testdata', user=user) server = self.get_server() server.auth.login_password(user.user_name, 'password') server.systems.release(system.fqdn) with session.begin(): session.refresh(system) session.refresh(system.reservations[0]) self.assert_(system.user is None) self.assertEquals(system.reservations[0].user, user) assert_datetime_within(system.reservations[0].finish_time, tolerance=datetime.timedelta(seconds=10), reference=datetime.datetime.utcnow()) assert_durations_not_overlapping(system.reservations) released_activity = system.activity[0] self.assertEqual(released_activity.action, 'Returned') self.assertEqual(released_activity.field_name, 'User') self.assertEqual(released_activity.user, user) self.assertEqual(released_activity.old_value, user.user_name) self.assertEqual(released_activity.new_value, '') self.assertEqual(released_activity.service, 'XMLRPC')
def test_refresh_ldap_group_membership(self): with session.begin(): group = Group(group_name=u'alp', display_name=u'Australian Labor Party', ldap=True) old_member = data_setup.create_user(user_name=u'krudd') group.users.append(old_member) from bkr.server.tools.refresh_ldap import refresh_ldap refresh_ldap() with session.begin(): session.expire_all() self.assertEquals(group.users, [User.by_user_name(u'jgillard')]) # second time is a no-op refresh_ldap() with session.begin(): session.expire_all() self.assertEquals(group.users, [User.by_user_name(u'jgillard')])
def process_xmljob(self, xmljob, user, ignore_missing_tasks=False): # We start with the assumption that the owner == 'submitting user', until # we see otherwise. submitter = user if user.rootpw_expired: raise BX(_('Your root password has expired, please change or clear it in order to submit jobs.')) owner_name = xmljob.get_xml_attr('user', unicode, None) if owner_name: owner = User.by_user_name(owner_name) if owner is None: raise ValueError('%s is not a valid user name' % owner_name) if not submitter.is_delegate_for(owner): raise ValueError('%s is not a valid submission delegate for %s' % (submitter, owner)) else: owner = user group_name = xmljob.get_xml_attr('group', unicode, None) group = None if group_name: try: group = Group.by_name(group_name) except NoResultFound, e: raise ValueError('%s is not a valid group' % group_name) if group not in owner.groups: raise BX(_(u'User %s is not a member of group %s' % (owner.user_name, group.group_name)))
def test_power_quiescent_period_statefulness_not_elapsed(self): if daemons_running_externally(): raise SkipTest('cannot examine logs of remote beaker-provision') provision_process, = [p for p in processes if p.name == \ 'beaker-provision'] # Initial lookup of this system will reveal no state, so will delay # for the whole quiescent period try: provision_process.start_output_capture() with session.begin(): system = data_setup.create_system(lab_controller=self.get_lc()) system.power.power_type = PowerType.lazy_create(name=u'dummy') system.power.power_quiescent_period = 1 system.power.power_id = u'' # make power script not sleep system.power.delay_until = None system.action_power(action=u'off', service=u'testdata') wait_for_commands_to_finish(system, timeout=10) finally: provision_output = provision_process.finish_output_capture() self.assertIn('Entering quiescent period, delaying 1 seconds for ' 'command %s' % system.command_queue[0].id, provision_output) # Increase the quiescent period, to ensure we enter it try: provision_process.start_output_capture() with session.begin(): system = System.by_id(system.id, User.by_user_name('admin')) system.power.power_quiescent_period = 10 system.action_power(action=u'on', service=u'testdata') wait_for_commands_to_finish(system, timeout=15) finally: provision_output = provision_process.finish_output_capture() self.assertIn('Entering quiescent period', provision_output)
def test_ldap_group(self): group_name = 'wyfp' display_name = 'My LDAP Group' out = run_client(['bkr', 'group-create', '--ldap', '--display-name', display_name, group_name]) group = Group.by_name(group_name) self.assertEquals(group.ldap, True) self.assertEquals(group.users, [User.by_user_name(u'asaha')]) with session.begin(): rand_user = data_setup.create_user(password = '******') rand_client_config = create_client_config(username=rand_user.user_name, password='******') group_name = 'alp' display_name = 'ALP' try: out = run_client(['bkr', 'group-create', '--ldap', '--display-name', display_name, group_name], config = rand_client_config) self.fail('Must fail or die') except ClientError, e: self.assert_('Only admins can create LDAP groups' in e.stderr_output)
def test_refresh_ldap_group_membership(self): with session.begin(): group = Group(group_name=u'alp', display_name=u'Australian Labor Party', membership_type=GroupMembershipType.ldap) old_member = data_setup.create_user(user_name=u'krudd') group.add_member(old_member) run_command('refresh_ldap.py', 'beaker-refresh-ldap') with session.begin(): session.expire_all() self.assertEquals(group.users, [User.by_user_name(u'jgillard')]) # second time is a no-op run_command('refresh_ldap.py', 'beaker-refresh-ldap') with session.begin(): session.expire_all() self.assertEquals(group.users, [User.by_user_name(u'jgillard')])
def revoke_owner(self, group_id=None, id=None, **kw): if group_id is not None and id is not None: group = Group.by_id(group_id) user = User.by_id(id) service = 'WEBUI' else: group = Group.by_name(kw['group_name']) user = User.by_user_name(kw['member_name']) service = 'XMLRPC' if group.ldap: raise GroupOwnerModificationForbidden('An LDAP group does not have an owner') if not group.can_edit(identity.current.user): raise GroupOwnerModificationForbidden('You are not an owner of group %s' % group) if user not in group.users: raise GroupOwnerModificationForbidden('User is not a group member') if len(group.owners())==1 and not identity.current.user.is_admin(): raise GroupOwnerModificationForbidden('Cannot remove the only owner') else: for assoc in group.user_group_assocs: if assoc.user == user: if assoc.is_owner: assoc.is_owner = False group.record_activity(user=identity.current.user, service=service, field=u'Owner', action='Removed', old=user.user_name, new=u'') # hack to return the user removing this owner # so that if the user was logged in as a group # owner, he/she can be redirected appropriately return str(identity.current.user.user_id)
def find_user_or_create(user_name): user = User.by_user_name(user_name) if user is None: user = User(user_name=user_name) user.user_name = user_name session.add(user) return user
def save_system_access_policy(fqdn): system = _get_system_by_FQDN(fqdn) if not system.can_edit_policy(identity.current.user): raise Forbidden403('Cannot edit system policy') if system.custom_access_policy: policy = system.custom_access_policy else: policy = system.custom_access_policy = SystemAccessPolicy() data = read_json_request(request) # Figure out what is added, what is removed. # Rules are immutable, so if it has an id it is unchanged, # if it has no id it is new. kept_rule_ids = frozenset(r['id'] for r in data['rules'] if 'id' in r) removed = [] for old_rule in policy.rules: if old_rule.id not in kept_rule_ids: removed.append(old_rule) for old_rule in removed: system.record_activity(user=identity.current.user, service=u'HTTP', field=u'Access Policy Rule', action=u'Removed', old=repr(old_rule)) policy.rules.remove(old_rule) for rule in data['rules']: if 'id' not in rule: user = User.by_user_name(rule['user']) if rule['user'] else None group = Group.by_name(rule['group']) if rule['group'] else None permission = SystemPermission.from_string(rule['permission']) new_rule = policy.add_rule(user=user, group=group, everybody=rule['everybody'], permission=permission) system.record_activity(user=identity.current.user, service=u'HTTP', field=u'Access Policy Rule', action=u'Added', new=repr(new_rule)) return '', 204
def add_system_access_policy_rule(fqdn): system = _get_system_by_FQDN(fqdn) if not system.can_edit_policy(identity.current.user): raise Forbidden403('Cannot edit system policy') if system.custom_access_policy: policy = system.custom_access_policy else: policy = system.custom_access_policy = SystemAccessPolicy() rule = read_json_request(request) if rule['user']: user = User.by_user_name(rule['user']) if not user: raise BadRequest400("User '%s' does not exist" % rule['user']) else: user = None if rule['group']: try: group = Group.by_name(rule['group']) except NoResultFound: raise BadRequest400("Group '%s' does not exist" % rule['group']) else: group = None try: permission = SystemPermission.from_string(rule['permission']) except ValueError: raise BadRequest400 new_rule = policy.add_rule(user=user, group=group, everybody=rule['everybody'], permission=permission) system.record_activity(user=identity.current.user, service=u'HTTP', field=u'Access Policy Rule', action=u'Added', new=repr(new_rule)) return '', 204
def validate_python(self, form_fields, state): lc_id = form_fields.get('id', None) email_address = form_fields['email'] user_name = form_fields['lusername'] try: User.by_email_address(email_address) except NoResultFound: email_is_used = False else: email_is_used = True if User.by_user_name(user_name): new_user = False else: new_user = True if not lc_id: labcontroller = None luser = None else: labcontroller = LabController.by_id(lc_id) luser = labcontroller.user try: if not labcontroller and email_is_used: # New LC using dupe email raise ValueError if new_user and email_is_used: #New user using dupe email raise ValueError if luser: _check_user_email(email_address, luser.user_id) except ValueError: error = {'email' : self.message('not_unique', state)} raise Invalid('Email address is not unique', form_fields, state, error_dict=error)
def test_reject_expired_root_password(self): with session.begin(): ConfigItem.by_name('root_password_validity').set(90, user=User.by_user_name(data_setup.ADMIN_USER)) self.user.root_password = '******' self.user.rootpw_changed = datetime.datetime.utcnow() - datetime.timedelta(days=99) job_xml = ''' <job> <whiteboard>job for user with expired password</whiteboard> <recipeSet> <recipe> <distroRequires> <distro_name op="=" value="BlueShoeLinux5-5" /> <distro_arch op="=" value="i386" /> </distroRequires> <hostRequires/> <task name="/distribution/install" /> <task name="/distribution/reservesys" /> </recipe> </recipeSet> </job> ''' try: self.server.jobs.upload(job_xml) self.fail('should raise') except xmlrpclib.Fault, e: self.assert_('root password has expired' in e.faultString)
def test_can_search_custom_service(self): with session.begin(): distro_tree = data_setup.create_distro_tree() act1 = distro_tree.record_activity( user=User.by_user_name(data_setup.ADMIN_USER), service=u'TESTSERVICE', field=u'Nonesente', old=u'sdfas', new=u'sdfa', action=u'Removed') act2 = distro_tree.record_activity( user=User.by_user_name(data_setup.ADMIN_USER), service=u'TESTSERVICE2', field=u'Noneseonce', old=u'bsdf', new=u'sdfas', action=u'Removed') b = self.browser b.get(get_server_base() + 'activity/distrotree') b.find_element_by_class_name('search-query').send_keys('service:TESTSERVICE') b.find_element_by_class_name('grid-filter').submit() check_activity_search_results(b, present=[act1], absent=[act2])
def revoke_owner(self, group_id=None, id=None, **kw): if group_id is not None and id is not None: group = Group.by_id(group_id) user = User.by_id(id) service = 'WEBUI' else: group = Group.by_name(kw['group_name']) user = User.by_user_name(kw['member_name']) service = 'XMLRPC' if group.membership_type == GroupMembershipType.ldap: raise GroupOwnerModificationForbidden('An LDAP group does not have an owner') if not group.can_edit(identity.current.user): raise GroupOwnerModificationForbidden('You are not an owner of group %s' % group) if user not in group.users: raise GroupOwnerModificationForbidden('User is not a group member') if len(group.owners())==1 and not identity.current.user.is_admin(): raise GroupOwnerModificationForbidden('Cannot remove the only owner') else: group.revoke_ownership(user=user, agent=identity.current.user, service=service) # hack to return the user removing this owner # so that if the user was logged in as a group # owner, he/she can be redirected appropriately return str(identity.current.user.user_id)
def tearDown(self): admin_user = User.by_user_name(data_setup.ADMIN_USER) if getattr(self,'recipe_id', None): with session.begin(): recipe = Recipe.by_id(self.recipe_id) if recipe.resource.system.open_reservation: recipe.resource.release()
def grant_owner(self, group_id=None, id=None, **kw): if group_id is not None and id is not None: group = Group.by_id(group_id) user = User.by_id(id) service = 'WEBUI' else: group = Group.by_name(kw['group_name']) user = User.by_user_name(kw['member_name']) service = 'XMLRPC' if group.ldap: raise GroupOwnerModificationForbidden('An LDAP group does not have an owner') if not group.can_edit(identity.current.user): raise GroupOwnerModificationForbidden('You are not an owner of the group %s' % group) if user not in group.users: raise GroupOwnerModificationForbidden('User is not a group member') else: for assoc in group.user_group_assocs: if assoc.user == user: if not assoc.is_owner: assoc.is_owner = True group.record_activity(user=identity.current.user, service=service, field=u'Owner', action='Added', old=u'', new=user.user_name) return ''
def test_ldap_group(self): if not config.get("identity.ldap.enabled", False): raise SkipTest('Server is not configured for LDAP') group_name = u'wyfp' display_name = u'My LDAP Group' out = run_client(['bkr', 'group-create', '--ldap', '--display-name', display_name, group_name]) group = Group.by_name(group_name) self.assertEquals(group.membership_type, GroupMembershipType.ldap) self.assertEquals(group.users, [User.by_user_name(u'asaha')]) with session.begin(): rand_user = data_setup.create_user(password = '******') rand_client_config = create_client_config(username=rand_user.user_name, password='******') group_name = u'alp' display_name = u'ALP' try: out = run_client(['bkr', 'group-create', '--ldap', '--display-name', display_name, group_name], config = rand_client_config) self.fail('Must fail or die') except ClientError, e: self.assert_('Only admins can create LDAP groups' in e.stderr_output)
def add_ssh_public_key(username): """ Adds a new SSH public key for the given user account. Accepts mimetype:`text/plain` request bodies containing the SSH public key in the conventional OpenSSH format: <keytype> <key> <ident>. :param username: The user's username. """ user = User.by_user_name(username) if user is None: raise NotFound404('User %s does not exist' % username) if not user.can_edit(identity.current.user): raise Forbidden403('Cannot edit user %s' % user) if request.mimetype != 'text/plain': raise UnsupportedMediaType415('Request content type must be text/plain') with convert_internal_errors(): keytext = request.data.strip() if '\n' in keytext: raise ValueError('SSH public keys may not contain newlines') elements = keytext.split(None, 2) if len(elements) != 3: raise ValueError('Invalid SSH public key') key = SSHPubKey(*elements) user.sshpubkeys.append(key) session.flush() # to populate id return jsonify(key.__json__())
def login_oauth2(self, access_token, proxy_user=None): """ Authenticates the current session using OAuth2. The caller may act as a proxy on behalf of another user by passing the *proxy_user* argument. This requires that the caller has 'proxy_auth' permission. :param access_token: The OAuth2 access token :type access_token: string :param proxy_user: username on whose behalf the caller is proxying :type proxy_user: string or None """ token_info_resp = requests.post( self.OAUTH2_TOKEN_INFO_URL, timeout=get('identity.soldapprovider.timeout'), data={'client_id': self.OAUTH2_CLIENT_ID, 'client_secret': self.OAUTH2_CLIENT_SECRET, 'token': access_token}) token_info_resp.raise_for_status() token_info = token_info_resp.json() if not token_info['active']: raise LoginException(_(u'Invalid token')) if not 'https://beaker-project.org/oidc/scope' in token_info.get('scope', '').split(' '): raise LoginException(_(u'Token missing required scope')) username = token_info.get('sub') if not username: raise LoginException(_(u'Token missing subject')) user = User.by_user_name(username) if user is None: raise LoginException(_(u'Invalid username')) if not user.can_log_in(): raise LoginException(_(u'Invalid username')) if proxy_user: if not user.has_permission(u'proxy_auth'): raise LoginException(_(u'%s does not have proxy_auth permission') % user.user_name) proxied_user = User.by_user_name(proxy_user) if proxied_user is None: raise LoginException(_(u'Proxy user %s does not exist') % proxy_user) identity.set_authentication(proxied_user, proxied_by=user) else: identity.set_authentication(user) return username
def add_submission_delegate_by_name(self, new_delegate_name, service=u'XMLRPC'): user = identity.current.user new_delegate = User.by_user_name(new_delegate_name) if not new_delegate: raise BX(_(u'%s is not a valid user' % new_delegate_name)) user.add_submission_delegate(new_delegate, service) return new_delegate_name
def setUp(self): self.lc = data_setup.create_labcontroller() self.distro = data_setup.create_distro() self.distro_tree = data_setup.create_distro_tree(distro=self.distro, arch='x86_64', lab_controllers=[self.lc]) self.server = self.get_server() user = User.by_user_name(data_setup.ADMIN_USER) user.groups[0].permissions[:] = user.groups[0].permissions + [ Permission.by_name('distro_expire')]
def test_create_system_set_host_hypervisor(self): fqdn = data_setup.unique_name(u'mysystem%s') run_client(['bkr', 'system-create', fqdn, '--host-hypervisor=KVM']) with session.begin(): system = System.by_fqdn(fqdn, User.by_user_name(u'admin')) self.assertEquals(str(system.hypervisor), u'KVM') self.assertEquals(system.activity[0].new_value, u'KVM')
def test_can_search_by_distro_tree_specifics(self): with session.begin(): tree1 = data_setup.create_distro_tree(arch=u'i386') act1 = tree1.record_activity( user=User.by_user_name(data_setup.ADMIN_USER), service=u'TESTSERVICE', field=u'Nonesente', old=u'sdfas', new=u'sdfa', action=u'Added') tree2 = data_setup.create_distro_tree(arch=u'x86_64') act2 = tree2.record_activity( user=User.by_user_name(data_setup.ADMIN_USER), service=u'TESTSERVICE2', field=u'Noneseonce', old=u'bsdf', new=u'sdfas', action=u'Added') b = self.browser b.get(get_server_base() + 'activity/distrotree') b.find_element_by_class_name('search-query').send_keys('distro_tree.arch:i386') b.find_element_by_class_name('grid-filter').submit() check_activity_search_results(b, present=[act1], absent=[act2])
def test_create_system_set_condition(self): fqdn = data_setup.unique_name(u'mysystem%s') with session.begin(): lc = data_setup.create_labcontroller() run_client([ 'bkr', 'system-create', fqdn, '--lab-controller', str(lc.fqdn), '--condition=Automated' ]) with session.begin(): system = System.by_fqdn(fqdn, User.by_user_name(u'admin')) self.assertTrue(system.lab_controller, lc) self.assertEquals(str(system.status), u'Automated')
def test_cannot_reserve_system_in_use(self): with session.begin(): user = data_setup.create_user(password=u'password') system = data_setup.create_system(owner=user, status=SystemStatus.manual, shared=True) system.user = User.by_user_name(data_setup.ADMIN_USER) server = self.get_server() server.auth.login_password(user.user_name, 'password') try: server.systems.reserve(system.fqdn) self.fail('should raise') except xmlrpclib.Fault, e: self.assertIn('already reserved', e.faultString)
def setup_openstack(): with session.begin(): data_setup.create_openstack_region() session.flush() # Use a distinctive guest name prefix to give us a greater chance of # tracking instances back to the test run which created them. admin_user = User.by_user_name(data_setup.ADMIN_USER) guest_name_prefix = u'beaker-testsuite-%s-%s-' % ( datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S'), socket.gethostname()) ConfigItem.by_name(u'guest_name_prefix').set(guest_name_prefix, user=admin_user) ipxe_image.upload_image(_glance(), visibility=u'private')
def login_password(): """ Authenticates the current session using the given username and password. The caller may act as a proxy on behalf of another user by passing the *proxy_user* key. This requires that the caller has 'proxy_auth' permission. The request body must be a JSON object containing username and password. Proxy_user is optional. :jsonparam string username: Username :jsonparam string password: Password :jsonparam string proxy_user: Username on whose behalf the caller is proxying """ payload = read_json_request(request) username = payload.get('username') password = payload.get('password') proxy_user = payload.get('proxy_user') user = User.by_user_name(username) if user is None: raise Unauthorised401(u'Invalid username or password') if not user.can_log_in(): raise Unauthorised401(u'Invalid username or password') if not user.check_password(password): raise Unauthorised401(u'Invalid username or password') if proxy_user: if not user.has_permission(u'proxy_auth'): raise Unauthorised401(u'%s does not have proxy_auth permission' % user.user_name) proxied_user = User.by_user_name(proxy_user) if proxied_user is None: raise Unauthorised401(u'Proxy user %s does not exist' % proxy_user) identity.set_authentication(proxied_user, proxied_by=user) else: identity.set_authentication(user) return jsonify({'username': user.user_name})
def test_create_user(self): s = requests.Session() requests_login(s) response = post_json(get_server_base() + 'users/', session=s, data={ 'user_name': 'fbaggins', 'display_name': 'Frodo Baggins', 'email_address': '*****@*****.**'}) response.raise_for_status() with session.begin(): session.expire_all() user = User.by_user_name(u'fbaggins') self.assertEqual(response.json()['id'], user.user_id) self.assertEqual(response.json()['user_name'], 'fbaggins')
def add_submission_delegate(self, **kwargs): user = identity.current.user new_delegate_name = kwargs['user']['text'] new_delegate = User.by_user_name(new_delegate_name) if not new_delegate: flash(_(u'%s is not a valid user' % new_delegate_name)) redirect('.') try: user.add_submission_delegate(new_delegate, u'WEBUI') except NoChangeException, e: flash(_(unicode(e))) redirect('.')
def test_cannot_provision_automated_system(self): with session.begin(): system = data_setup.create_system(owner=User.by_user_name( data_setup.ADMIN_USER), status=u'Automated', shared=True) user = data_setup.create_user(password=u'password') self.server.auth.login_password(user.user_name, 'password') try: self.server.systems.provision(system.fqdn, 'distro') except xmlrpclib.Fault, e: self.assertIn('Reserve a system before provisioning', e.faultString)
def test_provision_expired_user_root_password(self): system = self.usable_system user = system.user with session.begin(): user.root_password = '******' user.rootpw_changed = datetime.datetime.utcnow() - datetime.timedelta(days=99) ConfigItem.by_name('root_password_validity')\ .set(90, user=User.by_user_name(data_setup.ADMIN_USER)) self.server.auth.login_password(user.user_name, 'password') try: self.server.systems.provision(system.fqdn, self.distro_tree.id) self.fail('should raise') except xmlrpclib.Fault, e: self.assert_('root password has expired' in e.faultString, e.faultString)
def delete_submission_delegate(username): """ Deletes a public SSH public key belonging to the given user account. :param username: The user's username. :param id: Database id of the SSH public key to be deleted. """ user = User.by_user_name(username) #XXX lockmode='update' if user is None: raise NotFound404('User %s does not exist' % username) if not user.can_edit(identity.current.user): raise Forbidden403('Cannot edit user %s' % user) if 'user_name' not in request.args: raise MethodNotAllowed405 submission_delegate = User.by_user_name(request.args['user_name']) if submission_delegate is None: raise NotFound404('Submission delegate %s does not exist' % request.args['user_name']) if not submission_delegate.is_delegate_for(user): raise Conflict409('User %s is not a submission delegate for %s' % (submission_delegate, user)) user.remove_submission_delegate(submission_delegate) return '', 204
def test_can_search_custom_service(self): with session.begin(): distro_tree = data_setup.create_distro_tree() act1 = distro_tree.record_activity(user=User.by_user_name( data_setup.ADMIN_USER), service=u'TESTSERVICE', field=u'Nonesente', old=u'sdfas', new=u'sdfa', action=u'Removed') act2 = distro_tree.record_activity(user=User.by_user_name( data_setup.ADMIN_USER), service=u'TESTSERVICE2', field=u'Noneseonce', old=u'bsdf', new=u'sdfas', action=u'Removed') b = self.browser b.get(get_server_base() + 'activity/distrotree') b.find_element_by_class_name('search-query').send_keys( 'service:TESTSERVICE') b.find_element_by_class_name('grid-filter').submit() check_activity_search_results(b, present=[act1], absent=[act2])
def test_cannot_provision_system_in_use(self): with session.begin(): system = data_setup.create_system( owner=User.by_user_name(data_setup.ADMIN_USER), status=SystemStatus.manual, shared=True) user = data_setup.create_user(password=u'password') other_user = data_setup.create_user() system.user = other_user self.server.auth.login_password(user.user_name, 'password') try: self.server.systems.provision(system.fqdn, 'distro') except xmlrpclib.Fault, e: self.assert_('Reserve a system before provisioning' in e.faultString)
def test_create_pool(self): b = self.browser login(b) b.get(get_server_base() + 'pools/') b.find_element_by_xpath('//button[normalize-space(string(.))="Create"]')\ .click() modal = b.find_element_by_class_name('modal') modal.find_element_by_name('name').send_keys('inflatable') modal.find_element_by_tag_name('form').submit() b.find_element_by_xpath('//title[text()="inflatable"]') with session.begin(): pool = SystemPool.by_name(u'inflatable') self.assertEquals(pool.owner, User.by_user_name(data_setup.ADMIN_USER))
def test_can_search_by_distro_name(self): with session.begin(): distro1 = data_setup.create_distro() act1 = distro1.record_activity(service=u'testdata', user=User.by_user_name( data_setup.ADMIN_USER), action=u'Nothing', field=u'Nonsense', old=u'asdf', new=u'omgwtfbbq') distro2 = data_setup.create_distro() act2 = distro2.record_activity(service=u'testdata', user=User.by_user_name( data_setup.ADMIN_USER), action=u'Nothing', field=u'Nonsense', old=u'asdf', new=u'lollercopter') b = self.browser b.get(get_server_base() + 'activity/distro') b.find_element_by_class_name('search-query').send_keys( 'distro.name:%s' % distro1.name) b.find_element_by_class_name('grid-filter').submit() check_activity_search_results(b, present=[act1], absent=[act2])
def test_can_search_by_distro_tree_specifics(self): with session.begin(): tree1 = data_setup.create_distro_tree(arch=u'i386') act1 = tree1.record_activity(user=User.by_user_name( data_setup.ADMIN_USER), service=u'TESTSERVICE', field=u'Nonesente', old=u'sdfas', new=u'sdfa', action=u'Added') tree2 = data_setup.create_distro_tree(arch=u'x86_64') act2 = tree2.record_activity(user=User.by_user_name( data_setup.ADMIN_USER), service=u'TESTSERVICE2', field=u'Noneseonce', old=u'bsdf', new=u'sdfas', action=u'Added') b = self.browser b.get(get_server_base() + 'activity/distrotree') b.find_element_by_class_name('search-query').send_keys( 'distro_tree.arch:i386') b.find_element_by_class_name('grid-filter').submit() check_activity_search_results(b, present=[act1], absent=[act2])
def test_create_system_defaults(self): fqdn = data_setup.unique_name(u'mysystem%s') run_client(['bkr', 'system-create', fqdn]) with session.begin(): system = System.by_fqdn(fqdn, User.by_user_name(u'admin')) self.assertTrue(system.owner.user_name, data_setup.ADMIN_USER) self.assertTrue(system.custom_access_policy.grants_everybody( SystemPermission.view)) # duplicate try: run_client(['bkr', 'system-create', fqdn]) self.fail('Must fail') except ClientError as e: self.assertIn("System with fqdn %r already exists" % fqdn, e.stderr_output)
def test_create_ldap_group(self): login(self.browser) b = self.browser b.get(get_server_base() + 'groups/new') b.find_element_by_name('group_name').send_keys('my_ldap_group') b.find_element_by_name('display_name').send_keys('My LDAP group') self.assertEquals(b.find_element_by_name('ldap').is_selected(), False) b.find_element_by_name('ldap').click() b.find_element_by_id('Group').submit() self.assertEquals(b.find_element_by_class_name('flash').text, 'OK') with session.begin(): group = Group.by_name(u'my_ldap_group') self.assertEquals(group.ldap, True) self.assertEquals(group.users, [User.by_user_name(u'my_ldap_user')])
def test_loaned_not_free(self): with session.begin(): lc1 = data_setup.create_labcontroller() self.system_one.lab_controller = lc1 b = self.browser b.get(get_server_base() + 'free') self.assertEquals(b.title, 'Free Systems') check_system_search_results(b, present=[], absent=[self.system_one]) with session.begin(): self.system_one.loaned = User.by_user_name(data_setup.ADMIN_USER) b.get(get_server_base() + 'free') self.assertEquals(b.title, 'Free Systems') check_system_search_results(b, present=[self.system_one])
def test_double_reserve(self): with session.begin(): user = data_setup.create_user(password=u'password') system = data_setup.create_system( owner=User.by_user_name(data_setup.ADMIN_USER), status=u'Manual', shared=True) self.assert_(system.user is None) server = self.get_server() server.auth.login_password(user.user_name, 'password') server.systems.reserve(system.fqdn) try: server.systems.reserve(system.fqdn) self.fail('should raise') except xmlrpclib.Fault, e: self.assert_('has already reserved system' in e.faultString)
def remove_submission_delegate_by_name(self, delegate_name, service=u'XMLRPC'): user = identity.current.user try: submission_delegate = User.by_user_name(delegate_name) except NoResultFound: raise BX(_(u'%s is not a valid user name' % delegate_name)) try: user.remove_submission_delegate(submission_delegate, service=service) except ValueError: raise BX(_(u'%s is not a submission delegate of %s' % \ (delegate_name, user))) return delegate_name
def test_double_release(self): with session.begin(): system = data_setup.create_system( owner=User.by_user_name(data_setup.ADMIN_USER), status=u'Manual', shared=True) user = data_setup.create_user(password=u'password') system.reserve_manually(service=u'testdata', user=user) server = self.get_server() server.auth.login_password(user.user_name, 'password') server.systems.release(system.fqdn) try: server.systems.release(system.fqdn) self.fail('should raise') except xmlrpclib.Fault, e: self.assert_('System %s is not currently reserved' % system.fqdn in e.faultString)
def test_cannot_release_when_not_current_user(self): with session.begin(): system = data_setup.create_system( owner=User.by_user_name(data_setup.ADMIN_USER), status=u'Manual', shared=True) user = data_setup.create_user(password=u'password') other_user = data_setup.create_user() system.reserve_manually(service=u'testdata', user=other_user) server = self.get_server() server.auth.login_password(user.user_name, 'password') try: server.systems.release(system.fqdn) self.fail('should raise') except xmlrpclib.Fault, e: self.assertIn('cannot unreserve system', e.faultString)
def get_user(username): """ Returns details about a Beaker user account. :param username: The user's username. """ user = User.by_user_name(username) if user is None: raise NotFound404('User %s does not exist' % username) attributes = user_full_json(user) if request_wants_json(): return jsonify(attributes) return render_tg_template('bkr.server.templates.user_edit_form', { 'attributes': attributes, 'url': user.href, })
def setUp(self): self.lab_controller = data_setup.create_labcontroller() self.distro_tree = data_setup.create_distro_tree(osmajor=u'Fedora20', arch=u'i386', lab_controllers=[self.lab_controller]) self.usable_system = data_setup.create_system(arch=u'i386', owner=User.by_user_name(data_setup.ADMIN_USER), status=u'Manual', shared=True) data_setup.configure_system_power(self.usable_system, power_type=u'drac', address=u'nowhere.example.com', user=u'teh_powz0r', password=u'onoffonoff', power_id=u'asdf') self.usable_system.lab_controller = self.lab_controller self.usable_system.user = data_setup.create_user(password=u'password') self.usable_system.provisions[self.distro_tree.arch] = Provision( arch=self.distro_tree.arch, kernel_options='ksdevice=eth0 console=ttyS0') self.server = self.get_server()
def save_system_access_policy(fqdn): system = _get_system_by_FQDN(fqdn) if not system.can_edit_policy(identity.current.user): raise Forbidden403('Cannot edit system policy') if system.custom_access_policy: policy = system.custom_access_policy else: policy = system.custom_access_policy = SystemAccessPolicy() data = read_json_request(request) # Figure out what is added, what is removed. # Rules are immutable, so if it has an id it is unchanged, # if it has no id it is new. kept_rule_ids = frozenset(r['id'] for r in data['rules'] if 'id' in r) removed = [] for old_rule in policy.rules: if old_rule.id not in kept_rule_ids: removed.append(old_rule) for old_rule in removed: system.record_activity(user=identity.current.user, service=u'HTTP', field=u'Access Policy Rule', action=u'Removed', old=repr(old_rule)) policy.rules.remove(old_rule) for rule in data['rules']: if 'id' not in rule: if rule['user']: user = User.by_user_name(rule['user']) if user is None: raise BadRequest400('No such user %r' % rule['user']) else: user = None try: group = Group.by_name(rule['group']) if rule['group'] else None except NoResultFound: raise BadRequest400('No such group %r' % rule['group']) permission = SystemPermission.from_string(rule['permission']) new_rule = policy.add_rule(user=user, group=group, everybody=rule['everybody'], permission=permission) system.record_activity(user=identity.current.user, service=u'HTTP', field=u'Access Policy Rule', action=u'Added', new=repr(new_rule)) return jsonify(policy.__json__())
def test_ldap_login_with_existing_email_address(self): # Logging in with an LDAP account would fail when there was another # existing account with the same e-mail address, since Beaker's # database schema was enforcing uniqueness. # 'bz1095010_user' is defined in bkr/inttest/ldap-data.ldif # with this e-mail address: email = u'*****@*****.**' with session.begin(): data_setup.create_user(user_name=u'bz1095010_other', email_address=email) b = self.browser login(b, u'bz1095010_user', u'password') b.find_element_by_xpath('//title[text()="Systems"]') with session.begin(): newly_created_user = User.by_user_name(u'bz1095010_user') self.assert_(newly_created_user is not None, 'bz1095010_user should have been created from LDAP')
def test_recipe_activity(self): with session.begin(): recipe = data_setup.create_recipe(whiteboard=u'oldwhiteboard') data_setup.create_job_for_recipes([recipe]) act = recipe.record_activity(service=u'testdata', user=User.by_user_name( data_setup.ADMIN_USER), action=u'Changed', field=u'Whiteboard', old=recipe.whiteboard, new=u'newwhiteboard') b = self.browser b.get(get_server_base() + 'activity/') b.find_element_by_class_name('search-query'). \ send_keys('field_name:Whiteboard new_value:newwhiteboard') b.find_element_by_class_name('grid-filter').submit() check_activity_search_results(b, present=[act])
def delete_ssh_public_key(username, id): """ Deletes a public SSH public key belonging to the given user account. :param username: The user's username. :param id: Database id of the SSH public key to be deleted. """ user = User.by_user_name(username) if user is None: raise NotFound404('User %s does not exist' % username) if not user.can_edit(identity.current.user): raise Forbidden403('Cannot edit user %s' % user) matching_keys = [k for k in user.sshpubkeys if k.id == id] if not matching_keys: raise NotFound404('SSH public key id %s does not belong to user %s' % (id, user)) key = matching_keys[0] session.delete(key) return '', 204
def validate_python(self, form_fields, state): user_id = form_fields['user_id'] user_name = form_fields['user_name'] existing_user = User.by_user_name(user_name) try: if not user_id: # New user if existing_user: # with a duplicate name raise ValueError else: if existing_user: current_user = User.by_id(user_id) if current_user != existing_user: raise ValueError except ValueError: error = {'user_name': self.message('not_unique', state)} raise Invalid('Login name is not unique', form_fields, state, error_dict=error)
def add_access_policy_rule(pool_name): """ Adds a new rule to the access policy for a system pool. Each rule in the policy grants a permission to a single user, a group of users, or to everybody. See :ref:`system-access-policies-api` for a description of the expected JSON parameters. :param pool_name: System pool's name. """ pool = _get_pool_by_name(pool_name) if not pool.can_edit_policy(identity.current.user): raise Forbidden403('Cannot edit system pool policy') policy = pool.access_policy rule = read_json_request(request) if rule.get('user', None): user = User.by_user_name(rule['user']) if not user: raise BadRequest400("User '%s' does not exist" % rule['user']) else: user = None if rule.get('group', None): try: group = Group.by_name(rule['group']) except NoResultFound: raise BadRequest400("Group '%s' does not exist" % rule['group']) else: group = None try: permission = SystemPermission.from_string(rule['permission']) except ValueError: raise BadRequest400('Invalid permission') new_rule = policy.add_rule(user=user, group=group, everybody=rule['everybody'], permission=permission) pool.record_activity(user=identity.current.user, service=u'HTTP', field=u'Access Policy Rule', action=u'Added', new=repr(new_rule)) return '', 204
def _get_owner(data): if data is None: data = {} user_name = data.get('user_name') group_name = data.get('group_name') if user_name and group_name: raise Forbidden403('System pool can have either an user or a group as owner') if user_name: owner = User.by_user_name(user_name) if owner is None: raise BadRequest400('No such user %s' % user_name) owner_type = 'user' if group_name: try: owner = Group.by_name(group_name) except NoResultFound: raise BadRequest400('No such group %r' % group_name) owner_type = 'group' return owner, owner_type