Пример #1
0
def get_formatter(fmt):
    """ Get Formatter"""
    formatter = {}
    if fmt:
        if fmt == 'quiet':
            formatter = formatters.QuietFormatter()
        elif fmt == 'parseable':
            # pylint: disable=bad-option-value
            formatter = formatters.ParseableFormatter()
    else:
        formatter = formatters.Formatter()

    return formatter
Пример #2
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
Пример #3
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
Пример #4
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']
    )
    parser.add_argument(
        '--format', help='Output Format', choices=['quiet', 'parseable', 'json']
    )

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

    configure_logging(vars(args[0])['log_level'])

    if vars(args[0])['template']:
        (defaults, template) = cfnlint.helpers.get_template_default_args(
            vars(args[0])['template'],
            vars(args[0])['ignore_bad_template'])

    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']:
        cfnlint.helpers.override_specs(vars(args)['override_spec'])

    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 not vars(args)['template']:
        parser.print_help()
        exit(1)

    matches = cfnlint.helpers.run_checks(
        vars(args)['template'], template, rules, transforms, vars(args)['ignore_checks'],
        vars(args)['regions'])

    exit_code = 0
    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))

    return exit_code