Пример #1
0
def user_enable_perm_to_sre(session, groups):  # noqa: F811
    """Adds the (USER_ENABLE, *) permission to the group `team-sre` """
    user_enable_perm, is_new = get_or_create_permission(
        session, USER_ENABLE, description="grouper.user.enable perm")
    session.commit()

    grant_permission(groups["team-sre"], user_enable_perm, argument="*")
Пример #2
0
def test_toggle_perm_audited(groups, permissions, http_client, base_url):  # noqa: F811
    perm_name = "audited"  # perm that is already audited
    nonpriv_user_name = "*****@*****.**"  # user with no audit perms and without PERMISSION_ADMIN
    nonpriv_user_team = "sad-team"
    nonpriv_headers = {"X-Grouper-User": nonpriv_user_name}
    priv_user_name = "*****@*****.**"  # user with AUDIT_MANAGER
    priv_headers = {"X-Grouper-User": priv_user_name}
    enable_url = url(base_url, "/permissions/{}/enable-auditing".format(perm_name))
    disable_url = url(base_url, "/permissions/{}/disable-auditing".format(perm_name))

    # Give nonpriv user audit view permissions, which shouldn't allow enabling/disabling auditing
    grant_permission(groups[nonpriv_user_team], permissions[AUDIT_VIEWER], argument="")

    # attempt to enable/disable auditing; both should fail due to lack of perms
    with pytest.raises(HTTPError):
        resp = yield http_client.fetch(enable_url, method="POST", headers=nonpriv_headers, body="")
    with pytest.raises(HTTPError):
        resp = yield http_client.fetch(
            disable_url, method="POST", headers=nonpriv_headers, body=""
        )

    # Now confirm that enabling/disabling auditing works as a privileged user
    # Note that enabling audits on an audited perm succeeds (same for disabling)
    resp = yield http_client.fetch(enable_url, method="POST", headers=priv_headers, body="")
    assert resp.code == 200
    # Perm is still audited
    resp = yield http_client.fetch(disable_url, method="POST", headers=priv_headers, body="")
    assert resp.code == 200
    # Perm no longer audited
    resp = yield http_client.fetch(disable_url, method="POST", headers=priv_headers, body="")
    assert resp.code == 200
    # Perm still not audited
    resp = yield http_client.fetch(enable_url, method="POST", headers=priv_headers, body="")
    assert resp.code == 200
Пример #3
0
def test_toggle_perm_audited(groups, permissions, http_client, base_url):  # noqa: F811
    perm_name = "audited"  # perm that is already audited
    nonpriv_user_name = "*****@*****.**"  # user with no audit perms and without PERMISSION_ADMIN
    nonpriv_user_team = "sad-team"
    nonpriv_headers = {"X-Grouper-User": nonpriv_user_name}
    priv_user_name = "*****@*****.**"  # user with AUDIT_MANAGER
    priv_headers = {"X-Grouper-User": priv_user_name}
    enable_url = url(base_url, "/permissions/{}/enable-auditing".format(perm_name))
    disable_url = url(base_url, "/permissions/{}/disable-auditing".format(perm_name))

    # Give nonpriv user audit view permissions, which shouldn't allow enabling/disabling auditing
    grant_permission(groups[nonpriv_user_team], permissions[AUDIT_VIEWER], argument="")

    # attempt to enable/disable auditing; both should fail due to lack of perms
    with pytest.raises(HTTPError):
        resp = yield http_client.fetch(enable_url, method="POST", headers=nonpriv_headers, body="")
    with pytest.raises(HTTPError):
        resp = yield http_client.fetch(
            disable_url, method="POST", headers=nonpriv_headers, body=""
        )

    # Now confirm that enabling/disabling auditing works as a privileged user
    # Note that enabling audits on an audited perm succeeds (same for disabling)
    resp = yield http_client.fetch(enable_url, method="POST", headers=priv_headers, body="")
    assert resp.code == 200
    # Perm is still audited
    resp = yield http_client.fetch(disable_url, method="POST", headers=priv_headers, body="")
    assert resp.code == 200
    # Perm no longer audited
    resp = yield http_client.fetch(disable_url, method="POST", headers=priv_headers, body="")
    assert resp.code == 200
    # Perm still not audited
    resp = yield http_client.fetch(enable_url, method="POST", headers=priv_headers, body="")
    assert resp.code == 200
Пример #4
0
def test_limited_permissions_global_approvers(
        session,
        standard_graph,
        groups,
        grantable_permissions,
        http_client,
        base_url  # noqa: F811
):
    """Test that notifications are not sent to global approvers."""
    perm_grant, _, perm1, _ = grantable_permissions
    grant_permission(groups["security-team"],
                     perm_grant,
                     argument="grantable.*")

    # SPECIFIC REQUEST: 'grantable.one', 'specific_arg' for 'sad-team'
    groupname = "sad-team"
    username = "******"
    fe_url = url(base_url, "/groups/{}/permission/request".format(groupname))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({
            "permission_name": perm1.name,
            "argument": "specific_arg",
            "reason": "blah blah black sheep",
            "argument_type": "text",
        }),
        headers={"X-Grouper-User": username},
    )
    assert resp.code == 200

    emails = _get_unsent_and_mark_as_sent_emails(session)
    assert_same_recipients(emails, ["*****@*****.**"])
Пример #5
0
def test_limited_permissions_global_approvers(
    session, standard_graph, groups, grantable_permissions, http_client, base_url  # noqa: F811
):
    """Test that notifications are not sent to global approvers."""
    perm_grant, _, perm1, _ = grantable_permissions
    grant_permission(groups["security-team"], perm_grant, argument="grantable.*")

    # SPECIFIC REQUEST: 'grantable.one', 'specific_arg' for 'sad-team'
    groupname = "sad-team"
    username = "******"
    fe_url = url(base_url, "/groups/{}/permission/request".format(groupname))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode(
            {
                "permission_name": perm1.name,
                "argument": "specific_arg",
                "reason": "blah blah black sheep",
                "argument_type": "text",
            }
        ),
        headers={"X-Grouper-User": username},
    )
    assert resp.code == 200

    emails = _get_unsent_and_mark_as_sent_emails(session)
    assert_same_recipients(emails, [u"*****@*****.**"])
Пример #6
0
def user_admin_perm_to_auditors(session, groups):  # noqa: F811
    """Adds a USER_ADMIN permission to the "auditors" group"""
    user_admin_perm, is_new = get_or_create_permission(
        session, USER_ADMIN, description="grouper.admin.users permission")
    session.commit()

    grant_permission(groups["auditors"], user_admin_perm)
Пример #7
0
def user_enable_perm_to_sre(session, groups):  # noqa: F811
    """Adds the (USER_ENABLE, *) permission to the group `team-sre` """
    user_enable_perm, is_new = get_or_create_permission(
        session, USER_ENABLE, description="grouper.user.enable perm"
    )
    session.commit()

    grant_permission(groups["team-sre"], user_enable_perm, argument="*")
Пример #8
0
def user_admin_perm_to_auditors(session, groups):  # noqa: F811
    """Adds a USER_ADMIN permission to the "auditors" group"""
    user_admin_perm, is_new = get_or_create_permission(
        session, USER_ADMIN, description="grouper.admin.users permission"
    )
    session.commit()

    grant_permission(groups["auditors"], user_admin_perm)
Пример #9
0
def test_grant_permission_to_tag(users, http_client, base_url, session):  # noqa: F811

    user = session.query(User).filter_by(username="******").scalar()

    perm = create_permission(session, TAG_EDIT)
    session.commit()

    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, TAG_EDIT),
        "*",
    )

    fe_url = url(base_url, "/tags")
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"tagname": "tyler_was_here", "description": "Test Tag Please Ignore"}),
        headers={"X-Grouper-User": user.username},
    )

    tag = PublicKeyTag.get(session, name="tyler_was_here")

    user = session.query(User).filter_by(username="******").scalar()

    fe_url = url(base_url, "/permissions/grant_tag/{}".format(tag.name))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"permission": TAG_EDIT, "argument": "*"}),
        headers={"X-Grouper-User": user.username},
    )

    assert resp.code == 200
    tag = PublicKeyTag.get(session, name="tyler_was_here")
    perm = get_permission(session, TAG_EDIT)
    assert (
        len(get_public_key_tag_permissions(session, tag)) == 1
    ), "The tag should have exactly 1 permission"
    assert (
        get_public_key_tag_permissions(session, tag)[0].name == perm.name
    ), "The tag's permission should be the one we added"
    assert (
        get_public_key_tag_permissions(session, tag)[0].argument == "*"
    ), "The tag's permission should be the one we added"

    # Make sure trying to add a permission to a tag doesn't fail horribly if it's already there
    user = session.query(User).filter_by(username="******").scalar()

    fe_url = url(base_url, "/permissions/grant_tag/{}".format(tag.name))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"permission": TAG_EDIT, "argument": "*"}),
        headers={"X-Grouper-User": user.username},
    )

    assert resp.code == 200
Пример #10
0
def test_grant_permission(session, standard_graph, groups, permissions):  # noqa: F811
    grant_permission(groups["sad-team"], permissions["ssh"], argument="host +other-host")
    with pytest.raises(AssertionError):
        grant_permission(groups["sad-team"], permissions["ssh"], argument="question?")
    account = ServiceAccount.get(session, name="*****@*****.**")
    grant_permission_to_service_account(session, account, permissions["ssh"], argument="*")
    with pytest.raises(AssertionError):
        grant_permission_to_service_account(
            session, account, permissions["ssh"], argument="question?"
        )
Пример #11
0
def test_grant_permission(session, standard_graph, groups, permissions):  # noqa: F811
    grant_permission(groups["sad-team"], permissions["ssh"], argument="host +other-host")
    with pytest.raises(AssertionError):
        grant_permission(groups["sad-team"], permissions["ssh"], argument="question?")
    account = ServiceAccount.get(session, name="*****@*****.**")
    grant_permission_to_service_account(session, account, permissions["ssh"], argument="*")
    with pytest.raises(AssertionError):
        grant_permission_to_service_account(
            session, account, permissions["ssh"], argument="question?"
        )
Пример #12
0
def test_revoke_permission_from_tag(users, http_client, base_url, session):  # noqa: F811

    user = session.query(User).filter_by(username="******").scalar()

    create_permission(session, TAG_EDIT)
    session.commit()

    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, TAG_EDIT),
        "*",
    )

    fe_url = url(base_url, "/tags")
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"tagname": "tyler_was_here", "description": "Test Tag Please Ignore"}),
        headers={"X-Grouper-User": user.username},
    )

    tag = PublicKeyTag.get(session, name="tyler_was_here")

    user = session.query(User).filter_by(username="******").scalar()

    fe_url = url(base_url, "/permissions/grant_tag/{}".format(tag.name))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"permission": TAG_EDIT, "argument": "*"}),
        headers={"X-Grouper-User": user.username},
    )

    assert resp.code == 200
    tag = PublicKeyTag.get(session, name="tyler_was_here")
    get_permission(session, TAG_EDIT)
    assert (
        len(get_public_key_tag_permissions(session, tag)) == 1
    ), "The tag should have exactly 1 permission"

    user = session.query(User).filter_by(username="******").scalar()

    mapping = get_public_key_tag_permissions(session, tag)[0]
    fe_url = url(base_url, "/permissions/{}/revoke_tag/{}".format(TAG_EDIT, mapping.mapping_id))
    resp = yield http_client.fetch(
        fe_url, method="POST", body="", headers={"X-Grouper-User": user.username}
    )

    assert resp.code == 200
    tag = PublicKeyTag.get(session, name="tyler_was_here")
    assert (
        len(get_public_key_tag_permissions(session, tag)) == 0
    ), "The tag should have no permissions"
Пример #13
0
def test_grantable_permissions(
    session, standard_graph, users, groups, grantable_permissions  # noqa: F811
):
    perm_grant, perm0, perm1, _ = grantable_permissions

    assert not user_grantable_permissions(session, users["*****@*****.**"]), "start with none"

    grant_permission(groups["auditors"], perm_grant, argument="notgrantable.one")
    assert not user_grantable_permissions(
        session, users["*****@*****.**"]
    ), "grant on non-existent is fine"

    grant_permission(groups["auditors"], perm_grant, argument=perm0.name)
    grants = user_grantable_permissions(session, users["*****@*****.**"])
    assert len(grants) == 1, "only specific permission grant"
    assert grants[0][0].name == perm0.name, "only specific permission grant"

    grant_permission(groups["auditors"], perm_grant, argument="grantable.*")
    grants = user_grantable_permissions(session, users["*****@*****.**"])
    assert len(grants) == 3, "wildcard grant should grab appropriat amount"
    assert sorted([x[0].name for x in grants]) == ["grantable", "grantable.one", "grantable.two"]

    args_by_perm = get_grantable_permissions(session, None)
    assert args_by_perm[perm1.name] == ["*"], "wildcard grant reflected in list of grantable"

    grant_permission(groups["auditors"], perm_grant, argument="{}/single_arg".format(perm1.name))
    args_by_perm = get_grantable_permissions(session, None)
    assert args_by_perm[perm1.name] == ["*"], "wildcard grant reflected cause no restricted perms"

    args_by_perm = get_grantable_permissions(session, [perm1.name])
    assert args_by_perm[perm1.name] == [
        "single_arg"
    ], "least permissive argument shown cause of restricted perms"
Пример #14
0
def test_grantable_permissions(
    session, standard_graph, users, groups, grantable_permissions  # noqa: F811
):
    perm_grant, perm0, perm1, _ = grantable_permissions

    assert not user_grantable_permissions(session, users["*****@*****.**"]), "start with none"

    grant_permission(groups["auditors"], perm_grant, argument="notgrantable.one")
    assert not user_grantable_permissions(
        session, users["*****@*****.**"]
    ), "grant on non-existent is fine"

    grant_permission(groups["auditors"], perm_grant, argument=perm0.name)
    grants = user_grantable_permissions(session, users["*****@*****.**"])
    assert len(grants) == 1, "only specific permission grant"
    assert grants[0][0].name == perm0.name, "only specific permission grant"

    grant_permission(groups["auditors"], perm_grant, argument="grantable.*")
    grants = user_grantable_permissions(session, users["*****@*****.**"])
    assert len(grants) == 3, "wildcard grant should grab appropriat amount"
    assert sorted([x[0].name for x in grants]) == ["grantable", "grantable.one", "grantable.two"]

    args_by_perm = get_grantable_permissions(session, None)
    assert args_by_perm[perm1.name] == ["*"], "wildcard grant reflected in list of grantable"

    grant_permission(groups["auditors"], perm_grant, argument="{}/single_arg".format(perm1.name))
    args_by_perm = get_grantable_permissions(session, None)
    assert args_by_perm[perm1.name] == ["*"], "wildcard grant reflected cause no restricted perms"

    args_by_perm = get_grantable_permissions(session, [perm1.name])
    assert args_by_perm[perm1.name] == [
        "single_arg"
    ], "least permissive argument shown cause of restricted perms"
Пример #15
0
def do_request_perms(groups, permissions, session, users):  # noqa: F811
    # Create the two test perms + PERMISSION_GRANT + PERMISSION_ADMIN, give GRANTING_TEAM
    # appropriate PERMISSION_GRANT, and make sure there's an admin (has PERMISSION_ADMIN)
    test_perm_granter = get_or_create_permission(
        session, PERM_WITH_GRANTER, description="perm with granter"
    )[0]
    test_perm_nogranter = get_or_create_permission(
        session, PERM_NO_GRANTER, description="perm without granter"
    )[0]
    grant_perm = get_or_create_permission(session, PERMISSION_GRANT)[0]
    admin_perm = get_or_create_permission(session, PERMISSION_ADMIN)[0]

    session.commit()

    grant_permission(
        groups[GRANTING_TEAM], grant_perm, argument="{}/{}".format(PERM_WITH_GRANTER, ARGUMENT)
    )
    grant_permission(groups[ADMIN_TEAM], admin_perm, argument="")

    # Request the two test perms from REQUESTING_TEAM
    create_request(
        session,
        users[REQUESTING_USER],
        groups[REQUESTING_TEAM],
        test_perm_granter,
        ARGUMENT,
        REASON,
    )
    create_request(
        session,
        users[REQUESTING_USER],
        groups[REQUESTING_TEAM],
        test_perm_nogranter,
        ARGUMENT,
        REASON,
    )

    # Finally make one more request from a user other than REQUESTING_USER
    create_request(
        session, users[GRANTING_USER], groups[GRANTING_TEAM], admin_perm, ARGUMENT, REASON
    )

    session.commit()
Пример #16
0
def test_edit_tag(users, http_client, base_url, session):  # noqa: F811

    user = session.query(User).filter_by(username="******").scalar()

    create_permission(session, TAG_EDIT)
    session.commit()

    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, TAG_EDIT),
        "*",
    )

    fe_url = url(base_url, "/tags")
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({
            "tagname": "tyler_was_here",
            "description": "Test Tag Please Ignore"
        }),
        headers={"X-Grouper-User": user.username},
    )

    tag = PublicKeyTag.get(session, name="tyler_was_here")

    assert (tag.description == "Test Tag Please Ignore"
            ), "The description should match what we created it with"

    user = session.query(User).filter_by(username="******").scalar()
    fe_url = url(base_url, "/tags/{}/edit".format(tag.id))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"description": "Don't tag me bro"}),
        headers={"X-Grouper-User": user.username},
    )

    assert resp.code == 200

    tag = PublicKeyTag.get(session, name="tyler_was_here")

    assert tag.description == "Don't tag me bro", "The description should have been updated"
Пример #17
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")
Пример #18
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
Пример #19
0
def test_limited_permissions(
        session,
        standard_graph,
        groups,
        grantable_permissions,
        http_client,
        base_url  # noqa: F811
):
    """Test that notifications are not sent to wildcard grant owners unless necessary."""
    perm_grant, _, perm1, _ = grantable_permissions
    # one super wildcard, one wildcard grant and one specific grant
    grant_permission(groups["sad-team"], perm_grant, argument="*")
    grant_permission(groups["all-teams"], perm_grant, argument="grantable.*")
    grant_permission(groups["security-team"],
                     perm_grant,
                     argument="{}/specific_arg".format(perm1.name))

    # SPECIFIC REQUEST: 'grantable.one', 'specific_arg' for 'sad-team'
    groupname = "sad-team"
    username = "******"
    fe_url = url(base_url, f"/permissions/request?group={groupname}")
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({
            "permission": perm1.name,
            "argument": "specific_arg",
            "reason": "blah blah black sheep",
        }),
        headers={"X-Grouper-User": username},
    )
    assert resp.code == 200

    emails = _get_unsent_and_mark_as_sent_emails(session)
    assert_same_recipients(emails, ["*****@*****.**"])
Пример #20
0
def do_request_perms(groups, permissions, session, users):  # noqa: F811
    # Create the two test perms + PERMISSION_GRANT + PERMISSION_ADMIN, give GRANTING_TEAM
    # appropriate PERMISSION_GRANT, and make sure there's an admin (has PERMISSION_ADMIN)
    test_perm_granter = get_or_create_permission(
        session, PERM_WITH_GRANTER, description="perm with granter")[0]
    test_perm_nogranter = get_or_create_permission(
        session, PERM_NO_GRANTER, description="perm without granter")[0]
    grant_perm = get_or_create_permission(session, PERMISSION_GRANT)[0]
    admin_perm = get_or_create_permission(session, PERMISSION_ADMIN)[0]

    session.commit()

    grant_permission(groups[GRANTING_TEAM],
                     grant_perm,
                     argument="{}/{}".format(PERM_WITH_GRANTER, ARGUMENT))
    grant_permission(groups[ADMIN_TEAM], admin_perm, argument="")

    # Request the two test perms from REQUESTING_TEAM
    create_request(
        session,
        users[REQUESTING_USER],
        groups[REQUESTING_TEAM],
        test_perm_granter,
        ARGUMENT,
        REASON,
    )
    create_request(
        session,
        users[REQUESTING_USER],
        groups[REQUESTING_TEAM],
        test_perm_nogranter,
        ARGUMENT,
        REASON,
    )

    # Finally make one more request from a user other than REQUESTING_USER
    create_request(session, users[GRANTING_USER], groups[GRANTING_TEAM],
                   admin_perm, ARGUMENT, REASON)

    session.commit()
Пример #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")
Пример #22
0
def test_permission_grant_to_owners(
    session, standard_graph, groups, grantable_permissions, permissions  # noqa: F811
):
    """Test we're getting correct owners according to granted
    'grouper.permission.grant' permissions."""
    perm_grant, _, perm1, perm2 = grantable_permissions

    # Disable the group with permission admin since otherwise they're an approver on everything,
    # and check that there are then no approvers.
    groups["permission-admins"].disable()
    session.commit()
    assert not get_owners_by_grantable_permission(session), "nothing to begin with"

    # grant a grant on a non-existent permission
    grant_permission(groups["auditors"], perm_grant, argument="notgrantable.one")
    assert not get_owners_by_grantable_permission(session), "ignore grants for non-existent perms"

    # grant a wildcard grant -- make sure all permissions are represented and
    # the grant isn't inherited
    grant_permission(groups["all-teams"], perm_grant, argument="grantable.*")
    owners_by_arg_by_perm = get_owners_by_grantable_permission(session)
    expected = [groups["all-teams"]]
    assert owners_by_arg_by_perm[perm1.name]["*"] == expected, "grants are not inherited"
    assert len(owners_by_arg_by_perm) == 2
    assert len(owners_by_arg_by_perm[perm1.name]) == 1
    assert len(owners_by_arg_by_perm[perm2.name]) == 1

    # grant on argument substring
    grant_permission(
        groups["team-sre"], perm_grant, argument="{}/somesubstring*".format(perm1.name)
    )
    owners_by_arg_by_perm = get_owners_by_grantable_permission(session)
    expected = [groups["all-teams"]]
    assert owners_by_arg_by_perm[perm1.name]["*"] == expected
    expected = [groups["team-sre"]]
    assert owners_by_arg_by_perm[perm1.name]["somesubstring*"] == expected

    # make sure get_owner() respect substrings
    res = [
        o.groupname
        for o, a in get_owner_arg_list(
            session, perm1, "somesubstring", owners_by_arg_by_perm=owners_by_arg_by_perm
        )
    ]
    assert sorted(res) == ["all-teams", "team-sre"], "should include substring wildcard matches"

    res = [
        o.groupname
        for o, a in get_owner_arg_list(
            session, perm1, "othersubstring", owners_by_arg_by_perm=owners_by_arg_by_perm
        )
    ]
    assert sorted(res) == ["all-teams"], "negative test of substring wildcard matches"

    # permission admins have all the power
    grant_permission(groups["security-team"], permissions[PERMISSION_ADMIN])
    owners_by_arg_by_perm = get_owners_by_grantable_permission(session)
    all_permissions = get_all_permissions(session)
    for perm in all_permissions:
        assert perm.name in owners_by_arg_by_perm, "all permission should be represented"
        assert (
            groups["security-team"] in owners_by_arg_by_perm[perm.name]["*"]
        ), "permission admin should be wildcard owners"
Пример #23
0
def test_exclude_disabled_permissions(
    session, standard_graph, graph, users, groups, permissions  # noqa: F811
):
    """
    Ensure that disabled permissions are excluded from various
    functions/methods that return data from the models.
    """
    perm_ssh = get_permission(session, "ssh")
    perm_grant = create_permission(session, PERMISSION_GRANT)
    session.commit()
    # this user has grouper.permission.grant with argument "ssh/*"
    grant_permission(groups["group-admins"], perm_grant, argument="ssh/*")
    graph.update_from_db(session)

    grant_perms = [
        x for x in user_permissions(session, users["*****@*****.**"]) if x.name == PERMISSION_GRANT
    ]
    assert "ssh" == filter_grantable_permissions(session, grant_perms)[0][0].name
    assert "ssh" in (p.name for p in get_all_permissions(session))
    assert "ssh" in (p.name for p in get_all_permissions(session, include_disabled=False))
    assert "ssh" in (p.name for p in get_all_permissions(session, include_disabled=True))
    assert "ssh" in get_grantable_permissions(session, [])
    assert "team-sre" in [g[0] for g in get_groups_by_permission(session, perm_ssh)]
    assert get_owner_arg_list(session, perm_ssh, "*")
    assert "ssh" in get_owners_by_grantable_permission(session)
    assert "ssh" in (x[0].name for x in user_grantable_permissions(session, users["*****@*****.**"]))
    assert user_has_permission(session, users["*****@*****.**"], "ssh")
    assert "ssh" in (p.name for p in user_permissions(session, users["*****@*****.**"]))
    assert "ssh" in (p["permission"] for p in graph.get_group_details("team-sre")["permissions"])
    assert "ssh" in (pt.name for pt in graph.get_permissions())
    assert "team-sre" in graph.get_permission_details("ssh")["groups"]
    assert "ssh" in (p["permission"] for p in graph.get_user_details("*****@*****.**")["permissions"])

    # now disable the ssh permission
    disable_permission(session, "ssh", users["*****@*****.**"].id)
    graph.update_from_db(session)

    grant_perms = [
        x for x in user_permissions(session, users["*****@*****.**"]) if x.name == PERMISSION_GRANT
    ]
    assert not filter_grantable_permissions(session, grant_perms)
    assert "ssh" not in (p.name for p in get_all_permissions(session))
    assert "ssh" not in (p.name for p in get_all_permissions(session, include_disabled=False))
    assert "ssh" in (p.name for p in get_all_permissions(session, include_disabled=True))
    assert "ssh" not in get_grantable_permissions(session, [])
    assert not get_groups_by_permission(session, perm_ssh)
    assert not get_owner_arg_list(session, perm_ssh, "*")
    assert "ssh" not in get_owners_by_grantable_permission(session)
    assert "ssh" not in (
        x[0].name for x in user_grantable_permissions(session, users["*****@*****.**"])
    )
    assert not user_has_permission(session, users["*****@*****.**"], "ssh")
    assert "ssh" not in (p.name for p in user_permissions(session, users["*****@*****.**"]))
    assert "ssh" not in (
        p["permission"] for p in graph.get_group_details("team-sre")["permissions"]
    )
    assert "ssh" not in (pt.name for pt in graph.get_permissions())
    assert not graph.get_permission_details("ssh")["groups"]
    assert "ssh" not in (
        p["permission"] for p in graph.get_user_details("*****@*****.**")["permissions"]
    )
Пример #24
0
def test_permission_request_flow(
    session, standard_graph, groups, grantable_permissions, http_client, base_url  # noqa: F811
):
    """Test that a permission request gets into the system correctly and
    notifications are sent correctly."""
    perm_grant, _, perm1, perm2 = grantable_permissions
    grant_permission(groups["all-teams"], perm_grant, argument="grantable.*")
    grant_permission(groups["security-team"], perm_grant, argument="grantable.one")
    grant_permission(groups["tech-ops"], perm_grant, argument="grantable.two")

    # REQUEST: permission with an invalid argument
    groupname = "serving-team"
    username = "******"
    fe_url = url(base_url, "/groups/{}/permission/request".format(groupname))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode(
            {
                "permission_name": "grantable.one",
                "argument": "some argument?",
                "reason": "blah blah black sheep",
                "argument_type": "text",
            }
        ),
        headers={"X-Grouper-User": username},
    )
    assert resp.code == 200
    assert b"Field must match" in resp.body
    emails = _get_unsent_and_mark_as_sent_emails(session)
    assert len(emails) == 0, "no emails queued"

    # REQUEST: 'grantable.one', 'some argument' for 'serving-team'
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode(
            {
                "permission_name": "grantable.one",
                "argument": "some argument",
                "reason": "blah blah black sheep",
                "argument_type": "text",
            }
        ),
        headers={"X-Grouper-User": username},
    )
    assert resp.code == 200

    emails = _get_unsent_and_mark_as_sent_emails(session)
    assert_same_recipients(emails, [u"*****@*****.**", u"*****@*****.**"])

    perms = _load_permissions_by_group_name(session, "serving-team")
    assert len(perms) == 1
    assert "grantable.one" not in perms, "requested permission shouldn't be granted immediately"

    user = User.get(session, name="*****@*****.**")
    request_tuple, total = get_requests(session, "pending", 10, 0, owner=user)
    assert len(request_tuple.requests) == 0, "random user shouldn't have a request"

    user = User.get(session, name="*****@*****.**")
    request_tuple, total = get_requests(session, "pending", 10, 0, owner=user)
    assert len(request_tuple.requests) == 1, "user in group with grant should have a request"

    # APPROVE grant: have '*****@*****.**' action this request as owner of
    # 'all-teams' which has the grant permission for the requested permission
    request_id = request_tuple.requests[0].id
    fe_url = url(base_url, "/permissions/requests/{}".format(request_id))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"status": "actioned", "reason": "lgtm"}),
        headers={"X-Grouper-User": user.name},
    )
    assert resp.code == 200

    perms = _load_permissions_by_group_name(session, "serving-team")
    assert len(perms) == 2
    assert "grantable.one" in perms, "requested permission shouldn't be granted immediately"

    emails = _get_unsent_and_mark_as_sent_emails(session)
    assert_same_recipients(emails, [u"*****@*****.**"])

    # (re)REQUEST: 'grantable.one', 'some argument' for 'serving-team'
    groupname = "serving-team"
    username = "******"
    fe_url = url(base_url, "/groups/{}/permission/request".format(groupname))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode(
            {
                "permission_name": "grantable.one",
                "argument": "some argument",
                "reason": "blah blah black sheep",
                "argument_type": "text",
            }
        ),
        headers={"X-Grouper-User": username},
    )
    assert resp.code == 200

    user = User.get(session, name="*****@*****.**")
    request_tuple, total = get_requests(session, "pending", 10, 0, owner=user)
    assert len(request_tuple.requests) == 0, "request for existing perm should fail"

    # REQUEST: 'grantable.two', 'some argument' for 'serving-team'
    groupname = "serving-team"
    username = "******"
    fe_url = url(base_url, "/groups/{}/permission/request".format(groupname))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode(
            {
                "permission_name": "grantable.two",
                "argument": "some argument",
                "reason": "blah blah black sheep",
                "argument_type": "text",
            }
        ),
        headers={"X-Grouper-User": username},
    )
    assert resp.code == 200

    emails = _get_unsent_and_mark_as_sent_emails(session)
    # because tech-ops team doesn't have an email, all of its members should get emailed instead
    assert_same_recipients(
        emails, [u"*****@*****.**", u"*****@*****.**", u"*****@*****.**", u"*****@*****.**"]
    )

    perms = _load_permissions_by_group_name(session, "serving-team")
    assert len(perms) == 2
    assert "grantable.two" not in perms, "requested permission shouldn't be granted immediately"

    user = User.get(session, name="*****@*****.**")
    request_tuple, total = get_requests(session, "pending", 10, 0, owner=user)
    assert len(request_tuple.requests) == 0, "random user shouldn't have a request"

    user = User.get(session, name="*****@*****.**")
    request_tuple, total = get_requests(session, "pending", 10, 0, owner=user)
    assert len(request_tuple.requests) == 1, "user in group with grant should have a request"

    # CANCEL request: have '*****@*****.**' cancel this request
    request_id = request_tuple.requests[0].id
    fe_url = url(base_url, "/permissions/requests/{}".format(request_id))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"status": "cancelled", "reason": "heck no"}),
        headers={"X-Grouper-User": user.name},
    )
    assert resp.code == 200

    emails = _get_unsent_and_mark_as_sent_emails(session)
    assert_same_recipients(emails, [u"*****@*****.**"])

    perms = _load_permissions_by_group_name(session, "serving-team")
    assert len(perms) == 2
    assert "grantable.two" not in perms, "no new permissions should be granted for this"
Пример #25
0
def test_grant_and_revoke(
        session,
        standard_graph,
        graph,
        groups,
        permissions,
        http_client,
        base_url  # noqa: F811
):
    """Test that permission grant and revokes are reflected correctly."""
    group_name = "team-sre"
    permission_name = "sudo"
    user_name = "*****@*****.**"

    def _check_graph_for_perm(graph):
        # type: (GroupGraph) -> bool
        return any([
            g["permission"] == permission_name and g["distance"] == 0
            for g in graph.get_group_details(group_name)["permissions"]
        ])

    # make some permission admins
    grant_permission(groups["security-team"], permissions[PERMISSION_ADMIN])

    # grant attempt by non-permission admin
    fe_url = url(base_url, "/permissions/grant/{}".format(group_name))
    with pytest.raises(HTTPError):
        yield http_client.fetch(
            fe_url,
            method="POST",
            body=urlencode({
                "permission": permission_name,
                "argument": "specific_arg"
            }),
            headers={"X-Grouper-User": "******"},
        )

    graph.update_from_db(session)
    assert not _check_graph_for_perm(graph), "no permissions granted"

    # grant by permission admin
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({
            "permission": permission_name,
            "argument": "specific_arg"
        }),
        headers={"X-Grouper-User": user_name},
    )
    assert resp.code == 200

    graph.update_from_db(session)
    assert _check_graph_for_perm(graph), "permissions granted, successfully"

    # figure out mapping_id of grant
    permission_id = get_permission(session, permission_name).id
    group_id = Group.get(session, name=group_name).id
    mapping = (session.query(PermissionMap).filter(
        PermissionMap.permission_id == permission_id,
        PermissionMap.group_id == group_id).first())

    # revoke permission by non-admin
    fe_url = url(
        base_url, "/permissions/{}/revoke/{}".format(permission_name,
                                                     mapping.id))
    with pytest.raises(HTTPError):
        yield http_client.fetch(fe_url,
                                method="POST",
                                body=urlencode({}),
                                headers={"X-Grouper-User": "******"})

    graph.update_from_db(session)
    assert _check_graph_for_perm(graph), "permissions not revoked"

    # revoke permission for realz
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   body=urlencode({}),
                                   headers={"X-Grouper-User": user_name})
    assert resp.code == 200

    graph.update_from_db(session)
    assert not _check_graph_for_perm(graph), "permissions revoked successfully"
Пример #26
0
def test_permission_grant_to_owners(
        session,
        standard_graph,
        groups,
        grantable_permissions,
        permissions  # noqa: F811
):
    """Test we're getting correct owners according to granted
    'grouper.permission.grant' permissions."""
    perm_grant, _, perm1, perm2 = grantable_permissions

    # Disable the group with permission admin since otherwise they're an approver on everything,
    # and check that there are then no approvers.
    groups["permission-admins"].disable()
    session.commit()
    assert not get_owners_by_grantable_permission(
        session), "nothing to begin with"

    # grant a grant on a non-existent permission
    grant_permission(groups["auditors"],
                     perm_grant,
                     argument="notgrantable.one")
    assert not get_owners_by_grantable_permission(
        session), "ignore grants for non-existent perms"

    # grant a wildcard grant -- make sure all permissions are represented and
    # the grant isn't inherited
    grant_permission(groups["all-teams"], perm_grant, argument="grantable.*")
    owners_by_arg_by_perm = get_owners_by_grantable_permission(session)
    expected = [groups["all-teams"]]
    assert owners_by_arg_by_perm[
        perm1.name]["*"] == expected, "grants are not inherited"
    assert len(owners_by_arg_by_perm) == 2
    assert len(owners_by_arg_by_perm[perm1.name]) == 1
    assert len(owners_by_arg_by_perm[perm2.name]) == 1

    # grant on argument substring
    grant_permission(groups["team-sre"],
                     perm_grant,
                     argument="{}/somesubstring*".format(perm1.name))
    owners_by_arg_by_perm = get_owners_by_grantable_permission(session)
    expected = [groups["all-teams"]]
    assert owners_by_arg_by_perm[perm1.name]["*"] == expected
    expected = [groups["team-sre"]]
    assert owners_by_arg_by_perm[perm1.name]["somesubstring*"] == expected

    # make sure get_owner() respect substrings
    res = [
        o.groupname for o, a in get_owner_arg_list(
            session,
            perm1,
            "somesubstring",
            owners_by_arg_by_perm=owners_by_arg_by_perm)
    ]
    assert sorted(res) == ["all-teams", "team-sre"
                           ], "should include substring wildcard matches"

    res = [
        o.groupname for o, a in get_owner_arg_list(
            session,
            perm1,
            "othersubstring",
            owners_by_arg_by_perm=owners_by_arg_by_perm)
    ]
    assert sorted(res) == ["all-teams"
                           ], "negative test of substring wildcard matches"

    # permission admins have all the power
    grant_permission(groups["security-team"], permissions[PERMISSION_ADMIN])
    owners_by_arg_by_perm = get_owners_by_grantable_permission(session)
    all_permissions = get_all_permissions(session)
    for perm in all_permissions:
        assert perm.name in owners_by_arg_by_perm, "all permission should be represented"
        assert (groups["security-team"]
                in owners_by_arg_by_perm[perm.name]["*"]
                ), "permission admin should be wildcard owners"
Пример #27
0
def test_permission_request_flow(
        session,
        standard_graph,
        groups,
        grantable_permissions,
        http_client,
        base_url  # noqa: F811
):
    """Test that a permission request gets into the system correctly and
    notifications are sent correctly."""
    perm_grant, _, perm1, perm2 = grantable_permissions
    grant_permission(groups["all-teams"], perm_grant, argument="grantable.*")
    grant_permission(groups["security-team"],
                     perm_grant,
                     argument="grantable.one")
    grant_permission(groups["tech-ops"], perm_grant, argument="grantable.two")

    # REQUEST: permission with an invalid argument
    groupname = "serving-team"
    username = "******"
    fe_url = url(base_url, "/groups/{}/permission/request".format(groupname))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({
            "permission_name": "grantable.one",
            "argument": "some argument?",
            "reason": "blah blah black sheep",
            "argument_type": "text",
        }),
        headers={"X-Grouper-User": username},
    )
    assert resp.code == 200
    assert b"Field must match" in resp.body
    emails = _get_unsent_and_mark_as_sent_emails(session)
    assert len(emails) == 0, "no emails queued"

    # REQUEST: 'grantable.one', 'some argument' for 'serving-team'
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({
            "permission_name": "grantable.one",
            "argument": "some argument",
            "reason": "blah blah black sheep",
            "argument_type": "text",
        }),
        headers={"X-Grouper-User": username},
    )
    assert resp.code == 200

    emails = _get_unsent_and_mark_as_sent_emails(session)
    assert_same_recipients(emails, ["*****@*****.**", "*****@*****.**"])

    perms = _load_permissions_by_group_name(session, "serving-team")
    assert len(perms) == 1
    assert "grantable.one" not in perms, "requested permission shouldn't be granted immediately"

    user = User.get(session, name="*****@*****.**")
    request_tuple, total = get_requests(session, "pending", 10, 0, owner=user)
    assert len(
        request_tuple.requests) == 0, "random user shouldn't have a request"

    user = User.get(session, name="*****@*****.**")
    request_tuple, total = get_requests(session, "pending", 10, 0, owner=user)
    assert len(request_tuple.requests
               ) == 1, "user in group with grant should have a request"

    # APPROVE grant: have '*****@*****.**' action this request as owner of
    # 'all-teams' which has the grant permission for the requested permission
    request_id = request_tuple.requests[0].id
    fe_url = url(base_url, "/permissions/requests/{}".format(request_id))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({
            "status": "actioned",
            "reason": "lgtm"
        }),
        headers={"X-Grouper-User": user.name},
    )
    assert resp.code == 200

    perms = _load_permissions_by_group_name(session, "serving-team")
    assert len(perms) == 2
    assert "grantable.one" in perms, "requested permission shouldn't be granted immediately"

    emails = _get_unsent_and_mark_as_sent_emails(session)
    assert_same_recipients(emails, ["*****@*****.**"])

    # (re)REQUEST: 'grantable.one', 'some argument' for 'serving-team'
    groupname = "serving-team"
    username = "******"
    fe_url = url(base_url, "/groups/{}/permission/request".format(groupname))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({
            "permission_name": "grantable.one",
            "argument": "some argument",
            "reason": "blah blah black sheep",
            "argument_type": "text",
        }),
        headers={"X-Grouper-User": username},
    )
    assert resp.code == 200

    user = User.get(session, name="*****@*****.**")
    request_tuple, total = get_requests(session, "pending", 10, 0, owner=user)
    assert len(
        request_tuple.requests) == 0, "request for existing perm should fail"

    # REQUEST: 'grantable.two', 'some argument' for 'serving-team'
    groupname = "serving-team"
    username = "******"
    fe_url = url(base_url, "/groups/{}/permission/request".format(groupname))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({
            "permission_name": "grantable.two",
            "argument": "some argument",
            "reason": "blah blah black sheep",
            "argument_type": "text",
        }),
        headers={"X-Grouper-User": username},
    )
    assert resp.code == 200

    emails = _get_unsent_and_mark_as_sent_emails(session)
    # because tech-ops team doesn't have an email, all of its members should get emailed instead
    assert_same_recipients(
        emails, ["*****@*****.**", "*****@*****.**", "*****@*****.**", "*****@*****.**"])

    perms = _load_permissions_by_group_name(session, "serving-team")
    assert len(perms) == 2
    assert "grantable.two" not in perms, "requested permission shouldn't be granted immediately"

    user = User.get(session, name="*****@*****.**")
    request_tuple, total = get_requests(session, "pending", 10, 0, owner=user)
    assert len(
        request_tuple.requests) == 0, "random user shouldn't have a request"

    user = User.get(session, name="*****@*****.**")
    request_tuple, total = get_requests(session, "pending", 10, 0, owner=user)
    assert len(request_tuple.requests
               ) == 1, "user in group with grant should have a request"

    # CANCEL request: have '*****@*****.**' cancel this request
    request_id = request_tuple.requests[0].id
    fe_url = url(base_url, "/permissions/requests/{}".format(request_id))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({
            "status": "cancelled",
            "reason": "heck no"
        }),
        headers={"X-Grouper-User": user.name},
    )
    assert resp.code == 200

    emails = _get_unsent_and_mark_as_sent_emails(session)
    assert_same_recipients(emails, ["*****@*****.**"])

    perms = _load_permissions_by_group_name(session, "serving-team")
    assert len(perms) == 2
    assert "grantable.two" not in perms, "no new permissions should be granted for this"
Пример #28
0
def test_tags(session, http_client, base_url, graph):  # noqa: F811
    perm = create_permission(session, TAG_EDIT)
    session.commit()

    create_permission(session, "it.literally.does.not.matter")
    session.commit()

    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, TAG_EDIT),
        "*",
    )
    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, "it.literally.does.not.matter"),
        "*",
    )

    tag = PublicKeyTag(name="tyler_was_here")
    tag.add(session)
    session.commit()

    tag = PublicKeyTag.get(session, name="tyler_was_here")

    grant_permission_to_tag(session, tag.id, perm.id, "prod")
    with pytest.raises(AssertionError):
        grant_permission_to_tag(session, tag.id, perm.id, "question?")

    user = session.query(User).filter_by(username="******").scalar()

    add_public_key(session, user, SSH_KEY_1)

    key = session.query(PublicKey).filter_by(user_id=user.id).scalar()

    add_tag_to_public_key(session, key, tag)

    user = session.query(User).filter_by(username="******").scalar()

    key = session.query(PublicKey).filter_by(user_id=user.id).scalar()
    assert (
        len(get_public_key_permissions(session, key)) == 1
    ), "The SSH Key should have only 1 permission"
    assert (
        get_public_key_permissions(session, key)[0].name == TAG_EDIT
    ), "The SSH key's permission should be TAG_EDIT"
    assert (
        get_public_key_permissions(session, key)[0].argument == "prod"
    ), "The SSH key's permission argument should be restricted to the tag's argument"
    assert len(user_permissions(session, user)) > 1, "The user should have more than 1 permission"

    graph.update_from_db(session)

    fe_url = url(base_url, "/users/{}".format(user.username))
    resp = yield http_client.fetch(fe_url)
    assert resp.code == 200
    body = json.loads(resp.body)
    pub_key = body["data"]["user"]["public_keys"][0]
    assert len(pub_key["tags"]) == 1, "The public key should only have 1 tag"
    assert pub_key["fingerprint"] == "e9:ae:c5:8f:39:9b:3a:9c:6a:b8:33:6b:cb:6f:ba:35"
    assert pub_key["fingerprint_sha256"] == "MP9uWaujW96EWxbjDtPdPWheoMDu6BZ8FZj0+CBkVWU"
    assert pub_key["tags"][0] == "tyler_was_here", "The public key should have the tag we gave it"
Пример #29
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
Пример #30
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
Пример #31
0
def test_grant_and_revoke(
    session, standard_graph, graph, groups, permissions, http_client, base_url  # noqa: F811
):
    """Test that permission grant and revokes are reflected correctly."""
    group_name = "team-sre"
    permission_name = "sudo"
    user_name = "*****@*****.**"

    def _check_graph_for_perm(graph):
        # type: (GroupGraph) -> bool
        return any(
            [
                g["permission"] == permission_name and g["distance"] == 0
                for g in graph.get_group_details(group_name)["permissions"]
            ]
        )

    # make some permission admins
    grant_permission(groups["security-team"], permissions[PERMISSION_ADMIN])

    # grant attempt by non-permission admin
    fe_url = url(base_url, "/permissions/grant/{}".format(group_name))
    with pytest.raises(HTTPError):
        yield http_client.fetch(
            fe_url,
            method="POST",
            body=urlencode({"permission": permission_name, "argument": "specific_arg"}),
            headers={"X-Grouper-User": "******"},
        )

    graph.update_from_db(session)
    assert not _check_graph_for_perm(graph), "no permissions granted"

    # grant by permission admin
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"permission": permission_name, "argument": "specific_arg"}),
        headers={"X-Grouper-User": user_name},
    )
    assert resp.code == 200

    graph.update_from_db(session)
    assert _check_graph_for_perm(graph), "permissions granted, successfully"

    # figure out mapping_id of grant
    permission_id = get_permission(session, permission_name).id
    group_id = Group.get(session, name=group_name).id
    mapping = (
        session.query(PermissionMap)
        .filter(PermissionMap.permission_id == permission_id, PermissionMap.group_id == group_id)
        .first()
    )

    # revoke permission by non-admin
    fe_url = url(base_url, "/permissions/{}/revoke/{}".format(permission_name, mapping.id))
    with pytest.raises(HTTPError):
        yield http_client.fetch(
            fe_url, method="POST", body=urlencode({}), headers={"X-Grouper-User": "******"}
        )

    graph.update_from_db(session)
    assert _check_graph_for_perm(graph), "permissions not revoked"

    # revoke permission for realz
    resp = yield http_client.fetch(
        fe_url, method="POST", body=urlencode({}), headers={"X-Grouper-User": user_name}
    )
    assert resp.code == 200

    graph.update_from_db(session)
    assert not _check_graph_for_perm(graph), "permissions revoked successfully"
Пример #32
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
Пример #33
0
def test_permissions(users, http_client, base_url, session):  # noqa: F811

    user = session.query(User).filter_by(username="******").scalar()

    create_permission(session, TAG_EDIT)
    session.commit()

    create_permission(session, "it.literally.does.not.matter")
    session.commit()

    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, TAG_EDIT),
        "*",
    )
    grant_permission(
        session.query(Group).filter_by(groupname="all-teams").scalar(),
        get_permission(session, "it.literally.does.not.matter"),
        "*",
    )

    fe_url = url(base_url, "/tags")
    yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"tagname": "tyler_was_here", "description": "Test Tag Please Ignore"}),
        headers={"X-Grouper-User": user.username},
    )

    tag = PublicKeyTag.get(session, name="tyler_was_here")

    user = session.query(User).filter_by(username="******").scalar()

    fe_url = url(base_url, "/permissions/grant_tag/{}".format(tag.name))
    yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"permission": TAG_EDIT, "argument": "prod"}),
        headers={"X-Grouper-User": user.username},
    )

    user = session.query(User).filter_by(username="******").scalar()
    # add SSH key
    fe_url = url(base_url, "/users/{}/public-key/add".format(user.username))
    yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"public_key": SSH_KEY_1}),
        headers={"X-Grouper-User": user.username},
    )

    key = session.query(PublicKey).filter_by(user_id=user.id).scalar()
    user = session.query(User).filter_by(username="******").scalar()

    fe_url = url(base_url, "/users/{}/public-key/{}/tag".format(user.username, key.id))
    yield http_client.fetch(
        fe_url,
        method="POST",
        body=urlencode({"tagname": "tyler_was_here"}),
        headers={"X-Grouper-User": user.username},
    )

    user = session.query(User).filter_by(username="******").scalar()

    key = session.query(PublicKey).filter_by(user_id=user.id).scalar()
    assert (
        len(get_public_key_permissions(session, key)) == 1
    ), "The SSH Key should have only 1 permission"
    assert (
        get_public_key_permissions(session, key)[0].name == TAG_EDIT
    ), "The SSH key's permission should be TAG_EDIT"
    assert (
        get_public_key_permissions(session, key)[0].argument == "prod"
    ), "The SSH key's permission argument should be restricted to the tag's argument"
    assert len(user_permissions(session, user)) > 1, "The user should have more than 1 permission"
Пример #34
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