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="*")
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
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, ["*****@*****.**"])
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"*****@*****.**"])
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)
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="*")
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)
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
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?" )
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"
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"
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()
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"
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")
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
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, ["*****@*****.**"])
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()
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"
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"] )
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"
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_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"
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"
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"
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
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
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_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"
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