Implemented checking policy documents for syntax errors.
This commit is contained in:
parent
99336cbe6a
commit
ef20b47f97
@ -34,6 +34,14 @@ class MalformedCertificate(RESTError):
|
|||||||
'MalformedCertificate', 'Certificate {cert} is malformed'.format(cert=cert))
|
'MalformedCertificate', 'Certificate {cert} is malformed'.format(cert=cert))
|
||||||
|
|
||||||
|
|
||||||
|
class MalformedPolicyDocument(RESTError):
|
||||||
|
code = 400
|
||||||
|
|
||||||
|
def __init__(self, message=""):
|
||||||
|
super(MalformedPolicyDocument, self).__init__(
|
||||||
|
'MalformedPolicyDocument', message)
|
||||||
|
|
||||||
|
|
||||||
class DuplicateTags(RESTError):
|
class DuplicateTags(RESTError):
|
||||||
code = 400
|
code = 400
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ from cryptography.hazmat.backends import default_backend
|
|||||||
from moto.core.exceptions import RESTError
|
from moto.core.exceptions import RESTError
|
||||||
from moto.core import BaseBackend, BaseModel
|
from moto.core import BaseBackend, BaseModel
|
||||||
from moto.core.utils import iso_8601_datetime_without_milliseconds, iso_8601_datetime_with_milliseconds
|
from moto.core.utils import iso_8601_datetime_without_milliseconds, iso_8601_datetime_with_milliseconds
|
||||||
|
from moto.iam.policy_validation import IAMPolicyDocumentValidator
|
||||||
|
|
||||||
from .aws_managed_policies import aws_managed_policies_data
|
from .aws_managed_policies import aws_managed_policies_data
|
||||||
from .exceptions import IAMNotFoundException, IAMConflictException, IAMReportNotPresentException, MalformedCertificate, \
|
from .exceptions import IAMNotFoundException, IAMConflictException, IAMReportNotPresentException, MalformedCertificate, \
|
||||||
@ -568,6 +569,9 @@ class IAMBackend(BaseBackend):
|
|||||||
policy.detach_from(self.get_user(user_name))
|
policy.detach_from(self.get_user(user_name))
|
||||||
|
|
||||||
def create_policy(self, description, path, policy_document, policy_name):
|
def create_policy(self, description, path, policy_document, policy_name):
|
||||||
|
iam_policy_document_validator = IAMPolicyDocumentValidator(policy_document)
|
||||||
|
iam_policy_document_validator.validate()
|
||||||
|
|
||||||
policy = ManagedPolicy(
|
policy = ManagedPolicy(
|
||||||
policy_name,
|
policy_name,
|
||||||
description=description,
|
description=description,
|
||||||
|
148
moto/iam/policy_validation.py
Normal file
148
moto/iam/policy_validation.py
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
from six import string_types
|
||||||
|
|
||||||
|
from moto.iam.exceptions import MalformedPolicyDocument
|
||||||
|
|
||||||
|
|
||||||
|
ALLOWED_TOP_ELEMENTS = [
|
||||||
|
"Version",
|
||||||
|
"Id",
|
||||||
|
"Statement",
|
||||||
|
"Conditions"
|
||||||
|
]
|
||||||
|
|
||||||
|
ALLOWED_VERSIONS = [
|
||||||
|
"2008-10-17",
|
||||||
|
"2012-10-17"
|
||||||
|
]
|
||||||
|
|
||||||
|
ALLOWED_STATEMENT_ELEMENTS = [
|
||||||
|
"Sid",
|
||||||
|
"Action",
|
||||||
|
"NotAction",
|
||||||
|
"Resource",
|
||||||
|
"NotResource",
|
||||||
|
"Effect",
|
||||||
|
"Condition"
|
||||||
|
]
|
||||||
|
|
||||||
|
ALLOWED_EFFECTS = [
|
||||||
|
"Allow",
|
||||||
|
"Deny"
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class IAMPolicyDocumentValidator:
|
||||||
|
|
||||||
|
def __init__(self, policy_document):
|
||||||
|
self._policy_document = policy_document
|
||||||
|
self._policy_json = {}
|
||||||
|
self._statements = []
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
try:
|
||||||
|
self._validate_syntax()
|
||||||
|
except Exception:
|
||||||
|
raise MalformedPolicyDocument("Syntax errors in policy.")
|
||||||
|
try:
|
||||||
|
self._validate_version()
|
||||||
|
except Exception:
|
||||||
|
raise MalformedPolicyDocument("Policy document must be version 2012-10-17 or greater.")
|
||||||
|
try:
|
||||||
|
self._validate_resource_exist()
|
||||||
|
except Exception:
|
||||||
|
raise MalformedPolicyDocument("Policy statement must contain resources.")
|
||||||
|
|
||||||
|
def _validate_syntax(self):
|
||||||
|
self._policy_json = json.loads(self._policy_document)
|
||||||
|
assert isinstance(self._policy_json, dict)
|
||||||
|
self._validate_top_elements()
|
||||||
|
self._validate_version_syntax()
|
||||||
|
self._validate_id_syntax()
|
||||||
|
self._validate_statements_syntax()
|
||||||
|
|
||||||
|
def _validate_top_elements(self):
|
||||||
|
top_elements = self._policy_json.keys()
|
||||||
|
for element in top_elements:
|
||||||
|
assert element in ALLOWED_TOP_ELEMENTS
|
||||||
|
|
||||||
|
def _validate_version_syntax(self):
|
||||||
|
if "Version" in self._policy_json:
|
||||||
|
assert self._policy_json["Version"] in ALLOWED_VERSIONS
|
||||||
|
|
||||||
|
def _validate_version(self):
|
||||||
|
assert self._policy_json["Version"] == "2012-10-17"
|
||||||
|
|
||||||
|
def _validate_statements_syntax(self):
|
||||||
|
assert "Statement" in self._policy_json
|
||||||
|
assert isinstance(self._policy_json["Statement"], (dict, list))
|
||||||
|
|
||||||
|
if isinstance(self._policy_json["Statement"], dict):
|
||||||
|
self._statements.append(self._policy_json["Statement"])
|
||||||
|
else:
|
||||||
|
self._statements += self._policy_json["Statement"]
|
||||||
|
|
||||||
|
assert self._statements
|
||||||
|
for statement in self._statements:
|
||||||
|
self._validate_statement_syntax(statement)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _validate_statement_syntax(statement):
|
||||||
|
assert isinstance(statement, dict)
|
||||||
|
for statement_element in statement.keys():
|
||||||
|
assert statement_element in ALLOWED_STATEMENT_ELEMENTS
|
||||||
|
|
||||||
|
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_resource_syntax(statement)
|
||||||
|
IAMPolicyDocumentValidator._validate_not_resource_syntax(statement)
|
||||||
|
IAMPolicyDocumentValidator._validate_condition_syntax(statement)
|
||||||
|
IAMPolicyDocumentValidator._validate_sid_syntax(statement)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
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 ALLOWED_EFFECTS]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _validate_resource_syntax(statement):
|
||||||
|
IAMPolicyDocumentValidator._validate_resource_like_syntax(statement, "Resource")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _validate_not_resource_syntax(statement):
|
||||||
|
IAMPolicyDocumentValidator._validate_resource_like_syntax(statement, "NotResource")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _validate_resource_like_syntax(statement, key):
|
||||||
|
if key in statement:
|
||||||
|
assert isinstance(statement[key], (string_types, list))
|
||||||
|
if isinstance(statement[key], list):
|
||||||
|
for resource in statement[key]:
|
||||||
|
assert isinstance(resource, string_types)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _validate_condition_syntax(statement):
|
||||||
|
if "Condition" in statement:
|
||||||
|
assert isinstance(statement["Condition"], dict)
|
||||||
|
for condition_key, condition_value in statement["Condition"].items():
|
||||||
|
assert isinstance(condition_value, dict)
|
||||||
|
for condition_data_key, condition_data_value in condition_value.items():
|
||||||
|
assert isinstance(condition_data_value, (list, string_types))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _validate_sid_syntax(statement):
|
||||||
|
if "Sid" in statement:
|
||||||
|
assert isinstance(statement["Sid"], string_types)
|
||||||
|
|
||||||
|
def _validate_id_syntax(self):
|
||||||
|
if "Id" in self._policy_document:
|
||||||
|
assert isinstance(self._policy_document["Id"], string_types)
|
||||||
|
|
||||||
|
def _validate_resource_exist(self):
|
||||||
|
for statement in self._statements:
|
||||||
|
assert "Resource" in statement
|
||||||
|
|
Loading…
Reference in New Issue
Block a user