def delete_system_access_policy_rules(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() # We expect some query string args specifying which rules should be # deleted. If those are not present, it's "Method Not Allowed". query = SystemAccessPolicyRule.query.filter( SystemAccessPolicyRule.policy == policy) if 'permission' in request.args: query = query.filter( SystemAccessPolicyRule.permission.in_( request.args.getlist('permission', type=SystemPermission.from_string))) else: raise MethodNotAllowed405 if 'user' in request.args: query = query.join(SystemAccessPolicyRule.user)\ .filter(User.user_name.in_(request.args.getlist('user'))) elif 'group' in request.args: query = query.join(SystemAccessPolicyRule.group)\ .filter(Group.group_name.in_(request.args.getlist('group'))) elif 'everybody' in request.args: query = query.filter(SystemAccessPolicyRule.everybody) else: raise MethodNotAllowed405 for rule in query: rule.record_deletion(service=u'HTTP') session.delete(rule) return '', 204
def create_pool(): """ Creates a new system pool in Beaker. The request must be :mimetype:`application/x-www-form-urlencoded` or :mimetype:`application/json`. :jsonparam string name: Name for the system pool. :jsonparam string description: Description of the system pool. :jsonparam object owner: JSON object containing a ``user_name`` key or ``group_name`` key identifying the owner for the system pool. :status 201: The system pool was successfully created. """ owner = None description = None u = identity.current.user if request.json: if 'name' not in request.json: raise BadRequest400('Missing pool name key') new_name = request.json['name'] if 'owner' in request.json: owner = request.json['owner'] if 'description' in request.json: description = request.json['description'] elif request.form: if 'name' not in request.form: raise BadRequest400('Missing pool name parameter') new_name = request.form['name'] if 'owner' in request.form: owner = request.form['owner'] if 'description' in request.form: description = request.form['description'] else: raise UnsupportedMediaType415 with convert_internal_errors(): if SystemPool.query.filter(SystemPool.name == new_name).count() != 0: raise Conflict409('System pool with name %r already exists' % new_name) pool = SystemPool(name=new_name, description=description) session.add(pool) if owner: owner, owner_type = _get_owner(owner) if owner_type == 'user': pool.owning_user = owner else: pool.owning_group = owner else: pool.owning_user = u # new systems pool are visible to everybody by default pool.access_policy = SystemAccessPolicy() pool.access_policy.add_rule(SystemPermission.view, everybody=True) pool.record_activity(user=u, service=u'HTTP', action=u'Created', field=u'Pool', new=unicode(pool)) response = jsonify(pool.__json__()) response.status_code = 201 response.headers.add('Location', absolute_url(pool.href)) return response
def add_system(): # We accept JSON or form-encoded for convenience if request.json: if 'fqdn' not in request.json: raise BadRequest400('Missing fqdn key') new_fqdn = request.json['fqdn'] elif request.form: if 'fqdn' not in request.form: raise BadRequest400('Missing fqdn parameter') new_fqdn = request.form['fqdn'] else: raise UnsupportedMediaType415 with convert_internal_errors(): if System.query.filter(System.fqdn == new_fqdn).count() != 0: raise Conflict409('System with fqdn %r already exists' % new_fqdn) system = System(fqdn=new_fqdn, owner=identity.current.user) session.add(system) # new systems are visible to everybody by default system.custom_access_policy = SystemAccessPolicy() system.custom_access_policy.add_rule(SystemPermission.view, everybody=True) # XXX this should be 201 with Location: /systems/FQDN/ but 302 is more # convenient because it lets us use a traditional browser form without AJAX # handling, and for now we're redirecting to /view/FQDN until that is moved # to /systems/FQDN/ return flask_redirect(url(u'/view/%s#essentials' % system.fqdn))
def system_count_metrics(): _system_count_metrics_for_query('all', System.query) _system_count_metrics_for_query('shared', System.query .outerjoin(System.active_access_policy) .filter(SystemAccessPolicy.grants_everybody(SystemPermission.reserve))) _system_count_metrics_for_query_grouped('by_arch', Arch.arch, System.query.join(System.arch)) _system_count_metrics_for_query_grouped('by_lab', LabController.fqdn, System.query.join(System.lab_controller))
def system_count_metrics(): _system_count_metrics_for_query('all', System.query) _system_count_metrics_for_query('shared', System.query .outerjoin(System.active_access_policy) .filter(SystemAccessPolicy.grants_everybody(SystemPermission.reserve))) _system_count_metrics_for_query_grouped('by_arch', Arch.arch, System.query.join(System.arch)) _system_count_metrics_for_query_grouped('by_lab', LabController.fqdn, System.query.join(System.lab_controller))
def create_system(arch=u'i386', type=SystemType.machine, status=SystemStatus.automated, owner=None, fqdn=None, shared=True, exclude_osmajor=[], exclude_osversion=[], hypervisor=None, kernel_type=None, date_added=None, return_existing=False, private=False, with_power=True, **kw): if owner is None: owner = create_user() if fqdn is None: fqdn = unique_name(u'system%s.testdata') if System.query.filter(System.fqdn == fqdn).count(): if return_existing: system = System.query.filter(System.fqdn == fqdn).first() for property, value in kw.iteritems(): setattr(system, property, value) else: raise ValueError('Attempted to create duplicate system %s' % fqdn) else: system = System(fqdn=fqdn,type=type, owner=owner, status=status, **kw) session.add(system) if date_added is not None: system.date_added = date_added system.custom_access_policy = SystemAccessPolicy() if not private: system.custom_access_policy.add_rule(SystemPermission.view, everybody=True) if shared: system.custom_access_policy.add_rule( permission=SystemPermission.reserve, everybody=True) if isinstance(arch, list): for a in arch: system.arch.append(Arch.by_name(a)) system.excluded_osmajor.extend(ExcludeOSMajor(arch=Arch.by_name(a), osmajor=osmajor) for osmajor in exclude_osmajor) system.excluded_osversion.extend(ExcludeOSVersion(arch=Arch.by_name(a), osversion=osversion) for osversion in exclude_osversion) else: system.arch.append(Arch.by_name(arch)) system.excluded_osmajor.extend(ExcludeOSMajor(arch=Arch.by_name(arch), osmajor=osmajor) for osmajor in exclude_osmajor) system.excluded_osversion.extend(ExcludeOSVersion(arch=Arch.by_name(arch), osversion=osversion) for osversion in exclude_osversion) if with_power: configure_system_power(system) if hypervisor: system.hypervisor = Hypervisor.by_name(hypervisor) if kernel_type: system.kernel_type = KernelType.by_name(kernel_type) system.date_modified = datetime.datetime.utcnow() log.debug('Created system %r', system) return system
def test_group_has_access_policy_rule_remove(self): with session.begin(): user = data_setup.create_user(password='******') system = data_setup.create_system(owner=user, shared=False) system.custom_access_policy = SystemAccessPolicy() group = data_setup.create_group(owner=user) p = system.custom_access_policy p.add_rule(permission=SystemPermission.edit_system, group=group) p.add_rule(permission=SystemPermission.edit_policy, group=group) b = self.browser login(b, user=user.user_name, password='******') # check current rules self.assertEquals(len(p.rules), 2) self.assert_(p.rules[0].user is None) self.assertEquals(p.rules[0].group, group) self.assert_(p.rules[1].user is None) self.assertEquals(p.rules[1].group, group) # save current rules for later use access_policy_rule_1 = repr(p.rules[0]) access_policy_rule_2 = repr(p.rules[1]) # delete the group b.get(get_server_base() + 'groups/mine') delete_and_confirm(b, "//tr[td/a[normalize-space(text())='%s']]" % group.group_name, delete_text='Delete Group') self.assertEqual( b.find_element_by_class_name('flash').text, '%s deleted' % group.display_name) with session.begin(): session.expire_all() # check if the access policy rule has been removed self.assertEquals(len(p.rules), 0) # Check whether the rules deleted have been recorded in the # Activity table self.assertEquals(system.activity[0].field_name, u'Access Policy Rule') self.assertEquals(system.activity[0].action, u'Removed') self.assertEquals(system.activity[0].old_value, access_policy_rule_2) self.assertEquals(system.activity[1].field_name, u'Access Policy Rule') self.assertEquals(system.activity[1].action, u'Removed') self.assertEquals(system.activity[1].old_value, access_policy_rule_1)
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 create_system_pool(name=None, description=u'A system Pool', owning_group=None, owning_user=None, systems=[]): if owning_group and owning_user: raise ValueError('Must supply either an owning user or an owning group') if not owning_group and not owning_user: owning_user = create_user() if name is None: name = unique_name(u'test-system-pool-%s') pool = SystemPool(name=name, description=description, owning_group=owning_group, owning_user=owning_user, systems=systems) pool.access_policy = SystemAccessPolicy() pool.access_policy.add_rule(SystemPermission.view, everybody=True) session.add(pool) log.debug('Created System Pool %s', pool.name) return pool
def get_system_access_policy(fqdn): # XXX need to consolidate this with SystemAccessPolicy.__json__ # (maybe get rid of filtering here and implement it client side instead) system = _get_system_by_FQDN(fqdn) policy = system.custom_access_policy # For now, we don't distinguish between an empty policy and an absent one. if not policy: return jsonify(SystemAccessPolicy.empty_json()) # filtering, if any if len(request.args.keys()) > 1: raise BadRequest400('Only one filtering criteria allowd') query = SystemAccessPolicyRule.query.\ filter(SystemAccessPolicyRule.policy == policy) if request.args.get('mine'): if not identity.current.user: raise Unauthorised401( "The 'mine' access policy filter requires authentication") query = query.join(SystemAccessPolicyRule.user)\ .filter(User.user_name.in_([identity.current.user.user_name])) elif request.args.get('user', None): query = query.join(SystemAccessPolicyRule.user)\ .filter(User.user_name.in_(request.args.getlist('user'))) elif request.args.get('group', None): query = query.join(SystemAccessPolicyRule.group)\ .filter(Group.group_name.in_(request.args.getlist('group'))) return jsonify({ 'id': policy.id, 'rules': [{ 'id': rule.id, 'user': rule.user.user_name if rule.user else None, 'group': rule.group.group_name if rule.group else None, 'everybody': rule.everybody, 'permission': unicode(rule.permission) } for rule in query], 'possible_permissions': [{ 'value': unicode(permission), 'label': unicode(permission.label) } for permission in SystemPermission], })
def get_system_access_policy(fqdn): # XXX need to consolidate this with SystemAccessPolicy.__json__ # (maybe get rid of filtering here and implement it client side instead) system = _get_system_by_FQDN(fqdn) policy = system.custom_access_policy # For now, we don't distinguish between an empty policy and an absent one. if not policy: return jsonify(SystemAccessPolicy.empty_json()) # filtering, if any if len(request.args.keys()) > 1: raise BadRequest400('Only one filtering criteria allowd') query = SystemAccessPolicyRule.query.\ filter(SystemAccessPolicyRule.policy == policy) if request.args.get('mine'): if not identity.current.user: raise Unauthorised401("The 'mine' access policy filter requires authentication") query = query.join(SystemAccessPolicyRule.user)\ .filter(User.user_name.in_([identity.current.user.user_name])) elif request.args.get('user', None): query = query.join(SystemAccessPolicyRule.user)\ .filter(User.user_name.in_(request.args.getlist('user'))) elif request.args.get('group', None): query = query.join(SystemAccessPolicyRule.group)\ .filter(Group.group_name.in_(request.args.getlist('group'))) return jsonify({ 'id': policy.id, 'rules': [ {'id': rule.id, 'user': rule.user.user_name if rule.user else None, 'group': rule.group.group_name if rule.group else None, 'everybody': rule.everybody, 'permission': unicode(rule.permission)} for rule in query], 'possible_permissions': [ {'value': unicode(permission), 'label': unicode(permission.label)} for permission in SystemPermission], })
def _import_row(self, data, log): if data['csv_type'] in system_types and ('fqdn' in data or 'id' in data): if data.get('id', None): try: system = System.query.filter(System.id == data['id']).one() except InvalidRequestError as e: raise ValueError('Non-existent system id') else: try: system = System.query.filter( System.fqdn == data['fqdn']).one() except InvalidRequestError: # Create new system with some defaults # Assume the system is broken until proven otherwise. # Also assumes its a machine. we have to pick something system = System(fqdn=data['fqdn'], owner=identity.current.user, type=SystemType.machine, status=SystemStatus.broken) session.add(system) # new systems are visible to everybody by default system.custom_access_policy = SystemAccessPolicy() system.custom_access_policy.add_rule(SystemPermission.view, everybody=True) if not system.can_edit(identity.current.user): raise ValueError('You are not the owner of %s' % system.fqdn) # we change the FQDN only when a valid system id is supplied if not data.get('id', None): data.pop('fqdn') self.from_csv(system, data, log) elif data['csv_type'] == 'user_group' and 'user' in data: user = User.by_user_name(data['user']) if user is None: raise ValueError('%s is not a valid user' % data['user']) CSV_GroupUser.from_csv(user, data, log) else: raise ValueError('Invalid csv_type %s or missing required fields' % data['csv_type'])
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 create_system(arch=u'i386', type=SystemType.machine, status=None, owner=None, fqdn=None, shared=True, exclude_osmajor=[], exclude_osversion=[], hypervisor=None, kernel_type=None, date_added=None, return_existing=False, private=False, with_power=True, lab_controller=None, **kw): if owner is None: owner = create_user() if fqdn is None: name = get_test_name() fqdn = unique_name(u'system%s.' + name.replace('_', '.')) if status is None: status = SystemStatus.automated if lab_controller is not None else SystemStatus.manual if System.query.filter(System.fqdn == fqdn).count(): if return_existing: system = System.query.filter(System.fqdn == fqdn).first() for property, value in kw.iteritems(): setattr(system, property, value) else: raise ValueError('Attempted to create duplicate system %s' % fqdn) else: system = System(fqdn=fqdn,type=type, owner=owner, status=status, lab_controller=lab_controller, **kw) session.add(system) # Normally the system would be "idle" when first added, and then becomes # "pending" when a user flips it to Automated status. But for simplicity in # the tests, we will just force it back to "idle" here since we know we # just created it. This lets a subsequent call to the scheduler pick it up # immediately, without going through an iteration of # schedule_pending_systems() first. system.scheduler_status = SystemSchedulerStatus.idle if date_added is not None: system.date_added = date_added system.custom_access_policy = SystemAccessPolicy() if not private: system.custom_access_policy.add_rule(SystemPermission.view, everybody=True) if shared: system.custom_access_policy.add_rule( permission=SystemPermission.reserve, everybody=True) if isinstance(arch, list): for a in arch: system.arch.append(Arch.by_name(a)) system.excluded_osmajor.extend(ExcludeOSMajor(arch=Arch.by_name(a), osmajor=osmajor) for osmajor in exclude_osmajor) system.excluded_osversion.extend(ExcludeOSVersion(arch=Arch.by_name(a), osversion=osversion) for osversion in exclude_osversion) elif arch is not None: system.arch.append(Arch.by_name(arch)) system.excluded_osmajor.extend(ExcludeOSMajor(arch=Arch.by_name(arch), osmajor=osmajor) for osmajor in exclude_osmajor) system.excluded_osversion.extend(ExcludeOSVersion(arch=Arch.by_name(arch), osversion=osversion) for osversion in exclude_osversion) if with_power: configure_system_power(system) if hypervisor: system.hypervisor = Hypervisor.by_name(hypervisor) if kernel_type: system.kernel_type = KernelType.by_name(kernel_type) system.date_modified = datetime.datetime.utcnow() log.debug('Created system %r', system) return system
def test_group_has_access_policy_rule_remove(self): with session.begin(): user = data_setup.create_user(password='******') system = data_setup.create_system(owner=user, shared=False) system.custom_access_policy = SystemAccessPolicy() group = data_setup.create_group(owner=user) p = system.custom_access_policy p.add_rule(permission=SystemPermission.edit_system, group=group) p.add_rule(permission=SystemPermission.edit_policy, group=group) b = self.browser login(b, user=user.user_name, password='******') # check current rules self.assertEquals(len(p.rules), 2) self.assert_(p.rules[0].user is None) self.assertEquals(p.rules[0].group, group) self.assert_(p.rules[1].user is None) self.assertEquals(p.rules[1].group, group) # save current rules for later use access_policy_rule_1 = repr(p.rules[0]) access_policy_rule_2 = repr(p.rules[1]) # delete the group b.get(get_server_base() + 'groups/mine') delete_and_confirm(b, "//tr[td/a[normalize-space(text())='%s']]" % group.group_name, delete_text='Delete Group') self.assertEqual( b.find_element_by_class_name('flash').text, '%s deleted' % group.display_name) # check if the access policy rule has been removed session.refresh(p) self.assertEquals(len(p.rules), 0) # Check whether the rules deleted have been recorded in the # Activity table b.get(get_server_base() + 'activity/') b.find_element_by_link_text('Show Search Options').click() b.find_element_by_xpath( "//select[@id='activitysearch_0_table']/option[@value='Action']" ).click() b.find_element_by_xpath( "//select[@id='activitysearch_0_operation']/option[@value='is']" ).click() b.find_element_by_xpath( "//input[@id='activitysearch_0_value']").send_keys('Removed') b.find_element_by_link_text('Add').click() b.find_element_by_xpath( "//select[@id='activitysearch_1_table']/option[@value='Property']" ).click() b.find_element_by_xpath( "//select[@id='activitysearch_1_operation']/option[@value='is']" ).click() b.find_element_by_xpath("//input[@id='activitysearch_1_value']" ).send_keys('Access Policy Rule') b.find_element_by_id('searchform').submit() self.assert_( is_activity_row_present(b, via='WEBUI', action='Removed', object_='System: %s' % system.fqdn, property_='Access Policy Rule', old_value=access_policy_rule_1, new_value='')) self.assert_( is_activity_row_present(b, via='WEBUI', action='Removed', object_='System: %s' % system.fqdn, property_='Access Policy Rule', old_value=access_policy_rule_2, new_value=''))