def test_sa_pubkeys(session, users, http_client, base_url): user = users['*****@*****.**'] # Add account create_role_user(session, user, '*****@*****.**', 'Hi', 'canjoin') u = User.get(session, name="*****@*****.**") g = Group.get(session, name="*****@*****.**") assert u is not None assert g is not None assert is_role_user(session, user=u) assert is_role_user(session, group=g) assert get_role_user(session, user=u).group.id == g.id assert get_role_user(session, group=g).user.id == u.id assert not is_role_user(session, user=user) assert not is_role_user(session, group=Group.get(session, name="team-sre")) assert not get_public_keys_of_user(session, user.id) with pytest.raises(HTTPError): # add it fe_url = url(base_url, '/users/{}/public-key/add'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({'public_key': SSH_KEY_1}), headers={'X-Grouper-User': "******"}) # add it fe_url = url(base_url, '/users/{}/public-key/add'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({'public_key': SSH_KEY_1}), headers={'X-Grouper-User': user.username}) assert resp.code == 200 # add bad key -- shouldn't add fe_url = url(base_url, '/users/{}/public-key/add'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({'public_key': SSH_KEY_BAD}), headers={'X-Grouper-User': user.username}) assert resp.code == 200 sa = User.get(session, name="*****@*****.**") keys = get_public_keys_of_user(session, sa.id) assert len(keys) == 1 assert keys[0].public_key == SSH_KEY_1 with pytest.raises(HTTPError): # delete it fe_url = url(base_url, '/users/{}/public-key/{}/delete'.format("*****@*****.**", keys[0].id)) resp = yield http_client.fetch(fe_url, method="POST", body='', headers={'X-Grouper-User': "******"}) # delete it fe_url = url(base_url, '/users/{}/public-key/{}/delete'.format("*****@*****.**", keys[0].id)) resp = yield http_client.fetch(fe_url, method="POST", body='', headers={'X-Grouper-User': user.username}) assert resp.code == 200 sa = User.get(session, name="*****@*****.**") assert not get_public_keys_of_user(session, sa.id)
def test_sa_tokens(session, users, http_client, base_url): user = users['*****@*****.**'] # Add account create_role_user(session, user, '*****@*****.**', 'Hi', 'canjoin') u = User.get(session, name="*****@*****.**") g = Group.get(session, name="*****@*****.**") assert u is not None assert g is not None assert is_role_user(session, user=u) assert is_role_user(session, group=g) assert get_role_user(session, user=u).group.id == g.id assert get_role_user(session, group=g).user.id == u.id assert not is_role_user(session, user=user) assert not is_role_user(session, group=Group.get(session, name="team-sre")) with pytest.raises(HTTPError): # Add token fe_url = url(base_url, '/users/{}/tokens/add'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({'name': 'myDHDToken'}), headers={'X-Grouper-User': "******"}) # Add token fe_url = url(base_url, '/users/{}/tokens/add'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({'name': 'myDHDToken'}), headers={'X-Grouper-User': user.username}) assert resp.code == 200 # Verify add fe_url = url(base_url, '/users/{}'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="GET", headers={'X-Grouper-User': user.username}) assert resp.code == 200 assert "Added token: myDHDToken" in resp.body with pytest.raises(HTTPError): # Disable token fe_url = url(base_url, '/users/{}/tokens/1/disable'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body="", headers={'X-Grouper-User': "******"}) # Disable token fe_url = url(base_url, '/users/{}/tokens/1/disable'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body="", headers={'X-Grouper-User': user.username}) assert resp.code == 200 # Verify disable fe_url = url(base_url, '/users/{}'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="GET", headers={'X-Grouper-User': user.username}) assert resp.code == 200 assert "Disabled token: myDHDToken" in resp.body
def post(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if not user_can_manage_group(self.session, group, self.current_user): return self.forbidden() form = GroupRemoveForm(self.request.arguments) if not form.validate(): return self.send_error(status_code=400) member_type, member_name = form.data["member_type"], form.data[ "member"] members = group.my_members() if not members.get((member_type.capitalize(), member_name), None): return self.notfound() removed_member = get_user_or_group(self.session, member_name, user_or_group=member_type) if self.current_user == removed_member: return self.send_error( status_code=400, reason="Can't remove yourself. Leave group instead.") role_user = is_role_user(self.session, group=group) if (role_user and get_role_user(self.session, group=group).user.name == removed_member.name): return self.send_error( status_code=400, reason= "Can't remove a service account user from the service account group." ) try: group.revoke_member(self.current_user, removed_member, "Removed by owner/np-owner/manager") AuditLog.log(self.session, self.current_user.id, 'remove_from_group', '{} was removed from the group.'.format( removed_member.name), on_group_id=group.id, on_user_id=removed_member.id) except PluginRejectedGroupMembershipUpdate as e: alert = Alert("danger", str(e)) if role_user: return self.redirect("/service/{}".format(group.name), alerts=[alert]) else: return self.redirect("/groups/{}".format(group.name), alerts=[alert]) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def post(self, *args: Any, **kwargs: Any) -> None: name = self.get_path_argument("name") group = Group.get(self.session, name=name) if not group: return self.notfound() members = group.my_members() if not user_role(self.current_user, members) in ("owner", "np-owner"): return self.forbidden() # Enabling and disabling service accounts via the group endpoints is forbidden # because we need the preserve_membership data that is only available via the # UserEnable form. if is_role_user(self.session, group=group): return self.forbidden() group.enable() self.session.commit() AuditLog.log( self.session, self.current_user.id, "enable_group", "Enabled group.", on_group_id=group.id, ) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def test_basic_request(graph, groups, permissions, session, standard_graph, users): # noqa: F811 group_sre = groups["team-sre"] group_not_sre = [g for name, g in groups.items() if name != "team-sre"] assert not any([ get_requests_by_group(session, group, status="pending").all() for group in groups.values() if not is_role_user(session, group=group) ]), "no group should start with pending requests" group_sre.add_member(users["*****@*****.**"], users["*****@*****.**"], reason="for the lulz") session.commit() request_not_sre = [ get_requests_by_group(session, group, status="pending").all() for group in group_not_sre ] assert not any( request_not_sre), "only affected group should show pending requests" request_sre = get_requests_by_group(session, group_sre, status="pending").all() assert len(request_sre) == 1, "affected group should have request" request = session.query(Request).filter_by(id=request_sre[0].id).scalar() request.update_status(users["*****@*****.**"], "actioned", "for being a good person") session.commit() assert not any([ get_requests_by_group(session, group, status="pending").all() for group in groups.values() ]), "no group should have requests after being actioned"
def post(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() members = group.my_members() if not user_role(self.current_user, members) in ("owner", "np-owner"): return self.forbidden() # Enabling and disabling service accounts via the group endpoints is forbidden # because we need the preserve_membership data that is only available via the # UserEnable form. if is_role_user(self.session, group=group): return self.forbidden() group.disable() self.session.commit() AuditLog.log(self.session, self.current_user.id, 'disable_group', 'Disabled group.', on_group_id=group.id) if group.audit: # complete the audit group.audit.complete = True self.session.commit() AuditLog.log(self.session, self.current_user.id, 'complete_audit', 'Disabling group completes group audit.', on_group_id=group.id) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def test_add_role_user(session, users, http_client, base_url): user = users['*****@*****.**'] # Add account create_role_user(session, user, '*****@*****.**', 'Hi', 'canjoin') u = User.get(session, name="*****@*****.**") g = Group.get(session, name="*****@*****.**") assert u is not None assert g is not None assert is_role_user(session, user=u) assert is_role_user(session, group=g) assert get_role_user(session, user=u).group.id == g.id assert get_role_user(session, group=g).user.id == u.id assert not is_role_user(session, user=user) assert not is_role_user(session, group=Group.get(session, name="team-sre"))
def test_add_role_user(session, users, http_client, base_url): # noqa: F811 user = users["*****@*****.**"] # Add account create_role_user(session, user, "*****@*****.**", "Hi", "canjoin") u = User.get(session, name="*****@*****.**") g = Group.get(session, name="*****@*****.**") assert u is not None assert g is not None assert is_role_user(session, user=u) assert is_role_user(session, group=g) assert get_role_user(session, user=u).group.id == g.id assert get_role_user(session, group=g).user.id == u.id assert not is_role_user(session, user=user) assert not is_role_user(session, group=Group.get(session, name="team-sre"))
def post(self, *args: Any, **kwargs: Any) -> None: name = self.get_path_argument("name") group = Group.get(self.session, name=name) if not group: return self.notfound() if not user_can_manage_group(self.session, group, self.current_user): return self.forbidden() form = GroupEditForm(self.request.arguments, obj=group) if not form.validate(): return self.render("group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors)) new_name = form.data["groupname"] renamed = group.groupname != new_name if renamed and is_role_user(self.session, group=group): form.groupname.errors.append( "You cannot change the name of service account groups") return self.render("group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors)) if renamed and Group.get(self.session, name=new_name): message = f"A group named '{new_name}' already exists (possibly disabled)" form.groupname.errors.append(message) return self.render("group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors)) group.groupname = new_name group.email_address = form.data["email_address"] group.description = form.data["description"] group.canjoin = form.data["canjoin"] group.auto_expire = form.data["auto_expire"] group.require_clickthru_tojoin = form.data["require_clickthru_tojoin"] Counter.incr(self.session, "updates") self.session.commit() AuditLog.log(self.session, self.current_user.id, "edit_group", "Edited group.", on_group_id=group.id) url = f"/groups/{group.name}" if renamed: url += "?refresh=yes" self.redirect(url)
def post(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if not user_can_manage_group(self.session, group, self.current_user): return self.forbidden() form = GroupRemoveForm(self.request.arguments) if not form.validate(): return self.send_error(status_code=400) member_type, member_name = form.data["member_type"], form.data["member"] members = group.my_members() if not members.get((member_type.capitalize(), member_name), None): return self.notfound() removed_member = get_user_or_group(self.session, member_name, user_or_group=member_type) if self.current_user == removed_member: return self.send_error( status_code=400, reason="Can't remove yourself. Leave group instead." ) role_user = is_role_user(self.session, group=group) if (role_user and get_role_user(self.session, group=group).user.name == removed_member.name): return self.send_error( status_code=400, reason="Can't remove a service account user from the service account group." ) try: group.revoke_member( self.current_user, removed_member, "Removed by owner/np-owner/manager" ) AuditLog.log(self.session, self.current_user.id, 'remove_from_group', '{} was removed from the group.'.format(removed_member.name), on_group_id=group.id, on_user_id=removed_member.id) except PluginRejectedGroupMembershipUpdate as e: alert = Alert("danger", str(e)) if role_user: return self.redirect("/service/{}".format(group.name), alerts=[alert]) else: return self.redirect("/groups/{}".format(group.name), alerts=[alert]) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def test_add_role_user(session, users, http_client, base_url): user = users['*****@*****.**'] # Add account fe_url = url(base_url, '/service/create') resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({ 'name': '*****@*****.**', "description": "Hi", "canjoin": "canjoin" }), headers={'X-Grouper-User': user.username}) assert resp.code == 200 assert User.get(session, name="*****@*****.**") is None assert Group.get(session, name="*****@*****.**") is None # Add account fe_url = url(base_url, '/service/create') resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({ 'name': '*****@*****.**', "description": "Hi", "canjoin": "canjoin" }), headers={'X-Grouper-User': user.username}) assert resp.code == 200 u = User.get(session, name="*****@*****.**") g = Group.get(session, name="*****@*****.**") assert u is not None assert g is not None assert is_role_user(session, user=u) assert is_role_user(session, group=g) assert get_role_user(session, user=u).group.id == g.id assert get_role_user(session, group=g).user.id == u.id assert not is_role_user(session, user=user) assert not is_role_user(session, group=Group.get(session, name="team-sre"))
def get(self, group_id=None, name=None): self.handle_refresh() group = Group.get(self.session, group_id, name) if not group: return self.notfound() if is_role_user(self.session, group=group): return self.redirect("/service/{}".format(group.groupname)) self.render( "group.html", group=group, **get_group_view_template_vars(self.session, self.current_user, group, self.graph) )
def get(self, group_id=None, name=None): self.handle_refresh() group = Group.get(self.session, group_id, name) if not group: return self.notfound() if is_role_user(self.session, group=group): return self.redirect("/service/{}".format(group.groupname)) self.render("group.html", group=group, **get_group_view_template_vars(self.session, self.current_user, group, self.graph))
def post(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if not user_can_manage_group(self.session, group, self.current_user): return self.forbidden() form = GroupEditForm(self.request.arguments, obj=group) if not form.validate(): return self.render("group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors)) if group.groupname != form.data["groupname"] and is_role_user( self.session, group=group): form.groupname.errors.append( "You cannot change the name of service account groups") return self.render("group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors)) group.groupname = form.data["groupname"] group.email_address = form.data["email_address"] group.description = form.data["description"] group.canjoin = form.data["canjoin"] group.auto_expire = form.data["auto_expire"] group.require_clickthru_tojoin = form.data["require_clickthru_tojoin"] Counter.incr(self.session, "updates") try: self.session.commit() except IntegrityError: self.session.rollback() form.groupname.errors.append("{} already exists".format( form.data["groupname"])) return self.render("group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors)) AuditLog.log(self.session, self.current_user.id, "edit_group", "Edited group.", on_group_id=group.id) return self.redirect("/groups/{}".format(group.name))
def get(self, *args, **kwargs): # type: (*Any, **Any) -> None group_id = kwargs.get("group_id") # type: Optional[int] name = kwargs.get("name") # type: Optional[str] self.handle_refresh() group = Group.get(self.session, group_id, name) if not group: return self.notfound() if is_role_user(self.session, group=group): return self.redirect("/service/{}".format(group.groupname)) self.render( "group.html", group=group, **get_group_view_template_vars(self.session, self.current_user, group, self.graph) )
def _get_group_tuples(session, enabled=True): ''' Returns a dict of groupname: GroupTuple. ''' out = {} groups = (session.query(Group).order_by( Group.groupname)).filter(Group.enabled == enabled) for group in groups: out[group.groupname] = GroupTuple(id=group.id, groupname=group.groupname, name=group.groupname, description=group.description, canjoin=group.canjoin, enabled=group.enabled, service_account=is_role_user( session, group=group), type="Group") return out
def get(self, *args: Any, **kwargs: Any) -> None: name = self.get_path_argument("name") self.handle_refresh() group = Group.get(self.session, name=name) if not group: return self.notfound() if is_role_user(self.session, group=group): return self.redirect("/service/{}".format(group.groupname)) self.render("group.html", group=group, audit_members_infos=get_group_audit_members_infos( self.session, group), **get_group_view_template_vars(self.session, self.current_user, group, self.graph))
def post(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if not user_can_manage_group(self.session, group, self.current_user): return self.forbidden() form = GroupEditForm(self.request.arguments, obj=group) if not form.validate(): return self.render( "group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors) ) if group.groupname != form.data["groupname"] and is_role_user(self.session, group=group): form.groupname.errors.append("You cannot change the name of service account groups") return self.render( "group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors) ) group.groupname = form.data["groupname"] group.email_address = form.data["email_address"] group.description = form.data["description"] group.canjoin = form.data["canjoin"] group.auto_expire = form.data["auto_expire"] group.require_clickthru_tojoin = form.data["require_clickthru_tojoin"] Counter.incr(self.session, "updates") try: self.session.commit() except IntegrityError: self.session.rollback() form.groupname.errors.append("{} already exists".format(form.data["groupname"])) return self.render( "group-edit.html", group=group, form=form, alerts=self.get_form_alerts(form.errors) ) AuditLog.log( self.session, self.current_user.id, "edit_group", "Edited group.", on_group_id=group.id ) return self.redirect("/groups/{}".format(group.name))
def get(self, *args, **kwargs): # type: (*Any, **Any) -> None group_id = kwargs.get("group_id") # type: Optional[int] name = kwargs.get("name") # type: Optional[str] self.handle_refresh() group = Group.get(self.session, group_id, name) if not group: return self.notfound() if is_role_user(self.session, group=group): return self.redirect("/service/{}".format(group.groupname)) self.render("group.html", group=group, audit_members_infos=get_group_audit_members_infos( self.session, group), **get_group_view_template_vars(self.session, self.current_user, group, self.graph))
def _get_group_tuples(session, enabled=True): ''' Returns a dict of groupname: GroupTuple. ''' out = {} groups = ( session.query(Group) .order_by(Group.groupname) ).filter( Group.enabled == enabled ) for group in groups: out[group.groupname] = GroupTuple( id=group.id, groupname=group.groupname, name=group.groupname, description=group.description, canjoin=group.canjoin, enabled=group.enabled, service_account=is_role_user(session, group=group), type="Group" ) return out
def post(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if not user_can_manage_group(self.session, group, self.current_user): return self.forbidden() members = group.my_members() my_role = user_role(self.current_user, members) form = self.get_form(role=my_role) if not form.validate(): return self.render("group-add.html", form=form, group=group, alerts=self.get_form_alerts(form.errors)) member = get_user_or_group(self.session, form.data["member"]) if member.type == "User" and is_role_user(self.session, member): # For service accounts, we want to always add the group to other groups, not the user member = get_role_user(self.session, user=member).group if not member: form.member.errors.append("User or group not found.") elif (member.type, member.name) in group.my_members(): form.member.errors.append( "User or group is already a member of this group.") elif group.name == member.name: form.member.errors.append( "By definition, this group is a member of itself already.") # Ensure this doesn't violate auditing constraints fail_message = 'This join is denied with this role at this time.' try: user_can_join = assert_can_join(group, member, role=form.data["role"]) except UserNotAuditor as e: user_can_join = False fail_message = e if not user_can_join: form.member.errors.append(fail_message) if form.member.errors: return self.render("group-add.html", form=form, group=group, alerts=self.get_form_alerts(form.errors)) expiration = None if form.data["expiration"]: expiration = datetime.strptime(form.data["expiration"], "%m/%d/%Y") try: group.add_member(requester=self.current_user, user_or_group=member, reason=form.data["reason"], status='actioned', expiration=expiration, role=form.data["role"]) except InvalidRoleForMember as e: return self.render("group-add.html", form=form, group=group, alerts=[Alert('danger', e.message)]) self.session.commit() on_user_id = member.id if member.type == "User" else None AuditLog.log(self.session, self.current_user.id, 'join_group', '{} added to group with role: {}'.format( member.name, form.data["role"]), on_group_id=group.id, on_user_id=on_user_id) if member.type == "User": send_email( self.session, [member.name], 'Added to group: {}'.format(group.name), 'request_actioned', settings, { 'group_name': group.name, 'actioned_by': self.current_user.name, 'reason': form.data['reason'], 'expiration': expiration, 'role': form.data['role'], }) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def test_sa_pubkeys(session, users, http_client, base_url): user = users['*****@*****.**'] # Add account fe_url = url(base_url, '/service/create') resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({ 'name': '*****@*****.**', "description": "Hi", "canjoin": "canjoin" }), headers={'X-Grouper-User': user.username}) assert resp.code == 200 assert User.get(session, name="*****@*****.**") is None assert Group.get(session, name="*****@*****.**") is None # Add account fe_url = url(base_url, '/service/create') resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({ 'name': '*****@*****.**', "description": "Hi", "canjoin": "canjoin" }), headers={'X-Grouper-User': user.username}) assert resp.code == 200 u = User.get(session, name="*****@*****.**") g = Group.get(session, name="*****@*****.**") assert u is not None assert g is not None assert is_role_user(session, user=u) assert is_role_user(session, group=g) assert get_role_user(session, user=u).group.id == g.id assert get_role_user(session, group=g).user.id == u.id assert not is_role_user(session, user=user) assert not is_role_user(session, group=Group.get(session, name="team-sre")) assert not get_public_keys_of_user(session, user.id) good_key = ( 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDCUQeasspT/etEJR2WUoR+h2sMOQYbJgr0Q' 'E+J8p97gEhmz107KWZ+3mbOwyIFzfWBcJZCEg9wy5Paj+YxbGONqbpXAhPdVQ2TLgxr41bNXvbcR' 'AxZC+Q12UZywR4Klb2kungKz4qkcmSZzouaKK12UxzGB3xQ0N+3osKFj3xA1+B6HqrVreU19XdVo' 'AJh0xLZwhw17/NDM+dAcEdMZ9V89KyjwjraXtOVfFhQF0EDF0ame8d6UkayGrAiXC2He0P2Cja+J' '371P27AlNLHFJij8WGxvcGGSeAxMLoVSDOOllLCYH5UieV8mNpX1kNe2LeA58ciZb0AXHaipSmCH' 'gh/ some-comment') bad_key = 'ssh-rsa AAAblahblahkey some-comment' with pytest.raises(HTTPError): # add it fe_url = url(base_url, '/users/{}/public-key/add'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({'public_key': good_key}), headers={'X-Grouper-User': "******"}) # add it fe_url = url(base_url, '/users/{}/public-key/add'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({'public_key': good_key}), headers={'X-Grouper-User': user.username}) assert resp.code == 200 # add bad key -- shouldn't add fe_url = url(base_url, '/users/{}/public-key/add'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({'public_key': bad_key}), headers={'X-Grouper-User': user.username}) assert resp.code == 200 sa = User.get(session, name="*****@*****.**") keys = get_public_keys_of_user(session, sa.id) assert len(keys) == 1 assert keys[0].public_key == good_key with pytest.raises(HTTPError): # delete it fe_url = url( base_url, '/users/{}/public-key/{}/delete'.format("*****@*****.**", keys[0].id)) resp = yield http_client.fetch(fe_url, method="POST", body='', headers={'X-Grouper-User': "******"}) # delete it fe_url = url( base_url, '/users/{}/public-key/{}/delete'.format("*****@*****.**", keys[0].id)) resp = yield http_client.fetch(fe_url, method="POST", body='', headers={'X-Grouper-User': user.username}) assert resp.code == 200 sa = User.get(session, name="*****@*****.**") assert not get_public_keys_of_user(session, sa.id)
def post(self, *args: Any, **kwargs: Any) -> None: name = self.get_path_argument("name") group = Group.get(self.session, name=name) if not group: return self.notfound() if not user_can_manage_group(self.session, group, self.current_user): return self.forbidden() members = group.my_members() my_role = user_role(self.current_user, members) form = self.get_form(role=my_role) if not form.validate(): return self.render("group-add.html", form=form, group=group, alerts=self.get_form_alerts(form.errors)) member = get_user_or_group(self.session, form.data["member"]) if member.type == "User" and is_role_user(self.session, member): # For service accounts, we want to always add the group to other groups, not the user member = get_role_user(self.session, user=member).group if not member: form.member.errors.append("User or group not found.") elif (member.type, member.name) in group.my_members(): form.member.errors.append( "User or group is already a member of this group.") elif group.name == member.name: form.member.errors.append( "By definition, this group is a member of itself already.") # Ensure this doesn't violate auditing constraints try: assert_can_join(group, member, role=form.data["role"]) except UserNotAuditor as e: form.member.errors.append(str(e)) if form.member.errors: return self.render("group-add.html", form=form, group=group, alerts=self.get_form_alerts(form.errors)) expiration = None if form.data["expiration"]: expiration = datetime.strptime(form.data["expiration"], "%m/%d/%Y") try: group.add_member( requester=self.current_user, user_or_group=member, reason=form.data["reason"], status="actioned", expiration=expiration, role=form.data["role"], ) except InvalidRoleForMember as e: return self.render("group-add.html", form=form, group=group, alerts=[Alert("danger", str(e))]) self.session.commit() on_user_id = member.id if member.type == "User" else None AuditLog.log( self.session, self.current_user.id, "join_group", "{} added to group with role: {}".format(member.name, form.data["role"]), on_group_id=group.id, on_user_id=on_user_id, ) if member.type == "User": send_email( self.session, [member.name], "Added to group: {}".format(group.name), "request_actioned", settings(), { "group_name": group.name, "actioned_by": self.current_user.name, "reason": form.data["reason"], "expiration": expiration, "role": form.data["role"], }, ) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def test_sa_tokens(session, users, http_client, base_url): # noqa: F811 user = users["*****@*****.**"] # Add account create_role_user(session, user, "*****@*****.**", "Hi", "canjoin") u = User.get(session, name="*****@*****.**") g = Group.get(session, name="*****@*****.**") assert u is not None assert g is not None assert is_role_user(session, user=u) assert is_role_user(session, group=g) assert get_role_user(session, user=u).group.id == g.id assert get_role_user(session, group=g).user.id == u.id assert not is_role_user(session, user=user) assert not is_role_user(session, group=Group.get(session, name="team-sre")) with pytest.raises(HTTPError): # Add token fe_url = url(base_url, "/users/{}/tokens/add".format("*****@*****.**")) resp = yield http_client.fetch( fe_url, method="POST", body=urlencode({"name": "myDHDToken"}), headers={"X-Grouper-User": "******"}, ) # Add token fe_url = url(base_url, "/users/{}/tokens/add".format("*****@*****.**")) resp = yield http_client.fetch( fe_url, method="POST", body=urlencode({"name": "myDHDToken"}), headers={"X-Grouper-User": user.username}, ) assert resp.code == 200 # Verify add fe_url = url(base_url, "/users/{}".format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="GET", headers={"X-Grouper-User": user.username}) assert resp.code == 200 assert b"Added token: myDHDToken" in resp.body with pytest.raises(HTTPError): # Disable token fe_url = url(base_url, "/users/{}/tokens/1/disable".format("*****@*****.**")) resp = yield http_client.fetch( fe_url, method="POST", body="", headers={"X-Grouper-User": "******"} ) # Disable token fe_url = url(base_url, "/users/{}/tokens/1/disable".format("*****@*****.**")) resp = yield http_client.fetch( fe_url, method="POST", body="", headers={"X-Grouper-User": user.username} ) assert resp.code == 200 # Verify disable fe_url = url(base_url, "/users/{}".format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="GET", headers={"X-Grouper-User": user.username}) assert resp.code == 200 assert b"Disabled token: myDHDToken" in resp.body
def test_sa_pubkeys(session, users, http_client, base_url): user = users['*****@*****.**'] # Add account create_role_user(session, user, '*****@*****.**', 'Hi', 'canjoin') u = User.get(session, name="*****@*****.**") g = Group.get(session, name="*****@*****.**") assert u is not None assert g is not None assert is_role_user(session, user=u) assert is_role_user(session, group=g) assert get_role_user(session, user=u).group.id == g.id assert get_role_user(session, group=g).user.id == u.id assert not is_role_user(session, user=user) assert not is_role_user(session, group=Group.get(session, name="team-sre")) assert not get_public_keys_of_user(session, user.id) with pytest.raises(HTTPError): # add it fe_url = url(base_url, '/users/{}/public-key/add'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode( {'public_key': SSH_KEY_1}), headers={'X-Grouper-User': "******"}) # add it fe_url = url(base_url, '/users/{}/public-key/add'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({'public_key': SSH_KEY_1}), headers={'X-Grouper-User': user.username}) assert resp.code == 200 # add bad key -- shouldn't add fe_url = url(base_url, '/users/{}/public-key/add'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body=urlencode({'public_key': SSH_KEY_BAD}), headers={'X-Grouper-User': user.username}) assert resp.code == 200 sa = User.get(session, name="*****@*****.**") keys = get_public_keys_of_user(session, sa.id) assert len(keys) == 1 assert keys[0].public_key == SSH_KEY_1 with pytest.raises(HTTPError): # delete it fe_url = url( base_url, '/users/{}/public-key/{}/delete'.format("*****@*****.**", keys[0].id)) resp = yield http_client.fetch(fe_url, method="POST", body='', headers={'X-Grouper-User': "******"}) # delete it fe_url = url( base_url, '/users/{}/public-key/{}/delete'.format("*****@*****.**", keys[0].id)) resp = yield http_client.fetch(fe_url, method="POST", body='', headers={'X-Grouper-User': user.username}) assert resp.code == 200 sa = User.get(session, name="*****@*****.**") assert not get_public_keys_of_user(session, sa.id)
def post(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if not user_can_manage_group(self.session, group, self.current_user): return self.forbidden() members = group.my_members() my_role = user_role(self.current_user, members) form = self.get_form(role=my_role) if not form.validate(): return self.render( "group-add.html", form=form, group=group, alerts=self.get_form_alerts(form.errors) ) member = get_user_or_group(self.session, form.data["member"]) if member.type == "User" and is_role_user(self.session, member): # For service accounts, we want to always add the group to other groups, not the user member = get_role_user(self.session, user=member).group if not member: form.member.errors.append("User or group not found.") elif (member.type, member.name) in group.my_members(): form.member.errors.append("User or group is already a member of this group.") elif group.name == member.name: form.member.errors.append("By definition, this group is a member of itself already.") # Ensure this doesn't violate auditing constraints fail_message = 'This join is denied with this role at this time.' try: user_can_join = assert_can_join(group, member, role=form.data["role"]) except UserNotAuditor as e: user_can_join = False fail_message = e if not user_can_join: form.member.errors.append(fail_message) if form.member.errors: return self.render( "group-add.html", form=form, group=group, alerts=self.get_form_alerts(form.errors) ) expiration = None if form.data["expiration"]: expiration = datetime.strptime(form.data["expiration"], "%m/%d/%Y") try: group.add_member( requester=self.current_user, user_or_group=member, reason=form.data["reason"], status='actioned', expiration=expiration, role=form.data["role"] ) except InvalidRoleForMember as e: return self.render( "group-add.html", form=form, group=group, alerts=[ Alert('danger', e.message) ] ) self.session.commit() on_user_id = member.id if member.type == "User" else None AuditLog.log(self.session, self.current_user.id, 'join_group', '{} added to group with role: {}'.format( member.name, form.data["role"]), on_group_id=group.id, on_user_id=on_user_id) if member.type == "User": send_email( self.session, [member.name], 'Added to group: {}'.format(group.name), 'request_actioned', settings, { 'group_name': group.name, 'actioned_by': self.current_user.name, 'reason': form.data['reason'], 'expiration': expiration, 'role': form.data['role'], } ) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def test_disable_role_user(session, users, http_client, base_url): user = users['*****@*****.**'] # Add account create_role_user(session, user, '*****@*****.**', 'Hi', 'canjoin') u = User.get(session, name="*****@*****.**") g = Group.get(session, name="*****@*****.**") assert u is not None assert g is not None assert is_role_user(session, user=u) assert is_role_user(session, group=g) assert get_role_user(session, user=u).group.id == g.id assert get_role_user(session, group=g).user.id == u.id assert not is_role_user(session, user=user) assert not is_role_user(session, group=Group.get(session, name="team-sre")) disable_role_user(session, user=u) u = User.get(session, name="*****@*****.**") assert not u.enabled, "The SA User should be disabled" g = Group.get(session, name="*****@*****.**") assert not g.enabled, "The SA Group should be disabled" enable_role_user(session, actor=user, group=g, preserve_membership=True) u = User.get(session, name="*****@*****.**") assert u.enabled, "The SA User should be enabled" g = Group.get(session, name="*****@*****.**") assert g.enabled, "The SA Group should be enabled" with pytest.raises(HTTPError): fe_url = url(base_url, '/groups/{}/disable'.format("*****@*****.**")) resp = yield http_client.fetch( fe_url, method="POST", body="", headers={'X-Grouper-User': user.username}) u = User.get(session, name="*****@*****.**") assert u.enabled, "Attempting to disable SAs through groups/disable should not work" g = Group.get(session, name="*****@*****.**") assert g.enabled, "Attempting to disable SAs through groups/disable should not work" fe_url = url(base_url, '/users/{}/disable'.format("*****@*****.**")) resp = yield http_client.fetch(fe_url, method="POST", body="", headers={'X-Grouper-User': user.username}) u = User.get(session, name="*****@*****.**") assert not u.enabled, "The SA User should be disabled" g = Group.get(session, name="*****@*****.**") assert not g.enabled, "The SA Group should be disabled" with pytest.raises(HTTPError): fe_url = url(base_url, '/groups/{}/enable'.format("*****@*****.**")) resp = yield http_client.fetch( fe_url, method="POST", body="", headers={'X-Grouper-User': user.username}) u = User.get(session, name="*****@*****.**") assert not u.enabled, "Attempting to enable SAs through groups/enable should not work" g = Group.get(session, name="*****@*****.**") assert not g.enabled, "Attempting to enable SAs through groups/enable should not work"
def test_disable_role_user(session, users, http_client, base_url): # noqa: F811 user = users["*****@*****.**"] # Add account create_role_user(session, user, "*****@*****.**", "Hi", "canjoin") u = User.get(session, name="*****@*****.**") g = Group.get(session, name="*****@*****.**") assert u is not None assert g is not None assert is_role_user(session, user=u) assert is_role_user(session, group=g) assert get_role_user(session, user=u).group.id == g.id assert get_role_user(session, group=g).user.id == u.id assert not is_role_user(session, user=user) assert not is_role_user(session, group=Group.get(session, name="team-sre")) disable_role_user(session, user=u) u = User.get(session, name="*****@*****.**") assert not u.enabled, "The SA User should be disabled" g = Group.get(session, name="*****@*****.**") assert not g.enabled, "The SA Group should be disabled" enable_role_user(session, actor=user, group=g, preserve_membership=True) u = User.get(session, name="*****@*****.**") assert u.enabled, "The SA User should be enabled" g = Group.get(session, name="*****@*****.**") assert g.enabled, "The SA Group should be enabled" with pytest.raises(HTTPError): fe_url = url(base_url, "/groups/{}/disable".format("*****@*****.**")) yield http_client.fetch( fe_url, method="POST", body="", headers={"X-Grouper-User": user.username} ) u = User.get(session, name="*****@*****.**") assert u.enabled, "Attempting to disable SAs through groups/disable should not work" g = Group.get(session, name="*****@*****.**") assert g.enabled, "Attempting to disable SAs through groups/disable should not work" fe_url = url(base_url, "/users/{}/disable".format("*****@*****.**")) yield http_client.fetch( fe_url, method="POST", body="", headers={"X-Grouper-User": user.username} ) u = User.get(session, name="*****@*****.**") assert not u.enabled, "The SA User should be disabled" g = Group.get(session, name="*****@*****.**") assert not g.enabled, "The SA Group should be disabled" with pytest.raises(HTTPError): fe_url = url(base_url, "/groups/{}/enable".format("*****@*****.**")) yield http_client.fetch( fe_url, method="POST", body="", headers={"X-Grouper-User": user.username} ) u = User.get(session, name="*****@*****.**") assert not u.enabled, "Attempting to enable SAs through groups/enable should not work" g = Group.get(session, name="*****@*****.**") assert not g.enabled, "Attempting to enable SAs through groups/enable should not work"