def get(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() status = self.get_argument("status", None) offset = int(self.get_argument("offset", 0)) limit = int(self.get_argument("limit", 100)) if limit > 9000: limit = 9000 requests = group.my_requests(status).order_by( Request.requested_at.desc() ) members = group.my_members() total = requests.count() requests = requests.offset(offset).limit(limit) current_user_role = { 'is_owner': user_role_index(self.current_user, members) in OWNER_ROLE_INDICES, 'is_approver': user_role_index(self.current_user, members) in APPROVER_ROLE_INDICIES, 'is_manager': user_role(self.current_user, members) == "manager", 'role': user_role(self.current_user, members), } self.render( "group-requests.html", group=group, requests=requests, members=members, status=status, statuses=REQUEST_STATUS_CHOICES, offset=offset, limit=limit, total=total, current_user_role=current_user_role, )
def get(self, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() status = self.get_argument("status", None) offset = int(self.get_argument("offset", 0)) limit = int(self.get_argument("limit", 100)) if limit > 9000: limit = 9000 requests = group.my_requests(status).order_by( Request.requested_at.desc() ) members = group.my_members() total = requests.count() requests = requests.offset(offset).limit(limit) current_user_role = { 'is_owner': user_role_index(self.current_user, members) in OWNER_ROLE_INDICES, 'is_approver': user_role_index(self.current_user, members) in APPROVER_ROLE_INDICES, 'is_manager': user_role(self.current_user, members) == "manager", 'role': user_role(self.current_user, members), } self.render( "group-requests.html", group=group, requests=requests, members=members, status=status, statuses=REQUEST_STATUS_CHOICES, offset=offset, limit=limit, total=total, current_user_role=current_user_role, )
def get_group_view_template_vars(session, actor, group, graph): # type: (Session, User, Group, GroupGraph) -> Dict[str, Any] ret = {} ret["grantable"] = user_grantable_permissions(session, actor) try: group_md = graph.get_group_details(group.name) except NoSuchGroup: # Very new group with no metadata yet, or it has been disabled and # excluded from in-memory cache. group_md = {} ret["members"] = group.my_members() ret["groups"] = group.my_groups() ret["service_accounts"] = get_service_accounts(session, group) ret["permissions"] = group_md.get("permissions", []) for permission in ret["permissions"]: permission["granted_on"] = datetime.fromtimestamp(permission["granted_on"]) ret["permission_requests_pending"] = [] for req in get_pending_request_by_group(session, group): granters = [] for owner, argument in get_owner_arg_list(session, req.permission, req.argument): granters.append(owner.name) ret["permission_requests_pending"].append((req, granters)) ret["audited"] = group_md.get("audited", False) ret["log_entries"] = group.my_log_entries() ret["num_pending"] = count_requests_by_group(session, group, status="pending") ret["current_user_role"] = { "is_owner": user_role_index(actor, ret["members"]) in OWNER_ROLE_INDICES, "is_approver": user_role_index(actor, ret["members"]) in APPROVER_ROLE_INDICES, "is_manager": user_role(actor, ret["members"]) == "manager", "is_member": user_role(actor, ret["members"]) is not None, "role": user_role(actor, ret["members"]), } ret["can_leave"] = ( ret["current_user_role"]["is_member"] and not ret["current_user_role"]["is_owner"] ) ret["statuses"] = AUDIT_STATUS_CHOICES # Add mapping_id to permissions structure ret["my_permissions"] = group.my_permissions() for perm_up in ret["permissions"]: for perm_direct in ret["my_permissions"]: if ( perm_up["permission"] == perm_direct.name and perm_up["argument"] == perm_direct.argument ): perm_up["mapping_id"] = perm_direct.mapping_id break ret["alerts"] = [] ret["self_pending"] = count_requests_by_group(session, group, status="pending", user=actor) if ret["self_pending"]: ret["alerts"].append(Alert("info", "You have a pending request to join this group.", None)) return ret
def get_group_view_template_vars(session, actor, group, graph): ret = {} ret["grantable"] = user_grantable_permissions(session, actor) try: group_md = graph.get_group_details(group.name) except NoSuchGroup: # Very new group with no metadata yet, or it has been disabled and # excluded from in-memory cache. group_md = {} ret["members"] = group.my_members() ret["groups"] = group.my_groups() ret["service_accounts"] = get_service_accounts(session, group) ret["permissions"] = group_md.get('permissions', []) ret["permission_requests_pending"] = [] for req in get_pending_request_by_group(session, group): granters = [] for owner, argument in get_owner_arg_list(session, req.permission, req.argument): granters.append(owner.name) ret["permission_requests_pending"].append((req, granters)) ret["audited"] = group_md.get('audited', False) ret["log_entries"] = group.my_log_entries() ret["num_pending"] = group.my_requests("pending").count() ret["current_user_role"] = { 'is_owner': user_role_index(actor, ret["members"]) in OWNER_ROLE_INDICES, 'is_approver': user_role_index(actor, ret["members"]) in APPROVER_ROLE_INDICES, 'is_manager': user_role(actor, ret["members"]) == "manager", 'is_member': user_role(actor, ret["members"]) is not None, 'role': user_role(actor, ret["members"]), } ret["can_leave"] = (ret["current_user_role"]['is_member'] and not ret["current_user_role"]['is_owner']) ret["statuses"] = AUDIT_STATUS_CHOICES # Add mapping_id to permissions structure ret["my_permissions"] = group.my_permissions() for perm_up in ret["permissions"]: for perm_direct in ret["my_permissions"]: if (perm_up['permission'] == perm_direct.name and perm_up['argument'] == perm_direct.argument): perm_up['mapping_id'] = perm_direct.mapping_id break ret["alerts"] = [] ret["self_pending"] = group.my_requests("pending", user=actor).count() if ret["self_pending"]: ret["alerts"].append( Alert('info', 'You have a pending request to join this group.', None)) return ret
def get_group_view_template_vars(session, actor, group, graph): ret = {} ret["grantable"] = user_grantable_permissions(session, actor) try: group_md = graph.get_group_details(group.name) except NoSuchGroup: # Very new group with no metadata yet, or it has been disabled and # excluded from in-memory cache. group_md = {} ret["members"] = group.my_members() ret["groups"] = group.my_groups() ret["permissions"] = group_md.get('permissions', []) ret["permission_requests_pending"] = [] for req in get_pending_request_by_group(session, group): granters = [] for owner, argument in get_owner_arg_list(session, req.permission, req.argument): granters.append(owner.name) ret["permission_requests_pending"].append((req, granters)) ret["audited"] = group_md.get('audited', False) ret["log_entries"] = group.my_log_entries() ret["num_pending"] = group.my_requests("pending").count() ret["current_user_role"] = { 'is_owner': user_role_index(actor, ret["members"]) in OWNER_ROLE_INDICES, 'is_approver': user_role_index(actor, ret["members"]) in APPROVER_ROLE_INDICIES, 'is_manager': user_role(actor, ret["members"]) == "manager", 'is_member': user_role(actor, ret["members"]) is not None, 'role': user_role(actor, ret["members"]), } ret["can_leave"] = (ret["current_user_role"]['is_member'] and not ret["current_user_role"]['is_owner']) ret["statuses"] = AUDIT_STATUS_CHOICES # Add mapping_id to permissions structure ret["my_permissions"] = group.my_permissions() for perm_up in ret["permissions"]: for perm_direct in ret["my_permissions"]: if (perm_up['permission'] == perm_direct.name and perm_up['argument'] == perm_direct.argument): perm_up['mapping_id'] = perm_direct.mapping_id break ret["alerts"] = [] ret["self_pending"] = group.my_requests("pending", user=actor).count() if ret["self_pending"]: ret["alerts"].append(Alert('info', 'You have a pending request to join this group.', None)) return ret
def get(self, request_id, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() members = group.my_members() my_role = user_role(self.current_user, members) if my_role not in ("manager", "owner", "np-owner"): return self.forbidden() request = self.session.query(Request).filter_by(id=request_id).scalar() if not request: return self.notfound() on_behalf = get_on_behalf_by_request(self.session, request) form = GroupRequestModifyForm(self.request.arguments) form.status.choices = self._get_choices(request.status) updates = request.my_status_updates() self.render( "group-request-update.html", group=group, request=request, on_behalf=on_behalf, members=members, form=form, statuses=REQUEST_STATUS_CHOICES, updates=updates )
def get(self, *args: Any, **kwargs: Any) -> None: request_id = self.get_path_argument("request_id") name = self.get_path_argument("name") group = Group.get(self.session, name=name) if not group: return self.notfound() members = group.my_members() my_role = user_role(self.current_user, members) if my_role not in ("manager", "owner", "np-owner"): return self.forbidden() request = self.session.query(Request).filter_by(id=request_id).scalar() if not request: return self.notfound() on_behalf = get_on_behalf_by_request(self.session, request) form = GroupRequestModifyForm(self.request.arguments) form.status.choices = self._get_choices(request.status) updates = request.my_status_updates() self.render( "group-request-update.html", group=group, request=request, on_behalf=on_behalf, members=members, form=form, statuses=REQUEST_STATUS_CHOICES, updates=updates, )
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 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_service_account(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 get(self, request_id, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() members = group.my_members() my_role = user_role(self.current_user, members) if my_role not in ("manager", "owner", "np-owner"): return self.forbidden() request = self.session.query(Request).filter_by(id=request_id).scalar() if not request: return self.notfound() form = GroupRequestModifyForm(self.request.arguments) form.status.choices = self._get_choices(request.status) updates = request.my_status_updates() self.render("group-request-update.html", group=group, request=request, members=members, form=form, statuses=REQUEST_STATUS_CHOICES, updates=updates)
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 get(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): return self.forbidden() return self.render("group-leave.html", group=group)
def get(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) return self.render( "group-add.html", form=self.get_form(role=my_role), group=group )
def get(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) return self.render("group-add.html", form=self.get_form(role=my_role), group=group)
def user_can_manage_group(session, group, user): # type: (Session, Group, User) -> bool """Determine if this user can manage the given group This returns true if this user object is a manager, owner, or np-owner of the given group. """ from grouper.user import user_role if not group: return False members = group.my_members() if user_role(user, members) in ("owner", "np-owner", "manager"): return True return False
def get(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) return self.render("group-add.html", form=self.get_form(role=my_role), group=group)
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] 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) return self.render("group-add.html", form=self.get_form(role=my_role), group=group)
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): return self.forbidden() group.revoke_member(self.current_user, self.current_user, "User self-revoked.") AuditLog.log(self.session, self.current_user.id, 'leave_group', '{} left the group.'.format(self.current_user.name), on_group_id=group.id) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def user_can_manage_group(session, group, user): """Determine if this user can manage the given group This returns true if this user object is a manager, owner, or np-owner of the given group. Args: group (Group): Group to check permissions against. Returns: bool: True or False on whether or not they can manage. """ from grouper.user import user_role if not group: return False members = group.my_members() if user_role(user, members) in ("owner", "np-owner", "manager"): return True return False
def get(self, group_id=None, name=None, name2=None, member_type=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if self.current_user.name == name2: return self.forbidden() members = group.my_members() my_role = user_role(self.current_user, members) if my_role not in ("manager", "owner", "np-owner"): return self.forbidden() member = members.get((member_type.capitalize(), name2), None) if not member: return self.notfound() edge = GroupEdge.get( self.session, group_id=group.id, member_type=OBJ_TYPES[member.type], member_pk=member.id, ) if not edge: return self.notfound() form = GroupEditMemberForm(self.request.arguments) form.role.choices = [["member", "Member"]] if my_role in ("owner", "np-owner"): form.role.choices.append(["manager", "Manager"]) form.role.choices.append(["owner", "Owner"]) form.role.choices.append(["np-owner", "No-Permissions Owner"]) form.role.data = edge.role form.expiration.data = edge.expiration.strftime( "%m/%d/%Y") if edge.expiration else None self.render( "group-edit-member.html", group=group, member=member, edge=edge, form=form, )
def get(self, group_id=None, name=None, name2=None, member_type=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if self.current_user.name == name2: return self.forbidden() members = group.my_members() my_role = user_role(self.current_user, members) if my_role not in ("manager", "owner", "np-owner"): return self.forbidden() member = members.get((member_type.capitalize(), name2), None) if not member: return self.notfound() edge = GroupEdge.get( self.session, group_id=group.id, member_type=OBJ_TYPES[member.type], member_pk=member.id, ) if not edge: return self.notfound() form = GroupEditMemberForm(self.request.arguments) form.role.choices = [["member", "Member"]] if my_role in ("owner", "np-owner"): form.role.choices.append(["manager", "Manager"]) form.role.choices.append(["owner", "Owner"]) form.role.choices.append(["np-owner", "No-Permissions Owner"]) form.role.data = edge.role form.expiration.data = edge.expiration.strftime("%m/%d/%Y") if edge.expiration else None self.render( "group-edit-member.html", group=group, member=member, edge=edge, form=form, )
def get(self, *args: Any, **kwargs: Any) -> None: name = self.get_path_argument("name") member_name = self.get_path_argument("member_name") member_type = self.get_path_argument("member_type") group = Group.get(self.session, name=name) if not group: return self.notfound() members = group.my_members() my_role = user_role(self.current_user, members) if my_role not in ("manager", "owner", "np-owner"): return self.forbidden() member = members.get((member_type.capitalize(), member_name), None) if not member: return self.notfound() edge = GroupEdge.get( self.session, group_id=group.id, member_type=OBJ_TYPES[member.type], member_pk=member.id, ) if not edge: return self.notfound() form = self._get_form(member_name, my_role, member_type) form.role.data = edge.role form.expiration.data = edge.expiration.strftime( "%m/%d/%Y") if edge.expiration else None self.render("group-edit-member.html", group=group, member=member, edge=edge, form=form)
def post(self, *args, **kwargs): # type: (*Any, **Any) -> None request_id = kwargs["request_id"] # type: int group_id = kwargs.get("group_id") # type: Optional[int] name = kwargs.get("name") # type: Optional[str] group = Group.get(self.session, group_id, name) if not group: return self.notfound() members = group.my_members() my_role = user_role(self.current_user, members) if my_role not in ("manager", "owner", "np-owner"): return self.forbidden() request = self.session.query(Request).filter_by(id=request_id).scalar() if not request: return self.notfound() on_behalf = get_on_behalf_by_request(self.session, request) form = GroupRequestModifyForm(self.request.arguments) form.status.choices = self._get_choices(request.status) updates = request.my_status_updates() if not form.status.choices: alerts = [Alert("info", "Request has already been processed")] return self.render( "group-request-update.html", group=group, request=request, on_behalf=on_behalf, members=members, form=form, alerts=alerts, statuses=REQUEST_STATUS_CHOICES, updates=updates, ) if not form.validate(): return self.render( "group-request-update.html", group=group, request=request, on_behalf=on_behalf, members=members, form=form, alerts=self.get_form_alerts(form.errors), statuses=REQUEST_STATUS_CHOICES, updates=updates, ) # We have to test this here, too, to ensure that someone can't sneak in with a pending # request that used to be allowed. if form.data["status"] != "cancelled": fail_message = "This join is denied with this role at this time." try: user_can_join = assert_can_join( request.requesting, on_behalf, role=request.edge.role ) except UserNotAuditor as e: user_can_join = False fail_message = str(e) if not user_can_join: return self.render( "group-request-update.html", group=group, request=request, on_behalf=on_behalf, members=members, form=form, statuses=REQUEST_STATUS_CHOICES, updates=updates, alerts=[Alert("danger", fail_message, "Audit Policy Enforcement")], ) request.update_status(self.current_user, form.data["status"], form.data["reason"]) self.session.commit() AuditLog.log( self.session, self.current_user.id, "update_request", "Updated request to status: {}".format(form.data["status"]), on_group_id=group.id, on_user_id=request.requester.id, ) edge = self.session.query(GroupEdge).filter_by(id=request.edge_id).one() approver_mail_to = [ user.name for user in group.my_approver_users() if user.name != self.current_user.name and user.name != request.requester.username ] subj = "Re: " + self.render_template( "email/pending_request_subj.tmpl", group=group.name, user=request.requester.username ) send_email( self.session, approver_mail_to, subj, "approver_request_updated", settings(), { "group_name": group.name, "requester": request.requester.username, "changed_by": self.current_user.name, "status": form.data["status"], "role": edge.role, "reason": form.data["reason"], "references_header": request.reference_id, }, ) if form.data["status"] == "actioned": send_email( self.session, [request.requester.name], "Added to group: {}".format(group.groupname), "request_actioned", settings(), { "group_name": group.name, "actioned_by": self.current_user.name, "reason": form.data["reason"], "expiration": edge.expiration, "role": edge.role, }, ) elif form.data["status"] == "cancelled": send_email( self.session, [request.requester.name], "Request to join cancelled: {}".format(group.groupname), "request_cancelled", settings(), { "group_name": group.name, "cancelled_by": self.current_user.name, "reason": form.data["reason"], "expiration": edge.expiration, "role": edge.role, }, ) # No explicit refresh because handler queries SQL. if form.data["redirect_aggregate"]: return self.redirect("/user/requests") else: return self.redirect("/groups/{}/requests".format(group.name))
def post(self, *args: Any, **kwargs: Any) -> None: name = self.get_path_argument("name") member_name = self.get_path_argument("member_name") member_type = self.get_path_argument("member_type") group = Group.get(self.session, name=name) if not group: return self.notfound() members = group.my_members() my_role = user_role(self.current_user, members) if my_role not in ("manager", "owner", "np-owner"): return self.forbidden() member = members.get((member_type.capitalize(), member_name), None) if not member: return self.notfound() if member.type == "Group": user_or_group = Group.get(self.session, member.id) else: user_or_group = User.get(self.session, member.id) if not user_or_group: return self.notfound() edge = GroupEdge.get( self.session, group_id=group.id, member_type=OBJ_TYPES[member.type], member_pk=member.id, ) if not edge: return self.notfound() form = self._get_form(member_name, my_role, member_type) if not form.validate(): return self.render( "group-edit-member.html", group=group, member=member, edge=edge, form=form, alerts=self.get_form_alerts(form.errors), ) try: assert_can_join(group, user_or_group, role=form.data["role"]) except UserNotAuditor as e: return self.render( "group-edit-member.html", form=form, group=group, member=member, edge=edge, alerts=[Alert("danger", str(e), "Audit Policy Enforcement")], ) expiration = None if form.data["expiration"]: expiration = datetime.strptime(form.data["expiration"], "%m/%d/%Y") try: group.edit_member( self.current_user, user_or_group, form.data["reason"], role=form.data["role"], expiration=expiration, ) except (InvalidRoleForMember, PluginRejectedGroupMembershipUpdate) as e: return self.render( "group-edit-member.html", form=form, group=group, member=member, edge=edge, alerts=[Alert("danger", str(e))], ) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def post(self, *args, **kwargs): # type: (*Any, **Any) -> None group_id = kwargs.get("group_id") # type: Optional[int] name = kwargs.get("name") # type: Optional[str] 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 = str(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", 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 post(self, request_id, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() members = group.my_members() my_role = user_role(self.current_user, members) if my_role not in ("manager", "owner", "np-owner"): return self.forbidden() request = self.session.query(Request).filter_by(id=request_id).scalar() if not request: return self.notfound() form = GroupRequestModifyForm(self.request.arguments) form.status.choices = self._get_choices(request.status) updates = request.my_status_updates() if not form.validate(): return self.render("group-request-update.html", group=group, request=request, members=members, form=form, alerts=self.get_form_alerts(form.errors), statuses=REQUEST_STATUS_CHOICES, updates=updates) # We have to test this here, too, to ensure that someone can't sneak in with a pending # request that used to be allowed. if form.data["status"] != "cancelled": fail_message = 'This join is denied with this role at this time.' try: user_can_join = assert_can_join(request.requesting, request.get_on_behalf(), role=request.edge.role) except UserNotAuditor as e: user_can_join = False fail_message = e if not user_can_join: return self.render("group-request-update.html", group=group, request=request, members=members, form=form, statuses=REQUEST_STATUS_CHOICES, updates=updates, alerts=[ Alert('danger', fail_message, 'Audit Policy Enforcement') ]) request.update_status(self.current_user, form.data["status"], form.data["reason"]) self.session.commit() AuditLog.log(self.session, self.current_user.id, 'update_request', 'Updated request to status: {}'.format( form.data["status"]), on_group_id=group.id, on_user_id=request.requester.id) edge = self.session.query(GroupEdge).filter_by( id=request.edge_id).one() approver_mail_to = [ user.name for user in group.my_approver_users() if user.name != self.current_user.name and user.name != request.requester.username ] send_email( self.session, approver_mail_to, "Request to join {} by {} has been {}".format( group.groupname, request.requester.name, form.data['status']), "approver_request_updated", settings, { 'group_name': group.name, 'requester': request.requester.username, 'changed_by': self.current_user.name, 'status': form.data['status'], 'role': edge.role, 'reason': form.data['reason'], }, ) if form.data['status'] == 'actioned': send_email( self.session, [request.requester.name], 'Added to group: {}'.format(group.groupname), 'request_actioned', settings, { 'group_name': group.name, 'actioned_by': self.current_user.name, 'reason': form.data['reason'], 'expiration': edge.expiration, 'role': edge.role, }) elif form.data['status'] == 'cancelled': send_email( self.session, [request.requester.name], 'Request to join cancelled: {}'.format(group.groupname), 'request_cancelled', settings, { 'group_name': group.name, 'cancelled_by': self.current_user.name, 'reason': form.data['reason'], 'expiration': edge.expiration, 'role': edge.role, }) # No explicit refresh because handler queries SQL. if form.data['redirect_aggregate']: return self.redirect("/user/requests") else: return self.redirect("/groups/{}/requests".format(group.name))
def post(self, group_id=None, name=None, name2=None, member_type=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if self.current_user.name == name2: return self.forbidden() members = group.my_members() my_role = user_role(self.current_user, members) if my_role not in ("manager", "owner", "np-owner"): return self.forbidden() member = members.get((member_type.capitalize(), name2), None) if not member: return self.notfound() if member.type == "Group": user_or_group = Group.get(self.session, member.id) else: user_or_group = User.get(self.session, member.id) if not user_or_group: return self.notfound() edge = GroupEdge.get( self.session, group_id=group.id, member_type=OBJ_TYPES[member.type], member_pk=member.id, ) if not edge: return self.notfound() form = GroupEditMemberForm(self.request.arguments) form.role.choices = [["member", "Member"]] if my_role in ("owner", "np-owner"): form.role.choices.append(["manager", "Manager"]) form.role.choices.append(["owner", "Owner"]) form.role.choices.append(["np-owner", "No-Permissions Owner"]) if not form.validate(): return self.render( "group-edit-member.html", group=group, member=member, edge=edge, form=form, alerts=self.get_form_alerts(form.errors), ) fail_message = 'This join is denied with this role at this time.' try: user_can_join = assert_can_join(group, user_or_group, role=form.data["role"]) except UserNotAuditor as e: user_can_join = False fail_message = e if not user_can_join: return self.render("group-edit-member.html", form=form, group=group, member=member, edge=edge, alerts=[ Alert('danger', fail_message, 'Audit Policy Enforcement') ]) expiration = None if form.data["expiration"]: expiration = datetime.strptime(form.data["expiration"], "%m/%d/%Y") try: group.edit_member(self.current_user, user_or_group, form.data["reason"], role=form.data["role"], expiration=expiration) except (InvalidRoleForMember, PluginRejectedGroupMembershipUpdate) as e: return self.render("group-edit-member.html", form=form, group=group, member=member, edge=edge, alerts=[Alert('danger', e.message)]) return self.redirect("/groups/{}?refresh=yes".format(group.name))
def post(self, request_id, group_id=None, name=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() members = group.my_members() my_role = user_role(self.current_user, members) if my_role not in ("manager", "owner", "np-owner"): return self.forbidden() request = self.session.query(Request).filter_by(id=request_id).scalar() if not request: return self.notfound() on_behalf = get_on_behalf_by_request(self.session, request) form = GroupRequestModifyForm(self.request.arguments) form.status.choices = self._get_choices(request.status) updates = request.my_status_updates() if not form.status.choices: alerts = [Alert("info", "Request has already been processed")] return self.render( "group-request-update.html", group=group, request=request, on_behalf=on_behalf, members=members, form=form, alerts=alerts, statuses=REQUEST_STATUS_CHOICES, updates=updates ) if not form.validate(): return self.render( "group-request-update.html", group=group, request=request, on_behalf=on_behalf, members=members, form=form, alerts=self.get_form_alerts(form.errors), statuses=REQUEST_STATUS_CHOICES, updates=updates ) # We have to test this here, too, to ensure that someone can't sneak in with a pending # request that used to be allowed. if form.data["status"] != "cancelled": fail_message = 'This join is denied with this role at this time.' try: user_can_join = assert_can_join( request.requesting, on_behalf, role=request.edge.role, ) except UserNotAuditor as e: user_can_join = False fail_message = e if not user_can_join: return self.render( "group-request-update.html", group=group, request=request, on_behalf=on_behalf, members=members, form=form, statuses=REQUEST_STATUS_CHOICES, updates=updates, alerts=[ Alert('danger', fail_message, 'Audit Policy Enforcement') ] ) request.update_status( self.current_user, form.data["status"], form.data["reason"] ) self.session.commit() AuditLog.log(self.session, self.current_user.id, 'update_request', 'Updated request to status: {}'.format(form.data["status"]), on_group_id=group.id, on_user_id=request.requester.id) edge = self.session.query(GroupEdge).filter_by( id=request.edge_id ).one() approver_mail_to = [ user.name for user in group.my_approver_users() if user.name != self.current_user.name and user.name != request.requester.username ] subj = "Re: " + self.render_template( 'email/pending_request_subj.tmpl', group=group.name, user=request.requester.username ) send_email( self.session, approver_mail_to, subj, "approver_request_updated", settings, { 'group_name': group.name, 'requester': request.requester.username, 'changed_by': self.current_user.name, 'status': form.data['status'], 'role': edge.role, 'reason': form.data['reason'], 'references_header': request.reference_id, }, ) if form.data['status'] == 'actioned': send_email( self.session, [request.requester.name], 'Added to group: {}'.format(group.groupname), 'request_actioned', settings, { 'group_name': group.name, 'actioned_by': self.current_user.name, 'reason': form.data['reason'], 'expiration': edge.expiration, 'role': edge.role, } ) elif form.data['status'] == 'cancelled': send_email( self.session, [request.requester.name], 'Request to join cancelled: {}'.format(group.groupname), 'request_cancelled', settings, { 'group_name': group.name, 'cancelled_by': self.current_user.name, 'reason': form.data['reason'], 'expiration': edge.expiration, 'role': edge.role, } ) # No explicit refresh because handler queries SQL. if form.data['redirect_aggregate']: return self.redirect("/user/requests") else: return self.redirect("/groups/{}/requests".format(group.name))
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_service_account(self.session, member): # For service accounts, we want to always add the group to other groups, not the user member = get_service_account(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() 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) 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 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 get_group_view_template_vars(session, actor, group, graph): # type: (Session, User, Group, GroupGraph) -> Dict[str, Any] ret = {} ret["grantable"] = user_grantable_permissions(session, actor) try: group_md = graph.get_group_details(group.name) except NoSuchGroup: # Very new group with no metadata yet, or it has been disabled and # excluded from in-memory cache. group_md = {} ret["members"] = group.my_members() ret["groups"] = group.my_groups() ret["service_accounts"] = get_service_accounts(session, group) ret["permissions"] = group_md.get("permissions", []) for permission in ret["permissions"]: permission["granted_on"] = datetime.fromtimestamp( permission["granted_on"]) ret["permission_requests_pending"] = [] for req in get_pending_request_by_group(session, group): granters = [] for owner, argument in get_owner_arg_list(session, req.permission, req.argument): granters.append(owner.name) ret["permission_requests_pending"].append((req, granters)) ret["audited"] = group_md.get("audited", False) ret["log_entries"] = group.my_log_entries() ret["num_pending"] = count_requests_by_group(session, group, status="pending") ret["current_user_role"] = { "is_owner": user_role_index(actor, ret["members"]) in OWNER_ROLE_INDICES, "is_approver": user_role_index(actor, ret["members"]) in APPROVER_ROLE_INDICES, "is_manager": user_role(actor, ret["members"]) == "manager", "is_member": user_role(actor, ret["members"]) is not None, "role": user_role(actor, ret["members"]), } ret["can_leave"] = (ret["current_user_role"]["is_member"] and not ret["current_user_role"]["is_owner"]) ret["statuses"] = AUDIT_STATUS_CHOICES # Add mapping_id to permissions structure ret["my_permissions"] = group.my_permissions() for perm_up in ret["permissions"]: for perm_direct in ret["my_permissions"]: if (perm_up["permission"] == perm_direct.name and perm_up["argument"] == perm_direct.argument): perm_up["mapping_id"] = perm_direct.mapping_id break ret["alerts"] = [] ret["self_pending"] = count_requests_by_group(session, group, status="pending", user=actor) if ret["self_pending"]: ret["alerts"].append( Alert("info", "You have a pending request to join this group.", None)) return ret
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 post(self, group_id=None, name=None, name2=None, member_type=None): group = Group.get(self.session, group_id, name) if not group: return self.notfound() if self.current_user.name == name2: return self.forbidden() members = group.my_members() my_role = user_role(self.current_user, members) if my_role not in ("manager", "owner", "np-owner"): return self.forbidden() member = members.get((member_type.capitalize(), name2), None) if not member: return self.notfound() if member.type == "Group": user_or_group = Group.get(self.session, member.id) else: user_or_group = User.get(self.session, member.id) if not user_or_group: return self.notfound() edge = GroupEdge.get( self.session, group_id=group.id, member_type=OBJ_TYPES[member.type], member_pk=member.id, ) if not edge: return self.notfound() form = GroupEditMemberForm(self.request.arguments) form.role.choices = [["member", "Member"]] if my_role in ("owner", "np-owner"): form.role.choices.append(["manager", "Manager"]) form.role.choices.append(["owner", "Owner"]) form.role.choices.append(["np-owner", "No-Permissions Owner"]) if not form.validate(): return self.render( "group-edit-member.html", group=group, member=member, edge=edge, form=form, alerts=self.get_form_alerts(form.errors), ) fail_message = 'This join is denied with this role at this time.' try: user_can_join = assert_can_join(group, user_or_group, role=form.data["role"]) except UserNotAuditor as e: user_can_join = False fail_message = e if not user_can_join: return self.render( "group-edit-member.html", form=form, group=group, member=member, edge=edge, alerts=[ Alert('danger', fail_message, 'Audit Policy Enforcement') ] ) expiration = None if form.data["expiration"]: expiration = datetime.strptime(form.data["expiration"], "%m/%d/%Y") try: group.edit_member(self.current_user, user_or_group, form.data["reason"], role=form.data["role"], expiration=expiration) except InvalidRoleForMember as e: return self.render( "group-edit-member.html", form=form, group=group, member=member, edge=edge, alerts=[ Alert('danger', e.message) ] ) return self.redirect("/groups/{}?refresh=yes".format(group.name))