-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #44 from underdog-tech/feat/console-reporter
feat: Create a console reporter
- Loading branch information
Showing
5 changed files
with
202 additions
and
65 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
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
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
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 |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package reporting | ||
|
||
import ( | ||
"fmt" | ||
"sort" | ||
"sync" | ||
|
||
"github.com/gookit/color" | ||
"github.com/underdog-tech/vulnbot/config" | ||
"golang.org/x/exp/maps" | ||
) | ||
|
||
// These match the colors of the icons that we are currently using in Slack | ||
func getConsoleSeverityColors() map[string]string { | ||
return map[string]string{ | ||
"Critical": "#c10003", | ||
"High": "#e32a33", | ||
"Moderate": "#e46919", | ||
"Low": "#2a9e30", | ||
} | ||
} | ||
|
||
// This will eventually pull from config instead | ||
func getConsoleEcosystemIcons() map[string]string { | ||
return map[string]string{ | ||
"Go": "🦦", | ||
"Maven": "🪶 ", | ||
"Npm": "⬢ ", | ||
"Pip": "🐍", | ||
"Rubygems": "♦️ ", | ||
} | ||
} | ||
|
||
type ConsoleReporter struct { | ||
Config config.TomlConfig | ||
} | ||
|
||
// SendSummaryReport generates a brief report summarizing all the discovered | ||
// vulnerabilities, and prints them out neatly and concisely to the console. | ||
func (c *ConsoleReporter) SendSummaryReport( | ||
header string, | ||
numRepos int, | ||
report VulnerabilityReport, | ||
wg *sync.WaitGroup, | ||
) error { | ||
defer wg.Done() | ||
summaryReport := color.Bold.Sprint(header) + "\n" | ||
summaryReport += fmt.Sprintf("Total repositories: %d\n", numRepos) | ||
summaryReport += fmt.Sprintf("Total vulnerabilities: %d\n", report.TotalCount) | ||
summaryReport += fmt.Sprintf("Affected repositories: %d\n", report.AffectedRepos) | ||
summaryReport += color.Bold.Sprint("Breakdown by Severity") + "\n" | ||
severities := getSeverityReportOrder() | ||
severityColors := getConsoleSeverityColors() | ||
for _, severity := range severities { | ||
title := color.HEX(severityColors[severity]).Sprint(severity) | ||
summaryReport += fmt.Sprintf("%s: %d\n", title, report.VulnsBySeverity[severity]) | ||
} | ||
summaryReport += color.Bold.Sprint("Breakdown by Ecosystem") + "\n" | ||
ecosystems := maps.Keys(report.VulnsByEcosystem) | ||
sort.Strings(ecosystems) | ||
ecosystemIcons := getConsoleEcosystemIcons() | ||
for _, ecosystem := range ecosystems { | ||
summaryReport += fmt.Sprintf("%s %s: %d\n", ecosystemIcons[ecosystem], ecosystem, report.VulnsByEcosystem[ecosystem]) | ||
} | ||
fmt.Printf(summaryReport) | ||
return nil | ||
} | ||
|
||
// SendTeamReports is a noop for the Console reporter for the time being. | ||
// Without taking a lot of time to focus on proper formatting, the output | ||
// of this could be quite overwhelming. | ||
func (c *ConsoleReporter) SendTeamReports( | ||
teamReports map[string]map[string]VulnerabilityReport, | ||
wg *sync.WaitGroup, | ||
) error { | ||
defer wg.Done() | ||
return nil | ||
} |
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 |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package reporting | ||
|
||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"sync" | ||
"testing" | ||
|
||
"github.com/gookit/color" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/underdog-tech/vulnbot/config" | ||
) | ||
|
||
func TestSendSummaryReport(t *testing.T) { | ||
origStdout := os.Stdout | ||
reader, writer, _ := os.Pipe() | ||
os.Stdout = writer | ||
|
||
reporter := ConsoleReporter{Config: config.TomlConfig{}} | ||
report := NewVulnerabilityReport() | ||
report.AffectedRepos = 2 | ||
report.TotalCount = 42 | ||
report.VulnsByEcosystem["Pip"] = 2 | ||
report.VulnsByEcosystem["Npm"] = 40 | ||
report.VulnsBySeverity["Critical"] = 10 | ||
report.VulnsBySeverity["High"] = 10 | ||
report.VulnsBySeverity["Moderate"] = 10 | ||
report.VulnsBySeverity["Low"] = 12 | ||
severityColors := getConsoleSeverityColors() | ||
ecosystemIcons := getConsoleEcosystemIcons() | ||
expected := fmt.Sprintf(`%s | ||
Total repositories: 13 | ||
Total vulnerabilities: 42 | ||
Affected repositories: 2 | ||
%s | ||
%s: 10 | ||
%s: 10 | ||
%s: 10 | ||
%s: 12 | ||
%s | ||
%s Npm: 40 | ||
%s Pip: 2 | ||
`, | ||
color.Bold.Sprint("OrgName Dependabot Report for now"), | ||
color.Bold.Sprint("Breakdown by Severity"), | ||
color.HEX(severityColors["Critical"]).Sprint("Critical"), | ||
color.HEX(severityColors["High"]).Sprint("High"), | ||
color.HEX(severityColors["Moderate"]).Sprint("Moderate"), | ||
color.HEX(severityColors["Low"]).Sprint("Low"), | ||
color.Bold.Sprint("Breakdown by Ecosystem"), | ||
ecosystemIcons["Npm"], | ||
ecosystemIcons["Pip"], | ||
) | ||
|
||
wg := new(sync.WaitGroup) | ||
wg.Add(1) | ||
reporter.SendSummaryReport("OrgName Dependabot Report for now", 13, report, wg) | ||
writer.Close() | ||
written, _ := ioutil.ReadAll(reader) | ||
os.Stdout = origStdout | ||
assert.Equal(t, expected, string(written)) | ||
} |