Important - the implementation has enough at this point to satisfy the requirements of tfsec - the example below is achievable
SARIF is the Static Analysis Results Interchange Format, this project seeks to provide a simple interface to generate reports in the SARIF format.
This example is taken directly from the Microsoft sarif pages
{
"version": "2.1.0",
"$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.4",
"runs": [
{
"tool": {
"driver": {
"name": "ESLint",
"informationUri": "https://eslint.org",
"rules": [
{
"id": "no-unused-vars",
"shortDescription": {
"text": "disallow unused variables"
},
"helpUri": "https://eslint.org/docs/rules/no-unused-vars",
"properties": {
"category": "Variables"
}
}
]
}
},
"artifacts": [
{
"location": {
"uri": "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js"
}
}
],
"results": [
{
"level": "error",
"message": {
"text": "'x' is assigned a value but never used."
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "file:///C:/dev/sarif/sarif-tutorials/samples/Introduction/simple-example.js",
"index": 0
},
"region": {
"startLine": 1,
"startColumn": 5
}
}
}
],
"ruleId": "no-unused-vars",
"ruleIndex": 0
}
]
}
]
}
One of the projects I like to contribute to is tfsec - this is a static analysis tool for Terraform which produces output in many formats. Generating SARIF reports is missing functionality and felt like it warranted being moved out to a project of its own.
For more information about SARIF, you can visit the Oasis Open site.
Add an import to github.com/owenrumney/go-sarif/sarif
Creating a new Sarif report is done by passing the version, the only supported at the moment is 2.1.0
The example below is taken from the tfsec
usage of go-sarif
. For context, at the end of the process a slice of Result
objects is returned with the relevant information about the check failures.
// create the report object
report, err := sarif.New(sarif.Version210)
if err != nil {
return err
}
// add a run to the report
run := report.AddRun("tfsec", "https://tfsec.dev")
// for each result add the rule, location and result to the report
for _, result := range results {
rule := run.AddRule(string(result.RuleID)).
WithDescription(result.Description).
WithHelpUri(fmt.Sprintf("https://tfsec.dev/%s/%s", strings.ToLower(string(result.RuleProvider)), result.RuleID))
ruleResult := run.AddResult(rule.Id).
WithMessage(string(result.RuleDescription)).
WithLevel(string(result.Severity)).
WithLocationDetails(result.Range.Filename, result.Range.StartLine, 1)
run.AddResultDetails(rule, ruleResult, result.Range.Filename)
}
// print the report to anything that implements `io.Writer`
return report.Write(w)