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