def test_get_directives(self):
        """ Test getting directives from a template """
        template_yaml = {
            'Resources': {
                'Type': 'AWS::S3::Bucket',
                'myBucket': {
                    'Properties': {
                        'BucketName': "bucket_test"
                    },
                    'Type': 'AWS::S3::Bucket'
                },
                'myBucket1': {
                    'Metadata': {
                        'cfn-lint': {
                            'config': {
                                'ignore_checks': [
                                    'E3012',
                                    'I1001'
                                ]
                            }
                        }
                    },
                    'Properties': {},
                    'Type': 'AWS::S3::Bucket'
                },
                'myBucket2': {
                    'Metadata': {
                        'cfn-lint': {
                            'config': {
                                'ignore_checks': [
                                    'E3012',
                                ]
                            }
                        }
                    },
                    'Properties': {},
                    'Type': 'AWS::S3::Bucket'
                }
            }
        }

        template = Template(
            'test.yaml',
            cfnlint.decode.cfn_yaml.loads(
                json.dumps(
                    template_yaml,
                    sort_keys=True,
                    indent=4, separators=(',', ': ')
                )
            )
        )
        directives = template.get_directives()
        expected_result = {
            'E3012': [
                {'end': (23, 10), 'start': (10, 9)},
                {'end': (36, 10), 'start': (24, 9)}
            ],
            'I1001': [
                {'end': (23, 10), 'start': (10, 9)}
            ]
        }
        self.assertEqual(len(expected_result), len(directives))
        for key, items in directives.items():
            self.assertIn(key, expected_result)
            if key in expected_result:
                self.assertEqualListOfDicts(items, expected_result.get(key))
Beispiel #2
0
class Runner(object):
    """Run all the rules"""
    def __init__(self,
                 rules,
                 filename,
                 template,
                 regions,
                 verbosity=0,
                 mandatory_rules=None):

        self.rules = rules
        self.filename = filename
        self.verbosity = verbosity
        self.mandatory_rules = mandatory_rules or []
        self.cfn = Template(filename, template, regions)

    def transform(self):
        """Transform logic"""
        LOGGER.debug('Transform templates if needed')
        sam_transform = 'AWS::Serverless-2016-10-31'
        matches = []
        transform_declaration = self.cfn.template.get('Transform', [])
        transform_type = transform_declaration if isinstance(
            transform_declaration, list) else [transform_declaration]
        # Don't call transformation if Transform is not specified to prevent
        # useless execution of the transformation.
        # Currently locked in to SAM specific
        if sam_transform not in transform_type:
            return matches
        # Save the Globals section so its available for rule processing
        self.cfn.transform_pre['Globals'] = self.cfn.template.get(
            'Globals', {})
        transform = Transform(self.filename, self.cfn.template,
                              self.cfn.regions[0])
        matches = transform.transform_template()
        self.cfn.template = transform.template()
        return matches

    def run(self):
        """Run rules"""
        LOGGER.info('Run scan of template %s', self.filename)
        matches = []
        if self.cfn.template is not None:
            matches.extend(self.rules.run(self.filename, self.cfn))

        # uniq the list of incidents and filter out exceptions from the template
        directives = self.cfn.get_directives()
        return_matches = []
        for match in matches:
            if not any(match == u for u in return_matches):
                if match.rule.id not in directives:
                    return_matches.append(match)
                else:
                    for mandatory_rule in self.mandatory_rules:
                        if match.rule.id.startswith(mandatory_rule):
                            return_matches.append(match)
                            break
                    else:
                        for directive in directives.get(match.rule.id):
                            start = directive.get('start')
                            end = directive.get('end')
                            if start[0] < match.linenumber < end[0]:
                                break
                            if start[0] == match.linenumber and start[
                                    1] <= match.columnnumber:
                                break
                            if end[0] == match.linenumber and end[
                                    1] >= match.columnnumberend:
                                break
                        else:
                            return_matches.append(match)

        return return_matches