From e44e0447a3f9c357573a7a15b8ec088c2c3c1094 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Sun, 11 Feb 2024 11:50:43 -0500 Subject: [PATCH] iam: add account tests for Group apis Signed-off-by: Casey Bodley (cherry picked from commit 4ca7967ae7716df385b525c4a6a5e2aa60cd4033) --- pytest.ini | 1 + s3tests_boto3/functional/test_iam.py | 155 +++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) diff --git a/pytest.ini b/pytest.ini index 4c456be..5da379d 100644 --- a/pytest.ini +++ b/pytest.ini @@ -16,6 +16,7 @@ markers = fails_on_rgw fails_on_s3 fails_with_subdomain + group iam_account iam_cross_account iam_role diff --git a/s3tests_boto3/functional/test_iam.py b/s3tests_boto3/functional/test_iam.py index 936dc24..e873fe1 100644 --- a/s3tests_boto3/functional/test_iam.py +++ b/s3tests_boto3/functional/test_iam.py @@ -928,6 +928,32 @@ def nuke_users(client, **kwargs): except: pass +def nuke_group_users(client, name): + p = client.get_paginator('get_group') + for response in p.paginate(GroupName=name): + for user in response['Users']: + try: + client.remove_user_from_group(GroupName=name, UserName=user['UserName']) + except: + pass + +def nuke_group(client, name): + # delete group policies and remove all users + try: + nuke_group_users(client, name) + except: + pass + client.delete_group(GroupName=name) + +def nuke_groups(client, **kwargs): + p = client.get_paginator('list_groups') + for response in p.paginate(**kwargs): + for user in response['Groups']: + try: + nuke_group(client, user['GroupName']) + except: + pass + def nuke_role_policies(client, name): p = client.get_paginator('list_role_policies') for response in p.paginate(RoleName=name): @@ -991,6 +1017,7 @@ def iam_root(configfile): yield client nuke_users(client, PathPrefix=get_iam_path_prefix()) + nuke_groups(client, PathPrefix=get_iam_path_prefix()) nuke_roles(client, PathPrefix=get_iam_path_prefix()) nuke_oidc_providers(client, get_iam_path_prefix()) @@ -1572,6 +1599,134 @@ def test_account_user_policy_allow(iam_root): retry_on('AccessDenied', 10, client.list_buckets) +def group_list_names(client, **kwargs): + p = client.get_paginator('list_groups') + names = [] + for response in p.paginate(**kwargs): + names += [u['GroupName'] for u in response['Groups']] + return names + +# IAM Group apis +@pytest.mark.group +@pytest.mark.iam_account +def test_account_group_create(iam_root): + path = get_iam_path_prefix() + name = make_iam_name('G1') + + assert [] == group_list_names(iam_root, PathPrefix=path) + + response = iam_root.create_group(GroupName=name, Path=path) + group = response['Group'] + assert path == group['Path'] + assert name == group['GroupName'] + assert len(group['GroupId']) + arn = group['Arn'] + assert arn.startswith('arn:aws:iam:') + assert arn.endswith(f':group{path}{name}') + + with pytest.raises(iam_root.exceptions.EntityAlreadyExistsException): + iam_root.create_group(GroupName=name) + + response = iam_root.get_group(GroupName=name) + assert group == response['Group'] + + assert [name] == group_list_names(iam_root, PathPrefix=path) + + iam_root.delete_group(GroupName=name) + + with pytest.raises(iam_root.exceptions.NoSuchEntityException): + iam_root.get_group(GroupName=name) + + assert [] == group_list_names(iam_root, PathPrefix=path) + +@pytest.mark.iam_account +@pytest.mark.group +def test_account_group_case_insensitive_name(iam_root): + path = get_iam_path_prefix() + name_upper = make_iam_name('G1') + name_lower = make_iam_name('g1') + response = iam_root.create_group(GroupName=name_upper, Path=path) + group = response['Group'] + + with pytest.raises(iam_root.exceptions.EntityAlreadyExistsException): + iam_root.create_group(GroupName=name_lower) + + response = iam_root.get_group(GroupName=name_lower) + assert group == response['Group'] + + iam_root.delete_group(GroupName=name_lower) + + with pytest.raises(iam_root.exceptions.NoSuchEntityException): + iam_root.delete_group(GroupName=name_upper) + +@pytest.mark.iam_account +@pytest.mark.group +def test_account_group_list(iam_root): + path = get_iam_path_prefix() + response = iam_root.list_groups(PathPrefix=path) + assert len(response['Groups']) == 0 + assert response['IsTruncated'] == False + + name1 = make_iam_name('aa') + name2 = make_iam_name('Ab') + name3 = make_iam_name('ac') + name4 = make_iam_name('Ad') + + # sort order is independent of Path and GroupName capitalization + iam_root.create_group(GroupName=name4, Path=path+'w/') + iam_root.create_group(GroupName=name3, Path=path+'x/') + iam_root.create_group(GroupName=name2, Path=path+'y/') + iam_root.create_group(GroupName=name1, Path=path+'z/') + + assert [name1, name2, name3, name4] == \ + group_list_names(iam_root, PathPrefix=path) + assert [name1, name2, name3, name4] == \ + group_list_names(iam_root, PathPrefix=path, PaginationConfig={'PageSize': 1}) + +@pytest.mark.group +@pytest.mark.iam_account +def test_account_group_update(iam_root): + path = get_iam_path_prefix() + name = make_iam_name('G1') + response = iam_root.create_group(GroupName=name, Path=path) + group_id = response['Group']['GroupId'] + + username = make_iam_name('U1') + iam_root.create_user(UserName=username, Path=path) + + iam_root.add_user_to_group(GroupName=name, UserName=username) + + response = iam_root.list_groups_for_user(UserName=username) + groups = response['Groups'] + assert len(groups) == 1 + assert path == groups[0]['Path'] + assert name == groups[0]['GroupName'] + assert group_id == groups[0]['GroupId'] + + new_path = path + 'new/' + new_name = make_iam_name('NG1') + iam_root.update_group(GroupName=name, NewPath=new_path, NewGroupName=new_name) + + response = iam_root.get_group(GroupName=new_name) + group = response['Group'] + assert new_path == group['Path'] + assert new_name == group['GroupName'] + assert group_id == group['GroupId'] + arn = group['Arn'] + assert arn.startswith('arn:aws:iam:') + assert arn.endswith(f':group{new_path}{new_name}') + users = response['Users'] + assert len(users) == 1 + assert username == users[0]['UserName'] + + response = iam_root.list_groups_for_user(UserName=username) + groups = response['Groups'] + assert len(groups) == 1 + assert new_path == groups[0]['Path'] + assert new_name == groups[0]['GroupName'] + assert group_id == groups[0]['GroupId'] + + assume_role_policy = json.dumps({ 'Version': '2012-10-17', 'Statement': [{