1""" 2Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3SPDX-License-Identifier: MIT-0 4""" 5from datetime import date 6from cfnlint.rules import CloudFormationLintRule 7from cfnlint.rules import RuleMatch 8 9 10class PolicyVersion(CloudFormationLintRule): 11 """Check if IAM Policy Version is correct""" 12 id = 'W2511' 13 shortdesc = 'Check IAM Resource Policies syntax' 14 description = 'See if the elements inside an IAM Resource policy are configured correctly.' 15 source_url = 'https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html' 16 tags = ['properties', 'iam'] 17 18 def __init__(self): 19 """Init""" 20 super(PolicyVersion, self).__init__() 21 self.resources_and_keys = { 22 'AWS::ECR::Repository': 'RepositoryPolicyText', 23 'AWS::Elasticsearch::Domain': 'AccessPolicies', 24 'AWS::KMS::Key': 'KeyPolicy', 25 'AWS::S3::BucketPolicy': 'PolicyDocument', 26 'AWS::SNS::TopicPolicy': 'PolicyDocument', 27 'AWS::SQS::QueuePolicy': 'PolicyDocument', 28 } 29 self.idp_and_keys = { 30 'AWS::IAM::Group': 'Policies', 31 'AWS::IAM::ManagedPolicy': 'PolicyDocument', 32 'AWS::IAM::Policy': 'PolicyDocument', 33 'AWS::IAM::Role': 'Policies', 34 'AWS::IAM::User': 'Policies', 35 } 36 for resource_type in self.resources_and_keys: 37 self.resource_property_types.append(resource_type) 38 for resource_type in self.idp_and_keys: 39 self.resource_property_types.append(resource_type) 40 41 def check_policy_document(self, value, path): 42 """Check policy document""" 43 matches = [] 44 45 if not isinstance(value, dict): 46 return matches 47 48 for e_v, e_p in value.items_safe(path[:]): 49 for p_vs, p_p in e_v.items_safe(e_p[:]): 50 version = p_vs.get('Version') 51 if version: 52 if version in ['2008-10-17', date(2008, 10, 17)]: 53 message = 'IAM Policy Version should be updated to \'2012-10-17\'.' 54 matches.append( 55 RuleMatch(p_p + ['Version'], message)) 56 return matches 57 58 def match_resource_properties(self, properties, resourcetype, path, cfn): 59 """Check CloudFormation Properties""" 60 matches = [] 61 62 key = None 63 if resourcetype in self.resources_and_keys: 64 key = self.resources_and_keys.get(resourcetype) 65 else: 66 key = self.idp_and_keys.get(resourcetype) 67 68 if key == 'Policies': 69 for index, policy in enumerate(properties.get(key, [])): 70 matches.extend( 71 cfn.check_value( 72 obj=policy, key='PolicyDocument', 73 path=path[:] + ['Policies', index], 74 check_value=self.check_policy_document, 75 )) 76 else: 77 matches.extend( 78 cfn.check_value( 79 obj=properties, key=key, 80 path=path[:], 81 check_value=self.check_policy_document 82 )) 83 84 return matches 85