def test_create(setup): # type: (SetupTest) -> None with setup.transaction(): setup.add_user_to_group("*****@*****.**", "some-group") setup.add_user_to_group("*****@*****.**", "other-group") run_ctl( setup, "service_account", "--actor", "*****@*****.**", "create", "*****@*****.**", "some-group", "foo +bar -(org)", "this is a service account.\n\n it is for testing", ) service_account = ServiceAccount.get(setup.session, name="*****@*****.**") assert service_account is not None assert service_account.user.name == "*****@*****.**" assert service_account.machine_set == "foo +bar -(org)" assert service_account.description == "this is a service account.\n\n it is for testing" group = Group.get(setup.session, name="some-group") assert group assert get_service_accounts(setup.session, group) == [service_account] # If the account already exists, creating it again returns an error and does nothing. with pytest.raises(SystemExit): run_ctl( setup, "service_account", "--actor", "*****@*****.**", "create", "*****@*****.**", "other-group", "foo", "another test", ) service_account = ServiceAccount.get(setup.session, name="*****@*****.**") assert service_account is not None assert service_account.machine_set == "foo +bar -(org)" assert service_account.description == "this is a service account.\n\n it is for testing" group = Group.get(setup.session, name="some-group") assert group assert get_service_accounts(setup.session, group) == [service_account]
def test_create_as_service_account(setup): """Test that a service account can create another service account.""" with setup.transaction(): setup.create_group("some-group") setup.create_service_account("*****@*****.**", "another-group") setup.grant_permission_to_service_account(USER_ADMIN, "", "*****@*****.**") run_ctl( setup, "service_account", "--actor", "*****@*****.**", "create", "*****@*****.**", "some-group", "foo +bar -(org)", "this is a service account.\n\n it is for testing", ) service_account = ServiceAccount.get(setup.session, name="*****@*****.**") assert service_account is not None assert service_account.user.name == "*****@*****.**" assert service_account.machine_set == "foo +bar -(org)" assert service_account.description == "this is a service account.\n\n it is for testing" group = Group.get(setup.session, name="some-group") assert get_service_accounts(setup.session, group) == [service_account]
def get_group_view_template_vars(session, actor, group, graph): # type: (Session, User, Group, GroupGraph) -> Dict[str, Any] ret = {} ret["grantable"] = user_grantable_permissions(session, actor) try: group_md = graph.get_group_details(group.name) except NoSuchGroup: # Very new group with no metadata yet, or it has been disabled and # excluded from in-memory cache. group_md = {} ret["members"] = group.my_members() ret["groups"] = group.my_groups() ret["service_accounts"] = get_service_accounts(session, group) ret["permissions"] = group_md.get("permissions", []) for permission in ret["permissions"]: permission["granted_on"] = datetime.fromtimestamp(permission["granted_on"]) ret["permission_requests_pending"] = [] for req in get_pending_request_by_group(session, group): granters = [] for owner, argument in get_owner_arg_list(session, req.permission, req.argument): granters.append(owner.name) ret["permission_requests_pending"].append((req, granters)) ret["audited"] = group_md.get("audited", False) ret["log_entries"] = group.my_log_entries() ret["num_pending"] = count_requests_by_group(session, group, status="pending") ret["current_user_role"] = { "is_owner": user_role_index(actor, ret["members"]) in OWNER_ROLE_INDICES, "is_approver": user_role_index(actor, ret["members"]) in APPROVER_ROLE_INDICES, "is_manager": user_role(actor, ret["members"]) == "manager", "is_member": user_role(actor, ret["members"]) is not None, "role": user_role(actor, ret["members"]), } ret["can_leave"] = ( ret["current_user_role"]["is_member"] and not ret["current_user_role"]["is_owner"] ) ret["statuses"] = AUDIT_STATUS_CHOICES # Add mapping_id to permissions structure ret["my_permissions"] = group.my_permissions() for perm_up in ret["permissions"]: for perm_direct in ret["my_permissions"]: if ( perm_up["permission"] == perm_direct.name and perm_up["argument"] == perm_direct.argument ): perm_up["mapping_id"] = perm_direct.mapping_id break ret["alerts"] = [] ret["self_pending"] = count_requests_by_group(session, group, status="pending", user=actor) if ret["self_pending"]: ret["alerts"].append(Alert("info", "You have a pending request to join this group.", None)) return ret
def get_group_view_template_vars(session, actor, group, graph): ret = {} ret["grantable"] = user_grantable_permissions(session, actor) try: group_md = graph.get_group_details(group.name) except NoSuchGroup: # Very new group with no metadata yet, or it has been disabled and # excluded from in-memory cache. group_md = {} ret["members"] = group.my_members() ret["groups"] = group.my_groups() ret["service_accounts"] = get_service_accounts(session, group) ret["permissions"] = group_md.get('permissions', []) ret["permission_requests_pending"] = [] for req in get_pending_request_by_group(session, group): granters = [] for owner, argument in get_owner_arg_list(session, req.permission, req.argument): granters.append(owner.name) ret["permission_requests_pending"].append((req, granters)) ret["audited"] = group_md.get('audited', False) ret["log_entries"] = group.my_log_entries() ret["num_pending"] = group.my_requests("pending").count() ret["current_user_role"] = { 'is_owner': user_role_index(actor, ret["members"]) in OWNER_ROLE_INDICES, 'is_approver': user_role_index(actor, ret["members"]) in APPROVER_ROLE_INDICES, 'is_manager': user_role(actor, ret["members"]) == "manager", 'is_member': user_role(actor, ret["members"]) is not None, 'role': user_role(actor, ret["members"]), } ret["can_leave"] = (ret["current_user_role"]['is_member'] and not ret["current_user_role"]['is_owner']) ret["statuses"] = AUDIT_STATUS_CHOICES # Add mapping_id to permissions structure ret["my_permissions"] = group.my_permissions() for perm_up in ret["permissions"]: for perm_direct in ret["my_permissions"]: if (perm_up['permission'] == perm_direct.name and perm_up['argument'] == perm_direct.argument): perm_up['mapping_id'] = perm_direct.mapping_id break ret["alerts"] = [] ret["self_pending"] = group.my_requests("pending", user=actor).count() if ret["self_pending"]: ret["alerts"].append( Alert('info', 'You have a pending request to join this group.', None)) return ret
def test_create_invalid_actor(setup): # type: (SetupTest) -> None with setup.transaction(): setup.create_group("some-group") with pytest.raises(SystemExit): run_ctl( setup, "service_account", "--actor", "*****@*****.**", "create", "*****@*****.**", "some-group", "foo", "another test", ) assert ServiceAccount.get(setup.session, name="*****@*****.**") is None group = Group.get(setup.session, name="some-group") assert get_service_accounts(setup.session, group) == []
def test_service_account_create(groups, service_accounts, session, tmpdir, users): # noqa: F811 machine_set = "foo +bar -(org)" description = "this is a service account.\n\n it is for testing" security_team_group = Group.get(session, name="security-team") good_actor_username = "******" good_service_account_name = "*****@*****.**" assert ServiceAccount.get(session, name=good_service_account_name) is None assert get_service_accounts(session, security_team_group) == [] # no-op if non-existing actor call_main( session, tmpdir, "service_account", "--actor", "*****@*****.**", "create", good_service_account_name, security_team_group.groupname, machine_set, description, ) # ... or if bad account name call_main( session, tmpdir, "service_account", "--actor", good_actor_username, "create", "bad-service-account-name", security_team_group.groupname, machine_set, description, ) # ... or non-existing owner group call_main( session, tmpdir, "service_account", "--actor", good_actor_username, "create", good_service_account_name, "non-such-owner-group", machine_set, description, ) # make sure no change was made assert ServiceAccount.get(session, name=good_service_account_name) is None assert get_service_accounts(session, security_team_group) == [] # now it works call_main( session, tmpdir, "service_account", "--actor", good_actor_username, "create", good_service_account_name, security_team_group.groupname, machine_set, description, ) service_account = ServiceAccount.get(session, name=good_service_account_name) assert service_account, "non-existing account should be created" assert service_account.user.name == good_service_account_name assert service_account.machine_set == machine_set assert service_account.description == description assert get_service_accounts(session, security_team_group) == [service_account] # no-op if account name already exists call_main( session, tmpdir, "service_account", "--actor", good_actor_username, "create", good_service_account_name, security_team_group.groupname, machine_set, description, ) service_account = ServiceAccount.get(session, name=good_service_account_name) assert service_account, "non-account should be created" assert service_account.user.name == good_service_account_name assert service_account.machine_set == machine_set assert service_account.description == description assert get_service_accounts(session, security_team_group) == [service_account] # actor can be a service account as well call_main( session, tmpdir, "service_account", "--actor", "*****@*****.**", "create", "*****@*****.**", security_team_group.groupname, machine_set + "2", description + "2", ) service_account_2 = ServiceAccount.get(session, name="*****@*****.**") assert service_account_2, "non-existing account should be created" assert service_account_2.user.name == "*****@*****.**" assert service_account_2.machine_set == (machine_set + "2") assert service_account_2.description == (description + "2") assert set(get_service_accounts(session, security_team_group)) == set( [service_account, service_account_2] )
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"] == []
def get_group_view_template_vars(session, actor, group, graph): # type: (Session, User, Group, GroupGraph) -> Dict[str, Any] ret = {} ret["grantable"] = user_grantable_permissions(session, actor) try: group_md = graph.get_group_details(group.name) except NoSuchGroup: # Very new group with no metadata yet, or it has been disabled and # excluded from in-memory cache. group_md = {} ret["members"] = group.my_members() ret["groups"] = group.my_groups() ret["service_accounts"] = get_service_accounts(session, group) ret["permissions"] = group_md.get("permissions", []) for permission in ret["permissions"]: permission["granted_on"] = datetime.fromtimestamp( permission["granted_on"]) ret["permission_requests_pending"] = [] for req in get_pending_request_by_group(session, group): granters = [] for owner, argument in get_owner_arg_list(session, req.permission, req.argument): granters.append(owner.name) ret["permission_requests_pending"].append((req, granters)) ret["audited"] = group_md.get("audited", False) ret["log_entries"] = group.my_log_entries() ret["num_pending"] = count_requests_by_group(session, group, status="pending") ret["current_user_role"] = { "is_owner": user_role_index(actor, ret["members"]) in OWNER_ROLE_INDICES, "is_approver": user_role_index(actor, ret["members"]) in APPROVER_ROLE_INDICES, "is_manager": user_role(actor, ret["members"]) == "manager", "is_member": user_role(actor, ret["members"]) is not None, "role": user_role(actor, ret["members"]), } ret["can_leave"] = (ret["current_user_role"]["is_member"] and not ret["current_user_role"]["is_owner"]) ret["statuses"] = AUDIT_STATUS_CHOICES # Add mapping_id to permissions structure ret["my_permissions"] = group.my_permissions() for perm_up in ret["permissions"]: for perm_direct in ret["my_permissions"]: if (perm_up["permission"] == perm_direct.name and perm_up["argument"] == perm_direct.argument): perm_up["mapping_id"] = perm_direct.mapping_id break ret["alerts"] = [] ret["self_pending"] = count_requests_by_group(session, group, status="pending", user=actor) if ret["self_pending"]: ret["alerts"].append( Alert("info", "You have a pending request to join this group.", None)) return ret
def test_service_accounts(setup): # type: (SetupTest) -> None """Tests remaining non-usecase service account functions.""" with setup.transaction(): setup.create_service_account("*****@*****.**", "team-sre", "some machines", "some service account") setup.add_user_to_group("*****@*****.**", "team-sre", "owner") setup.add_user_to_group("*****@*****.**", "admins") setup.grant_permission_to_group(USER_ADMIN, "", "admins") setup.add_user_to_group("*****@*****.**", "team-sre") setup.create_user("*****@*****.**") setup.grant_permission_to_service_account("team-sre", "*", "*****@*****.**") setup.create_group("security-team") group = Group.get(setup.session, name="team-sre") assert group accounts = get_service_accounts(setup.session, group) assert len(accounts) == 1 service_account = accounts[0] assert service_account.user.name == "*****@*****.**" assert service_account.user.is_service_account # zorkian should be able to manage the account, as should gary, but oliver (not a member of the # group) should not. zorkian_user = User.get(setup.session, name="*****@*****.**") assert zorkian_user gary_user = User.get(setup.session, name="*****@*****.**") assert gary_user oliver_user = User.get(setup.session, name="*****@*****.**") assert oliver_user assert can_manage_service_account(setup.session, service_account, zorkian_user) assert can_manage_service_account(setup.session, service_account, gary_user) assert not can_manage_service_account(setup.session, service_account, oliver_user) # Diabling the service account should remove the link to the group. disable_service_account(setup.session, zorkian_user, service_account) assert service_account.user.enabled == False assert get_service_accounts(setup.session, group) == [] # The user should also be gone from the graph and have its permissions removed. setup.graph.update_from_db(setup.session) group_details = setup.graph.get_group_details("team-sre") assert "service_accounts" not in group_details metadata = setup.graph.user_metadata["*****@*****.**"] assert not metadata["enabled"] assert "owner" not in metadata["service_account"] user_details = setup.graph.get_user_details("*****@*****.**") assert user_details["permissions"] == [] # We can re-enable and attach to a different group. new_group = Group.get(setup.session, name="security-team") assert new_group enable_service_account(setup.session, zorkian_user, service_account, new_group) assert service_account.user.enabled == True assert get_service_accounts(setup.session, group) == [] accounts = get_service_accounts(setup.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. setup.graph.update_from_db(setup.session) group_details = setup.graph.get_group_details("security-team") assert group_details["service_accounts"] == ["*****@*****.**"] metadata = setup.graph.user_metadata["*****@*****.**"] assert metadata["service_account"]["owner"] == "security-team" user_details = setup.graph.get_user_details("*****@*****.**") assert user_details["permissions"] == []
def test_service_account_create( make_session, groups, service_accounts, session, users # noqa: F811 ): make_session.return_value = session machine_set = "foo +bar -(org)" description = "this is a service account.\n\n it is for testing" security_team_group = Group.get(session, name="security-team") good_actor_username = "******" good_service_account_name = "*****@*****.**" assert ServiceAccount.get(session, name=good_service_account_name) is None assert get_service_accounts(session, security_team_group) == [] # no-op if non-existing actor call_main( session, "service_account", "--actor", "*****@*****.**", "create", good_service_account_name, security_team_group.groupname, machine_set, description, ) # ... or if bad account name call_main( session, "service_account", "--actor", good_actor_username, "create", "bad-service-account-name", security_team_group.groupname, machine_set, description, ) # ... or non-existing owner group call_main( session, "service_account", "--actor", good_actor_username, "create", good_service_account_name, "non-such-owner-group", machine_set, description, ) # make sure no change was made assert ServiceAccount.get(session, name=good_service_account_name) is None assert get_service_accounts(session, security_team_group) == [] # now it works call_main( session, "service_account", "--actor", good_actor_username, "create", good_service_account_name, security_team_group.groupname, machine_set, description, ) service_account = ServiceAccount.get(session, name=good_service_account_name) assert service_account, "non-existing account should be created" assert service_account.user.name == good_service_account_name assert service_account.machine_set == machine_set assert service_account.description == description assert get_service_accounts(session, security_team_group) == [service_account] # no-op if account name already exists call_main( session, "service_account", "--actor", good_actor_username, "create", good_service_account_name, security_team_group.groupname, machine_set, description, ) service_account = ServiceAccount.get(session, name=good_service_account_name) assert service_account, "non-account should be created" assert service_account.user.name == good_service_account_name assert service_account.machine_set == machine_set assert service_account.description == description assert get_service_accounts(session, security_team_group) == [service_account] # actor can be a service account as well call_main( session, "service_account", "--actor", "*****@*****.**", "create", "*****@*****.**", security_team_group.groupname, machine_set + "2", description + "2", ) service_account_2 = ServiceAccount.get(session, name="*****@*****.**") assert service_account_2, "non-existing account should be created" assert service_account_2.user.name == "*****@*****.**" assert service_account_2.machine_set == (machine_set + "2") assert service_account_2.description == (description + "2") assert set(get_service_accounts(session, security_team_group)) == set( [service_account, service_account_2] )