iam: add account tests for Role apis

adds test cases for the following iam actions:
* CreateRole
* GetRole
* ListRoles
* DeleteRole
* UpdateRole

verified to pass against aws when an account root user's credentials are
provided in the [iam] section of s3tests.conf

Signed-off-by: Casey Bodley <cbodley@redhat.com>
(cherry picked from commit d4ada317e1)
This commit is contained in:
Casey Bodley 2024-01-26 15:23:40 -05:00
parent a684c035fa
commit 7a5ef470d6
2 changed files with 207 additions and 0 deletions

View file

@ -17,6 +17,7 @@ markers =
fails_on_s3 fails_on_s3
fails_with_subdomain fails_with_subdomain
iam_account iam_account
iam_role
iam_tenant iam_tenant
iam_user iam_user
lifecycle lifecycle

View file

@ -922,6 +922,32 @@ def nuke_users(client, **kwargs):
except: except:
pass pass
def nuke_role_policies(client, name):
p = client.get_paginator('list_role_policies')
for response in p.paginate(RoleName=name):
for policy in response['PolicyNames']:
try:
client.delete_role_policy(RoleName=name, PolicyName=policy)
except:
pass
def nuke_role(client, name):
# delete role policies, etc
try:
nuke_role_policies(client, name)
except:
pass
client.delete_role(RoleName=name)
def nuke_roles(client, **kwargs):
p = client.get_paginator('list_roles')
for response in p.paginate(**kwargs):
for role in response['Roles']:
try:
nuke_role(client, role['RoleName'])
except:
pass
# fixture for iam account root user # fixture for iam account root user
@pytest.fixture @pytest.fixture
def iam_root(configfile): def iam_root(configfile):
@ -935,6 +961,7 @@ def iam_root(configfile):
yield client yield client
nuke_users(client, PathPrefix=get_iam_path_prefix()) nuke_users(client, PathPrefix=get_iam_path_prefix())
nuke_roles(client, PathPrefix=get_iam_path_prefix())
# IAM User apis # IAM User apis
@ -1512,3 +1539,182 @@ def test_account_user_policy_allow(iam_root):
# the policy may take a bit to start working. retry until it returns # the policy may take a bit to start working. retry until it returns
# something other than AccessDenied # something other than AccessDenied
retry_on('AccessDenied', 10, client.list_buckets) retry_on('AccessDenied', 10, client.list_buckets)
assume_role_policy = json.dumps({
'Version': '2012-10-17',
'Statement': [{
'Effect': 'Allow',
'Action': 'sts:AssumeRole',
'Principal': {'AWS': '*'}
}]
})
# IAM Role apis
@pytest.mark.iam_account
@pytest.mark.iam_role
def test_account_role_create(iam_root):
path = get_iam_path_prefix()
name1 = make_iam_name('R1')
desc = 'my role description'
max_duration = 43200
response = iam_root.create_role(RoleName=name1, Path=path, AssumeRolePolicyDocument=assume_role_policy, Description=desc, MaxSessionDuration=max_duration)
role = response['Role']
assert role['Path'] == path
assert role['RoleName'] == name1
assert assume_role_policy == json.dumps(role['AssumeRolePolicyDocument'])
assert len(role['RoleId'])
arn = role['Arn']
assert arn.startswith('arn:aws:iam:')
assert arn.endswith(f':role{path}{name1}')
assert role['CreateDate'] > datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc)
# AWS doesn't include these for CreateRole, only GetRole
#assert desc == role['Description']
#assert max_duration == role['MaxSessionDuration']
response = iam_root.get_role(RoleName=name1)
role = response['Role']
assert arn == role['Arn']
assert desc == role['Description']
assert max_duration == role['MaxSessionDuration']
path2 = get_iam_path_prefix() + 'foo/'
with pytest.raises(iam_root.exceptions.EntityAlreadyExistsException):
iam_root.create_role(RoleName=name1, Path=path2, AssumeRolePolicyDocument=assume_role_policy)
name2 = make_iam_name('R2')
response = iam_root.create_role(RoleName=name2, Path=path2, AssumeRolePolicyDocument=assume_role_policy)
role = response['Role']
assert role['Path'] == path2
assert role['RoleName'] == name2
@pytest.mark.iam_account
@pytest.mark.iam_role
def test_account_role_case_insensitive_name(iam_root):
path = get_iam_path_prefix()
name_upper = make_iam_name('R1')
name_lower = make_iam_name('r1')
response = iam_root.create_role(RoleName=name_upper, Path=path, AssumeRolePolicyDocument=assume_role_policy)
rid = response['Role']['RoleId']
# name is case-insensitive, so 'r1' should also conflict
with pytest.raises(iam_root.exceptions.EntityAlreadyExistsException):
iam_root.create_role(RoleName=name_lower, AssumeRolePolicyDocument=assume_role_policy)
# search for 'r1' should return the same 'R1' role
response = iam_root.get_role(RoleName=name_lower)
assert rid == response['Role']['RoleId']
# delete for 'r1' should delete the same 'R1' role
iam_root.delete_role(RoleName=name_lower)
with pytest.raises(iam_root.exceptions.NoSuchEntityException):
iam_root.get_role(RoleName=name_lower)
@pytest.mark.iam_account
@pytest.mark.iam_role
def test_account_role_delete(iam_root):
path = get_iam_path_prefix()
name = make_iam_name('U1')
with pytest.raises(iam_root.exceptions.NoSuchEntityException):
iam_root.delete_role(RoleName=name)
response = iam_root.create_role(RoleName=name, Path=path, AssumeRolePolicyDocument=assume_role_policy)
uid = response['Role']['RoleId']
create_date = response['Role']['CreateDate']
iam_root.delete_role(RoleName=name)
response = iam_root.create_role(RoleName=name, Path=path, AssumeRolePolicyDocument=assume_role_policy)
assert uid != response['Role']['RoleId']
assert create_date <= response['Role']['CreateDate']
def role_list_names(client, **kwargs):
p = client.get_paginator('list_roles')
rolenames = []
for response in p.paginate(**kwargs):
rolenames += [u['RoleName'] for u in response['Roles']]
return rolenames
@pytest.mark.iam_account
@pytest.mark.iam_role
def test_account_role_list(iam_root):
path = get_iam_path_prefix()
response = iam_root.list_roles(PathPrefix=path)
assert len(response['Roles']) == 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 CreateDate, Path, and RoleName capitalization
iam_root.create_role(RoleName=name4, Path=path+'w/', AssumeRolePolicyDocument=assume_role_policy)
iam_root.create_role(RoleName=name3, Path=path+'x/', AssumeRolePolicyDocument=assume_role_policy)
iam_root.create_role(RoleName=name2, Path=path+'y/', AssumeRolePolicyDocument=assume_role_policy)
iam_root.create_role(RoleName=name1, Path=path+'z/', AssumeRolePolicyDocument=assume_role_policy)
assert [name1, name2, name3, name4] == \
role_list_names(iam_root, PathPrefix=path)
assert [name1, name2, name3, name4] == \
role_list_names(iam_root, PathPrefix=path, PaginationConfig={'PageSize': 1})
@pytest.mark.iam_account
@pytest.mark.iam_role
def test_account_role_list_path_prefix(iam_root):
path = get_iam_path_prefix()
response = iam_root.list_roles(PathPrefix=path)
assert len(response['Roles']) == 0
assert response['IsTruncated'] == False
name1 = make_iam_name('a')
name2 = make_iam_name('b')
name3 = make_iam_name('c')
name4 = make_iam_name('d')
iam_root.create_role(RoleName=name1, Path=path, AssumeRolePolicyDocument=assume_role_policy)
iam_root.create_role(RoleName=name2, Path=path, AssumeRolePolicyDocument=assume_role_policy)
iam_root.create_role(RoleName=name3, Path=path+'a/', AssumeRolePolicyDocument=assume_role_policy)
iam_root.create_role(RoleName=name4, Path=path+'a/x/', AssumeRolePolicyDocument=assume_role_policy)
assert [name1, name2, name3, name4] == \
role_list_names(iam_root, PathPrefix=path)
assert [name1, name2, name3, name4] == \
role_list_names(iam_root, PathPrefix=path,
PaginationConfig={'PageSize': 1})
assert [name3, name4] == \
role_list_names(iam_root, PathPrefix=path+'a')
assert [name3, name4] == \
role_list_names(iam_root, PathPrefix=path+'a',
PaginationConfig={'PageSize': 1})
assert [name4] == \
role_list_names(iam_root, PathPrefix=path+'a/x')
assert [name4] == \
role_list_names(iam_root, PathPrefix=path+'a/x',
PaginationConfig={'PageSize': 1})
assert [] == role_list_names(iam_root, PathPrefix=path+'a/x/d')
@pytest.mark.iam_account
@pytest.mark.iam_role
def test_account_role_update(iam_root):
path = get_iam_path_prefix()
name = make_iam_name('a')
with pytest.raises(iam_root.exceptions.NoSuchEntityException):
iam_root.update_role(RoleName=name)
iam_root.create_role(RoleName=name, Path=path, AssumeRolePolicyDocument=assume_role_policy)
response = iam_root.get_role(RoleName=name)
assert name == response['Role']['RoleName']
arn = response['Role']['Arn']
rid = response['Role']['RoleId']
desc = 'my role description'
iam_root.update_role(RoleName=name, Description=desc, MaxSessionDuration=43200)
response = iam_root.get_role(RoleName=name)
assert rid == response['Role']['RoleId']
assert arn == response['Role']['Arn']
assert desc == response['Role']['Description']
assert 43200 == response['Role']['MaxSessionDuration']