Run black on moto & test directories.

This commit is contained in:
Asher Foa 2019-10-31 08:44:26 -07:00
commit 96e5b1993d
507 changed files with 52541 additions and 47814 deletions

View file

@ -6,17 +6,9 @@ from six import string_types
from moto.iam.exceptions import MalformedPolicyDocument
VALID_TOP_ELEMENTS = [
"Version",
"Id",
"Statement",
"Conditions"
]
VALID_TOP_ELEMENTS = ["Version", "Id", "Statement", "Conditions"]
VALID_VERSIONS = [
"2008-10-17",
"2012-10-17"
]
VALID_VERSIONS = ["2008-10-17", "2012-10-17"]
VALID_STATEMENT_ELEMENTS = [
"Sid",
@ -25,13 +17,10 @@ VALID_STATEMENT_ELEMENTS = [
"Resource",
"NotResource",
"Effect",
"Condition"
"Condition",
]
VALID_EFFECTS = [
"Allow",
"Deny"
]
VALID_EFFECTS = ["Allow", "Deny"]
VALID_CONDITIONS = [
"StringEquals",
@ -60,34 +49,41 @@ VALID_CONDITIONS = [
"ArnLike",
"ArnNotEquals",
"ArnNotLike",
"Null"
"Null",
]
VALID_CONDITION_PREFIXES = [
"ForAnyValue:",
"ForAllValues:"
]
VALID_CONDITION_PREFIXES = ["ForAnyValue:", "ForAllValues:"]
VALID_CONDITION_POSTFIXES = [
"IfExists"
]
VALID_CONDITION_POSTFIXES = ["IfExists"]
SERVICE_TYPE_REGION_INFORMATION_ERROR_ASSOCIATIONS = {
"iam": 'IAM resource {resource} cannot contain region information.',
"s3": 'Resource {resource} can not contain region information.'
"iam": "IAM resource {resource} cannot contain region information.",
"s3": "Resource {resource} can not contain region information.",
}
VALID_RESOURCE_PATH_STARTING_VALUES = {
"iam": {
"values": ["user/", "federated-user/", "role/", "group/", "instance-profile/", "mfa/", "server-certificate/",
"policy/", "sms-mfa/", "saml-provider/", "oidc-provider/", "report/", "access-report/"],
"error_message": 'IAM resource path must either be "*" or start with {values}.'
"values": [
"user/",
"federated-user/",
"role/",
"group/",
"instance-profile/",
"mfa/",
"server-certificate/",
"policy/",
"sms-mfa/",
"saml-provider/",
"oidc-provider/",
"report/",
"access-report/",
],
"error_message": 'IAM resource path must either be "*" or start with {values}.',
}
}
class IAMPolicyDocumentValidator:
def __init__(self, policy_document):
self._policy_document = policy_document
self._policy_json = {}
@ -102,7 +98,9 @@ class IAMPolicyDocumentValidator:
try:
self._validate_version()
except Exception:
raise MalformedPolicyDocument("Policy document must be version 2012-10-17 or greater.")
raise MalformedPolicyDocument(
"Policy document must be version 2012-10-17 or greater."
)
try:
self._perform_first_legacy_parsing()
self._validate_resources_for_formats()
@ -112,7 +110,9 @@ class IAMPolicyDocumentValidator:
try:
self._validate_sid_uniqueness()
except Exception:
raise MalformedPolicyDocument("Statement IDs (SID) in a single policy must be unique.")
raise MalformedPolicyDocument(
"Statement IDs (SID) in a single policy must be unique."
)
try:
self._validate_action_like_exist()
except Exception:
@ -176,8 +176,8 @@ class IAMPolicyDocumentValidator:
for statement_element in statement.keys():
assert statement_element in VALID_STATEMENT_ELEMENTS
assert ("Resource" not in statement or "NotResource" not in statement)
assert ("Action" not in statement or "NotAction" not in statement)
assert "Resource" not in statement or "NotResource" not in statement
assert "Action" not in statement or "NotAction" not in statement
IAMPolicyDocumentValidator._validate_effect_syntax(statement)
IAMPolicyDocumentValidator._validate_action_syntax(statement)
@ -191,23 +191,33 @@ class IAMPolicyDocumentValidator:
def _validate_effect_syntax(statement):
assert "Effect" in statement
assert isinstance(statement["Effect"], string_types)
assert statement["Effect"].lower() in [allowed_effect.lower() for allowed_effect in VALID_EFFECTS]
assert statement["Effect"].lower() in [
allowed_effect.lower() for allowed_effect in VALID_EFFECTS
]
@staticmethod
def _validate_action_syntax(statement):
IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax(statement, "Action")
IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax(
statement, "Action"
)
@staticmethod
def _validate_not_action_syntax(statement):
IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax(statement, "NotAction")
IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax(
statement, "NotAction"
)
@staticmethod
def _validate_resource_syntax(statement):
IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax(statement, "Resource")
IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax(
statement, "Resource"
)
@staticmethod
def _validate_not_resource_syntax(statement):
IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax(statement, "NotResource")
IAMPolicyDocumentValidator._validate_string_or_list_of_strings_syntax(
statement, "NotResource"
)
@staticmethod
def _validate_string_or_list_of_strings_syntax(statement, key):
@ -223,22 +233,28 @@ class IAMPolicyDocumentValidator:
assert isinstance(statement["Condition"], dict)
for condition_key, condition_value in statement["Condition"].items():
assert isinstance(condition_value, dict)
for condition_element_key, condition_element_value in condition_value.items():
for (
condition_element_key,
condition_element_value,
) in condition_value.items():
assert isinstance(condition_element_value, (list, string_types))
if IAMPolicyDocumentValidator._strip_condition_key(condition_key) not in VALID_CONDITIONS:
if (
IAMPolicyDocumentValidator._strip_condition_key(condition_key)
not in VALID_CONDITIONS
):
assert not condition_value # empty dict
@staticmethod
def _strip_condition_key(condition_key):
for valid_prefix in VALID_CONDITION_PREFIXES:
if condition_key.startswith(valid_prefix):
condition_key = condition_key[len(valid_prefix):]
condition_key = condition_key[len(valid_prefix) :]
break # strip only the first match
for valid_postfix in VALID_CONDITION_POSTFIXES:
if condition_key.endswith(valid_postfix):
condition_key = condition_key[:-len(valid_postfix)]
condition_key = condition_key[: -len(valid_postfix)]
break # strip only the first match
return condition_key
@ -254,15 +270,17 @@ class IAMPolicyDocumentValidator:
def _validate_resource_exist(self):
for statement in self._statements:
assert ("Resource" in statement or "NotResource" in statement)
assert "Resource" in statement or "NotResource" in statement
if "Resource" in statement and isinstance(statement["Resource"], list):
assert statement["Resource"]
elif "NotResource" in statement and isinstance(statement["NotResource"], list):
elif "NotResource" in statement and isinstance(
statement["NotResource"], list
):
assert statement["NotResource"]
def _validate_action_like_exist(self):
for statement in self._statements:
assert ("Action" in statement or "NotAction" in statement)
assert "Action" in statement or "NotAction" in statement
if "Action" in statement and isinstance(statement["Action"], list):
assert statement["Action"]
elif "NotAction" in statement and isinstance(statement["NotAction"], list):
@ -287,13 +305,19 @@ class IAMPolicyDocumentValidator:
def _validate_action_prefix(action):
action_parts = action.split(":")
if len(action_parts) == 1 and action_parts[0] != "*":
raise MalformedPolicyDocument("Actions/Conditions must be prefaced by a vendor, e.g., iam, sdb, ec2, etc.")
raise MalformedPolicyDocument(
"Actions/Conditions must be prefaced by a vendor, e.g., iam, sdb, ec2, etc."
)
elif len(action_parts) > 2:
raise MalformedPolicyDocument("Actions/Condition can contain only one colon.")
raise MalformedPolicyDocument(
"Actions/Condition can contain only one colon."
)
vendor_pattern = re.compile(r'[^a-zA-Z0-9\-.]')
vendor_pattern = re.compile(r"[^a-zA-Z0-9\-.]")
if action_parts[0] != "*" and vendor_pattern.search(action_parts[0]):
raise MalformedPolicyDocument("Vendor {vendor} is not valid".format(vendor=action_parts[0]))
raise MalformedPolicyDocument(
"Vendor {vendor} is not valid".format(vendor=action_parts[0])
)
def _validate_resources_for_formats(self):
self._validate_resource_like_for_formats("Resource")
@ -310,30 +334,51 @@ class IAMPolicyDocumentValidator:
for resource in sorted(statement[key], reverse=True):
self._validate_resource_format(resource)
if self._resource_error == "":
IAMPolicyDocumentValidator._legacy_parse_resource_like(statement, key)
IAMPolicyDocumentValidator._legacy_parse_resource_like(
statement, key
)
def _validate_resource_format(self, resource):
if resource != "*":
resource_partitions = resource.partition(":")
if resource_partitions[1] == "":
self._resource_error = 'Resource {resource} must be in ARN format or "*".'.format(resource=resource)
self._resource_error = 'Resource {resource} must be in ARN format or "*".'.format(
resource=resource
)
return
resource_partitions = resource_partitions[2].partition(":")
if resource_partitions[0] != "aws":
remaining_resource_parts = resource_partitions[2].split(":")
arn1 = remaining_resource_parts[0] if remaining_resource_parts[0] != "" or len(remaining_resource_parts) > 1 else "*"
arn2 = remaining_resource_parts[1] if len(remaining_resource_parts) > 1 else "*"
arn3 = remaining_resource_parts[2] if len(remaining_resource_parts) > 2 else "*"
arn4 = ":".join(remaining_resource_parts[3:]) if len(remaining_resource_parts) > 3 else "*"
arn1 = (
remaining_resource_parts[0]
if remaining_resource_parts[0] != ""
or len(remaining_resource_parts) > 1
else "*"
)
arn2 = (
remaining_resource_parts[1]
if len(remaining_resource_parts) > 1
else "*"
)
arn3 = (
remaining_resource_parts[2]
if len(remaining_resource_parts) > 2
else "*"
)
arn4 = (
":".join(remaining_resource_parts[3:])
if len(remaining_resource_parts) > 3
else "*"
)
self._resource_error = 'Partition "{partition}" is not valid for resource "arn:{partition}:{arn1}:{arn2}:{arn3}:{arn4}".'.format(
partition=resource_partitions[0],
arn1=arn1,
arn2=arn2,
arn3=arn3,
arn4=arn4
arn4=arn4,
)
return
@ -345,8 +390,16 @@ class IAMPolicyDocumentValidator:
service = resource_partitions[0]
if service in SERVICE_TYPE_REGION_INFORMATION_ERROR_ASSOCIATIONS.keys() and not resource_partitions[2].startswith(":"):
self._resource_error = SERVICE_TYPE_REGION_INFORMATION_ERROR_ASSOCIATIONS[service].format(resource=resource)
if service in SERVICE_TYPE_REGION_INFORMATION_ERROR_ASSOCIATIONS.keys() and not resource_partitions[
2
].startswith(
":"
):
self._resource_error = SERVICE_TYPE_REGION_INFORMATION_ERROR_ASSOCIATIONS[
service
].format(
resource=resource
)
return
resource_partitions = resource_partitions[2].partition(":")
@ -354,13 +407,19 @@ class IAMPolicyDocumentValidator:
if service in VALID_RESOURCE_PATH_STARTING_VALUES.keys():
valid_start = False
for valid_starting_value in VALID_RESOURCE_PATH_STARTING_VALUES[service]["values"]:
for valid_starting_value in VALID_RESOURCE_PATH_STARTING_VALUES[
service
]["values"]:
if resource_partitions[2].startswith(valid_starting_value):
valid_start = True
break
if not valid_start:
self._resource_error = VALID_RESOURCE_PATH_STARTING_VALUES[service]["error_message"].format(
values=", ".join(VALID_RESOURCE_PATH_STARTING_VALUES[service]["values"])
self._resource_error = VALID_RESOURCE_PATH_STARTING_VALUES[service][
"error_message"
].format(
values=", ".join(
VALID_RESOURCE_PATH_STARTING_VALUES[service]["values"]
)
)
def _perform_first_legacy_parsing(self):
@ -373,7 +432,9 @@ class IAMPolicyDocumentValidator:
assert statement["Effect"] in VALID_EFFECTS # case-sensitive matching
if "Condition" in statement:
for condition_key, condition_value in statement["Condition"].items():
IAMPolicyDocumentValidator._legacy_parse_condition(condition_key, condition_value)
IAMPolicyDocumentValidator._legacy_parse_condition(
condition_key, condition_value
)
@staticmethod
def _legacy_parse_resource_like(statement, key):
@ -389,20 +450,31 @@ class IAMPolicyDocumentValidator:
@staticmethod
def _legacy_parse_condition(condition_key, condition_value):
stripped_condition_key = IAMPolicyDocumentValidator._strip_condition_key(condition_key)
stripped_condition_key = IAMPolicyDocumentValidator._strip_condition_key(
condition_key
)
if stripped_condition_key.startswith("Date"):
for condition_element_key, condition_element_value in condition_value.items():
for (
condition_element_key,
condition_element_value,
) in condition_value.items():
if isinstance(condition_element_value, string_types):
IAMPolicyDocumentValidator._legacy_parse_date_condition_value(condition_element_value)
IAMPolicyDocumentValidator._legacy_parse_date_condition_value(
condition_element_value
)
else: # it has to be a list
for date_condition_value in condition_element_value:
IAMPolicyDocumentValidator._legacy_parse_date_condition_value(date_condition_value)
IAMPolicyDocumentValidator._legacy_parse_date_condition_value(
date_condition_value
)
@staticmethod
def _legacy_parse_date_condition_value(date_condition_value):
if "t" in date_condition_value.lower() or "-" in date_condition_value:
IAMPolicyDocumentValidator._validate_iso_8601_datetime(date_condition_value.lower())
IAMPolicyDocumentValidator._validate_iso_8601_datetime(
date_condition_value.lower()
)
else: # timestamp
assert 0 <= int(date_condition_value) <= 9223372036854775807
@ -410,7 +482,11 @@ class IAMPolicyDocumentValidator:
def _validate_iso_8601_datetime(datetime):
datetime_parts = datetime.partition("t")
negative_year = datetime_parts[0].startswith("-")
date_parts = datetime_parts[0][1:].split("-") if negative_year else datetime_parts[0].split("-")
date_parts = (
datetime_parts[0][1:].split("-")
if negative_year
else datetime_parts[0].split("-")
)
year = "-" + date_parts[0] if negative_year else date_parts[0]
assert -292275054 <= int(year) <= 292278993
if len(date_parts) > 1:
@ -444,7 +520,9 @@ class IAMPolicyDocumentValidator:
assert 0 <= int(time_zone_minutes) <= 59
else:
seconds_with_decimal_fraction = time_parts[2]
seconds_with_decimal_fraction_partition = seconds_with_decimal_fraction.partition(".")
seconds_with_decimal_fraction_partition = seconds_with_decimal_fraction.partition(
"."
)
seconds = seconds_with_decimal_fraction_partition[0]
assert 0 <= int(seconds) <= 59
if seconds_with_decimal_fraction_partition[1] == ".":