Exemple #1
0
    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))
Exemple #2
0
    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))
Exemple #3
0
    def get(self, *args: Any, **kwargs: Any) -> None:
        name = self.get_path_argument("name")

        self.handle_refresh()
        user = User.get(self.session, name=name)

        if not user or not user.role_user:
            return self.notfound()

        group = Group.get(self.session, name=name)
        if not group:
            return self.notfound()
        actor = self.current_user
        graph = self.graph
        session = self.session
        self.render("role-user.html",
                    user=user,
                    group=group,
                    audit_members_infos=get_group_audit_members_infos(
                        self.session, group),
                    **get_role_user_view_template_vars(session, actor, user,
                                                       group, graph))
Exemple #4
0
    def get(self, *args, **kwargs):
        # type: (*Any, **Any) -> None
        user_id = kwargs.get("user_id")  # type: Optional[int]
        name = kwargs.get("name")  # type: Optional[str]

        self.handle_refresh()
        user = User.get(self.session, user_id, name)

        if not user or not user.role_user:
            return self.notfound()

        group = Group.get(self.session, name=name)
        actor = self.current_user
        graph = self.graph
        session = self.session
        self.render("service.html",
                    user=user,
                    group=group,
                    audit_members_infos=get_group_audit_members_infos(
                        self.session, group),
                    **get_role_user_view_template_vars(session, actor, user,
                                                       group, graph))
Exemple #5
0
def test_audit_end_to_end(session, users, groups, http_client, base_url,
                          graph):  # noqa: F811
    """ Tests an end-to-end audit cycle. """
    groupname = "audited-team"

    gary_id = users["*****@*****.**"].id

    # make everyone an auditor or global audit will have issues
    add_member(groups["auditors"], users["*****@*****.**"])
    add_member(groups["auditors"], users["*****@*****.**"])
    add_member(groups["auditors"], users["*****@*****.**"])
    add_member(groups["auditors"], users["*****@*****.**"])

    # add some users to test removal
    add_member(groups[groupname], users["*****@*****.**"])
    add_member(groups[groupname], users["*****@*****.**"])

    graph.update_from_db(session)

    # start the audit
    end_at_str = (datetime.now() + timedelta(days=10)).strftime("%m/%d/%Y")
    fe_url = url(base_url, "/audits/create")
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"ends_at": end_at_str}),
        headers={"X-Grouper-User": "******"},
    )
    assert resp.code == 200

    open_audits = get_audits(session, only_open=True).all()
    assert len(open_audits) == 4, "audits created"

    assert groupname in [x.group.name for x in open_audits
                         ], "group we expect also gets audit"

    # pull all the info we need to resolve audits, avoids detached sqlalchemy sessions
    # (DetachedInstanceError)
    all_group_ids = [x.group.id for x in open_audits]
    open_audits = [
        Audit(
            x.id,
            next(iter(x.group.my_owners())),
            x.group.name,
            [
                MyAuditMemberInfo(
                    ami.audit_member_obj.id,
                    ami.audit_member_obj.edge.member_type,
                    ami.audit_member_obj.edge_id,
                ) for ami in get_group_audit_members_infos(session, x.group)
            ],
        ) for x in open_audits
    ]

    # approve everything but the one we added members to
    for one_audit in open_audits:
        fe_url = url(base_url,
                     "/audits/{}/complete".format(one_audit.audit_id))

        if one_audit.group_name == groupname:
            continue

        # blanket approval
        body = urlencode({
            "audit_{}".format(ami.am_id): "approved"
            for ami in one_audit.audit_members_infos
        })

        resp = yield http_client.fetch(
            fe_url,
            method="POST",
            body=body,
            headers={"X-Grouper-User": one_audit.owner_name})
        assert resp.code == 200

    open_audits = get_audits(session, only_open=True).all()
    assert len(open_audits) == 1, "only our test group remaining"

    one_audit = open_audits[0]
    one_audit.id

    body_dict = {}
    for ami in get_group_audit_members_infos(session, one_audit.group):
        if gary_id == ami.member_obj.id:
            # deny
            body_dict["audit_{}".format(ami.audit_member_obj.id)] = "remove"
        else:
            # approve
            body_dict["audit_{}".format(ami.audit_member_obj.id)] = "approved"

    owner_name = next(iter(one_audit.group.my_owners()))
    fe_url = url(base_url, "/audits/{}/complete".format(one_audit.id))
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   body=urlencode(body_dict),
                                   headers={"X-Grouper-User": owner_name})
    assert resp.code == 200

    # check all the logs
    assert len(AuditLog.get_entries(
        session, action="start_audit")) == 1, "global start is logged"
    assert (len(AuditLog.get_entries(
        session,
        action="complete_global_audit")) == 1), "global complete is logged"

    for group_id in all_group_ids:
        assert (len(
            AuditLog.get_entries(
                session,
                on_group_id=group_id,
                action="complete_audit",
                category=AuditLogCategory.audit,
            )) == 1), "complete entry for each group"

    assert (len(
        AuditLog.get_entries(session,
                             on_user_id=gary_id,
                             category=AuditLogCategory.audit)) == 1
            ), "removal AuditLog entry on user"
Exemple #6
0
    def post(self, audit_id):
        if not user_has_permission(self.session, self.current_user,
                                   PERMISSION_AUDITOR):
            return self.forbidden()

        audit = self.session.query(Audit).filter(Audit.id == audit_id).one()

        # only owners can complete
        owner_ids = {member.id for member in audit.group.my_owners().values()}
        if self.current_user.id not in owner_ids:
            return self.forbidden()

        if audit.complete:
            return self.redirect("/groups/{}".format(audit.group.name))

        edges = {}
        for argument in self.request.arguments:
            if argument.startswith("audit_"):
                edges[int(argument.split("_")
                          [1])] = self.request.arguments[argument][0].decode()

        for audit_member_info in get_group_audit_members_infos(
                self.session, audit.group):
            if audit_member_info.audit_member_obj.id in edges:
                # You can only approve yourself (otherwise you can remove yourself
                # from the group and leave it ownerless)
                if audit_member_info.member_obj.id == self.current_user.id:
                    audit_member_info.audit_member_obj.status = "approved"
                elif edges[audit_member_info.audit_member_obj.
                           id] in AUDIT_STATUS_CHOICES:
                    audit_member_info.audit_member_obj.status = edges[
                        audit_member_info.audit_member_obj.id]

        self.session.commit()

        # If there are still pending statuses, then redirect to the group page.
        if group_has_pending_audit_members(self.session, audit.group):
            return self.redirect("/groups/{}".format(audit.group.name))

        # Complete audits have to be "enacted" now. This means anybody marked as remove has to
        # be removed from the group now.
        try:
            for audit_member_info in get_group_audit_members_infos(
                    self.session, audit.group):
                member_obj = audit_member_info.member_obj
                if audit_member_info.audit_member_obj.status == "remove":
                    audit.group.revoke_member(self.current_user, member_obj,
                                              "Revoked as part of audit.")
                    AuditLog.log(
                        self.session,
                        self.current_user.id,
                        "remove_member",
                        "Removed membership in audit: {}".format(
                            member_obj.name),
                        on_group_id=audit.group.id,
                        on_user_id=member_obj.id,
                        category=AuditLogCategory.audit,
                    )
        except PluginRejectedGroupMembershipUpdate as e:
            alert = Alert("danger", str(e))
            return self.redirect("/groups/{}".format(audit.group.name),
                                 alerts=[alert])

        audit.complete = True
        self.session.commit()

        # Now cancel pending emails
        cancel_async_emails(self.session, "audit-{}".format(audit.group.id))

        AuditLog.log(
            self.session,
            self.current_user.id,
            "complete_audit",
            "Completed group audit.",
            on_group_id=audit.group.id,
            category=AuditLogCategory.audit,
        )

        # check if all audits are complete
        if get_audits(self.session, only_open=True).count() == 0:
            AuditLog.log(
                self.session,
                self.current_user.id,
                "complete_global_audit",
                "last open audit have been completed",
                category=AuditLogCategory.audit,
            )

        return self.redirect("/groups/{}".format(audit.group.name))