address PR comments

This commit is contained in:
Nick Stocchero 2020-08-02 21:16:44 -06:00
commit ff84b63484
4 changed files with 232 additions and 90 deletions

View file

@ -27,8 +27,8 @@ from .utils import (
convert_flask_to_responses_response,
)
ACCOUNT_ID = os.environ.get("MOTO_ACCOUNT_ID", "123456789012")
CONFIG_BACKEND_DELIM = "\x1e" # Record Seperator "RS" ASCII Character
class BaseMockAWS(object):
@ -768,15 +768,29 @@ class ConfigQueryModel(object):
def aggregate_regions(self, path, backend_region, resource_region):
"""
Returns a list of "region\1eresourcename" strings
This method will is called for both aggregated and non-aggregated calls for config resources.
It will figure out how to return the full list of resources for a given regional backend and append them to a final list.
It produces a list of both the region and the resource name with a delimiter character (CONFIG_BACKEND_DELIM, ASCII Record separator, \x1e).
IE: "us-east-1\x1ei-1234567800"
Each config-enabled resource has a method named `list_config_service_resources` which has to parse the delimiter
...
:param path: - A dict accessor string applied to the backend that locates the resource.
:param backend_region:
:param resource_region:
:return: - Returns a list of "region\x1eresourcename" strings
"""
filter_region = backend_region or resource_region
if filter_region:
filter_resources = list(self.backends[filter_region].__dict__[path].keys())
return map(
lambda resource: "{}\1e{}".format(filter_region, resource),
filter_resources,
return list(
map(
lambda resource: "{}{}{}".format(
filter_region, CONFIG_BACKEND_DELIM, resource
),
filter_resources,
)
)
# If we don't have a filter region
@ -784,7 +798,7 @@ class ConfigQueryModel(object):
for region in self.backends:
this_region_resources = list(self.backends[region].__dict__[path].keys())
for resource in this_region_resources:
ret.append("{}\1e{}".format(region, resource))
ret.append("{}{}{}".format(region, CONFIG_BACKEND_DELIM, resource))
return ret

View file

@ -4,6 +4,8 @@ from moto.core.exceptions import InvalidNextTokenException
from moto.core.models import ConfigQueryModel
from moto.iam import iam_backends
CONFIG_BACKEND_DELIM = "\x1e" # Record Seperator "RS" ASCII Character
class RoleConfigQuery(ConfigQueryModel):
def list_config_service_resources(
@ -15,18 +17,17 @@ class RoleConfigQuery(ConfigQueryModel):
backend_region=None,
resource_region=None,
):
# For aggregation -- did we get both a resource ID and a resource name?
if resource_ids and resource_name:
# If the values are different, then return an empty list:
if resource_name not in resource_ids:
return [], None
# IAM roles are "global" and aren't assigned into any availability zone
# The resource ID is a AWS-assigned random string like "AROA0BSVNSZKXVHS00SBJ"
# The resource name is a user-assigned string like "MyDevelopmentAdminRole"
role_list = self.aggregate_regions("roles", backend_region, resource_region)
# Grab roles from backend
role_list = self.aggregate_regions("roles", "global", None)
if not role_list:
return [], None
# Pagination logic:
# Pagination logic
sorted_roles = sorted(role_list)
new_token = None
@ -34,7 +35,7 @@ class RoleConfigQuery(ConfigQueryModel):
if not next_token:
start = 0
else:
# "Tokens" are region + \00 + resource ID.
# "Tokens" are region + \x1e + resource ID.
if next_token not in sorted_roles:
raise InvalidNextTokenException()
@ -46,13 +47,16 @@ class RoleConfigQuery(ConfigQueryModel):
if len(sorted_roles) > (start + limit):
new_token = sorted_roles[start + limit]
# Each element is a string of "region\x1eresource_id"
return (
[
{
"type": "AWS::IAM::Role",
"id": role.split("\1e")[1],
"name": role.split("\1e")[1],
"region": role.split("\1e")[0],
"id": role.split(CONFIG_BACKEND_DELIM)[1],
"name": self.backends["global"]
.roles[role.split(CONFIG_BACKEND_DELIM)[1]]
.name,
"region": role.split(CONFIG_BACKEND_DELIM)[0],
}
for role in role_list
],
@ -71,7 +75,7 @@ class RoleConfigQuery(ConfigQueryModel):
if resource_name and role.name != resource_name:
return
# Format the bucket to the AWS Config format:
# Format the role to the AWS Config format:
config_data = role.to_config_dict()
# The 'configuration' field is also a JSON string:
@ -95,16 +99,19 @@ class PolicyConfigQuery(ConfigQueryModel):
backend_region=None,
resource_region=None,
):
# For aggregation -- did we get both a resource ID and a resource name?
if resource_ids and resource_name:
# If the values are different, then return an empty list:
if resource_name not in resource_ids:
return [], None
# IAM policies are "global" and aren't assigned into any availability zone
# The resource ID is a AWS-assigned random string like "ANPA0BSVNSZK00SJSPVUJ"
# The resource name is a user-assigned string like "my-development-policy"
# We don't want to include AWS Managed Policies
# We don't want to include AWS Managed Policies. This technically needs to
# respect the configuration recorder's 'includeGlobalResourceTypes' setting,
# but it's default set be default, and moto's config doesn't yet support
# custom configuration recorders, we'll just behave as default.
policy_list = filter(
lambda policy: not policy.split("\1e")[1].startswith("arn:aws:iam::aws"),
self.aggregate_regions("managed_policies", backend_region, resource_region),
lambda policy: not policy.split(CONFIG_BACKEND_DELIM)[1].startswith(
"arn:aws:iam::aws"
),
self.aggregate_regions("managed_policies", "global", None),
)
if not policy_list:
@ -118,7 +125,7 @@ class PolicyConfigQuery(ConfigQueryModel):
if not next_token:
start = 0
else:
# "Tokens" are region + \00 + resource ID.
# "Tokens" are region + \x1e + resource ID.
if next_token not in sorted_policies:
raise InvalidNextTokenException()
@ -134,9 +141,13 @@ class PolicyConfigQuery(ConfigQueryModel):
[
{
"type": "AWS::IAM::Policy",
"id": policy.split("\1e")[1],
"name": policy.split("\1e")[1],
"region": policy.split("\1e")[0],
"id": self.backends["global"]
.managed_policies[policy.split(CONFIG_BACKEND_DELIM)[1]]
.id,
"name": self.backends["global"]
.managed_policies[policy.split(CONFIG_BACKEND_DELIM)[1]]
.name,
"region": policy.split(CONFIG_BACKEND_DELIM)[0],
}
for policy in policy_list
],
@ -155,7 +166,7 @@ class PolicyConfigQuery(ConfigQueryModel):
if resource_name and policy.name != resource_name:
return
# Format the bucket to the AWS Config format:
# Format the policy to the AWS Config format:
config_data = policy.to_config_dict()
# The 'configuration' field is also a JSON string: