Esempio n. 1
0
def test_remove_last_owner_via_audit(async_server, browser, users, groups, session):  # noqa: F811
    future = datetime.utcnow() + timedelta(1)

    add_member(groups["auditors"], users["*****@*****.**"], role="owner")
    add_member(groups["audited-team"], users["*****@*****.**"], role="owner", expiration=future)

    session.commit()

    fe_url = url(async_server, "/audits/create")
    browser.get(fe_url)

    page = AuditsCreatePage(browser)

    page.set_end_date(future.strftime("%m/%d/%Y"))
    page.submit()

    fe_url = url(async_server, "/groups/audited-team")
    browser.get(fe_url)

    page = GroupViewPage(browser)

    audit_modal = page.get_audit_modal()
    audit_modal.find_member_row("*****@*****.**").set_audit_status("remove")
    audit_modal.confirm()

    assert page.current_url.endswith("/groups/audited-team")
    assert page.has_text(group_ownership_policy.EXCEPTION_MESSAGE)
Esempio n. 2
0
def test_remove_last_owner_via_audit(async_server, browser, users, groups, session):  # noqa: F811
    future = datetime.utcnow() + timedelta(1)

    add_member(groups["auditors"], users["*****@*****.**"], role="owner")
    add_member(groups["audited-team"], users["*****@*****.**"], role="owner", expiration=future)

    session.commit()

    fe_url = url(async_server, "/audits/create")
    browser.get(fe_url)

    page = AuditsCreatePage(browser)

    page.set_end_date(future.strftime("%m/%d/%Y"))
    page.submit()

    fe_url = url(async_server, "/groups/audited-team")
    browser.get(fe_url)

    page = GroupViewPage(browser)

    audit_modal = page.get_audit_modal()
    audit_modal.find_member_row("*****@*****.**").set_audit_status("remove")
    audit_modal.confirm()

    assert page.current_url.endswith("/groups/audited-team")
    assert page.has_text(group_ownership_policy.EXCEPTION_MESSAGE)
def test_can_add_owner_twice(get_plugin_proxy, session, groups, users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    owner = users["*****@*****.**"]

    add_member(group, owner, role="owner")
    add_member(group, owner, role="owner")
def test_can_disable_member(get_plugin_proxy, session, groups, users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    member = users["*****@*****.**"]

    add_member(group, member)
    disable_user(session, member)
def test_can_disable_member(get_plugin_proxy, session, groups,
                            users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    member = users["*****@*****.**"]

    add_member(group, member)
    disable_user(session, member)
def test_can_add_owner_twice(get_plugin_proxy, session, groups,
                             users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    owner = users["*****@*****.**"]

    add_member(group, owner, role="owner")
    add_member(group, owner, role="owner")
def test_cant_demote_last_owner(get_plugin_proxy, groups, users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    owner = users["*****@*****.**"]

    add_member(group, owner, role="owner")

    with pytest.raises(PluginRejectedGroupMembershipUpdate):
        group.edit_member(owner, owner, "Unit Testing", role="member")
def test_cant_disable_last_owner(get_plugin_proxy, session, groups, users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    owner = users["*****@*****.**"]

    add_member(group, owner, role="owner")

    with pytest.raises(PluginRejectedDisablingUser):
        disable_user(session, owner)
def test_cant_demote_last_owner(get_plugin_proxy, groups, users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    owner = users["*****@*****.**"]

    add_member(group, owner, role="owner")

    with pytest.raises(PluginRejectedGroupMembershipUpdate):
        group.edit_member(owner, owner, "Unit Testing", role="member")
def test_cant_disable_last_owner(get_plugin_proxy, session, groups,
                                 users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    owner = users["*****@*****.**"]

    add_member(group, owner, role="owner")

    with pytest.raises(PluginRejectedDisablingUser):
        disable_user(session, owner)
def test_cant_expire_last_owner(get_plugin_proxy, groups, users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    owner = users["*****@*****.**"]

    expiration = datetime.utcnow() + timedelta(1)

    add_member(group, owner, role="owner")

    with pytest.raises(PluginRejectedGroupMembershipUpdate):
        group.edit_member(owner, owner, "Unit Testing", expiration=expiration)
def test_cant_expire_last_owner(get_plugin_proxy, groups, users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    owner = users["*****@*****.**"]

    expiration = datetime.utcnow() + timedelta(1)

    add_member(group, owner, role="owner")

    with pytest.raises(PluginRejectedGroupMembershipUpdate):
        group.edit_member(owner, owner, "Unit Testing", expiration=expiration)
def test_can_always_revoke_members(get_plugin_proxy, groups, users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    owner = users["*****@*****.**"]
    member = users["*****@*****.**"]

    expiration = datetime.utcnow() + timedelta(1)

    add_member(group, owner, role="owner", expiration=expiration)
    add_member(group, member)

    revoke_member(group, member)
def test_can_always_revoke_members(get_plugin_proxy, groups,
                                   users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    owner = users["*****@*****.**"]
    member = users["*****@*****.**"]

    expiration = datetime.utcnow() + timedelta(1)

    add_member(group, owner, role="owner", expiration=expiration)
    add_member(group, member)

    revoke_member(group, member)
def test_cant_revoke_last_permanent_owner(get_plugin_proxy, groups, users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    first_owner = users["*****@*****.**"]
    second_owner = users["*****@*****.**"]

    expiration = datetime.utcnow() + timedelta(1)

    add_member(group, first_owner, role="owner", expiration=expiration)
    add_member(group, second_owner, role="owner")

    with pytest.raises(PluginRejectedGroupMembershipUpdate):
        revoke_member(group, second_owner)
Esempio n. 16
0
def test_graph_edit_role(
        session,
        graph,
        standard_graph,
        groups,
        users,
        http_client,
        base_url  # noqa: F811
):
    """Test that membership role changes are refected in the graph."""
    user_role = graph.get_group_details(
        "tech-ops")["users"]["*****@*****.**"]["rolename"]
    assert user_role == "np-owner"

    # Ensure they are auditors so that they can be owner.
    add_member(groups["auditors"], users["*****@*****.**"])
    session.commit()

    # np-owner cannot upgrade themselves to owner
    resp = yield http_client.fetch(
        url(base_url, "/groups/tech-ops/edit/user/[email protected]"),
        method="POST",
        headers={"X-Grouper-User": "******"},
        body=urlencode({
            "role": "owner",
            "reason": "testing"
        }),
    )
    assert resp.code == 200
    graph.update_from_db(session)
    user_role = graph.get_group_details(
        "tech-ops")["users"]["*****@*****.**"]["rolename"]
    assert user_role == "np-owner"

    # but an owner can
    resp = yield http_client.fetch(
        url(base_url, "/groups/tech-ops/edit/user/[email protected]"),
        method="POST",
        headers={"X-Grouper-User": "******"},
        body=urlencode({
            "role": "owner",
            "reason": "testing"
        }),
    )
    assert resp.code == 200
    graph.update_from_db(session)
    user_role = graph.get_group_details(
        "tech-ops")["users"]["*****@*****.**"]["rolename"]
    assert user_role == "owner"
def test_cant_revoke_last_permanent_owner(get_plugin_proxy, groups,
                                          users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    first_owner = users["*****@*****.**"]
    second_owner = users["*****@*****.**"]

    expiration = datetime.utcnow() + timedelta(1)

    add_member(group, first_owner, role="owner", expiration=expiration)
    add_member(group, second_owner, role="owner")

    with pytest.raises(PluginRejectedGroupMembershipUpdate):
        revoke_member(group, second_owner)
Esempio n. 18
0
def expired_graph(session, graph, groups, users):  # noqa: F811
    now = datetime.utcnow()

    # expired user membership
    add_member(groups["team-sre"], users["*****@*****.**"], role="owner")
    add_member(groups["team-sre"], users["*****@*****.**"], expiration=now)

    # expired group membership
    add_member(groups["serving-team"], users["*****@*****.**"], role="owner")
    add_member(groups["serving-team"], groups["team-sre"], expiration=now)

    # expired user membership in disabled group
    add_member(groups["sad-team"], users["*****@*****.**"], expiration=now)
    groups["sad-team"].disable()
    session.commit()

    return graph
def test_cant_revoke_last_npowner(get_plugin_proxy, session, groups, users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    first_owner = users["*****@*****.**"]
    second_owner = users["*****@*****.**"]

    add_member(group, first_owner, role="np-owner")
    add_member(group, second_owner, role="np-owner")

    # Revoking the first owner does not raise an exception
    revoke_member(group, first_owner)

    session.commit()

    with pytest.raises(PluginRejectedGroupMembershipUpdate):
        revoke_member(group, second_owner)
def test_cant_revoke_last_npowner(get_plugin_proxy, session, groups,
                                  users):  # noqa: F811
    get_plugin_proxy.return_value = PluginProxy([GroupOwnershipPolicyPlugin()])

    group = groups["team-infra"]
    first_owner = users["*****@*****.**"]
    second_owner = users["*****@*****.**"]

    add_member(group, first_owner, role="np-owner")
    add_member(group, second_owner, role="np-owner")

    # Revoking the first owner does not raise an exception
    revoke_member(group, first_owner)

    session.commit()

    with pytest.raises(PluginRejectedGroupMembershipUpdate):
        revoke_member(group, second_owner)
Esempio n. 21
0
def test_list_public_keys(async_server, browser, session, users,
                          groups):  # noqa: F811
    permission = Permission.get_or_create(session,
                                          name=AUDIT_SECURITY,
                                          description="")[0]
    user = users["*****@*****.**"]
    group = groups["group-admins"]

    add_member(group, user, role="owner")
    grant_permission(group, permission, "public_keys")

    # Pagination defaults to 100 keys per page
    for i in range(120):
        key = PublicKey(
            user=user,
            public_key="KEY:{}".format(i),
            fingerprint="MD5:{}".format(i),
            fingerprint_sha256="SHA256:{}".format(i),
            key_size=4096,
            key_type="ssh-rsa",
            comment="",
        )
        key.add(session)

    session.commit()

    fe_url = url(async_server, "/users/public-keys")
    browser.get(fe_url)

    page = PublicKeysPage(browser)

    row = page.find_public_key_row("SHA256:0")
    assert row.user == user.username
    assert row.key_size == "4096"
    assert row.key_type == "ssh-rsa"

    assert page.find_public_key_row("SHA256:99")

    with pytest.raises(NoSuchElementException):
        page.find_public_key_row("SHA256:100")
Esempio n. 22
0
def test_list_public_keys(async_server, browser, session, users, groups):  # noqa: F811
    permission = Permission.get_or_create(session, name=AUDIT_SECURITY, description="")[0]
    user = users["*****@*****.**"]
    group = groups["group-admins"]

    add_member(group, user, role="owner")
    grant_permission(group, permission, "public_keys")

    # Pagination defaults to 100 keys per page
    for i in range(120):
        key = PublicKey(
            user=user,
            public_key="KEY:{}".format(i),
            fingerprint="MD5:{}".format(i),
            fingerprint_sha256="SHA256:{}".format(i),
            key_size=4096,
            key_type="ssh-rsa",
            comment="",
        )
        key.add(session)

    session.commit()

    fe_url = url(async_server, "/users/public-keys")
    browser.get(fe_url)

    page = PublicKeysPage(browser)

    row = page.find_public_key_row("SHA256:0")
    assert row.user == user.username
    assert row.key_size == "4096"
    assert row.key_type == "ssh-rsa"

    assert page.find_public_key_row("SHA256:99")

    with pytest.raises(NoSuchElementException):
        page.find_public_key_row("SHA256:100")
Esempio n. 23
0
def test_graph_cycle_direct(session, graph, users, groups):  # noqa: F811
    """ Test adding members where all descendants already exist."""

    add_member(groups["team-sre"], users["*****@*****.**"])
    add_member(groups["tech-ops"], users["*****@*****.**"])

    add_member(groups["team-sre"], groups["tech-ops"])
    add_member(groups["tech-ops"], groups["team-sre"])

    session.commit()
    graph.update_from_db(session)
    assert get_users(graph, "team-sre") == set(["*****@*****.**", "*****@*****.**"])
    assert get_users(graph, "team-sre", cutoff=1) == set(["*****@*****.**"])

    assert get_users(graph, "tech-ops") == set(["*****@*****.**", "*****@*****.**"])
    assert get_users(graph, "tech-ops", cutoff=1) == set(["*****@*****.**"])

    assert get_groups(graph, "*****@*****.**") == set(["team-sre", "tech-ops"])
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["team-sre"])

    assert get_groups(graph, "*****@*****.**") == set(["team-sre", "tech-ops"])
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["tech-ops"])
Esempio n. 24
0
def test_graph_cycle_direct(session, graph, users, groups):  # noqa: F811
    """ Test adding members where all descendants already exist."""

    add_member(groups["team-sre"], users["*****@*****.**"])
    add_member(groups["tech-ops"], users["*****@*****.**"])

    add_member(groups["team-sre"], groups["tech-ops"])
    add_member(groups["tech-ops"], groups["team-sre"])

    session.commit()
    graph.update_from_db(session)
    assert get_users(graph, "team-sre") == set(["*****@*****.**", "*****@*****.**"])
    assert get_users(graph, "team-sre", cutoff=1) == set(["*****@*****.**"])

    assert get_users(graph, "tech-ops") == set(["*****@*****.**", "*****@*****.**"])
    assert get_users(graph, "tech-ops", cutoff=1) == set(["*****@*****.**"])

    assert get_groups(graph, "*****@*****.**") == set(["team-sre", "tech-ops"])
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["team-sre"])

    assert get_groups(graph, "*****@*****.**") == set(["team-sre", "tech-ops"])
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["tech-ops"])
Esempio n. 25
0
def standard_graph(session, graph, users, groups, service_accounts, permissions):
    """Setup a standard graph used for many tests. In graph form:

    +-----------------------+
    |                       |
    |  team-sre             |
    |    * gary (o)         +---------------------------------+
    |    * zay              |                                 |
    |    * zorkian          |                                 |
    |    * service (s)      |                     +-----------v-----------+
    |                       |                     |                       |
    +-----------------------+                     |  serving-team         |
    +-----------------------+           +--------->    * zorkian (o)      |
    |                       |           |         |                       |
    |  tech-ops             |           |         +-----------+-----------+
    |    * zay (o)          |           |                     |
    |    * gary             +-----------+                     |
    |    * figurehead (np)  |                                 |
    |                       |                                 |
    +-----------------------+                                 |
    +-----------------------+                     +-----------v-----------+
    |                       |                     |                       |
    |  security-team        |                     |  team-infra           |
    |    * oliver (o)       +--------------------->    * gary (o)         |
    |    * figurehead       |                     |                       |
    |                       |                     +-----------+-----------+
    +-----------------------+                                 |
    +-----------------------+                                 |
    |                       |                                 |
    |  sad-team             |                                 |
    |    * zorkian (o)      |                                 |
    |    * oliver           |                     +-----------v-----------+
    |                       |                     |                       |
    +-----------------------+                     |  all-teams            |
    +-----------------------+                     |    * testuser (o)     |
    |                       |                     |                       |
    |  audited-team         |                     +-----------------------+
    |    * zorkian (o)      |
    |                       |
    +-----------------------+
    +-----------------------+
    |                       |
    |  auditors             |
    |    * zorkian (o)      |
    |                       |
    +-----------------------+
    +-----------------------+
    |                       |
    |  user-admins          |
    |    * tyleromeara (o)  |
    |    * cbguder (o)      |
    |                       |
    +-----------------------+
    +-----------------------+
    |                       |
    |  group-admins         |
    |    * cbguder (o)      |
    |                       |
    +-----------------------+
    +-----------------------+
    |                       |
    |  permission-admins    |
    |    * gary (o)         |
    |    * cbguder          |
    |                       |
    +-----------------------+

    Arrows denote member of the source in the destination group. (o) for
    owners, (np) for non-permissioned owners, (s) for service accounts.
    """
    add_member(groups["team-sre"], users["*****@*****.**"], role="owner")
    add_member(groups["team-sre"], users["*****@*****.**"])
    add_member(groups["team-sre"], users["*****@*****.**"])
    grant_permission(groups["team-sre"], permissions["ssh"], argument="*")
    grant_permission(groups["team-sre"], permissions["team-sre"], argument="*")

    add_member(groups["serving-team"], users["*****@*****.**"], role="owner")
    add_member(groups["serving-team"], groups["team-sre"])
    add_member(groups["serving-team"], groups["tech-ops"])
    grant_permission(groups["serving-team"], permissions["audited"])

    add_member(groups["tech-ops"], users["*****@*****.**"], role="owner")
    add_member(groups["tech-ops"], users["*****@*****.**"])
    add_member(groups["tech-ops"], users["*****@*****.**"], role="np-owner")
    grant_permission(groups["tech-ops"], permissions["ssh"], argument="shell")

    add_member(groups["security-team"], users["*****@*****.**"], role="owner")
    add_member(groups["security-team"], users["*****@*****.**"], role="member")

    add_member(groups["sad-team"], users["*****@*****.**"], role="owner")
    add_member(groups["sad-team"], users["*****@*****.**"])
    grant_permission(groups["sad-team"], permissions["owner"], argument="sad-team")

    add_member(groups["audited-team"], users["*****@*****.**"], role="owner")
    grant_permission(groups["audited-team"], permissions["audited"])

    add_member(groups["team-infra"], users["*****@*****.**"], role="owner")
    add_member(groups["team-infra"], groups["serving-team"])
    add_member(groups["team-infra"], groups["security-team"])
    grant_permission(groups["team-infra"], permissions["sudo"], argument="shell")

    add_member(groups["auditors"], users["*****@*****.**"], role="owner")
    grant_permission(groups["auditors"], permissions[AUDIT_VIEWER])
    grant_permission(groups["auditors"], permissions[AUDIT_MANAGER])
    grant_permission(groups["auditors"], permissions[PERMISSION_AUDITOR])

    add_member(groups["all-teams"], users["*****@*****.**"], role="owner")
    add_member(groups["all-teams"], groups["team-infra"])

    add_member(groups["user-admins"], users["*****@*****.**"], role="owner")
    add_member(groups["user-admins"], users["*****@*****.**"], role="owner")
    grant_permission(groups["user-admins"], permissions[USER_ADMIN])

    add_member(groups["group-admins"], users["*****@*****.**"], role="owner")
    grant_permission(groups["group-admins"], permissions[GROUP_ADMIN])

    add_member(groups["permission-admins"], users["*****@*****.**"], role="owner")
    add_member(groups["permission-admins"], users["*****@*****.**"], role="member")
    grant_permission(groups["permission-admins"], permissions[PERMISSION_ADMIN])

    session.commit()
    graph.update_from_db(session)

    return graph
Esempio n. 26
0
def expiring_graph(session, graph, users, groups, permissions):  # noqa: F811
    now = datetime.utcnow()
    note_exp_now = now + timedelta(settings().expiration_notice_days)
    week = timedelta(7)

    add_member(groups["team-sre"], users["*****@*****.**"], role="owner")
    add_member(groups["team-sre"], users["*****@*****.**"], role="owner")
    add_member(groups["team-sre"], users["*****@*****.**"], expiration=note_exp_now + week)
    add_member(groups["team-sre"], users["*****@*****.**"])
    add_member(
        groups["team-sre"], users["*****@*****.**"], role="owner", expiration=note_exp_now + week
    )
    revoke_member(groups["team-sre"], users["*****@*****.**"])
    grant_permission(groups["team-sre"], permissions["ssh"], argument="*")

    add_member(groups["serving-team"], users["*****@*****.**"], role="owner")
    add_member(groups["serving-team"], groups["team-sre"], expiration=note_exp_now + week)
    add_member(groups["serving-team"], groups["tech-ops"])
    grant_permission(groups["serving-team"], permissions["audited"])

    add_member(groups["tech-ops"], users["*****@*****.**"], role="owner")
    add_member(groups["tech-ops"], users["*****@*****.**"], expiration=note_exp_now + 2 * week)
    grant_permission(groups["tech-ops"], permissions["ssh"], argument="shell")

    return graph
Esempio n. 27
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"
Esempio n. 28
0
def test_graph_add_member_existing(session, graph, users,
                                   groups):  # noqa: F811
    """ Test adding members to an existing relationship."""

    add_member(groups["team-sre"], users["*****@*****.**"], role="owner")
    add_member(groups["tech-ops"], users["*****@*****.**"], role="owner")

    add_member(groups["team-infra"], users["*****@*****.**"], role="owner")
    add_member(groups["team-infra"], groups["team-sre"])
    add_member(groups["team-infra"], groups["tech-ops"])

    add_member(groups["all-teams"], users["*****@*****.**"], role="owner")
    add_member(groups["all-teams"], groups["team-infra"])

    add_member(groups["team-sre"], users["*****@*****.**"])
    add_member(groups["tech-ops"], users["*****@*****.**"])

    session.commit()
    graph.update_from_db(session)

    assert get_users(graph, "team-sre") == set(["*****@*****.**", "*****@*****.**"])
    assert get_users(graph, "tech-ops") == set(["*****@*****.**", "*****@*****.**"])

    assert get_users(graph, "team-infra") == set(["*****@*****.**", "*****@*****.**"])
    assert get_users(graph, "team-infra", cutoff=1) == set(["*****@*****.**"])

    assert get_users(graph, "all-teams") == set(
        ["*****@*****.**", "*****@*****.**", "*****@*****.**"])
    assert get_users(graph, "all-teams", cutoff=1) == set(["*****@*****.**"])

    assert get_groups(graph, "*****@*****.**") == set(
        ["team-sre", "all-teams", "tech-ops", "team-infra"])
    assert get_groups(graph, "*****@*****.**",
                      cutoff=1) == set(["team-sre", "tech-ops", "team-infra"])

    assert get_groups(graph, "*****@*****.**") == set(
        ["team-sre", "all-teams", "tech-ops", "team-infra"])
    assert get_groups(graph, "*****@*****.**",
                      cutoff=1) == set(["team-sre", "tech-ops"])

    assert get_groups(graph, "*****@*****.**") == set(["all-teams"])
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["all-teams"])
Esempio n. 29
0
def test_graph_cycle_indirect(session, graph, users, groups):  # noqa: F811
    """ Test adding a member that will create a cycle.

        gary         zay            testuser
         |            |                |
        sre <----- tech-ops <----- team-infra <--
         |                                       |
         |                                       |
          --------> all-teams --------------------

    """

    add_member(groups["team-sre"], users["*****@*****.**"])
    add_member(groups["tech-ops"], users["*****@*****.**"])
    add_member(groups["team-infra"], users["*****@*****.**"])

    add_member(groups["team-sre"], groups["tech-ops"])
    add_member(groups["tech-ops"], groups["team-infra"])
    add_member(groups["team-infra"], groups["all-teams"])

    add_member(groups["all-teams"], groups["team-sre"])

    session.commit()
    graph.update_from_db(session)
    all_users = set(["*****@*****.**", "*****@*****.**", "*****@*****.**"])
    all_groups = set(["team-sre", "all-teams", "tech-ops", "team-infra"])

    assert get_users(graph, "team-sre") == all_users
    assert get_users(graph, "team-sre", cutoff=1) == set(["*****@*****.**"])

    assert get_users(graph, "tech-ops") == all_users
    assert get_users(graph, "tech-ops", cutoff=1) == set(["*****@*****.**"])

    assert get_users(graph, "team-infra") == all_users
    assert get_users(graph, "team-infra", cutoff=1) == set(["*****@*****.**"])

    assert get_users(graph, "all-teams") == all_users
    assert get_users(graph, "all-teams", cutoff=1) == set([])

    assert get_groups(graph, "*****@*****.**") == all_groups
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["team-sre"])

    assert get_groups(graph, "*****@*****.**") == all_groups
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["tech-ops"])

    assert get_groups(graph, "*****@*****.**") == all_groups
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["team-infra"])
Esempio n. 30
0
def test_expiration_notifications(
    expiring_graph, session, users, groups, permissions  # noqa: F811
):
    now = datetime.utcnow()
    note_exp_now = now + timedelta(settings().expiration_notice_days)
    day = timedelta(1)
    week = timedelta(7)

    # What expirations are coming up in the next day?  Next week?
    upcoming_expirations = _get_unsent_expirations(session, now + day)
    assert upcoming_expirations == []

    upcoming_expirations = _get_unsent_expirations(session, now + week)
    assert sorted(upcoming_expirations) == [
        # Group, subgroup, subgroup owners.
        ("serving-team", "team-sre", "*****@*****.**"),
        ("serving-team", "team-sre", "*****@*****.**"),
        # Group, user, user.
        ("team-sre", "*****@*****.**", "*****@*****.**"),
    ]

    # Make someone expire a week from now.
    edit_member(groups["team-sre"], users["*****@*****.**"], expiration=note_exp_now + week)
    upcoming_expirations = _get_unsent_expirations(session, now + week)
    assert sorted(upcoming_expirations) == [
        # Group, subgroup, subgroup owners.
        ("serving-team", "team-sre", "*****@*****.**"),
        ("serving-team", "team-sre", "*****@*****.**"),
        # Group, user, user.
        ("team-sre", "*****@*****.**", "*****@*****.**"),
        ("team-sre", "*****@*****.**", "*****@*****.**"),
    ]

    # Now cancel that expiration.
    edit_member(groups["team-sre"], users["*****@*****.**"], expiration=None)
    upcoming_expirations = _get_unsent_expirations(session, now + week)
    assert sorted(upcoming_expirations) == [
        # Group, subgroup, subgroup owners.
        ("serving-team", "team-sre", "*****@*****.**"),
        ("serving-team", "team-sre", "*****@*****.**"),
        # Group, user, user.
        ("team-sre", "*****@*****.**", "*****@*****.**"),
    ]

    # Make an ordinary member an owner.
    edit_member(groups["team-sre"], users["*****@*****.**"], role="owner")
    upcoming_expirations = _get_unsent_expirations(session, now + week)
    assert sorted(upcoming_expirations) == [
        # Group, subgroup, subgroup owners.
        ("serving-team", "team-sre", "*****@*****.**"),
        ("serving-team", "team-sre", "*****@*****.**"),
        ("serving-team", "team-sre", "*****@*****.**"),
        # Group, user, user.
        ("team-sre", "*****@*****.**", "*****@*****.**"),
    ]

    # Make an owner an ordinary member.
    edit_member(groups["team-sre"], users["*****@*****.**"], role="member")
    upcoming_expirations = _get_unsent_expirations(session, now + week)
    assert sorted(upcoming_expirations) == [
        # Group, subgroup, subgroup owners.
        ("serving-team", "team-sre", "*****@*****.**"),
        ("serving-team", "team-sre", "*****@*****.**"),
        # Group, user, user.
        ("team-sre", "*****@*****.**", "*****@*****.**"),
    ]

    # Send notices about expirations coming up in the next day, next week.
    notices_sent = process_async_emails(settings(), session, now + day, dry_run=True)
    assert notices_sent == 0

    notices_sent = process_async_emails(settings(), session, now + week, dry_run=True)
    assert notices_sent == 3
    # ("serving-team", "team-sre", "*****@*****.**")
    # ("serving-team", "team-sre", "*****@*****.**")
    # ("team-sre", "*****@*****.**", "*****@*****.**")

    # Notices in the upcoming week have already been sent, but there's another
    # two weeks from now.
    upcoming_expirations = _get_unsent_expirations(session, now + week)
    assert upcoming_expirations == []

    upcoming_expirations = _get_unsent_expirations(session, now + 2 * week)
    assert upcoming_expirations == [("tech-ops", "*****@*****.**", "*****@*****.**")]

    # We already sent these notices.
    notices_sent = process_async_emails(settings(), session, now + week, dry_run=True)
    assert notices_sent == 0

    # Extend gary's membership to beyond worth mentioning expiration in two weeks.
    add_member(groups["tech-ops"], users["*****@*****.**"], expiration=note_exp_now + 3 * week)

    upcoming_expirations = _get_unsent_expirations(session, now + 2 * week)
    assert upcoming_expirations == []

    notices_sent = process_async_emails(settings(), session, now + 2 * week, dry_run=True)
    assert notices_sent == 0
Esempio n. 31
0
def setup_desc_to_ances(session, users, groups):  # noqa: F811
    add_member(groups["team-sre"], users["*****@*****.**"], role="owner")
    add_member(groups["team-sre"], users["*****@*****.**"])

    add_member(groups["tech-ops"], users["*****@*****.**"], role="owner")
    add_member(groups["tech-ops"], users["*****@*****.**"])

    add_member(groups["team-infra"], users["*****@*****.**"], role="owner")
    add_member(groups["team-infra"], groups["team-sre"])
    add_member(groups["team-infra"], groups["tech-ops"])

    add_member(groups["all-teams"], users["*****@*****.**"], role="owner")
    add_member(groups["all-teams"], groups["team-infra"])
Esempio n. 32
0
def test_aggregate_request(
    graph, groups, permissions, session, standard_graph, users  # noqa: F811
):
    gary = users["*****@*****.**"]
    not_involved = [
        user for name, user in iteritems(users) if name not in ("*****@*****.**", "*****@*****.**")
    ]

    assert not any(
        [user_requests_aggregate(session, u).all() for u in itervalues(users)]
    ), "should have no pending requests to begin with"

    # one request to one team
    groups["team-sre"].add_member(
        users["*****@*****.**"], users["*****@*****.**"], reason="for the lulz"
    )
    session.commit()

    assert len(user_requests_aggregate(session, gary).all()) == 1, "one pending request for owner"
    assert not any(
        [user_requests_aggregate(session, u).all() for u in not_involved]
    ), "no pending requests if you're not the owner"

    # two request to two teams, same owner
    groups["team-infra"].add_member(
        users["*****@*****.**"], users["*****@*****.**"], reason="for the lulz"
    )
    session.commit()

    request_gary = user_requests_aggregate(session, gary).all()
    assert len(request_gary) == 2, "two pending request for owner"
    assert not any(
        [user_requests_aggregate(session, u).all() for u in not_involved]
    ), "no pending requests if you're not the owner"

    # resolving one request should reflect
    request = session.query(Request).filter_by(id=request_gary[0].id).scalar()
    request.update_status(users["*****@*****.**"], "actioned", "for being a good person")
    session.commit()

    assert len(user_requests_aggregate(session, gary).all()) == 1, "one pending request for owner"
    assert not any(
        [user_requests_aggregate(session, u).all() for u in not_involved]
    ), "no pending requests if you're not the owner"

    # requests to dependent teams should reflect apprpriately
    groups["security-team"].add_member(
        users["*****@*****.**"], users["*****@*****.**"], reason="for the lulz"
    )
    session.commit()

    assert (
        len(user_requests_aggregate(session, gary).all()) == 1
    ), "super owner should not get request"
    assert (
        len(user_requests_aggregate(session, users["*****@*****.**"]).all()) == 1
    ), "owner should get request"
    user_not_gary_oliver = [
        u for n, u in iteritems(users) if n not in ("*****@*****.**", "*****@*****.**")
    ]
    assert not any([user_requests_aggregate(session, u).all() for u in user_not_gary_oliver])

    # manager and np-owner should get requests
    figurehead = users["*****@*****.**"]
    add_member(groups["audited-team"], figurehead, role="manager")
    assert (
        len(user_requests_aggregate(session, figurehead).all()) == 0
    ), "no request for np-owner at first"

    groups["tech-ops"].add_member(
        users["*****@*****.**"], users["*****@*****.**"], reason="for the lulz"
    )
    assert len(user_requests_aggregate(session, figurehead).all()) == 1, "request for np-owner"

    groups["audited-team"].add_member(
        users["*****@*****.**"], users["*****@*****.**"], reason="for the lulz"
    )
    assert (
        len(user_requests_aggregate(session, figurehead).all()) == 2
    ), "request for np-owner and manager"
Esempio n. 33
0
def standard_graph(session, graph, users, groups, service_accounts, permissions):
    """Setup a standard graph used for many tests. In graph form:

    +-----------------------+
    |                       |
    |  team-sre             |
    |    * gary (o)         +---------------------------------+
    |    * zay              |                                 |
    |    * zorkian          |                                 |
    |    * service (s)      |                     +-----------v-----------+
    |                       |                     |                       |
    +-----------------------+                     |  serving-team         |
    +-----------------------+           +--------->    * zorkian (o)      |
    |                       |           |         |                       |
    |  tech-ops             |           |         +-----------+-----------+
    |    * zay (o)          |           |                     |
    |    * gary             +-----------+                     |
    |    * figurehead (np)  |                                 |
    |                       |                                 |
    +-----------------------+                                 |
    +-----------------------+                     +-----------v-----------+
    |                       |                     |                       |
    |  security-team        |                     |  team-infra           |
    |    * oliver (o)       +--------------------->    * gary (o)         |
    |    * figurehead       |                     |                       |
    |                       |                     +-----------+-----------+
    +-----------------------+                                 |
    +-----------------------+                                 |
    |                       |                                 |
    |  sad-team             |                                 |
    |    * zorkian (o)      |                                 |
    |    * oliver           |                     +-----------v-----------+
    |                       |                     |                       |
    +-----------------------+                     |  all-teams            |
    +-----------------------+                     |    * testuser (o)     |
    |                       |                     |                       |
    |  audited-team         |                     +-----------------------+
    |    * zorkian (o)      |
    |                       |
    +-----------------------+
    +-----------------------+
    |                       |
    |  auditors             |
    |    * zorkian (o)      |
    |                       |
    +-----------------------+
    +-----------------------+
    |                       |
    |  user-admins          |
    |    * tyleromeara (o)  |
    |    * cbguder (o)      |
    |                       |
    +-----------------------+
    +-----------------------+
    |                       |
    |  group-admins         |
    |    * cbguder (o)      |
    |                       |
    +-----------------------+
    +-----------------------+
    |                       |
    |  permission-admins    |
    |    * gary (o)         |
    |    * cbguder          |
    |                       |
    +-----------------------+

    Arrows denote member of the source in the destination group. (o) for
    owners, (np) for non-permissioned owners, (s) for service accounts.
    """
    add_member(groups["team-sre"], users["*****@*****.**"], role="owner")
    add_member(groups["team-sre"], users["*****@*****.**"])
    add_member(groups["team-sre"], users["*****@*****.**"])
    grant_permission(groups["team-sre"], permissions["ssh"], argument="*")
    grant_permission(groups["team-sre"], permissions["team-sre"], argument="*")

    add_member(groups["serving-team"], users["*****@*****.**"], role="owner")
    add_member(groups["serving-team"], groups["team-sre"])
    add_member(groups["serving-team"], groups["tech-ops"])
    grant_permission(groups["serving-team"], permissions["audited"])

    add_member(groups["tech-ops"], users["*****@*****.**"], role="owner")
    add_member(groups["tech-ops"], users["*****@*****.**"])
    add_member(groups["tech-ops"], users["*****@*****.**"], role="np-owner")
    grant_permission(groups["tech-ops"], permissions["ssh"], argument="shell")

    add_member(groups["security-team"], users["*****@*****.**"], role="owner")
    add_member(groups["security-team"], users["*****@*****.**"], role="member")

    add_member(groups["sad-team"], users["*****@*****.**"], role="owner")
    add_member(groups["sad-team"], users["*****@*****.**"])
    grant_permission(groups["sad-team"], permissions["owner"], argument="sad-team")

    add_member(groups["audited-team"], users["*****@*****.**"], role="owner")
    grant_permission(groups["audited-team"], permissions["audited"])

    add_member(groups["team-infra"], users["*****@*****.**"], role="owner")
    add_member(groups["team-infra"], groups["serving-team"])
    add_member(groups["team-infra"], groups["security-team"])
    grant_permission(groups["team-infra"], permissions["sudo"], argument="shell")

    add_member(groups["auditors"], users["*****@*****.**"], role="owner")
    grant_permission(groups["auditors"], permissions[AUDIT_VIEWER])
    grant_permission(groups["auditors"], permissions[AUDIT_MANAGER])
    grant_permission(groups["auditors"], permissions[PERMISSION_AUDITOR])

    add_member(groups["all-teams"], users["*****@*****.**"], role="owner")
    add_member(groups["all-teams"], groups["team-infra"])

    add_member(groups["user-admins"], users["*****@*****.**"], role="owner")
    add_member(groups["user-admins"], users["*****@*****.**"], role="owner")
    grant_permission(groups["user-admins"], permissions[USER_ADMIN])

    add_member(groups["group-admins"], users["*****@*****.**"], role="owner")
    grant_permission(groups["group-admins"], permissions[GROUP_ADMIN])

    add_member(groups["permission-admins"], users["*****@*****.**"], role="owner")
    add_member(groups["permission-admins"], users["*****@*****.**"], role="member")
    grant_permission(groups["permission-admins"], permissions[PERMISSION_ADMIN])

    session.commit()
    graph.update_from_db(session)

    return graph
Esempio n. 34
0
def test_promote_nonauditors(
        mock_gagn,
        standard_graph,
        graph,
        users,
        groups,
        session,
        permissions  # noqa: F811
):
    """ Test expiration auditing and notification. """

    assert graph.get_group_details("audited-team")["audited"]

    #
    # Ensure auditors promotion for all approvers
    #
    approver_roles = ["owner", "np-owner", "manager"]

    affected_users = set(
        ["*****@*****.**", "*****@*****.**", "*****@*****.**", "*****@*****.**"])
    for idx, role in enumerate(approver_roles):

        # Add non-auditor as an approver to an audited group
        add_member(groups["audited-team"], users["*****@*****.**"], role=role)
        graph.update_from_db(session)
        assert not affected_users.intersection(get_users(graph, "auditors"))

        # do the promotion logic
        background = BackgroundProcessor(settings, None)
        background.promote_nonauditors(session)

        # Check that the users now added to auditors group
        graph.update_from_db(session)
        assert affected_users.intersection(get_users(
            graph, "auditors")) == affected_users
        unsent_emails = _get_unsent_emails_and_send(session)
        assert any([
            'Subject: Added as member to group "auditors"' in email.body
            and "To: [email protected]" in email.body for email in unsent_emails
        ])
        assert any([
            'Subject: Added as member to group "auditors"' in email.body
            and "To: [email protected]" in email.body for email in unsent_emails
        ])
        assert any([
            'Subject: Added as member to group "auditors"' in email.body
            and "To: [email protected]" in email.body for email in unsent_emails
        ])

        audits = AuditLog.get_entries(session, action="nonauditor_promoted")
        assert len(audits) == len(affected_users) * (idx + 1)

        # reset for next iteration
        revoke_member(groups["audited-team"], users["*****@*****.**"])
        for username in affected_users:
            revoke_member(groups["auditors"], users[username])

    #
    # Ensure nonauditor, nonapprovers in audited groups do not get promoted
    #

    # first, run a promotion to get any other promotion that we don't
    # care about out of the way
    background = BackgroundProcessor(settings, None)
    background.promote_nonauditors(session)

    prev_audit_log_count = len(
        AuditLog.get_entries(session, action="nonauditor_promoted"))

    member_roles = ["member"]
    for idx, role in enumerate(member_roles):

        # Add non-auditor as a non-approver to an audited group
        add_member(groups["audited-team"], users["*****@*****.**"], role=role)

        # do the promotion logic
        background = BackgroundProcessor(settings, None)
        background.promote_nonauditors(session)

        # Check that the user is not added to auditors group
        graph.update_from_db(session)
        assert "*****@*****.**" not in get_users(graph, "auditors")

        assert not any([
            'Subject: Added as member to group "auditors"' in email.body
            and "To: [email protected]" in email.body
            for email in _get_unsent_emails_and_send(session)
        ])

        audits = AuditLog.get_entries(session, action="nonauditor_promoted")
        assert len(audits) == prev_audit_log_count

        revoke_member(groups["audited-team"], users["*****@*****.**"])
Esempio n. 35
0
def test_auditor_promotion(mock_nnp, mock_gagn, session, graph, permissions,
                           users):  # noqa: F811
    """Test automatic promotion of non-auditor approvers

    We set up our own group/user/permission for testing instead of
    using the `standard_graph` fixture---retrofitting it to work for
    us and also not break existing tests is too cumbersome.

    So here are our groups:

    very-special-auditors:
      * user14

    group-1:
      * user11 (o)
      * user12
      * user13 (np-o)
      * user14 (o, a)

    group-2:
      * user13 (np-o)
      * user21 (o)
      * user22

    group-3:
      * user22 (o)
      * user12 (o)

    group-4:
      * user21 (np-o)
      * user41
      * user42 (o)
      * user43 (np-o)

    o: owner, np-o: no-permission owner, a: auditor

    group-1 and group-2 have the permission that we will enable
    auditing. group-4 will be a subgroup of group-1 and thus will
    inherit the audited permission from group-1.

    The expected outcome is: user11, user13, user21, user42, and
    user43 will be added to the auditors group.

    """
    settings = BackgroundSettings()
    set_global_settings(settings)

    #
    # set up our test part of the graph
    #

    # create groups
    AUDITED_GROUP = "audited"
    AUDITORS_GROUP = mock_gagn.return_value = "very-special-auditors"
    PERMISSION_NAME = "test-permission"
    all_groups = {
        groupname: Group.get_or_create(session, groupname=groupname)[0]
        for groupname in ("group-1", "group-2", "group-3", "group-4",
                          AUDITORS_GROUP)
    }
    # create users
    users.update({
        username + "@a.co": User.get_or_create(session,
                                               username=username + "@a.co")[0]
        for username in (
            "user11",
            "user12",
            "user13",
            "user14",
            "user21",
            "user22",
            "user23",
            "user41",
            "user42",
            "user43",
        )
    })
    # create permissions
    permissions.update({
        permission: get_or_create_permission(
            session,
            permission,
            description="{} permission".format(permission))[0]
        for permission in [PERMISSION_NAME]
    })
    # add users to groups
    for (groupname, username, role) in (
        ("group-1", "user11", "owner"),
        ("group-1", "user12", "member"),
        ("group-1", "user13", "np-owner"),
        ("group-1", "user14", "owner"),
        ("group-2", "user13", "np-owner"),
        ("group-2", "user21", "owner"),
        ("group-2", "user22", "member"),
        ("group-3", "user12", "owner"),
        ("group-3", "user22", "owner"),
        ("group-4", "user21", "np-owner"),
        ("group-4", "user41", "member"),
        ("group-4", "user42", "owner"),
        ("group-4", "user43", "np-owner"),
    ):
        add_member(all_groups[groupname], users[username + "@a.co"], role=role)
    # add group-4 as member of group-1
    add_member(all_groups["group-1"], all_groups["group-4"])
    # add user14 to auditors group
    add_member(all_groups[AUDITORS_GROUP], users["*****@*****.**"])
    # grant permissions to groups
    #
    # give the test permission to groups 1 and 2, and group 4 should
    # also inherit from group 1
    grant_permission(all_groups["group-1"], permissions[PERMISSION_NAME])
    grant_permission(all_groups["group-2"], permissions[PERMISSION_NAME])
    grant_permission(all_groups[AUDITORS_GROUP],
                     permissions[PERMISSION_AUDITOR])

    graph.update_from_db(session)
    # done setting up

    # now a few pre-op checks
    assert not graph.get_group_details("group-1").get(AUDITED_GROUP)
    assert not graph.get_group_details("group-4").get(AUDITED_GROUP)
    assert get_users(graph, AUDITORS_GROUP) == set(["*****@*****.**"])
    assert get_users(graph, "group-3") == set(["*****@*****.**", "*****@*****.**"])

    #
    # run the promotion logic -> nothing should happen because the
    # test-permission is not yet audited
    #
    background = BackgroundProcessor(settings, None)
    background.promote_nonauditors(session)
    graph.update_from_db(session)

    # nothing should have happened
    assert not graph.get_group_details("group-1").get(AUDITED_GROUP)
    assert not graph.get_group_details("group-4").get(AUDITED_GROUP)
    assert get_users(graph, AUDITORS_GROUP) == set(["*****@*****.**"])
    assert mock_nnp.call_count == 0

    #
    # now enable auditing for the permission and run the promotion
    # logic again
    #
    enable_permission_auditing(session, PERMISSION_NAME,
                               users["*****@*****.**"].id)
    graph.update_from_db(session)
    assert graph.get_group_details("group-1").get(AUDITED_GROUP)
    assert graph.get_group_details("group-4").get(AUDITED_GROUP)

    background = BackgroundProcessor(settings, None)
    background.promote_nonauditors(session)
    graph.update_from_db(session)

    # check that stuff happened
    assert get_users(graph, AUDITORS_GROUP) == set([
        "*****@*****.**", "*****@*****.**", "*****@*****.**", "*****@*****.**",
        "*****@*****.**", "*****@*****.**"
    ])
    expected_calls = [
        call(settings, session, users["*****@*****.**"],
             all_groups[AUDITORS_GROUP], set(["group-1"])),
        call(
            settings,
            session,
            users["*****@*****.**"],
            all_groups[AUDITORS_GROUP],
            set(["group-1", "group-2"]),
        ),
        call(
            settings,
            session,
            users["*****@*****.**"],
            all_groups[AUDITORS_GROUP],
            set(["group-2", "group-4"]),
        ),
        call(settings, session, users["*****@*****.**"],
             all_groups[AUDITORS_GROUP], set(["group-4"])),
        call(settings, session, users["*****@*****.**"],
             all_groups[AUDITORS_GROUP], set(["group-4"])),
    ]
    assert mock_nnp.call_count == len(expected_calls)
    mock_nnp.assert_has_calls(expected_calls, any_order=True)

    #
    # run the background promotion logic again, and nothing should
    # happen
    #
    mock_nnp.reset_mock()
    background = BackgroundProcessor(settings, None)
    background.promote_nonauditors(session)
    assert mock_nnp.call_count == 0
Esempio n. 36
0
def setup_desc_to_ances(session, users, groups):  # noqa: F811
    add_member(groups["team-sre"], users["*****@*****.**"], role="owner")
    add_member(groups["team-sre"], users["*****@*****.**"])

    add_member(groups["tech-ops"], users["*****@*****.**"], role="owner")
    add_member(groups["tech-ops"], users["*****@*****.**"])

    add_member(groups["team-infra"], users["*****@*****.**"], role="owner")
    add_member(groups["team-infra"], groups["team-sre"])
    add_member(groups["team-infra"], groups["tech-ops"])

    add_member(groups["all-teams"], users["*****@*****.**"], role="owner")
    add_member(groups["all-teams"], groups["team-infra"])
Esempio n. 37
0
def test_graph_add_member_existing(session, graph, users, groups):  # noqa: F811
    """ Test adding members to an existing relationship."""

    add_member(groups["team-sre"], users["*****@*****.**"], role="owner")
    add_member(groups["tech-ops"], users["*****@*****.**"], role="owner")

    add_member(groups["team-infra"], users["*****@*****.**"], role="owner")
    add_member(groups["team-infra"], groups["team-sre"])
    add_member(groups["team-infra"], groups["tech-ops"])

    add_member(groups["all-teams"], users["*****@*****.**"], role="owner")
    add_member(groups["all-teams"], groups["team-infra"])

    add_member(groups["team-sre"], users["*****@*****.**"])
    add_member(groups["tech-ops"], users["*****@*****.**"])

    session.commit()
    graph.update_from_db(session)

    assert get_users(graph, "team-sre") == set(["*****@*****.**", "*****@*****.**"])
    assert get_users(graph, "tech-ops") == set(["*****@*****.**", "*****@*****.**"])

    assert get_users(graph, "team-infra") == set(["*****@*****.**", "*****@*****.**"])
    assert get_users(graph, "team-infra", cutoff=1) == set(["*****@*****.**"])

    assert get_users(graph, "all-teams") == set(["*****@*****.**", "*****@*****.**", "*****@*****.**"])
    assert get_users(graph, "all-teams", cutoff=1) == set(["*****@*****.**"])

    assert get_groups(graph, "*****@*****.**") == set(
        ["team-sre", "all-teams", "tech-ops", "team-infra"]
    )
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["team-sre", "tech-ops", "team-infra"])

    assert get_groups(graph, "*****@*****.**") == set(
        ["team-sre", "all-teams", "tech-ops", "team-infra"]
    )
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["team-sre", "tech-ops"])

    assert get_groups(graph, "*****@*****.**") == set(["all-teams"])
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["all-teams"])
Esempio n. 38
0
def test_auditor_promotion(mock_nnp, mock_gagn, session, graph, permissions, users):  # noqa: F811
    """Test automatic promotion of non-auditor approvers

    We set up our own group/user/permission for testing instead of
    using the `standard_graph` fixture---retrofitting it to work for
    us and also not break existing tests is too cumbersome.

    So here are our groups:

    very-special-auditors:
      * user14

    group-1:
      * user11 (o)
      * user12
      * user13 (np-o)
      * user14 (o, a)

    group-2:
      * user13 (np-o)
      * user21 (o)
      * user22

    group-3:
      * user22 (o)
      * user12 (o)

    group-4:
      * user21 (np-o)
      * user41
      * user42 (o)
      * user43 (np-o)

    o: owner, np-o: no-permission owner, a: auditor

    group-1 and group-2 have the permission that we will enable
    auditing. group-4 will be a subgroup of group-1 and thus will
    inherit the audited permission from group-1.

    The expected outcome is: user11, user13, user21, user42, and
    user43 will be added to the auditors group.

    """
    settings = BackgroundSettings()
    set_global_settings(settings)

    #
    # set up our test part of the graph
    #

    # create groups
    AUDITED_GROUP = "audited"
    AUDITORS_GROUP = mock_gagn.return_value = "very-special-auditors"
    PERMISSION_NAME = "test-permission"
    all_groups = {
        groupname: Group.get_or_create(session, groupname=groupname)[0]
        for groupname in ("group-1", "group-2", "group-3", "group-4", AUDITORS_GROUP)
    }
    # create users
    users.update(
        {
            username + "@a.co": User.get_or_create(session, username=username + "@a.co")[0]
            for username in (
                "user11",
                "user12",
                "user13",
                "user14",
                "user21",
                "user22",
                "user23",
                "user41",
                "user42",
                "user43",
            )
        }
    )
    # create permissions
    permissions.update(
        {
            permission: get_or_create_permission(
                session, permission, description="{} permission".format(permission)
            )[0]
            for permission in [PERMISSION_NAME]
        }
    )
    # add users to groups
    for (groupname, username, role) in (
        ("group-1", "user11", "owner"),
        ("group-1", "user12", "member"),
        ("group-1", "user13", "np-owner"),
        ("group-1", "user14", "owner"),
        ("group-2", "user13", "np-owner"),
        ("group-2", "user21", "owner"),
        ("group-2", "user22", "member"),
        ("group-3", "user12", "owner"),
        ("group-3", "user22", "owner"),
        ("group-4", "user21", "np-owner"),
        ("group-4", "user41", "member"),
        ("group-4", "user42", "owner"),
        ("group-4", "user43", "np-owner"),
    ):
        add_member(all_groups[groupname], users[username + "@a.co"], role=role)
    # add group-4 as member of group-1
    add_member(all_groups["group-1"], all_groups["group-4"])
    # add user14 to auditors group
    add_member(all_groups[AUDITORS_GROUP], users["*****@*****.**"])
    # grant permissions to groups
    #
    # give the test permission to groups 1 and 2, and group 4 should
    # also inherit from group 1
    grant_permission(all_groups["group-1"], permissions[PERMISSION_NAME])
    grant_permission(all_groups["group-2"], permissions[PERMISSION_NAME])
    grant_permission(all_groups[AUDITORS_GROUP], permissions[PERMISSION_AUDITOR])

    graph.update_from_db(session)
    # done setting up

    # now a few pre-op checks
    assert not graph.get_group_details("group-1").get(AUDITED_GROUP)
    assert not graph.get_group_details("group-4").get(AUDITED_GROUP)
    assert get_users(graph, AUDITORS_GROUP) == set(["*****@*****.**"])
    assert get_users(graph, "group-3") == set(["*****@*****.**", "*****@*****.**"])

    #
    # run the promotion logic -> nothing should happen because the
    # test-permission is not yet audited
    #
    background = BackgroundProcessor(settings, None)
    background.promote_nonauditors(session)
    graph.update_from_db(session)

    # nothing should have happened
    assert not graph.get_group_details("group-1").get(AUDITED_GROUP)
    assert not graph.get_group_details("group-4").get(AUDITED_GROUP)
    assert get_users(graph, AUDITORS_GROUP) == set(["*****@*****.**"])
    assert mock_nnp.call_count == 0

    #
    # now enable auditing for the permission and run the promotion
    # logic again
    #
    enable_permission_auditing(session, PERMISSION_NAME, users["*****@*****.**"].id)
    graph.update_from_db(session)
    assert graph.get_group_details("group-1").get(AUDITED_GROUP)
    assert graph.get_group_details("group-4").get(AUDITED_GROUP)

    background = BackgroundProcessor(settings, None)
    background.promote_nonauditors(session)
    graph.update_from_db(session)

    # check that stuff happened
    assert get_users(graph, AUDITORS_GROUP) == set(
        ["*****@*****.**", "*****@*****.**", "*****@*****.**", "*****@*****.**", "*****@*****.**", "*****@*****.**"]
    )
    expected_calls = [
        call(
            settings, session, users["*****@*****.**"], all_groups[AUDITORS_GROUP], set(["group-1"])
        ),
        call(
            settings,
            session,
            users["*****@*****.**"],
            all_groups[AUDITORS_GROUP],
            set(["group-1", "group-2"]),
        ),
        call(
            settings,
            session,
            users["*****@*****.**"],
            all_groups[AUDITORS_GROUP],
            set(["group-2", "group-4"]),
        ),
        call(
            settings, session, users["*****@*****.**"], all_groups[AUDITORS_GROUP], set(["group-4"])
        ),
        call(
            settings, session, users["*****@*****.**"], all_groups[AUDITORS_GROUP], set(["group-4"])
        ),
    ]
    assert mock_nnp.call_count == len(expected_calls)
    mock_nnp.assert_has_calls(expected_calls, any_order=True)

    #
    # run the background promotion logic again, and nothing should
    # happen
    #
    mock_nnp.reset_mock()
    background = BackgroundProcessor(settings, None)
    background.promote_nonauditors(session)
    assert mock_nnp.call_count == 0
Esempio n. 39
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
    AuditMember = namedtuple("AuditMember", "am_id, edge_type, edge_id")
    Audit = namedtuple("Audit", "audit_id, owner_name, group_name, audit_members")
    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,
            [AuditMember(am.id, am.edge.member_type, am.edge_id) for am in x.my_members()],
        )
        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(am.am_id): "approved" for am in one_audit.audit_members}
        )

        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 am in one_audit.my_members():
        if gary_id == am.member.id:
            # deny
            body_dict["audit_{}".format(am.id)] = "remove"
        else:
            # approve
            body_dict["audit_{}".format(am.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"
Esempio n. 40
0
def test_aggregate_request(
        graph,
        groups,
        permissions,
        session,
        standard_graph,
        users  # noqa: F811
):
    gary = users["*****@*****.**"]
    not_involved = [
        user for name, user in users.items()
        if name not in ("*****@*****.**", "*****@*****.**")
    ]

    assert not any([
        user_requests_aggregate(session, u).all() for u in users.values()
    ]), "should have no pending requests to begin with"

    # one request to one team
    groups["team-sre"].add_member(users["*****@*****.**"],
                                  users["*****@*****.**"],
                                  reason="for the lulz")
    session.commit()

    assert len(user_requests_aggregate(
        session, gary).all()) == 1, "one pending request for owner"
    assert not any(
        [user_requests_aggregate(session, u).all()
         for u in not_involved]), "no pending requests if you're not the owner"

    # two request to two teams, same owner
    groups["team-infra"].add_member(users["*****@*****.**"],
                                    users["*****@*****.**"],
                                    reason="for the lulz")
    session.commit()

    request_gary = user_requests_aggregate(session, gary).all()
    assert len(request_gary) == 2, "two pending request for owner"
    assert not any(
        [user_requests_aggregate(session, u).all()
         for u in not_involved]), "no pending requests if you're not the owner"

    # resolving one request should reflect
    request = session.query(Request).filter_by(id=request_gary[0].id).scalar()
    request.update_status(users["*****@*****.**"], "actioned",
                          "for being a good person")
    session.commit()

    assert len(user_requests_aggregate(
        session, gary).all()) == 1, "one pending request for owner"
    assert not any(
        [user_requests_aggregate(session, u).all()
         for u in not_involved]), "no pending requests if you're not the owner"

    # requests to dependent teams should reflect apprpriately
    groups["security-team"].add_member(users["*****@*****.**"],
                                       users["*****@*****.**"],
                                       reason="for the lulz")
    session.commit()

    assert (len(user_requests_aggregate(
        session, gary).all()) == 1), "super owner should not get request"
    assert (len(user_requests_aggregate(
        session, users["*****@*****.**"]).all()) == 1), "owner should get request"
    user_not_gary_oliver = [
        u for n, u in users.items() if n not in ("*****@*****.**", "*****@*****.**")
    ]
    assert not any([
        user_requests_aggregate(session, u).all() for u in user_not_gary_oliver
    ])

    # manager and np-owner should get requests
    figurehead = users["*****@*****.**"]
    add_member(groups["audited-team"], figurehead, role="manager")
    assert (len(user_requests_aggregate(
        session, figurehead).all()) == 0), "no request for np-owner at first"

    groups["tech-ops"].add_member(users["*****@*****.**"],
                                  users["*****@*****.**"],
                                  reason="for the lulz")
    assert len(user_requests_aggregate(
        session, figurehead).all()) == 1, "request for np-owner"

    groups["audited-team"].add_member(users["*****@*****.**"],
                                      users["*****@*****.**"],
                                      reason="for the lulz")
    assert (len(user_requests_aggregate(
        session, figurehead).all()) == 2), "request for np-owner and manager"
Esempio n. 41
0
def test_graph_cycle_indirect(session, graph, users, groups):  # noqa: F811
    """ Test adding a member that will create a cycle.

        gary         zay            testuser
         |            |                |
        sre <----- tech-ops <----- team-infra <--
         |                                       |
         |                                       |
          --------> all-teams --------------------

    """

    add_member(groups["team-sre"], users["*****@*****.**"])
    add_member(groups["tech-ops"], users["*****@*****.**"])
    add_member(groups["team-infra"], users["*****@*****.**"])

    add_member(groups["team-sre"], groups["tech-ops"])
    add_member(groups["tech-ops"], groups["team-infra"])
    add_member(groups["team-infra"], groups["all-teams"])

    add_member(groups["all-teams"], groups["team-sre"])

    session.commit()
    graph.update_from_db(session)
    all_users = set(["*****@*****.**", "*****@*****.**", "*****@*****.**"])
    all_groups = set(["team-sre", "all-teams", "tech-ops", "team-infra"])

    assert get_users(graph, "team-sre") == all_users
    assert get_users(graph, "team-sre", cutoff=1) == set(["*****@*****.**"])

    assert get_users(graph, "tech-ops") == all_users
    assert get_users(graph, "tech-ops", cutoff=1) == set(["*****@*****.**"])

    assert get_users(graph, "team-infra") == all_users
    assert get_users(graph, "team-infra", cutoff=1) == set(["*****@*****.**"])

    assert get_users(graph, "all-teams") == all_users
    assert get_users(graph, "all-teams", cutoff=1) == set([])

    assert get_groups(graph, "*****@*****.**") == all_groups
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["team-sre"])

    assert get_groups(graph, "*****@*****.**") == all_groups
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["tech-ops"])

    assert get_groups(graph, "*****@*****.**") == all_groups
    assert get_groups(graph, "*****@*****.**", cutoff=1) == set(["team-infra"])