Beispiel #1
0
def test_shell(session, users, http_client, base_url, graph):  # noqa: F811
    user = users["*****@*****.**"]
    assert not get_user_metadata_by_key(session, user.id,
                                        USER_METADATA_SHELL_KEY)

    set_user_metadata(session, user.id, USER_METADATA_SHELL_KEY, "/bin/bash")
    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)
    assert body["data"]["user"]["metadata"] != [], "There should be metadata"
    assert len(body["data"]["user"]
               ["metadata"]) == 1, "There should only be 1 metadata!"
    assert (body["data"]["user"]["metadata"][0]["data_key"] == "shell"
            ), "There should only be 1 metadata!"
    assert (body["data"]["user"]["metadata"][0]["data_value"] == "/bin/bash"
            ), "The shell should be set to the correct value"

    set_user_metadata(session, user.id, USER_METADATA_SHELL_KEY, "/bin/zsh")
    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)
    assert body["data"]["user"]["metadata"] != [], "There should be metadata"
    assert (body["data"]["user"]["metadata"][0]["data_key"] == "shell"
            ), "There should only be 1 metadata!"
    assert (body["data"]["user"]["metadata"][0]["data_value"] == "/bin/zsh"
            ), "The shell should be set to the correct value"
    assert len(body["data"]["user"]
               ["metadata"]) == 1, "There should only be 1 metadata!"
Beispiel #2
0
def test_graph_disable(
        session,
        graph,
        users,
        groups,
        user_admin_perm_to_auditors,
        http_client,
        base_url  # noqa: F811
):
    graph.update_from_db(session)
    old_users = graph.users
    assert sorted(old_users) == sorted(list(users.keys()) + ["*****@*****.**"])

    # disable a user
    username = u"*****@*****.**"
    fe_url = url(base_url, "/users/{}/disable".format(username))
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": "******"},
                                   body=urlencode({}))
    assert resp.code == 200

    graph.update_from_db(session)
    assert len(graph.users) == (len(old_users) -
                                1), "disabled user removed from graph"
    assert username not in graph.users
Beispiel #3
0
def test_github_username(session, users, http_client, base_url,
                         graph):  # noqa: F811
    user = users["*****@*****.**"]
    assert get_user_metadata_by_key(session, user.id,
                                    USER_METADATA_GITHUB_USERNAME_KEY) is None

    set_user_metadata(session, user.id, USER_METADATA_GITHUB_USERNAME_KEY,
                      "zorkian-on-gh")
    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)
    [metadata] = body["data"]["user"]["metadata"]
    assert metadata["data_key"] == "github_username"
    assert metadata["data_value"] == "zorkian-on-gh"

    set_user_metadata(session, user.id, USER_METADATA_GITHUB_USERNAME_KEY,
                      None)
    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)
    assert body["data"]["user"]["metadata"] == []
Beispiel #4
0
def test_graph_disable(session, graph, groups, http_client,
                       base_url):  # noqa: F811
    """ Test that disabled groups work with the graph as expected."""
    groupname = u"serving-team"

    graph.update_from_db(session)
    old_groups = graph.groups
    assert sorted(old_groups) == sorted(groups.keys())
    assert groupname in graph.permission_metadata

    # disable a group
    fe_url = url(base_url, "/groups/{}/disable".format(groupname))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        headers={"X-Grouper-User": "******"},
        body=urlencode({"name": groupname}),
    )
    assert resp.code == 200

    graph.update_from_db(session)
    assert len(graph.groups) == (len(old_groups) -
                                 1), "disabled group removed from graph"
    assert groupname not in graph.groups
    assert groupname not in graph.permission_metadata
Beispiel #5
0
def test_graph_desc_to_ances(session, graph, users, groups):  # noqa: F811
    """ Test adding members where all descendants already exist."""

    setup_desc_to_ances(session, users, groups)
    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"])
Beispiel #6
0
def test_shell(session, users, http_client, base_url, graph):  # noqa: F811
    user = users["*****@*****.**"]
    assert not get_user_metadata_by_key(session, user.id, USER_METADATA_SHELL_KEY)

    set_user_metadata(session, user.id, USER_METADATA_SHELL_KEY, "/bin/bash")
    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)
    assert body["data"]["user"]["metadata"] != [], "There should be metadata"
    assert len(body["data"]["user"]["metadata"]) == 1, "There should only be 1 metadata!"
    assert (
        body["data"]["user"]["metadata"][0]["data_key"] == "shell"
    ), "There should only be 1 metadata!"
    assert (
        body["data"]["user"]["metadata"][0]["data_value"] == "/bin/bash"
    ), "The shell should be set to the correct value"

    set_user_metadata(session, user.id, USER_METADATA_SHELL_KEY, "/bin/zsh")
    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)
    assert body["data"]["user"]["metadata"] != [], "There should be metadata"
    assert (
        body["data"]["user"]["metadata"][0]["data_key"] == "shell"
    ), "There should only be 1 metadata!"
    assert (
        body["data"]["user"]["metadata"][0]["data_value"] == "/bin/zsh"
    ), "The shell should be set to the correct value"
    assert len(body["data"]["user"]["metadata"]) == 1, "There should only be 1 metadata!"
Beispiel #7
0
def test_graph_desc_to_ances(session, graph, users, groups):  # noqa: F811
    """ Test adding members where all descendants already exist."""

    setup_desc_to_ances(session, users, groups)
    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"])
Beispiel #8
0
def test_machine_set_plugin(session, standard_graph, graph, http_client,
                            base_url):  # noqa: F811
    get_plugin_proxy().add_plugin(MachineSetPlugin())
    admin = "*****@*****.**"

    # Edit the metadata of an existing service account.  This should fail (although return 200)
    # including the appropriate error.
    update = {
        "description": "some service account",
        "machine_set": "not valid"
    }
    fe_url = url(base_url, "/groups/team-sre/service/[email protected]/edit")
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": admin},
                                   body=urlencode(update))
    assert resp.code == 200
    assert b"[email protected] has invalid machine set" in resp.body
    graph.update_from_db(session)
    metadata = graph.user_metadata["*****@*****.**"]
    assert metadata["service_account"]["machine_set"] == "some machines"

    # Use a valid machine set, and then this should go through.
    update["machine_set"] = "is okay"
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": admin},
                                   body=urlencode(update))
    assert resp.code == 200
    graph.update_from_db(session)
    metadata = graph.user_metadata["*****@*****.**"]
    assert metadata["service_account"]["machine_set"] == "is okay"
Beispiel #9
0
def test_groups_email(groups, session, graph, http_client, base_url):  # noqa: F811
    expected_address = "*****@*****.**"
    sad = groups["sad-team"]
    sad.email_address = expected_address
    session.commit()
    Counter.incr(session, "updates")
    graph.update_from_db(session)

    api_url = url(base_url, "/groups/{}".format(sad.name))
    resp = yield http_client.fetch(api_url)
    body = json.loads(resp.body)

    assert body["data"]["group"]["contacts"]["email"] == expected_address
Beispiel #10
0
def test_groups_email(groups, session, graph, http_client, base_url):  # noqa: F811
    expected_address = "*****@*****.**"
    sad = groups["sad-team"]
    sad.email_address = expected_address
    session.commit()
    Counter.incr(session, "updates")
    graph.update_from_db(session)

    api_url = url(base_url, "/groups/{}".format(sad.name))
    resp = yield http_client.fetch(api_url)
    body = json.loads(resp.body)

    assert body["data"]["group"]["contacts"]["email"] == expected_address
Beispiel #11
0
def test_user_enable_disable(
    session,  # noqa: F811
    graph,  # noqa: F811
    users,  # noqa: F811
    user_admin_perm_to_auditors,
    user_enable_perm_to_sre,
    http_client,
    base_url,
):
    username = "******"
    old_groups = sorted(get_groups(graph, username))
    headers_admin = {"X-Grouper-User": "******"}
    headers_enable = {"X-Grouper-User": "******"}
    body_preserve = urlencode({"preserve_membership": "true"})
    body_base = urlencode({})

    # disable user
    fe_url = url(base_url, "/users/{}/disable".format(username))
    resp = yield http_client.fetch(fe_url, method="POST", headers=headers_admin, body=body_base)
    assert resp.code == 200

    # Attempt to enable user, preserving groups, as user with `grouper.user.enable`.
    # Should fail due to lack of admin perm.
    fe_url = url(base_url, "/users/{}/enable".format(username))
    with pytest.raises(HTTPError):
        resp = yield http_client.fetch(
            fe_url, method="POST", headers=headers_enable, body=body_preserve
        )

    # enable user, PRESERVE groups, as a user with the correct admin permission
    fe_url = url(base_url, "/users/{}/enable".format(username))
    resp = yield http_client.fetch(
        fe_url, method="POST", headers=headers_admin, body=body_preserve
    )
    assert resp.code == 200
    graph.update_from_db(session)
    assert old_groups == sorted(get_groups(graph, username)), "nothing should be removed"

    # disable user again
    fe_url = url(base_url, "/users/{}/disable".format(username))
    resp = yield http_client.fetch(fe_url, method="POST", headers=headers_admin, body=body_base)
    assert resp.code == 200

    # Attempt to enable user, PURGE groups. Should now succeed even with
    # only the `grouper.user.enable` perm.
    fe_url = url(base_url, "/users/{}/enable".format(username))
    resp = yield http_client.fetch(fe_url, method="POST", headers=headers_enable, body=body_base)
    assert resp.code == 200

    graph.update_from_db(session)
    assert len(get_groups(graph, username)) == 0, "all group membership should be removed"
Beispiel #12
0
def test_user_enable_disable(
    session,  # noqa: F811
    graph,  # noqa: F811
    users,  # noqa: F811
    user_admin_perm_to_auditors,
    user_enable_perm_to_sre,
    http_client,
    base_url,
):
    username = u"*****@*****.**"
    old_groups = sorted(get_groups(graph, username))
    headers_admin = {"X-Grouper-User": "******"}
    headers_enable = {"X-Grouper-User": "******"}
    body_preserve = urlencode({"preserve_membership": "true"})
    body_base = urlencode({})

    # disable user
    fe_url = url(base_url, "/users/{}/disable".format(username))
    resp = yield http_client.fetch(fe_url, method="POST", headers=headers_admin, body=body_base)
    assert resp.code == 200

    # Attempt to enable user, preserving groups, as user with `grouper.user.enable`.
    # Should fail due to lack of admin perm.
    fe_url = url(base_url, "/users/{}/enable".format(username))
    with pytest.raises(HTTPError):
        resp = yield http_client.fetch(
            fe_url, method="POST", headers=headers_enable, body=body_preserve
        )

    # enable user, PRESERVE groups, as a user with the correct admin permission
    fe_url = url(base_url, "/users/{}/enable".format(username))
    resp = yield http_client.fetch(
        fe_url, method="POST", headers=headers_admin, body=body_preserve
    )
    assert resp.code == 200
    graph.update_from_db(session)
    assert old_groups == sorted(get_groups(graph, username)), "nothing should be removed"

    # disable user again
    fe_url = url(base_url, "/users/{}/disable".format(username))
    resp = yield http_client.fetch(fe_url, method="POST", headers=headers_admin, body=body_base)
    assert resp.code == 200

    # Attempt to enable user, PURGE groups. Should now succeed even with
    # only the `grouper.user.enable` perm.
    fe_url = url(base_url, "/users/{}/enable".format(username))
    resp = yield http_client.fetch(fe_url, method="POST", headers=headers_enable, body=body_base)
    assert resp.code == 200

    graph.update_from_db(session)
    assert len(get_groups(graph, username)) == 0, "all group membership should be removed"
Beispiel #13
0
def test_graph_edit_role(session, graph, standard_graph, groups, users):  # noqa: F811
    """Test that membership role changes are refected in the graph."""
    username = "******"

    user_role = graph.get_group_details("tech-ops")["users"][username]["rolename"]
    assert user_role == "np-owner"

    groups["tech-ops"].edit_member(
        users["*****@*****.**"], users[username], "a reason", role="owner"
    )

    graph.update_from_db(session)
    user_role = graph.get_group_details("tech-ops")["users"][username]["rolename"]
    assert user_role == "owner"
Beispiel #14
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"
Beispiel #15
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"])
Beispiel #16
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"])
Beispiel #17
0
def test_graph_edit_role(session, graph, standard_graph, groups,
                         users):  # noqa: F811
    """Test that membership role changes are refected in the graph."""
    username = "******"

    user_role = graph.get_group_details(
        "tech-ops")["users"][username]["rolename"]
    assert user_role == "np-owner"

    groups["tech-ops"].edit_member(users["*****@*****.**"],
                                   users[username],
                                   "a reason",
                                   role="owner")

    graph.update_from_db(session)
    user_role = graph.get_group_details(
        "tech-ops")["users"][username]["rolename"]
    assert user_role == "owner"
Beispiel #18
0
def test_graph_disable(
    session, graph, users, groups, user_admin_perm_to_auditors, http_client, base_url  # noqa: F811
):
    graph.update_from_db(session)
    old_users = graph.users
    assert sorted(old_users) == sorted(list(users.keys()) + ["*****@*****.**"])

    # disable a user
    username = u"*****@*****.**"
    fe_url = url(base_url, "/users/{}/disable".format(username))
    resp = yield http_client.fetch(
        fe_url, method="POST", headers={"X-Grouper-User": "******"}, body=urlencode({})
    )
    assert resp.code == 200

    graph.update_from_db(session)
    assert len(graph.users) == (len(old_users) - 1), "disabled user removed from graph"
    assert username not in graph.users
Beispiel #19
0
def test_passwords_api(session, users, http_client, base_url, graph):  # noqa: F811
    user = users["*****@*****.**"]
    TEST_PASSWORD = "******"

    add_new_user_password(session, "test", TEST_PASSWORD, user.id)
    assert len(user_passwords(session, user)) == 1, "The user should only have a single password"

    graph.update_from_db(session)
    c = Counter.get(session, name="updates")
    api_url = url(base_url, "/users/{}".format(user.username))
    resp = yield http_client.fetch(api_url)
    body = json.loads(resp.body)
    assert body["checkpoint"] == c.count, "The API response is not up to date"
    assert (
        body["data"]["user"]["passwords"] != []
    ), "The user should not have an empty passwords field"
    assert (
        body["data"]["user"]["passwords"][0]["name"] == "test"
    ), "The password should have the same name"
    assert (
        body["data"]["user"]["passwords"][0]["func"] == "crypt(3)-$6$"
    ), "This test does not support any hash functions other than crypt(3)-$6$"
    assert body["data"]["user"]["passwords"][0]["hash"] == crypt.crypt(
        TEST_PASSWORD, body["data"]["user"]["passwords"][0]["salt"]
    ), (
        "The hash should be the same as hashing the password and the salt together using the"
        " hashing function"
    )
    assert body["data"]["user"]["passwords"][0]["hash"] != crypt.crypt(
        "hello", body["data"]["user"]["passwords"][0]["salt"]
    ), (
        "The hash should not be the same as hashing the wrong password and the salt together"
        " using the hashing function"
    )

    delete_user_password(session, "test", user.id)
    c = Counter.get(session, name="updates")
    graph.update_from_db(session)
    api_url = url(base_url, "/users/{}".format(user.username))
    resp = yield http_client.fetch(api_url)
    body = json.loads(resp.body)
    assert body["checkpoint"] == c.count, "The API response is not up to date"
    assert body["data"]["user"]["passwords"] == [], "The user should not have any passwords"
Beispiel #20
0
def test_passwords_api(session, users, http_client, base_url, graph):  # noqa: F811
    user = users["*****@*****.**"]
    TEST_PASSWORD = "******"

    add_new_user_password(session, "test", TEST_PASSWORD, user.id)
    assert len(user_passwords(session, user)) == 1, "The user should only have a single password"

    graph.update_from_db(session)
    c = Counter.get(session, name="updates")
    api_url = url(base_url, "/users/{}".format(user.username))
    resp = yield http_client.fetch(api_url)
    body = json.loads(resp.body)
    assert body["checkpoint"] == c.count, "The API response is not up to date"
    assert (
        body["data"]["user"]["passwords"] != []
    ), "The user should not have an empty passwords field"
    assert (
        body["data"]["user"]["passwords"][0]["name"] == "test"
    ), "The password should have the same name"
    assert (
        body["data"]["user"]["passwords"][0]["func"] == "crypt(3)-$6$"
    ), "This test does not support any hash functions other than crypt(3)-$6$"
    assert body["data"]["user"]["passwords"][0]["hash"] == crypt.crypt(
        TEST_PASSWORD, body["data"]["user"]["passwords"][0]["salt"]
    ), (
        "The hash should be the same as hashing the password and the salt together using the"
        " hashing function"
    )
    assert body["data"]["user"]["passwords"][0]["hash"] != crypt.crypt(
        "hello", body["data"]["user"]["passwords"][0]["salt"]
    ), (
        "The hash should not be the same as hashing the wrong password and the salt together"
        " using the hashing function"
    )

    delete_user_password(session, "test", user.id)
    c = Counter.get(session, name="updates")
    graph.update_from_db(session)
    api_url = url(base_url, "/users/{}".format(user.username))
    resp = yield http_client.fetch(api_url)
    body = json.loads(resp.body)
    assert body["checkpoint"] == c.count, "The API response is not up to date"
    assert body["data"]["user"]["passwords"] == [], "The user should not have any passwords"
Beispiel #21
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"])
Beispiel #22
0
def test_service_account_fe_edit(
        session,
        standard_graph,
        graph,
        http_client,
        base_url  # noqa: F811
):
    owner = "*****@*****.**"
    plebe = "*****@*****.**"
    admin = "*****@*****.**"

    # Unrelated people cannot edit the service account.
    fe_url = url(base_url, "/groups/team-sre/service/[email protected]/edit")
    update = {"description": "desc", "machine_set": "machines"}
    with pytest.raises(HTTPError):
        yield http_client.fetch(fe_url,
                                method="POST",
                                headers={"X-Grouper-User": plebe},
                                body=urlencode(update))

    # A group member can.
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": owner},
                                   body=urlencode(update))
    assert resp.code == 200
    graph.update_from_db(session)
    metadata = graph.user_metadata["*****@*****.**"]
    assert metadata["service_account"]["description"] == "desc"
    assert metadata["service_account"]["machine_set"] == "machines"

    # A user admin also can.
    update["description"] = "done by admin"
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": admin},
                                   body=urlencode(update))
    assert resp.code == 200
    graph.update_from_db(session)
    metadata = graph.user_metadata["*****@*****.**"]
    assert metadata["service_account"]["description"] == "done by admin"
Beispiel #23
0
def test_github_username(session, users, http_client, base_url, graph):  # noqa: F811
    user = users["*****@*****.**"]
    assert get_user_metadata_by_key(session, user.id, USER_METADATA_GITHUB_USERNAME_KEY) is None

    set_user_metadata(session, user.id, USER_METADATA_GITHUB_USERNAME_KEY, "zorkian-on-gh")
    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)
    [metadata] = body["data"]["user"]["metadata"]
    assert metadata["data_key"] == "github_username"
    assert metadata["data_value"] == "zorkian-on-gh"

    set_user_metadata(session, user.id, USER_METADATA_GITHUB_USERNAME_KEY, None)
    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)
    assert body["data"]["user"]["metadata"] == []
Beispiel #24
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"])
Beispiel #25
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"])
Beispiel #26
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"])
Beispiel #27
0
def test_graph_disable(session, graph, groups, http_client, base_url):  # noqa: F811
    """ Test that disabled groups work with the graph as expected."""
    groupname = u"serving-team"

    graph.update_from_db(session)
    old_groups = graph.groups
    assert sorted(old_groups) == sorted(groups.keys())
    assert "permissions" in graph.get_group_details(groupname)

    # disable a group
    fe_url = url(base_url, "/groups/{}/disable".format(groupname))
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        headers={"X-Grouper-User": "******"},
        body=urlencode({"name": groupname}),
    )
    assert resp.code == 200

    graph.update_from_db(session)
    assert len(graph.groups) == (len(old_groups) - 1), "disabled group removed from graph"
    assert groupname not in graph.groups
    with pytest.raises(NoSuchGroup):
        graph.get_group_details(groupname)
Beispiel #28
0
def test_disabling_permission(
    session, groups, standard_graph, graph, http_client, base_url  # noqa: F811
):
    """
    This tests disabling via the front-end route, including checking
    that the user is authorized to disable permissions.
    """
    perm_name = "sudo"
    nonpriv_user_name = "*****@*****.**"  # user without PERMISSION_ADMIN
    nonpriv_headers = {"X-Grouper-User": nonpriv_user_name}
    priv_user_name = "*****@*****.**"  # user with PERMISSION_ADMIN
    priv_headers = {"X-Grouper-User": priv_user_name}
    disable_url = url(base_url, "/permissions/{}/disable".format(perm_name))
    disable_url_non_exist_perm = url(base_url, "/permissions/no.exists/disable")

    assert "sudo:shell" in get_user_permissions(graph, "*****@*****.**")
    assert "sudo:shell" in get_user_permissions(graph, "*****@*****.**")

    # attempt to disable the permission -> should fail cuz actor
    # doesn't have PERMISSION_ADMIN
    with pytest.raises(HTTPError) as exc:
        yield http_client.fetch(disable_url, method="POST", headers=nonpriv_headers, body="")
    assert exc.value.code == 403
    # check that no change
    assert get_permission(session, perm_name).enabled
    graph.update_from_db(session)
    assert "sudo:shell" in get_user_permissions(graph, "*****@*****.**")
    assert "sudo:shell" in get_user_permissions(graph, "*****@*****.**")

    # an actor with PERMISSION_ADMIN is allowed to disable the
    # permission
    resp = yield http_client.fetch(disable_url, method="POST", headers=priv_headers, body="")
    assert resp.code == 200
    assert not get_permission(session, perm_name).enabled
    graph.update_from_db(session)
    assert "sudo:shell" not in get_user_permissions(graph, "*****@*****.**")
    assert "sudo:shell" not in get_user_permissions(graph, "*****@*****.**")

    with pytest.raises(HTTPError) as exc:
        yield http_client.fetch(
            disable_url_non_exist_perm, method="POST", headers=priv_headers, body=""
        )
    assert exc.value.code == 404

    #
    # make sure that when disabling the permission, all mappings of
    # it, i.e., with different arguments, are disabled
    #

    # the standard_graph grants 'ssh' with args '*' and 'shell' to two
    # different groups
    assert "ssh:*" in get_group_permissions(graph, "team-sre")
    assert "ssh:shell" in get_group_permissions(graph, "tech-ops")
    # disable the perm
    disable_url_ssh_pem = url(base_url, "/permissions/ssh/disable")
    resp = yield http_client.fetch(
        disable_url_ssh_pem, method="POST", headers=priv_headers, body=""
    )
    assert resp.code == 200
    assert not get_permission(session, "ssh").enabled
    graph.update_from_db(session)
    assert "ssh:*" not in get_group_permissions(graph, "team-sre")
    assert "ssh:shell" not in get_group_permissions(graph, "tech-ops")
def test_machine_set_plugin(
        mocker,
        session,
        standard_graph,
        graph,
        http_client,
        base_url  # noqa: F811
):
    mocker.patch("grouper.service_account.get_plugin_proxy",
                 return_value=PluginProxy([MachineSetPlugin()]))
    admin = "*****@*****.**"

    # Edit the metadata of an existing service account.  This should fail (although return 200)
    # including the appropriate error.
    update = {
        "description": "some service account",
        "machine_set": "not valid"
    }
    fe_url = url(base_url, "/groups/team-sre/service/[email protected]/edit")
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": admin},
                                   body=urlencode(update))
    assert resp.code == 200
    assert "[email protected] has invalid machine set" in resp.body
    graph.update_from_db(session)
    metadata = graph.user_metadata["*****@*****.**"]
    assert metadata["service_account"]["machine_set"] == "some machines"

    # Use a valid machine set, and then this should go through.
    update["machine_set"] = "is okay"
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": admin},
                                   body=urlencode(update))
    assert resp.code == 200
    graph.update_from_db(session)
    metadata = graph.user_metadata["*****@*****.**"]
    assert metadata["service_account"]["machine_set"] == "is okay"

    # Try creating a new service account with an invalid machine set.
    data = {
        "name": "*****@*****.**",
        "description": "some other service account",
        "machine_set": "not valid",
    }
    fe_url = url(base_url, "/groups/team-sre/service/create")
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": admin},
                                   body=urlencode(data))
    assert resp.code == 200
    assert "[email protected] has invalid machine set" in resp.body
    graph.update_from_db(session)
    assert "*****@*****.**" not in graph.users

    # But this should go through with a valid machine set.
    data["machine_set"] = "is okay"
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": admin},
                                   body=urlencode(data))
    assert resp.code == 200
    graph.update_from_db(session)
    metadata = graph.user_metadata["*****@*****.**"]
    assert metadata["service_account"][
        "description"] == "some other service account"
    assert metadata["service_account"]["machine_set"] == "is okay"
Beispiel #30
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"
def test_service_account_fe_perms(
        session,
        standard_graph,
        graph,
        http_client,
        base_url  # noqa: F811
):
    admin = "*****@*****.**"
    owner = "*****@*****.**"
    plebe = "*****@*****.**"

    # Unrelated people cannot create a service account
    fe_url = url(base_url, "/groups/team-sre/service/create")
    with pytest.raises(HTTPError):
        yield http_client.fetch(
            fe_url,
            method="POST",
            headers={"X-Grouper-User": plebe},
            body=urlencode({
                "name": "service_account",
                "description": "*",
                "machine_set": "*"
            }),
        )
    # But group members can create service accounts
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        headers={"X-Grouper-User": owner},
        body=urlencode({
            "name": "service_account",
            "description": "*",
            "machine_set": "*"
        }),
    )
    assert resp.code == 200

    # Unrelated people cannot grant a permission.
    fe_url = url(base_url, "/groups/team-sre/service/[email protected]/grant")
    with pytest.raises(HTTPError):
        yield http_client.fetch(
            fe_url,
            method="POST",
            headers={"X-Grouper-User": plebe},
            body=urlencode({
                "permission": "team-sre",
                "argument": "*"
            }),
        )

    # Even group owners cannot grant an unrelated permission.
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        headers={"X-Grouper-User": owner},
        body=urlencode({
            "permission": "other-perm",
            "argument": "*"
        }),
    )
    assert resp.code == 200
    graph.update_from_db(session)
    metadata = graph.get_user_details("*****@*****.**")
    assert metadata["permissions"] == []

    # Group owners can delegate a team permission.
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        headers={"X-Grouper-User": owner},
        body=urlencode({
            "permission": "team-sre",
            "argument": "*"
        }),
    )
    assert resp.code == 200

    # Global user admins still cannot grant an unrelated permission.
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        headers={"X-Grouper-User": admin},
        body=urlencode({
            "permission": "other-perm",
            "argument": "*"
        }),
    )
    assert resp.code == 200
    graph.update_from_db(session)
    metadata = graph.get_user_details("*****@*****.**")
    assert len(metadata["permissions"]) == 1

    # But can delegate a team permission.
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        headers={"X-Grouper-User": admin},
        body=urlencode({
            "permission": "ssh",
            "argument": "*"
        }),
    )
    assert resp.code == 200

    # Check that the permissions are reflected in the graph.
    graph.update_from_db(session)
    metadata = graph.get_user_details("*****@*****.**")
    perms = [(p["permission"], p["argument"]) for p in metadata["permissions"]]
    assert sorted(perms) == [("ssh", "*"), ("team-sre", "*")]

    # Find the mapping IDs of the two permissions.
    service_account = ServiceAccount.get(session, name="*****@*****.**")
    perms = service_account_permissions(session, service_account)

    # Unrelated people cannot revoke a permission.
    fe_url = url(
        base_url, "/groups/team-sre/service/[email protected]/revoke/{}".format(
            perms[0].mapping_id))
    with pytest.raises(HTTPError):
        yield http_client.fetch(fe_url,
                                method="POST",
                                headers={"X-Grouper-User": plebe},
                                body=urlencode({}))

    # But the group owner and a global admin can.
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": admin},
                                   body=urlencode({}))
    assert resp.code == 200
    fe_url = url(
        base_url, "/groups/team-sre/service/[email protected]/revoke/{}".format(
            perms[1].mapping_id))
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": owner},
                                   body=urlencode({}))
    assert resp.code == 200

    # This should have removed all the permissions.
    graph.update_from_db(session)
    metadata = graph.get_user_details("*****@*****.**")
    assert metadata["permissions"] == []
def test_service_accounts(
        session,
        standard_graph,
        graph,
        users,
        groups,
        permissions  # noqa: F811
):
    # Create a service account.
    service_account = ServiceAccount.get(session, name="*****@*****.**")
    assert service_account.description == "some service account"
    assert service_account.machine_set == "some machines"
    assert service_account.user.name == "*****@*****.**"
    assert service_account.user.enabled == True
    assert service_account.user.is_service_account == True
    accounts = get_service_accounts(session, groups["team-sre"])
    assert len(accounts) == 1
    assert accounts[0].user.name == "*****@*****.**"
    assert is_service_account(session, service_account.user)

    # Duplicates should raise an exception.
    with pytest.raises(DuplicateServiceAccount):
        create_service_account(session, users["*****@*****.**"], "*****@*****.**",
                               "dup", "dup", groups["team-sre"])

    # zorkian should be able to manage the account, as should gary, but oliver (not a member of the
    # group) should not.
    assert can_manage_service_account(session, service_account,
                                      users["*****@*****.**"])
    assert can_manage_service_account(session, service_account,
                                      users["*****@*****.**"])
    assert not can_manage_service_account(session, service_account,
                                          users["*****@*****.**"])

    # Check that the user appears in the graph.
    graph.update_from_db(session)
    metadata = graph.user_metadata["*****@*****.**"]
    assert metadata["enabled"]
    assert metadata["service_account"]["description"] == "some service account"
    assert metadata["service_account"]["machine_set"] == "some machines"
    assert metadata["service_account"]["owner"] == "team-sre"
    group_details = graph.get_group_details("team-sre")
    assert group_details["service_accounts"] == ["*****@*****.**"]

    # Grant a permission to the service account and check it in the graph.
    grant_permission_to_service_account(session, service_account,
                                        permissions["team-sre"], "*")
    graph.update_from_db(session)
    user_details = graph.get_user_details("*****@*****.**")
    assert user_details["permissions"][0]["permission"] == "team-sre"
    assert user_details["permissions"][0]["argument"] == "*"

    # Diabling the service account should remove the link to the group.
    disable_service_account(session, users["*****@*****.**"], service_account)
    assert service_account.user.enabled == False
    assert get_service_accounts(session, groups["team-sre"]) == []

    # The user should also be gone from the graph and have its permissions removed.
    graph.update_from_db(session)
    group_details = graph.get_group_details("team-sre")
    assert "service_accounts" not in group_details
    metadata = graph.user_metadata["*****@*****.**"]
    assert not metadata["enabled"]
    assert "owner" not in metadata["service_account"]
    user_details = graph.get_user_details("*****@*****.**")
    assert user_details["permissions"] == []

    # We can re-enable and attach to a different group.
    new_group = groups["security-team"]
    enable_service_account(session, users["*****@*****.**"], service_account,
                           new_group)
    assert service_account.user.enabled == True
    assert get_service_accounts(session, groups["team-sre"]) == []
    accounts = get_service_accounts(session, new_group)
    assert len(accounts) == 1
    assert accounts[0].user.name == "*****@*****.**"

    # Check that this is reflected in the graph and the user has no permissions.
    graph.update_from_db(session)
    group_details = graph.get_group_details("security-team")
    assert group_details["service_accounts"] == ["*****@*****.**"]
    metadata = graph.user_metadata["*****@*****.**"]
    assert metadata["service_account"]["owner"] == "security-team"
    user_details = graph.get_user_details("*****@*****.**")
    assert user_details["permissions"] == []
Beispiel #33
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"
def test_service_account_fe_disable(
        session,
        standard_graph,
        graph,
        http_client,
        base_url  # noqa: F811
):
    admin = "*****@*****.**"
    owner = "*****@*****.**"
    plebe = "*****@*****.**"

    # Unrelated people cannot disable the service account.
    fe_url = url(base_url,
                 "/groups/security-team/service/[email protected]/disable")
    with pytest.raises(HTTPError):
        yield http_client.fetch(fe_url,
                                method="POST",
                                headers={"X-Grouper-User": plebe},
                                body=urlencode({}))

    # Group members can disable the service account.
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": owner},
                                   body=urlencode({}))
    assert resp.code == 200
    graph.update_from_db(session)
    metadata = graph.user_metadata["*****@*****.**"]
    assert not metadata["enabled"]
    group_details = graph.get_group_details("team-sre")
    assert "service_accounts" not in group_details

    # The group owner cannot enable the account, since the group ownership has been lost
    fe_url = url(base_url, "/service/[email protected]/enable")
    with pytest.raises(HTTPError):
        yield http_client.fetch(
            fe_url,
            method="POST",
            headers={"X-Grouper-User": owner},
            body=urlencode({"owner": "team-sre"}),
        )

    # A global admin can enable the account.
    resp = yield http_client.fetch(
        fe_url,
        method="POST",
        headers={"X-Grouper-User": admin},
        body=urlencode({"owner": "team-sre"}),
    )
    assert resp.code == 200
    graph.update_from_db(session)
    metadata = graph.user_metadata["*****@*****.**"]
    assert metadata["enabled"]
    assert metadata["service_account"]["owner"] == "team-sre"
    group_details = graph.get_group_details("team-sre")
    assert group_details["service_accounts"] == ["*****@*****.**"]

    # And can also disable the account even though they're not a member of the group.
    fe_url = url(base_url,
                 "/groups/security-team/service/[email protected]/disable")
    resp = yield http_client.fetch(fe_url,
                                   method="POST",
                                   headers={"X-Grouper-User": admin},
                                   body=urlencode({}))
    assert resp.code == 200
    graph.update_from_db(session)
    metadata = graph.user_metadata["*****@*****.**"]
    assert not metadata["enabled"]
Beispiel #35
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"
Beispiel #36
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"]
    )
Beispiel #37
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
Beispiel #38
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"
Beispiel #39
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
Beispiel #40
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["*****@*****.**"])
Beispiel #41
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"