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))
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 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 } }
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')
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))
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)
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)
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' } }
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))
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
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)
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
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)
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 } }
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))
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'])
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' } }
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)
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)
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
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
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)