def transform_template(self): """ Transform the Template using the Serverless Application Model. """ matches = [] try: # Output the SAM Translator version in debug mode LOGGER.info('SAM Translator: %s', samtranslator.__version__) sam_translator = Translator( managed_policy_map=self._managed_policy_map, sam_parser=self._sam_parser) self._replace_local_codeuri() # Tell SAM to use the region we're linting in, this has to be # controlled using the default AWS mechanisms, see also: # https://github.com/awslabs/serverless-application-model/blob/master/samtranslator/translator/arn_generator.py LOGGER.info('Setting AWS_DEFAULT_REGION to %s', self._region) os.environ['AWS_DEFAULT_REGION'] = self._region self._template = convert_dict( sam_translator.translate(sam_template=self._template, parameter_values=self._parameters)) LOGGER.info('Transformed template: \n%s', format_json_string(self._template)) except InvalidDocumentException as e: message = 'Error transforming template: {0}' for cause in e.causes: matches.append(Match( 1, 1, 1, 1, self._filename, TransformError(), message.format(cause.message))) except Exception as e: # pylint: disable=W0703 LOGGER.debug('Error transforming template: %s', str(e)) LOGGER.debug('Stack trace: %s', e, exc_info=True) message = 'Error transforming template: {0}' matches.append(Match( 1, 1, 1, 1, self._filename, TransformError(), message.format(str(e)))) return matches
def run_checks(filename, template, rules, regions, mandatory_rules=None): """Run Checks against the template""" if regions: if not set(regions).issubset(set(REGIONS)): unsupported_regions = list(set(regions).difference(set(REGIONS))) msg = 'Regions %s are unsupported. Supported regions are %s' % ( unsupported_regions, REGIONS) raise InvalidRegionException(msg, 32) errors = [] runner = cfnlint.runner.Runner(rules, filename, template, regions, mandatory_rules=mandatory_rules) # Transform logic helps with handling serverless templates ignore_transform_error = False if not rules.is_rule_enabled(TransformError()): ignore_transform_error = True errors.extend(runner.transform()) if errors: if ignore_transform_error: return ([]) # if there is a transform error we can't continue return (errors) # Only do rule analysis if Transform was successful try: errors.extend(runner.run()) except Exception as err: # pylint: disable=W0703 msg = 'Tried to process rules on file %s but got an error: %s' % ( filename, str(err)) UnexpectedRuleException(msg, 1) errors.sort(key=lambda x: (x.filename, x.linenumber, x.rule.id)) return (errors)
def print_matches(self, matches, rules=None, filenames=None): """Output all the matches""" if not rules: rules = RulesCollection() # These "base" rules are not passed into formatters rules.extend([ParseError(), TransformError(), RuleError()]) results = [] for match in matches: results.append( sarif.Result( rule_id=match.rule.id, message=sarif.Message(text=match.message), level=self._to_sarif_level(match.rule.severity), locations=[ sarif.Location( physical_location=sarif.PhysicalLocation( artifact_location=sarif.ArtifactLocation( uri=match.filename, uri_base_id=self.uri_base_id, ), region=sarif.Region( start_column=match.columnnumber, start_line=match.linenumber, end_column=match.columnnumberend, end_line=match.linenumberend, ), )) ], )) # Output only the rules that have matches matched_rules = set(r.rule_id for r in results) rules_map = {r.id: r for r in list(rules)} rules = [ sarif.ReportingDescriptor( id=rule_id, short_description=sarif.MultiformatMessageString( text=rules_map[rule_id].shortdesc), full_description=sarif.MultiformatMessageString( text=rules_map[rule_id].description), help_uri=rules_map[rule_id].source_url if rules_map[rule_id] else None) for rule_id in matched_rules ] run = sarif.Run( tool=sarif.Tool(driver=sarif.ToolComponent( name='cfn-lint', short_description=sarif.MultiformatMessageString( text=('Validates AWS CloudFormation templates against' ' the resource specification and additional' ' checks.')), information_uri= 'https://github.com/aws-cloudformation/cfn-lint', rules=rules, version=cfnlint.version.__version__, ), ), original_uri_base_ids={ self.uri_base_id: sarif.ArtifactLocation( description=sarif.MultiformatMessageString( 'The directory in which cfn-lint was run.')) }, results=results, ) log = sarif.SarifLog(version=self.version, schema_uri=self.schema, runs=[run]) # IMPORTANT: 'warning' is the default level in SARIF and will be # stripped by serialization. return to_json(log)