This repository has been archived by the owner on Oct 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added optional flag and functionality for combined trivy output parsi…
…ng (#115) * added optional flag and functionality for combined trivy output parsing * address comments
- Loading branch information
1 parent
8236e43
commit 0ededc7
Showing
3 changed files
with
219 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,77 +1,106 @@ | ||
package main | ||
|
||
import ( | ||
v1 "github.com/thought-machine/dracon/api/proto/v1" | ||
"github.com/thought-machine/dracon/producers/docker_trivy/types" | ||
"fmt" | ||
"log" | ||
"strings" | ||
"flag" | ||
|
||
"fmt" | ||
"log" | ||
"strings" | ||
|
||
"github.com/thought-machine/dracon/producers" | ||
v1 "github.com/thought-machine/dracon/api/proto/v1" | ||
"github.com/thought-machine/dracon/producers/docker_trivy/types" | ||
"github.com/thought-machine/dracon/producers" | ||
) | ||
|
||
var Combined bool | ||
|
||
func main() { | ||
if err := producers.ParseFlags(); err != nil { | ||
log.Fatal(err) | ||
} | ||
flag.BoolVar(&Combined, "combinedout", false, "Output is the combined output of Trivy against multiple images, expects {<img-name>:[<regular trivy output>],<other-img>:[<trivy out for 'other-img'>]}") | ||
|
||
if err := producers.ParseFlags(); err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
inFile, err := producers.ReadInFile() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
inFile, err := producers.ReadInFile() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
var results []types.TrivyOut | ||
if err := producers.ParseJSON(inFile, &results); err != nil { | ||
log.Fatal(err) | ||
} | ||
if Combined { | ||
var results types.CombinedOut | ||
if err := producers.ParseJSON(inFile, &results); err != nil { | ||
log.Fatal(err) | ||
} | ||
if err := producers.WriteDraconOut( | ||
"trivy", | ||
parseCombinedOut(results), | ||
); err != nil { | ||
log.Fatal(err) | ||
} | ||
} else { | ||
var results []types.TrivyOut | ||
if err := producers.ParseJSON(inFile, &results); err != nil { | ||
log.Fatal(err) | ||
} | ||
if err := producers.WriteDraconOut( | ||
"trivy", | ||
parseSingleOut(results), | ||
); err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
if err := producers.WriteDraconOut( | ||
"trivy", | ||
parseOut(results), | ||
); err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
} | ||
func parseCombinedOut(results types.CombinedOut) []*v1.Issue { | ||
issues := []*v1.Issue{} | ||
for img, output := range results { | ||
log.Printf("Parsing Combined Output for %s\n", img) | ||
for _, res := range output { | ||
target := res.Target | ||
for _, vuln := range res.Vulnerable { | ||
issues = append(issues, parseResult(&vuln, target)) | ||
} | ||
} | ||
} | ||
return issues | ||
} | ||
|
||
func parseOut(results []types.TrivyOut) []*v1.Issue { | ||
issues := []*v1.Issue{} | ||
for _, res := range results { | ||
target := res.Target | ||
func parseSingleOut(results []types.TrivyOut) []*v1.Issue { | ||
issues := []*v1.Issue{} | ||
for _, res := range results { | ||
target := res.Target | ||
|
||
for _, vuln := range res.Vulnerable { | ||
issues = append(issues, parseResult(&vuln, target)) | ||
} | ||
} | ||
return issues | ||
} | ||
for _, vuln := range res.Vulnerable { | ||
issues = append(issues, parseResult(&vuln, target)) | ||
} | ||
} | ||
return issues | ||
} | ||
|
||
// TrivySeverityToDracon maps Trivy Severity Strings to dracon struct | ||
func TrivySeverityToDracon(severity string) v1.Severity { | ||
switch severity { | ||
case "LOW": | ||
return v1.Severity_SEVERITY_LOW | ||
case "MEDIUM": | ||
return v1.Severity_SEVERITY_MEDIUM | ||
case "HIGH": | ||
return v1.Severity_SEVERITY_HIGH | ||
case "CRITICAL": | ||
return v1.Severity_SEVERITY_CRITICAL | ||
default: | ||
return v1.Severity_SEVERITY_INFO | ||
} | ||
} | ||
switch severity { | ||
case "LOW": | ||
return v1.Severity_SEVERITY_LOW | ||
case "MEDIUM": | ||
return v1.Severity_SEVERITY_MEDIUM | ||
case "HIGH": | ||
return v1.Severity_SEVERITY_HIGH | ||
case "CRITICAL": | ||
return v1.Severity_SEVERITY_CRITICAL | ||
default: | ||
return v1.Severity_SEVERITY_INFO | ||
} | ||
} | ||
|
||
func parseResult(r *types.TrivyVulnerability, target string) *v1.Issue { | ||
cvss := r.CVSS.Nvd.V3Score | ||
return &v1.Issue{ | ||
Target: target, | ||
Type: "Container image vulnerability", | ||
Title: fmt.Sprintf("[%s][%s] %s", target, r.CVE, r.Title), | ||
Severity: TrivySeverityToDracon(r.Severity), | ||
Confidence: v1.Confidence_CONFIDENCE_MEDIUM, | ||
Cvss: cvss, | ||
Description: fmt.Sprintf("CVSS Score: %v\nCvssVector: %s\nCve: %s\nCwe: %s\nReference: %s\nOriginal Description:%s\n", | ||
r.CVSS.Nvd.V3Score, r.CVSS.Nvd.V3Vector, r.CVE, strings.Join(r.CweIDs[:], ","), r.PrimaryURL, r.Description), | ||
} | ||
return &v1.Issue{ | ||
Target: target, | ||
Type: "Container image vulnerability", | ||
Title: fmt.Sprintf("[%s][%s] %s", target, r.CVE, r.Title), | ||
Severity: TrivySeverityToDracon(r.Severity), | ||
Confidence: v1.Confidence_CONFIDENCE_MEDIUM, | ||
Cvss: r.CVSS.Nvd.V3Score, | ||
Description: fmt.Sprintf("CVSS Score: %v\nCvssVector: %s\nCve: %s\nCwe: %s\nReference: %s\nOriginal Description:%s\n", | ||
r.CVSS.Nvd.V3Score, r.CVSS.Nvd.V3Vector, r.CVE, strings.Join(r.CweIDs[:], ","), r.PrimaryURL, r.Description), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,102 +1,145 @@ | ||
package main | ||
|
||
import ( | ||
v1 "github.com/thought-machine/dracon/api/proto/v1" | ||
"github.com/thought-machine/dracon/producers/docker_trivy/types" | ||
"encoding/json" | ||
"fmt" | ||
"testing" | ||
|
||
"encoding/json" | ||
"fmt" | ||
"testing" | ||
"github.com/stretchr/testify/assert" | ||
|
||
v1 "github.com/thought-machine/dracon/api/proto/v1" | ||
"github.com/thought-machine/dracon/producers/docker_trivy/types" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestParseOut(t *testing.T) { | ||
var results []types.TrivyOut | ||
err := json.Unmarshal([]byte(exampleOutput), &results) | ||
if err != nil { | ||
t.Logf(err.Error()) | ||
t.Fail() | ||
} | ||
issues := parseOut(results) | ||
func TestParseCombinedOut(t *testing.T) { | ||
var results types.CombinedOut | ||
combinedOutput := fmt.Sprintf(`{"ubuntu:latest":%s,"alpine:latest":%s}`,exampleOutput,exampleOutput) | ||
err := json.Unmarshal([]byte(combinedOutput), &results) | ||
if err != nil { | ||
t.Logf(err.Error()) | ||
t.Fail() | ||
} | ||
issues := parseCombinedOut(results) | ||
|
||
expectedIssues := []*v1.Issue{&v1.Issue{ | ||
Target: "ubuntu (ubuntu 18.04)", | ||
Type: "Container image vulnerability", | ||
Title: "[ubuntu (ubuntu 18.04)][CVE-2020-27350] apt: integer overflows and underflows while parsing .deb packages", | ||
Severity: v1.Severity_SEVERITY_MEDIUM, | ||
Cvss: 5.7, | ||
Confidence: v1.Confidence_CONFIDENCE_MEDIUM, | ||
Description: fmt.Sprintf("CVSS Score: %v\nCvssVector: %s\nCve: %s\nCwe: %s\nReference: %s\nOriginal Description:%s\n", | ||
"5.7", "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:L/I:L/A:L", "CVE-2020-27350", | ||
"CWE-190", "https://avd.aquasec.com/nvd/cve-2020-27350", "APT had several integer overflows and underflows while parsing .deb packages, aka GHSL-2020-168 GHSL-2020-169, in files apt-pkg/contrib/extracttar.cc, apt-pkg/deb/debfile.cc, and apt-pkg/contrib/arfile.cc. This issue affects: apt 1.2.32ubuntu0 versions prior to 1.2.32ubuntu0.2; 1.6.12ubuntu0 versions prior to 1.6.12ubuntu0.2; 2.0.2ubuntu0 versions prior to 2.0.2ubuntu0.2; 2.1.10ubuntu0 versions prior to 2.1.10ubuntu0.1;"), | ||
}} | ||
|
||
found := 0 | ||
assert.Equal(t, 2, len(issues)) | ||
for _, issue := range issues { | ||
singleMatch := 0 | ||
for _, expected := range expectedIssues { | ||
if expected.Title == issue.Title { | ||
singleMatch++ | ||
found++ | ||
assert.Equal(t, singleMatch, 1) //assert no duplicates | ||
assert.EqualValues(t, expected.Type, issue.Type) | ||
assert.EqualValues(t, expected.Title, issue.Title) | ||
assert.EqualValues(t, expected.Severity, issue.Severity) | ||
assert.EqualValues(t, expected.Cvss, issue.Cvss) | ||
assert.EqualValues(t, expected.Confidence, issue.Confidence) | ||
assert.EqualValues(t, expected.Description, issue.Description) | ||
} | ||
} | ||
} | ||
assert.Equal(t, found, len(issues)) //assert everything has been found | ||
} | ||
|
||
func TestParseSingleOut(t *testing.T) { | ||
var results []types.TrivyOut | ||
err := json.Unmarshal([]byte(exampleOutput), &results) | ||
if err != nil { | ||
t.Logf(err.Error()) | ||
t.Fail() | ||
} | ||
issues := parseSingleOut(results) | ||
|
||
expectedIssues := make([]*v1.Issue, 1) | ||
expectedIssues[0] = &v1.Issue{ | ||
Target: "ubuntu (ubuntu 18.04)", | ||
Type: "Container image vulnerability", | ||
Title: "[ubuntu (ubuntu 18.04)][CVE-2020-27350] apt: integer overflows and underflows while parsing .deb packages", | ||
Severity: v1.Severity_SEVERITY_MEDIUM, | ||
Cvss: 5.7, | ||
Confidence: v1.Confidence_CONFIDENCE_MEDIUM, | ||
Description: fmt.Sprintf("CVSS Score: %v\nCvssVector: %s\nCve: %s\nCwe: %s\nReference: %s\nOriginal Description:%s\n", | ||
"5.7", "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:L/I:L/A:L", "CVE-2020-27350", | ||
"CWE-190", "https://avd.aquasec.com/nvd/cve-2020-27350", "APT had several integer overflows and underflows while parsing .deb packages, aka GHSL-2020-168 GHSL-2020-169, in files apt-pkg/contrib/extracttar.cc, apt-pkg/deb/debfile.cc, and apt-pkg/contrib/arfile.cc. This issue affects: apt 1.2.32ubuntu0 versions prior to 1.2.32ubuntu0.2; 1.6.12ubuntu0 versions prior to 1.6.12ubuntu0.2; 2.0.2ubuntu0 versions prior to 2.0.2ubuntu0.2; 2.1.10ubuntu0 versions prior to 2.1.10ubuntu0.1;"), | ||
} | ||
expectedIssues := []*v1.Issue{&v1.Issue{ | ||
Target: "ubuntu (ubuntu 18.04)", | ||
Type: "Container image vulnerability", | ||
Title: "[ubuntu (ubuntu 18.04)][CVE-2020-27350] apt: integer overflows and underflows while parsing .deb packages", | ||
Severity: v1.Severity_SEVERITY_MEDIUM, | ||
Cvss: 5.7, | ||
Confidence: v1.Confidence_CONFIDENCE_MEDIUM, | ||
Description: fmt.Sprintf("CVSS Score: %v\nCvssVector: %s\nCve: %s\nCwe: %s\nReference: %s\nOriginal Description:%s\n", | ||
"5.7", "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:L/I:L/A:L", "CVE-2020-27350", | ||
"CWE-190", "https://avd.aquasec.com/nvd/cve-2020-27350", "APT had several integer overflows and underflows while parsing .deb packages, aka GHSL-2020-168 GHSL-2020-169, in files apt-pkg/contrib/extracttar.cc, apt-pkg/deb/debfile.cc, and apt-pkg/contrib/arfile.cc. This issue affects: apt 1.2.32ubuntu0 versions prior to 1.2.32ubuntu0.2; 1.6.12ubuntu0 versions prior to 1.6.12ubuntu0.2; 2.0.2ubuntu0 versions prior to 2.0.2ubuntu0.2; 2.1.10ubuntu0 versions prior to 2.1.10ubuntu0.1;"), | ||
}} | ||
|
||
found := 0 | ||
assert.Equal(t, len(expectedIssues), len(issues)) | ||
for _, issue := range issues { | ||
singleMatch := 0 | ||
for _, expected := range expectedIssues { | ||
if expected.Title == issue.Title { | ||
singleMatch++ | ||
found++ | ||
assert.Equal(t, singleMatch, 1) //assert no duplicates | ||
assert.EqualValues(t, expected.Type, issue.Type) | ||
assert.EqualValues(t, expected.Title, issue.Title) | ||
assert.EqualValues(t, expected.Severity, issue.Severity) | ||
assert.EqualValues(t, expected.Cvss, issue.Cvss) | ||
assert.EqualValues(t, expected.Confidence, issue.Confidence) | ||
assert.EqualValues(t, expected.Description, issue.Description) | ||
} | ||
} | ||
} | ||
assert.Equal(t, found, len(issues)) //assert everything has been found | ||
found := 0 | ||
assert.Equal(t, len(expectedIssues), len(issues)) | ||
for _, issue := range issues { | ||
singleMatch := 0 | ||
for _, expected := range expectedIssues { | ||
if expected.Title == issue.Title { | ||
singleMatch++ | ||
found++ | ||
assert.Equal(t, singleMatch, 1) //assert no duplicates | ||
assert.EqualValues(t, expected.Type, issue.Type) | ||
assert.EqualValues(t, expected.Title, issue.Title) | ||
assert.EqualValues(t, expected.Severity, issue.Severity) | ||
assert.EqualValues(t, expected.Cvss, issue.Cvss) | ||
assert.EqualValues(t, expected.Confidence, issue.Confidence) | ||
assert.EqualValues(t, expected.Description, issue.Description) | ||
} | ||
} | ||
} | ||
assert.Equal(t, found, len(issues)) //assert everything has been found | ||
} | ||
|
||
var exampleOutput = ` | ||
[ | ||
{ | ||
{ | ||
"Target": "ubuntu (ubuntu 18.04)", | ||
"Type": "ubuntu", | ||
"Vulnerabilities": [ | ||
{ | ||
"VulnerabilityID": "CVE-2020-27350", | ||
"PkgName": "apt", | ||
"InstalledVersion": "1.6.12", | ||
"FixedVersion": "1.6.12ubuntu0.2", | ||
"Layer": { | ||
"DiffID": "sha256:a090697502b8d19fbc83afb24d8fb59b01e48bf87763a00ca55cfff42423ad36" | ||
}, | ||
"SeveritySource": "ubuntu", | ||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2020-27350", | ||
"Title": "apt: integer overflows and underflows while parsing .deb packages", | ||
"Description": "APT had several integer overflows and underflows while parsing .deb packages, aka GHSL-2020-168 GHSL-2020-169, in files apt-pkg/contrib/extracttar.cc, apt-pkg/deb/debfile.cc, and apt-pkg/contrib/arfile.cc. This issue affects: apt 1.2.32ubuntu0 versions prior to 1.2.32ubuntu0.2; 1.6.12ubuntu0 versions prior to 1.6.12ubuntu0.2; 2.0.2ubuntu0 versions prior to 2.0.2ubuntu0.2; 2.1.10ubuntu0 versions prior to 2.1.10ubuntu0.1;", | ||
"Severity": "MEDIUM", | ||
"CweIDs": [ | ||
"CWE-190" | ||
], | ||
"CVSS": { | ||
"nvd": { | ||
"V2Vector": "AV:L/AC:L/Au:N/C:P/I:P/A:P", | ||
"V3Vector": "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:L/I:L/A:L", | ||
"V2Score": 4.6, | ||
"V3Score": 5.7 | ||
}, | ||
"redhat": { | ||
"V3Vector": "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:L/I:L/A:L", | ||
"V3Score": 5.7 | ||
} | ||
}, | ||
"References": [ | ||
"https://bugs.launchpad.net/bugs/1899193", | ||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-27350", | ||
"https://security.netapp.com/advisory/ntap-20210108-0005/", | ||
"https://usn.ubuntu.com/usn/usn-4667-1", | ||
"https://usn.ubuntu.com/usn/usn-4667-2", | ||
"https://www.debian.org/security/2020/dsa-4808" | ||
], | ||
"PublishedDate": "2020-12-10T04:15:00Z", | ||
"LastModifiedDate": "2021-01-08T12:15:00Z" | ||
}]}] | ||
` | ||
{ | ||
"VulnerabilityID": "CVE-2020-27350", | ||
"PkgName": "apt", | ||
"InstalledVersion": "1.6.12", | ||
"FixedVersion": "1.6.12ubuntu0.2", | ||
"Layer": { | ||
"DiffID": "sha256:a090697502b8d19fbc83afb24d8fb59b01e48bf87763a00ca55cfff42423ad36" | ||
}, | ||
"SeveritySource": "ubuntu", | ||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2020-27350", | ||
"Title": "apt: integer overflows and underflows while parsing .deb packages", | ||
"Description": "APT had several integer overflows and underflows while parsing .deb packages, aka GHSL-2020-168 GHSL-2020-169, in files apt-pkg/contrib/extracttar.cc, apt-pkg/deb/debfile.cc, and apt-pkg/contrib/arfile.cc. This issue affects: apt 1.2.32ubuntu0 versions prior to 1.2.32ubuntu0.2; 1.6.12ubuntu0 versions prior to 1.6.12ubuntu0.2; 2.0.2ubuntu0 versions prior to 2.0.2ubuntu0.2; 2.1.10ubuntu0 versions prior to 2.1.10ubuntu0.1;", | ||
"Severity": "MEDIUM", | ||
"CweIDs": [ | ||
"CWE-190" | ||
], | ||
"CVSS": { | ||
"nvd": { | ||
"V2Vector": "AV:L/AC:L/Au:N/C:P/I:P/A:P", | ||
"V3Vector": "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:L/I:L/A:L", | ||
"V2Score": 4.6, | ||
"V3Score": 5.7 | ||
}, | ||
"redhat": { | ||
"V3Vector": "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:L/I:L/A:L", | ||
"V3Score": 5.7 | ||
} | ||
}, | ||
"References": [ | ||
"https://bugs.launchpad.net/bugs/1899193", | ||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-27350", | ||
"https://security.netapp.com/advisory/ntap-20210108-0005/", | ||
"https://usn.ubuntu.com/usn/usn-4667-1", | ||
"https://usn.ubuntu.com/usn/usn-4667-2", | ||
"https://www.debian.org/security/2020/dsa-4808" | ||
], | ||
"PublishedDate": "2020-12-10T04:15:00Z", | ||
"LastModifiedDate": "2021-01-08T12:15:00Z" | ||
}]}] | ||
` |
Oops, something went wrong.