Ejemplo n.º 1
0
class TestInclude(BaseTestCase):
    """Used for Testing Rules"""

    def setUp(self):
        """Setup"""
        self.collection = RulesCollection()
        self.collection.register(Configuration())

    def tearDown(self):
        """Tear Down"""
        # Reset the Spec override to prevent other tests to fail
        cfnlint.helpers.initialize_specs()

    def test_fail_run(self):
        """Failure test required"""
        filename = 'test/fixtures/templates/bad/override/include.yaml'
        template = self.load_template(filename)

        with open('test/fixtures/templates/override_spec/include.json') as fp:
            custom_spec = json.load(fp)
        cfnlint.helpers.set_specs(custom_spec)

        bad_runner = Runner(self.collection, filename, template, ['us-east-1'], [])
        errs = bad_runner.run()
        self.assertEqual(2, len(errs))
Ejemplo n.º 2
0
 def setUp(self):
     """ SetUp template object"""
     self.rules = RulesCollection()
     rulesdirs = [DEFAULT_RULESDIR]
     for rulesdir in rulesdirs:
         self.rules.extend(
             RulesCollection.create_from_directory(rulesdir))
Ejemplo n.º 3
0
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.extend(
                RulesCollection.create_from_directory(rulesdir))

        self.filenames = {
            "config_rule": {
                "filename": 'fixtures/templates/quickstart/config-rules.json',
                "failures": 4
            },
            "iam": {
                "filename": 'fixtures/templates/quickstart/iam.json',
                "failures": 4
            },
            "nat_instance": {
                "filename": 'fixtures/templates/quickstart/nat-instance.json',
                "failures": 2
            },
            "vpc_management": {
                "filename": 'fixtures/templates/quickstart/vpc-management.json',
                "failures": 35
            },
            "vpc": {
                "filename": 'fixtures/templates/quickstart/vpc.json',
                "failures": 40
            },
            "poller": {
                "filename": 'fixtures/templates/public/lambda-poller.json',
                "failures": 0
            }
        }
Ejemplo n.º 4
0
class TestDefaultArguments(BaseTestCase):
    """Test Run Checks """
    def setUp(self):
        """Setup"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.extend(RulesCollection.create_from_directory(rulesdir))

    def test_good_template(self):
        """Test success run"""

        filename = 'templates/good/generic.yaml'
        (_,
         template) = cfnlint.helpers.get_template_default_args(filename, True)

        results = cfnlint.helpers.run_checks(filename, template, self.rules,
                                             {}, {}, ['us-east-1'])

        assert (results == [])

    def test_bad_template(self):
        """Test bad template"""

        filename = 'templates/quickstart/nat-instance.json'
        (_,
         template) = cfnlint.helpers.get_template_default_args(filename, True)

        results = cfnlint.helpers.run_checks(filename, template, self.rules,
                                             {}, {}, ['us-east-1'])

        assert (results[0].rule.id == 'W2506')
        assert (results[1].rule.id == 'W2001')
Ejemplo n.º 5
0
class TestOverrideRequired(BaseTestCase):
    """Used for Testing Rules"""

    def setUp(self):
        """Setup"""
        self.collection = RulesCollection()
        self.collection.register(Required())

    def tearDown(self):
        """Tear Down"""
        # Reset the Spec override to prevent other tests to fail
        cfnlint.helpers.initialize_specs()

    def test_success_run(self):
        """Success test"""
        filename = 'templates/good/override/required.yaml'
        template = self.load_template(filename)
        custom_spec = json.load(open('templates/override_spec/required.json'))

        cfnlint.helpers.override_specs(custom_spec)

        good_runner = Runner(self.collection, [], filename, template, [], ['us-east-1'], [])
        self.assertEqual([], good_runner.run())

    def test_fail_run(self):
        """Failure test required"""
        filename = 'templates/bad/override/required.yaml'
        template = self.load_template(filename)
        custom_spec = json.load(open('templates/override_spec/required.json'))

        cfnlint.helpers.override_specs(custom_spec)

        bad_runner = Runner(self.collection, [], filename, template, [], ['us-east-1'], [])
        errs = bad_runner.run()
        self.assertEqual(1, len(errs))
Ejemplo n.º 6
0
class TestYamlParse(BaseTestCase):
    """Test YAML Parsing """
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.extend(RulesCollection.create_from_directory(rulesdir))

        self.filenames = {
            "config_rule": {
                "filename": 'fixtures/templates/public/lambda-poller.yaml',
                "failures": 0
            }
        }

    def test_success_parse(self):
        """Test Successful JSON Parsing"""
        for _, values in self.filenames.items():
            filename = values.get('filename')
            failures = values.get('failures')
            template = cfnlint.decode.cfn_yaml.load(filename)
            cfn = Template(filename, template, ['us-east-1'])

            matches = list()
            matches.extend(self.rules.run(filename, cfn))
            assert len(
                matches
            ) == failures, 'Expected {} failures, got {} on {}'.format(
                failures, len(matches), filename)
Ejemplo n.º 7
0
class TestCfnJson(BaseTestCase):
    """Test JSON Parsing """
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.extend(RulesCollection.create_from_directory(rulesdir))

        self.filenames = {
            "config_rule": {
                "filename": 'templates/quickstart/config-rules.json',
                "failures": 0
            },
            "iam": {
                "filename": 'templates/quickstart/iam.json',
                "failures": 0
            },
            "nat_instance": {
                "filename": 'templates/quickstart/nat-instance.json',
                "failures": 2
            },
            "vpc_management": {
                "filename": 'templates/quickstart/vpc-management.json',
                "failures": 16
            },
            "vpc": {
                "filename": 'templates/quickstart/vpc.json',
                "failures": 1
            }
        }

    def test_success_parse(self):
        """Test Successful JSON Parsing"""
        for _, values in self.filenames.items():
            filename = values.get('filename')
            failures = values.get('failures')
            template = json.load(open(filename),
                                 cls=cfnlint.cfn_json.CfnJSONDecoder)
            cfn = Template(template, ['us-east-1'])

            matches = list()
            matches.extend(self.rules.run(filename, cfn, []))
            assert len(
                matches) == failures, 'Expected {} failures, got {}'.format(
                    failures, len(matches))

    def test_fail_run(self):
        """Test failure run"""

        filename = 'templates/bad/json_parse.json'

        try:
            json.load(open(filename), cls=cfnlint.cfn_json.CfnJSONDecoder)
        except cfnlint.cfn_json.JSONDecodeError:
            assert (True)
            return

        assert (False)
Ejemplo n.º 8
0
def get_rules(rulesdir, ignore_rules):
    """Get rules"""
    rules = RulesCollection(ignore_rules)
    rules_dirs = [DEFAULT_RULESDIR] + rulesdir
    for rules_dir in rules_dirs:
        rules.extend(RulesCollection.create_from_directory(rules_dir))

    return rules
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.extend(
                RulesCollection.create_from_directory(rulesdir))

        self.filenames = {
            'config_rule': {
                "filename": 'fixtures/templates/public/lambda-poller.yaml',
                "failures": 0
            },
            'watchmaker': {
                "filename": 'fixtures/templates/public/watchmaker.json',
                "failures": 0
            },
            'nist_high_master': {
                'filename': 'fixtures/templates/quickstart/nist_high_master.yaml',
                'results_filename': 'fixtures/results/quickstart/nist_high_master.json'
            },
            'nist_application': {
                'filename': 'fixtures/templates/quickstart/nist_application.yaml',
                'results_filename': 'fixtures/results/quickstart/nist_application.json'
            },
            'nist_config_rules': {
                'filename': 'fixtures/templates/quickstart/nist_config_rules.yaml',
                'results_filename': 'fixtures/results/quickstart/nist_config_rules.json'
            },
            'nist_iam': {
                'filename': 'fixtures/templates/quickstart/nist_iam.yaml',
                'results_filename': 'fixtures/results/quickstart/nist_iam.json'
            },
            'nist_logging': {
                'filename': 'fixtures/templates/quickstart/nist_logging.yaml',
                'results_filename': 'fixtures/results/quickstart/nist_logging.json'
            },
            'nist_vpc_management': {
                'filename': 'fixtures/templates/quickstart/nist_vpc_management.yaml',
                'results_filename': 'fixtures/results/quickstart/nist_vpc_management.json'
            },
            'nist_vpc_production': {
                'filename': 'fixtures/templates/quickstart/nist_vpc_production.yaml',
                'results_filename': 'fixtures/results/quickstart/nist_vpc_production.json'
            },
            'openshift_master': {
                'filename': 'fixtures/templates/quickstart/openshift_master.yaml',
                'failures': 0
            },
            'openshift': {
                'filename': 'fixtures/templates/quickstart/openshift.yaml',
                'results_filename': 'fixtures/results/quickstart/openshift.json'
            },
            'cis_benchmark': {
                'filename': 'fixtures/templates/quickstart/cis_benchmark.yaml',
                'results_filename': 'fixtures/results/quickstart/cis_benchmark.json'
            }
        }
Ejemplo n.º 10
0
class TestNulls(BaseTestCase):
    """Test Null Value Parsing """
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.extend(RulesCollection.create_from_directory(rulesdir))

    def test_success_run(self):
        """Test success run"""

        filename = 'templates/good/generic.yaml'

        try:
            fp = open(filename)
            loader = cfnlint.cfn_yaml.MarkedLoader(fp.read())
            loader.add_multi_constructor('!',
                                         cfnlint.cfn_yaml.multi_constructor)
            loader.get_single_data()
        except cfnlint.cfn_yaml.CfnParseError:
            assert (False)
            return

        assert (True)

    def test_fail_json_run(self):
        """Test failure run"""

    def test_fail_run(self):
        """Test failure run"""

        filename = 'templates/bad/null_values.json'

        try:
            json.load(open(filename), cls=cfnlint.cfn_json.CfnJSONDecoder)
        except cfnlint.cfn_json.JSONDecodeError as err:
            self.assertIn("Null Error \"EbsOptimized\"", err.msg)
            return

        assert (False)

    def test_fail_yaml_run(self):
        """Test failure run"""

        filename = 'templates/bad/null_values.yaml'

        try:
            fp = open(filename)
            loader = cfnlint.cfn_yaml.MarkedLoader(fp.read())
            loader.add_multi_constructor('!',
                                         cfnlint.cfn_yaml.multi_constructor)
            loader.get_single_data()
        except cfnlint.cfn_yaml.CfnParseError:
            assert (True)
            return

        assert (False)
class TestTemplate(BaseTestCase):
    """Test Template RulesCollection in cfnlint """
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.extend(RulesCollection.create_from_directory(rulesdir))

    def test_rule_ids_unique(self):
        """Test Rule IDs are Unique"""
        existing_rules = []
        for rule in self.rules:
            self.assertFalse(rule.id in existing_rules)
            existing_rules.append(rule.id)

    def test_success_run(self):
        """ Test Run Logic"""
        filename = 'templates/good/generic.yaml'
        fp = open(filename)
        loader = cfnlint.cfn_yaml.MarkedLoader(fp.read())
        loader.add_multi_constructor("!", cfnlint.cfn_yaml.multi_constructor)
        template = loader.get_single_data()
        cfn = Template(template, ['us-east-1'])

        matches = list()
        matches.extend(self.rules.run(filename, cfn, []))
        assert (matches == [])

    def test_fail_run(self):
        """Test failure run"""
        filename = 'templates/bad/generic.yaml'
        fp = open(filename)
        loader = cfnlint.cfn_yaml.MarkedLoader(fp.read())
        loader.add_multi_constructor("!", cfnlint.cfn_yaml.multi_constructor)
        template = loader.get_single_data()
        cfn = Template(template, ['us-east-1'])

        matches = list()
        matches.extend(self.rules.run(filename, cfn, []))
        assert len(matches) == 27, 'Expected {} failures, got {}'.format(
            27, len(matches))

    def test_fail_sub_properties_run(self):
        """Test failure run"""
        filename = 'templates/bad/properties_onlyone.yaml'
        fp = open(filename)
        loader = cfnlint.cfn_yaml.MarkedLoader(fp.read())
        loader.add_multi_constructor("!", cfnlint.cfn_yaml.multi_constructor)
        template = loader.get_single_data()
        cfn = Template(template, ['us-east-1'])

        matches = list()
        matches.extend(self.rules.run(filename, cfn, []))
        assert len(matches) == 3, 'Expected {} failures, got {}'.format(
            2, len(matches))
Ejemplo n.º 12
0
def get_rules(rulesdir, ignore_rules, include_rules):
    """Get rules"""
    rules = RulesCollection(ignore_rules, include_rules)
    rules_dirs = [DEFAULT_RULESDIR] + rulesdir
    try:
        for rules_dir in rules_dirs:
            rules.extend(
                RulesCollection.create_from_directory(rules_dir))
    except OSError as e:
        raise UnexpectedRuleException('Tried to append rules but got an error: %s' % str(e), 1)
    return rules
Ejemplo n.º 13
0
class TestYamlParse(BaseTestCase):
    """Test YAML Parsing """
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.extend(RulesCollection.create_from_directory(rulesdir))

        self.filenames = {
            "config_rule": {
                "filename":
                'test/fixtures/templates/public/lambda-poller.yaml',
                "failures": 0
            },
            "generic_bad": {
                "filename": 'test/fixtures/templates/bad/generic.yaml',
                "failures": 34
            }
        }

    def test_success_parse(self):
        """Test Successful YAML Parsing"""
        for _, values in self.filenames.items():
            filename = values.get('filename')
            failures = values.get('failures')
            template = cfnlint.decode.cfn_yaml.load(filename)
            cfn = Template(filename, template, ['us-east-1'])

            matches = []
            matches.extend(self.rules.run(filename, cfn))
            assert len(
                matches
            ) == failures, 'Expected {} failures, got {} on {}'.format(
                failures, len(matches), filename)

    def test_success_parse_stdin(self):
        """Test Successful YAML Parsing through stdin"""
        for _, values in self.filenames.items():
            filename = '-'
            failures = values.get('failures')
            with open(values.get('filename'), 'r') as fp:
                file_content = fp.read()

            with patch('sys.stdin', StringIO(file_content)):
                template = cfnlint.decode.cfn_yaml.load(filename)
                cfn = Template(filename, template, ['us-east-1'])

                matches = []
                matches.extend(self.rules.run(filename, cfn))
                assert len(
                    matches
                ) == failures, 'Expected {} failures, got {} on {}'.format(
                    failures, len(matches), filename)
Ejemplo n.º 14
0
def get_rules(rulesdir, ignore_rules):
    """Get rules"""
    rules = RulesCollection(ignore_rules)
    rules_dirs = [DEFAULT_RULESDIR] + rulesdir
    try:
        for rules_dir in rules_dirs:
            rules.extend(RulesCollection.create_from_directory(rules_dir))
    except OSError as e:
        LOGGER.error('Tried to append rules but got an error: %s', str(e))
        exit(1)

    return rules
Ejemplo n.º 15
0
class TestDuplicate(BaseTestCase):
    """Test Duplicates Parsing """
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.extend(
                RulesCollection.create_from_directory(rulesdir))

    def test_success_run(self):
        """Test success run"""

        filename = 'fixtures/templates/good/generic.yaml'

        try:
            cfnlint.decode.cfn_yaml.load(filename)
        except cfnlint.decode.cfn_yaml.CfnParseError:
            assert(False)
            return

        assert(True)

    def test_fail_json_run(self):
        """Test failure run"""

    def test_fail_run(self):
        """Test failure run"""

        filename = 'fixtures/templates/bad/duplicate.json'

        try:
            with open(filename) as fp:
                json.load(fp, cls=cfnlint.decode.cfn_json.CfnJSONDecoder)
        except cfnlint.decode.cfn_json.JSONDecodeError:
            assert(True)
            return

        assert(False)

    def test_fail_yaml_run(self):
        """Test failure run"""

        filename = 'fixtures/templates/bad/duplicate.yaml'

        try:
            cfnlint.decode.cfn_yaml.load(filename)
        except cfnlint.decode.cfn_yaml.CfnParseError:
            assert(True)
            return

        assert(False)
Ejemplo n.º 16
0
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.extend(RulesCollection.create_from_directory(rulesdir))

        self.filenames = {
            "config_rule": {
                "filename": 'fixtures/templates/public/lambda-poller.yaml',
                "failures": 0
            }
        }
Ejemplo n.º 17
0
class TestNulls(BaseTestCase):
    """Test Null Value Parsing """
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.create_from_directory(rulesdir)

    def test_success_run(self):
        """Test success run"""

        filename = 'test/fixtures/templates/good/generic.yaml'

        try:
            cfnlint.decode.cfn_yaml.load(filename)
        except cfnlint.decode.cfn_yaml.CfnParseError:
            assert (False)
            return

        assert (True)

    def test_fail_json_run(self):
        """Test failure run"""

    def test_fail_run(self):
        """Test failure run"""

        filename = 'test/fixtures/templates/bad/null_values.json'

        try:
            with open(filename) as fp:
                json.load(fp, cls=cfnlint.decode.cfn_json.CfnJSONDecoder)
        except cfnlint.decode.cfn_json.JSONDecodeError as err:
            self.assertIn("Null Error \"EbsOptimized\"", err.msg)
            return

        assert (False)

    def test_fail_yaml_run(self):
        """Test failure run"""

        filename = 'test/fixtures/templates/bad/null_values.yaml'

        try:
            cfnlint.decode.cfn_yaml.load(filename)
        except cfnlint.decode.cfn_yaml.CfnParseError:
            assert (True)
            return

        assert (False)
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection(include_rules=['I'])
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.extend(RulesCollection.create_from_directory(rulesdir))

        self.filenames = {
            'generic': {
                "filename": 'test/fixtures/templates/good/generic.yaml',
                "failures": 0
            },
            'minimal': {
                "filename": 'test/fixtures/templates/good/minimal.yaml',
                "failures": 0
            },
            'transform': {
                "filename": 'test/fixtures/templates/good/transform.yaml',
                "failures": 0
            },
            'transform_bad': {
                "filename":
                'test/fixtures/templates/bad/transform_serverless_template.yaml',
                "failures": 3
            },
            'conditions': {
                "filename": 'test/fixtures/templates/good/conditions.yaml',
                "failures": 0
            },
            'resources_codepipeline': {
                'filename':
                'test/fixtures/templates/good/resources_codepipeline.yaml',
                'failures': 0
            },
            'transform_serverless_api': {
                'filename':
                'test/fixtures/templates/good/transform_serverless_api.yaml',
                'failures': 0
            },
            'transform_serverless_function': {
                'filename':
                'test/fixtures/templates/good/transform_serverless_function.yaml',
                'failures': 0
            },
            'transform_serverless_globals': {
                'filename':
                'test/fixtures/templates/good/transform_serverless_globals.yaml',
                'failures': 0
            }
        }
class TestTemplate(BaseTestCase):
    """Test Template RulesCollection in cfnlint """
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.extend(RulesCollection.create_from_directory(rulesdir))

    def test_rule_ids_unique(self):
        """Test Rule IDs are Unique"""
        existing_rules = []
        for rule in self.rules:
            self.assertFalse(rule.id in existing_rules)
            existing_rules.append(rule.id)
class TestBaseTemplate(BaseRuleTestCase):
    """Test base template"""
    def setUp(self):
        """Setup"""
        self.collection = RulesCollection()
        self.collection.register(Base())

    def test_file_negative(self):
        """Failure test"""
        failure = 'test/fixtures/templates/bad/template.yaml'
        try:
            Runner(self.collection, failure, True)
            self.assertEqual(1, 0)
        except Exception:
            pass
class TestTemplate(BaseTestCase):
    """Test Template RulesCollection in cfnlint """
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.extend(RulesCollection.create_from_directory(rulesdir))

    def test_rule_ids_unique(self):
        """Test Rule IDs are Unique"""
        existing_rules = []
        for rule in self.rules:
            self.assertFalse(rule.id in existing_rules)
            existing_rules.append(rule.id)

    def test_success_run(self):
        """ Test Run Logic"""
        filename = 'fixtures/templates/good/generic.yaml'
        template = cfnlint.decode.cfn_yaml.load(filename)
        cfn = Template(filename, template, ['us-east-1'])

        matches = list()
        matches.extend(self.rules.run(filename, cfn))
        assert (matches == [])

    def test_fail_run(self):
        """Test failure run"""
        filename = 'fixtures/templates/bad/generic.yaml'
        template = cfnlint.decode.cfn_yaml.load(filename)
        cfn = Template(filename, template, ['us-east-1'])

        matches = list()
        matches.extend(self.rules.run(filename, cfn))
        assert len(matches) == 31, 'Expected {} failures, got {}'.format(
            31, len(matches))

    def test_fail_sub_properties_run(self):
        """Test failure run"""
        filename = 'fixtures/templates/bad/properties_onlyone.yaml'
        template = cfnlint.decode.cfn_yaml.load(filename)
        cfn = Template(filename, template, ['us-east-1'])

        matches = list()
        matches.extend(self.rules.run(filename, cfn))
        assert len(matches) == 3, 'Expected {} failures, got {}'.format(
            2, len(matches))
Ejemplo n.º 22
0
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection()
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.create_from_directory(rulesdir)

        self.filenames = {
            "config_rule": {
                "filename":
                'test/fixtures/templates/public/lambda-poller.yaml',
                "failures": 1
            },
            "generic_bad": {
                "filename": 'test/fixtures/templates/bad/generic.yaml',
                "failures": 35
            }
        }
    def test_success_filtering_of_rules_exclude_longer(self):
        """Test extend function"""
        class rule_e0000(CloudFormationLintRule):
            """Error Rule"""
            id = 'E0000'

        class rule_e0010(CloudFormationLintRule):
            """Error Rule"""
            id = 'E0010'

        class rule_e0002(CloudFormationLintRule):
            """Error Rule"""
            id = 'E0002'

        rules_to_add = [rule_e0000, rule_e0010, rule_e0002]
        rules = RulesCollection(ignore_rules=['E0002'])
        rules.extend(rules_to_add)
        self.assertEqual(len(rules), 2)
        for rule in rules:
            self.assertIn(rule.id, ['E0000', 'E0010'])
    def test_success_filtering_of_rules_default(self):
        """Test extend function"""
        class rule_e0000(CloudFormationLintRule):
            """Error Rule"""
            id = 'E0000'

        class rule_w0000(CloudFormationLintRule):
            """Warning Rule"""
            id = 'W0000'

        class rule_i0000(CloudFormationLintRule):
            """Info Rule"""
            id = 'I0000'

        rules_to_add = [rule_e0000, rule_w0000, rule_i0000]
        rules = RulesCollection(ignore_rules=None, include_rules=None)
        rules.extend(rules_to_add)
        self.assertEqual(len(rules), 2)
        for rule in rules:
            self.assertIn(rule.id, ['W0000', 'E0000'])
Ejemplo n.º 25
0
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection(
            include_rules=['I'],
            include_experimental=True,
            configure_rules={'E3012': {
                'strict': 'false'
            }})
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.create_from_directory(rulesdir)

        self.filenames = {
            'nist_high_master': {
                'filename':
                'test/fixtures/templates/quickstart/nist_high_master.yaml',
                'results_filename':
                'test/fixtures/results/quickstart/non_strict/nist_high_master.json'
            },
            'nist_application': {
                'filename':
                'test/fixtures/templates/quickstart/nist_application.yaml',
                'results_filename':
                'test/fixtures/results/quickstart/non_strict/nist_application.json'
            },
            'openshift': {
                'filename':
                'test/fixtures/templates/quickstart/openshift.yaml',
                'results_filename':
                'test/fixtures/results/quickstart/non_strict/openshift.json'
            },
            'cis_benchmark': {
                'filename':
                'test/fixtures/templates/quickstart/cis_benchmark.yaml',
                'results_filename':
                'test/fixtures/results/quickstart/non_strict/cis_benchmark.json'
            }
        }
Ejemplo n.º 26
0
class TestPropertyVpcId(BaseRuleTestCase):
    """Test Password Property Configuration"""
    def setUp(self):
        """Setup"""
        self.collection = RulesCollection()
        self.collection.register(ImageId())

    success_templates = [
        'templates/good/generic.yaml',
        'templates/quickstart/nist_high_master.yaml',
        'templates/quickstart/nist_config_rules.yaml',
        'templates/quickstart/nist_iam.yaml',
        'templates/quickstart/nist_logging.yaml',
        'templates/quickstart/nist_vpc_production.yaml',
        'templates/quickstart/openshift_master.yaml',
        'templates/quickstart/openshift.yaml',
        'templates/quickstart/cis_benchmark.yaml',
        'templates/good/minimal.yaml', 'templates/good/transform.yaml',
        'templates/good/conditions.yaml'
    ]

    def test_file_positive(self):
        """Success test"""
        self.helper_file_positive()

    def test_file_negative_nist_app(self):
        """Failure test"""
        self.helper_file_negative('templates/quickstart/nist_application.yaml',
                                  3)

    def test_file_negative_nist_mgmt(self):
        """Failure test"""
        self.helper_file_negative(
            'templates/quickstart/nist_vpc_management.yaml', 1)

    def test_file_negative(self):
        """Failure test"""
        self.helper_file_negative('templates/bad/properties_imageid.yaml', 1)
Ejemplo n.º 27
0
class TestDirectives(BaseTestCase):
    """Test Directives """
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection(include_rules=['I'])
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.create_from_directory(rulesdir)

    def test_templates(self):
        """Test ignoring certain rules"""
        filename = 'test/fixtures/templates/bad/core/directives.yaml'
        failures = 5

        template = cfnlint.decode.cfn_yaml.load(filename)
        runner = Runner(self.rules, filename, template, ['us-east-1'])
        matches = []
        matches.extend(runner.transform())
        if not matches:
            matches.extend(runner.run())
        assert len(
            matches) == failures, 'Expected {} failures, got {} on {}'.format(
                failures, len(matches), filename)
Ejemplo n.º 28
0
def main():
    """Main Function"""
    parser = argparse.ArgumentParser(description='CloudFormation Linter')
    parser.add_argument(
        '--template', help='CloudFormation Template')
    parser.add_argument(
        '--ignore-bad-template', help='Ignore failures with Bad template',
        action='store_true'
    )
    parser.add_argument(
        '--log-level', help='Log Level', choices=['info', 'debug']
    )

    defaults = {}
    args = parser.parse_known_args()
    template = {}

    # Setup Logging
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    if vars(args[0])['log_level'] == 'info':
        LOGGER.setLevel(logging.INFO)
    elif vars(args[0])['log_level'] == 'debug':
        LOGGER.setLevel(logging.DEBUG)
    else:
        LOGGER.setLevel(logging.ERROR)
    log_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    ch.setFormatter(log_formatter)
    LOGGER.addHandler(ch)

    # Read template to get configuration items
    if vars(args[0])['template']:
        try:
            filename = vars(args[0])['template']
            fp = open(filename)
            loader = cfnlint.parser.MarkedLoader(fp.read())
            loader.add_multi_constructor("!", cfnlint.parser.multi_constructor)
            template = loader.get_single_data()
            if template is dict:
                defaults = template.get('Metadata', {}).get('cfn-lint', {}).get('config', {})
        except IOError as e:
            if e.errno == 2:
                LOGGER.error("Template file not found: %s", filename)
                sys.exit(1)
            elif e.errno == 21:
                LOGGER.error("Template references a directory, not a file: %s", filename)
                sys.exit(1)
            elif e.errno == 13:
                LOGGER.error("Permission denied when accessing template file: %s", filename)
                sys.exit(1)
        except (ParserError, ScannerError) as err:
            if vars(args[0])['ignore_bad_template']:
                LOGGER.info('Template %s is maflormed: %s', filename, err)
            else:
                LOGGER.error('Template %s is maflormed: %s', filename, err)
                sys.exit(1)

    parser.add_argument(
        '--format', help='Output Format', choices=['quiet', 'parseable', 'json']
    )
    parser.add_argument(
        '--list-rules', dest='listrules', default=False,
        action='store_true', help="list all the rules"
    )
    parser.add_argument(
        '--regions', dest='regions', default=['us-east-1'], nargs='*',
        help="list the regions to validate against."
    )
    parser.add_argument(
        '--append-rules', dest='rulesdir', default=[], nargs='*',
        help="specify one or more rules directories using "
             "one or more --append-rules arguments. "
    )
    parser.add_argument(
        '--ignore-checks', dest='ignore_checks', default=[], nargs='*',
        help="only check rules whose id do not match these values"
    )

    parser.add_argument(
        '--version', help='Version of cfn-lint', action='version',
        version='%(prog)s {version}'.format(version=__version__)
    )
    parser.add_argument(
        '--update-specs', help='Update the CloudFormation Specs',
        action='store_true'
    )

    parser.set_defaults(**defaults)
    args = parser.parse_args()

    if vars(args)['format']:
        if vars(args)['format'] == 'quiet':
            formatter = formatters.QuietFormatter()
        elif vars(args)['format'] == 'parseable':
            # pylint: disable=bad-option-value
            formatter = formatters.ParseableFormatter()
    else:
        formatter = formatters.Formatter()

    if vars(args)['update_specs']:
        cfnlint.helpers.update_resource_specs()
        exit(0)

    rules = RulesCollection()
    rulesdirs = [cfnlint.DEFAULT_RULESDIR] + vars(args)['rulesdir']
    for rulesdir in rulesdirs:
        rules.extend(
            RulesCollection.create_from_directory(rulesdir))

    if vars(args)['listrules']:
        print(rules)
        return 0

    if vars(args)['regions']:
        supported_regions = [
            'ap-south-1',
            'sa-east-1',
            'ap-northeast-1',
            'ap-northeast-2',
            'ap-southeast-1',
            'ap-southeast-2',
            'ca-central-1',
            'eu-central-1',
            'eu-west-1',
            'eu-west-2',
            'us-west-2',
            'us-east-1',
            'us-east-2',
            'us-west-1'
        ]
        for region in vars(args)['regions']:
            if region not in supported_regions:
                LOGGER.error('Supported regions are %s', supported_regions)
                return(1)

    exit_code = 0
    if vars(args)['template']:
        matches = list()
        runner = cfnlint.Runner(
            rules, vars(args)['template'], template, vars(args)['ignore_checks'],
            vars(args)['regions'])
        matches.extend(runner.run())
        matches.sort(key=lambda x: (x.filename, x.linenumber, x.rule.id))
        exit_code = len(matches)
        if vars(args)['format'] == 'json':
            print(json.dumps(matches, indent=4, cls=CustomEncoder))
        else:
            for match in matches:
                print(formatter.format(match))
    else:
        parser.print_help()

    return exit_code
Ejemplo n.º 29
0
def main():
    """Main Function"""
    parser = ArgumentParser(description='CloudFormation Linter')
    parser.add_argument('--template', help='CloudFormation Template')
    parser.add_argument('--ignore-bad-template',
                        help='Ignore failures with Bad template',
                        action='store_true')
    parser.add_argument('--log-level',
                        help='Log Level',
                        choices=['info', 'debug'])

    defaults = {}
    args = parser.parse_known_args()
    template = {}

    # Setup Logging
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    if vars(args[0])['log_level'] == 'info':
        LOGGER.setLevel(logging.INFO)
    elif vars(args[0])['log_level'] == 'debug':
        LOGGER.setLevel(logging.DEBUG)
    else:
        LOGGER.setLevel(logging.ERROR)
    log_formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    ch.setFormatter(log_formatter)
    LOGGER.addHandler(ch)

    # Read template to get configuration items
    if vars(args[0])['template']:
        try:
            filename = vars(args[0])['template']
            fp = open(filename)
            loader = cfnlint.parser.MarkedLoader(fp.read())
            loader.add_multi_constructor('!', cfnlint.parser.multi_constructor)
            template = loader.get_single_data()
            if template is dict:
                defaults = template.get('Metadata',
                                        {}).get('cfn-lint',
                                                {}).get('config', {})
        except IOError as e:
            if e.errno == 2:
                LOGGER.error('Template file not found: %s', filename)
                sys.exit(1)
            elif e.errno == 21:
                LOGGER.error('Template references a directory, not a file: %s',
                             filename)
                sys.exit(1)
            elif e.errno == 13:
                LOGGER.error(
                    'Permission denied when accessing template file: %s',
                    filename)
                sys.exit(1)
        except DuplicateError as err:
            LOGGER.error('Template %s contains duplicates: %s', filename, err)
            sys.exit(1)
        except NullError as err:
            LOGGER.error('Template %s contains nulls: %s', filename, err)
            sys.exit(1)
        except (ParserError, ScannerError) as err:
            try:
                template = json.load(open(filename),
                                     cls=cfnlint.cfn_json.CfnJSONDecoder)
            except cfnlint.cfn_json.JSONDecodeError as json_err:
                if vars(args[0])['ignore_bad_template']:
                    LOGGER.info('Template %s is malformed: %s', filename,
                                err.problem)
                    LOGGER.error('Tried to parse %s as JSON but got error: %s',
                                 filename, str(json_err))
                else:
                    LOGGER.error('Template %s is malformed: %s', filename,
                                 err.problem)
                    LOGGER.error('Tried to parse %s as JSON but got error: %s',
                                 filename, str(json_err))
                sys.exit(1)
            except Exception as json_err:  # pylint: disable=W0703
                if vars(args[0])['ignore_bad_template']:
                    LOGGER.info('Template %s is malformed: %s', filename,
                                err.problem)
                    LOGGER.info('Tried to parse %s as JSON but got error: %s',
                                filename, str(json_err))
                else:
                    LOGGER.error('Template %s is malformed: %s', filename,
                                 err.problem)
                    LOGGER.error('Tried to parse %s as JSON but got error: %s',
                                 filename, str(json_err))
                    sys.exit(1)

    parser.add_argument('--format',
                        help='Output Format',
                        choices=['quiet', 'parseable', 'json'])
    parser.add_argument('--list-rules',
                        dest='listrules',
                        default=False,
                        action='store_true',
                        help='list all the rules')
    parser.add_argument('--regions',
                        dest='regions',
                        default=['us-east-1'],
                        nargs='*',
                        help='list the regions to validate against.')
    parser.add_argument('--append-rules',
                        dest='rulesdir',
                        default=[],
                        nargs='*',
                        help='specify one or more rules directories using '
                        'one or more --append-rules arguments. ')
    parser.add_argument(
        '--ignore-checks',
        dest='ignore_checks',
        default=[],
        nargs='*',
        help='only check rules whose id do not match these values')

    parser.add_argument(
        '--override-spec',
        dest='override_spec',
        help='A CloudFormation Spec override file that allows customization')

    parser.add_argument(
        '--version',
        help='Version of cfn-lint',
        action='version',
        version='%(prog)s {version}'.format(version=__version__))
    parser.add_argument('--update-specs',
                        help='Update the CloudFormation Specs',
                        action='store_true')

    parser.set_defaults(**defaults)
    args = parser.parse_args()

    if vars(args)['format']:
        if vars(args)['format'] == 'quiet':
            formatter = formatters.QuietFormatter()
        elif vars(args)['format'] == 'parseable':
            # pylint: disable=bad-option-value
            formatter = formatters.ParseableFormatter()
    else:
        formatter = formatters.Formatter()

    if vars(args)['override_spec']:
        try:
            filename = vars(args)['override_spec']
            custom_spec_data = json.load(open(filename))

            cfnlint.helpers.override_specs(custom_spec_data)
        except IOError as e:
            if e.errno == 2:
                LOGGER.error('Override spec file not found: %s', filename)
                sys.exit(1)
            elif e.errno == 21:
                LOGGER.error(
                    'Override spec file references a directory, not a file: %s',
                    filename)
                sys.exit(1)
            elif e.errno == 13:
                LOGGER.error(
                    'Permission denied when accessing override spec file: %s',
                    filename)
                sys.exit(1)
        except (ValueError) as err:
            LOGGER.error('Override spec file %s is malformed: %s', filename,
                         err)
            sys.exit(1)

    if vars(args)['update_specs']:
        cfnlint.helpers.update_resource_specs()
        exit(0)

    rules = RulesCollection()
    rulesdirs = [cfnlint.DEFAULT_RULESDIR] + vars(args)['rulesdir']
    for rulesdir in rulesdirs:
        rules.extend(RulesCollection.create_from_directory(rulesdir))

    if vars(args)['listrules']:
        print(rules)
        return 0

    transforms = TransformsCollection()
    transformdirs = [cfnlint.DEFAULT_TRANSFORMSDIR]
    for transformdir in transformdirs:
        transforms.extend(
            TransformsCollection.create_from_directory(transformdir))

    if vars(args)['regions']:
        supported_regions = [
            'ap-south-1', 'sa-east-1', 'ap-northeast-1', 'ap-northeast-2',
            'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'eu-central-1',
            'eu-west-1', 'eu-west-2', 'us-west-2', 'us-east-1', 'us-east-2',
            'us-west-1'
        ]
        for region in vars(args)['regions']:
            if region not in supported_regions:
                LOGGER.error('Supported regions are %s', supported_regions)
                return (32)

    exit_code = 0
    if vars(args)['template']:
        matches = list()
        runner = cfnlint.Runner(rules, transforms,
                                vars(args)['template'], template,
                                vars(args)['ignore_checks'],
                                vars(args)['regions'])
        matches.extend(runner.transform())
        # Only do rule analysis if Transform was successful
        if not matches:
            try:
                matches.extend(runner.run())
            except Exception as err:  # pylint: disable=W0703
                LOGGER.error(
                    'Tried to process rules on file %s but got an error: %s',
                    filename, str(err))
                exit(1)
        matches.sort(key=lambda x: (x.filename, x.linenumber, x.rule.id))
        for match in matches:
            if match.rule.id[0] == 'W':
                exit_code = exit_code | 4
            elif match.rule.id[0] == 'E':
                exit_code = exit_code | 2
        if vars(args)['format'] == 'json':
            print(json.dumps(matches, indent=4, cls=CustomEncoder))
        else:
            for match in matches:
                print(formatter.format(match))
    else:
        parser.print_help()

    return exit_code
Ejemplo n.º 30
0
class TestQuickStartTemplatesNonStrict(BaseTestCase):
    """Test QuickStart Templates Parsing """
    def setUp(self):
        """ SetUp template object"""
        self.rules = RulesCollection(
            include_rules=['I'],
            include_experimental=True,
            configure_rules={'E3012': {
                'strict': 'false'
            }})
        rulesdirs = [DEFAULT_RULESDIR]
        for rulesdir in rulesdirs:
            self.rules.create_from_directory(rulesdir)

        self.filenames = {
            'nist_high_master': {
                'filename':
                'test/fixtures/templates/quickstart/nist_high_master.yaml',
                'results_filename':
                'test/fixtures/results/quickstart/non_strict/nist_high_master.json'
            },
            'nist_application': {
                'filename':
                'test/fixtures/templates/quickstart/nist_application.yaml',
                'results_filename':
                'test/fixtures/results/quickstart/non_strict/nist_application.json'
            },
            'openshift': {
                'filename':
                'test/fixtures/templates/quickstart/openshift.yaml',
                'results_filename':
                'test/fixtures/results/quickstart/non_strict/openshift.json'
            },
            'cis_benchmark': {
                'filename':
                'test/fixtures/templates/quickstart/cis_benchmark.yaml',
                'results_filename':
                'test/fixtures/results/quickstart/non_strict/cis_benchmark.json'
            }
        }

    def test_templates(self):
        """Test Successful JSON Parsing"""
        for _, values in self.filenames.items():
            filename = values.get('filename')
            failures = values.get('failures')
            results_filename = values.get('results_filename')
            template = cfnlint.decode.cfn_yaml.load(filename)

            runner = Runner(self.rules, filename, template, ['us-east-1'])
            matches = []
            matches.extend(runner.transform())
            if not matches:
                matches.extend(runner.run())

            if results_filename:
                with open(results_filename) as json_data:
                    correct = json.load(json_data)

                assert len(matches) == len(
                    correct), 'Expected {} failures, got {} on {}'.format(
                        len(correct), len(matches), filename)
                for c in correct:
                    matched = False
                    for match in matches:
                        if c['Location']['Start']['LineNumber'] == match.linenumber and \
                                c['Location']['Start']['ColumnNumber'] == match.columnnumber and \
                                c['Rule']['Id'] == match.rule.id:
                            matched = True
                    assert matched is True, 'Expected error {} at line {}, column {} in matches for {}'.format(
                        c['Rule']['Id'], c['Location']['Start']['LineNumber'],
                        c['Location']['Start']['ColumnNumber'], filename)
            else:
                assert len(
                    matches
                ) == failures, 'Expected {} failures, got {} on {}'.format(
                    failures, len(matches), filename)