Run black on moto & test directories.
This commit is contained in:
parent
c820395dbf
commit
96e5b1993d
507 changed files with 52541 additions and 47814 deletions
|
|
@ -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] == ".":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue