issue-3379 iam list_roles: implement PathPrefix, MaxItems and Marker (#3380)

* issue-3379 iam list_roles: implement PathPrefix, MaxItems and Marker

* issue-3379 fix cloudformation test
This commit is contained in:
waynemetcalfe 2020-10-12 12:13:20 +01:00 committed by GitHub
parent ea0ba91f63
commit 0a938f7bb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 106 additions and 18 deletions

View File

@ -2011,16 +2011,23 @@ class IAMBackend(BaseBackend):
user.name = new_user_name
self.users[new_user_name] = self.users.pop(user_name)
def list_roles(self, path_prefix, marker, max_items):
roles = None
try:
roles = self.roles.values()
except KeyError:
raise IAMNotFoundException(
"Users {0}, {1}, {2} not found".format(path_prefix, marker, max_items)
)
def list_roles(self, path_prefix=None, marker=None, max_items=None):
path_prefix = path_prefix if path_prefix else "/"
max_items = int(max_items) if max_items else 100
start_index = int(marker) if marker else 0
return roles
roles = self.roles.values()
roles = filter_items_with_path_prefix(path_prefix, roles)
sorted_roles = sorted(roles, key=lambda role: role.id)
roles_to_return = sorted_roles[start_index : start_index + max_items]
if len(sorted_roles) <= (start_index + max_items):
marker = None
else:
marker = str(start_index + max_items)
return roles_to_return, marker
def upload_signing_certificate(self, user_name, body):
user = self.get_user(user_name)

View File

@ -133,7 +133,7 @@ class IamResponse(BaseResponse):
entity_users.append(user.name)
elif entity == "Role":
roles = iam_backend.list_roles(path_prefix, marker, max_items)
roles, _ = iam_backend.list_roles(path_prefix, marker, max_items)
if roles:
for role in roles:
for p in role.managed_policies:
@ -156,7 +156,7 @@ class IamResponse(BaseResponse):
if p == policy_arn:
entity_users.append(user.name)
roles = iam_backend.list_roles(path_prefix, marker, max_items)
roles, _ = iam_backend.list_roles(path_prefix, marker, max_items)
if roles:
for role in roles:
for p in role.managed_policies:
@ -356,9 +356,13 @@ class IamResponse(BaseResponse):
return template.render()
def list_roles(self):
roles = iam_backend.get_roles()
path_prefix = self._get_param("PathPrefix", "/")
marker = self._get_param("Marker", "0")
max_items = self._get_param("MaxItems", 100)
roles, marker = iam_backend.list_roles(path_prefix, marker, max_items)
template = self.response_template(LIST_ROLES_TEMPLATE)
return template.render(roles=roles)
return template.render(roles=roles, marker=marker)
def list_instance_profiles(self):
profiles = iam_backend.get_instance_profiles()
@ -1379,7 +1383,10 @@ REMOVE_ROLE_FROM_INSTANCE_PROFILE_TEMPLATE = """<RemoveRoleFromInstanceProfileRe
LIST_ROLES_TEMPLATE = """<ListRolesResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
<ListRolesResult>
<IsTruncated>false</IsTruncated>
<IsTruncated>{{ 'true' if marker else 'false' }}</IsTruncated>
{% if marker %}
<Marker>{{ marker }}</Marker>
{% endif %}
<Roles>
{% for role in roles %}
<member>

View File

@ -870,7 +870,7 @@ def test_iam_roles():
}
]
},
"Path": "my-path",
"Path": "/my-path/",
"Policies": [
{
"PolicyDocument": {
@ -939,7 +939,7 @@ def test_iam_roles():
# Role name is not specified, so randomly generated - can't check exact name
if "with-path" in role.role_name:
role_name_to_id["with-path"] = role.role_id
role.path.should.equal("my-path")
role.path.should.equal("/my-path/")
else:
role_name_to_id["no-path"] = role.role_id
role.role_name.should.equal("my-role-no-path-name")

View File

@ -155,13 +155,13 @@ def test_create_role_and_instance_profile():
conn = boto.connect_iam()
conn.create_instance_profile("my-profile", path="my-path")
conn.create_role(
"my-role", assume_role_policy_document="some policy", path="my-path"
"my-role", assume_role_policy_document="some policy", path="/my-path/"
)
conn.add_role_to_instance_profile("my-profile", "my-role")
role = conn.get_role("my-role")
role.path.should.equal("my-path")
role.path.should.equal("/my-path/")
role.assume_role_policy_document.should.equal("some policy")
profile = conn.get_instance_profile("my-profile")
@ -3933,3 +3933,77 @@ def test_policy_config_client():
)["BaseConfigurationItems"][0]["resourceName"]
== policies[8]["name"]
)
@mock_iam()
def test_list_roles_with_more_than_100_roles_no_max_items_defaults_to_100():
iam = boto3.client("iam", region_name="us-east-1")
for i in range(150):
iam.create_role(
RoleName="test_role_{}".format(i), AssumeRolePolicyDocument="some policy"
)
response = iam.list_roles()
roles = response["Roles"]
assert response["IsTruncated"] is True
assert len(roles) == 100
@mock_iam()
def test_list_roles_max_item_and_marker_values_adhered():
iam = boto3.client("iam", region_name="us-east-1")
for i in range(10):
iam.create_role(
RoleName="test_role_{}".format(i), AssumeRolePolicyDocument="some policy"
)
response = iam.list_roles(MaxItems=2)
roles = response["Roles"]
assert response["IsTruncated"] is True
assert len(roles) == 2
response = iam.list_roles(Marker=response["Marker"])
roles = response["Roles"]
assert response["IsTruncated"] is False
assert len(roles) == 8
@mock_iam()
def test_list_roles_path_prefix_value_adhered():
iam = boto3.client("iam", region_name="us-east-1")
iam.create_role(
RoleName="test_role_without_path", AssumeRolePolicyDocument="some policy"
)
iam.create_role(
RoleName="test_role_with_path",
AssumeRolePolicyDocument="some policy",
Path="/TestPath/",
)
response = iam.list_roles(PathPrefix="/TestPath/")
roles = response["Roles"]
assert len(roles) == 1
assert roles[0]["RoleName"] == "test_role_with_path"
@mock_iam()
def test_list_roles_none_found_returns_empty_list():
iam = boto3.client("iam", region_name="us-east-1")
response = iam.list_roles()
roles = response["Roles"]
assert len(roles) == 0
response = iam.list_roles(PathPrefix="/TestPath")
roles = response["Roles"]
assert len(roles) == 0
response = iam.list_roles(Marker="10")
roles = response["Roles"]
assert len(roles) == 0
response = iam.list_roles(MaxItems=10)
roles = response["Roles"]
assert len(roles) == 0