Skip to content

Commit

Permalink
feat(policies): display policy breaches in tabulated form (#158)
Browse files Browse the repository at this point in the history
* feat: display policy breaches in tabulated way

* refactor: use category group in policy breach

* chore: add yaml formatting

* chore: update snapshots
  • Loading branch information
elsapet committed Nov 23, 2022
1 parent b4e7fa9 commit 10e2312
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 31 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/bearer/curio
go 1.18

require (
github.com/TwiN/go-color v1.4.0
github.com/bradleyjkemp/cupaloy v2.3.0+incompatible
github.com/ghodss/yaml v1.0.0
github.com/go-enry/go-enry/v2 v2.8.3
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/TwiN/go-color v1.4.0 h1:fNbOwOrvup5oj934UragnW0B1WKaAkkB85q19Y7h4ng=
github.com/TwiN/go-color v1.4.0/go.mod h1:0QTVEPlu+AoCyTrho7bXbVkrCkVpdQr7YF7PYWEtSxM=
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
Expand Down
2 changes: 1 addition & 1 deletion integration/flags/.snapshots/TestInitCommand-init
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ policy:
only-policy: []
skip-policy: []
report:
format: json
format: ""
output: ""
report: detectors
scan:
Expand Down
2 changes: 1 addition & 1 deletion integration/flags/.snapshots/TestMetadataFlags-help-scan
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Worker Flags
--workers int number of processing workers to spawn (default 1)

Report Flags
-f, --format string Specify report format (json, yaml) (default "json")
-f, --format string Specify report format (json, yaml)
--output string Specify output path for report
--report string Specify the kind of report (detectors, dataflow, policies, stats) (default "detectors")

Expand Down
2 changes: 1 addition & 1 deletion integration/flags/.snapshots/TestMetadataFlags-scan-help
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Worker Flags
--workers int number of processing workers to spawn (default 1)

Report Flags
-f, --format string Specify report format (json, yaml) (default "json")
-f, --format string Specify report format (json, yaml)
--output string Specify output path for report
--report string Specify the kind of report (detectors, dataflow, policies, stats) (default "detectors")

Expand Down
7 changes: 3 additions & 4 deletions integration/flags/.snapshots/TestReportFlags-report-policies
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
critical:
- policyname: Logger leaks
policydescription: Logger leaks detected
linenumber: ""
- policy_name: Logger leaks
policy_description: Logger leaks detected
filename: users.rb
category: Contact
category_group: Personal data


--
Expand Down
12 changes: 11 additions & 1 deletion pkg/commands/artifact/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,18 @@ func (r *runner) Report(config settings.Config, report types.Report) error {
logger = outputhandler.PlainLogger(reportFile)
}

if config.Report.Report == flag.ReportPolicies && config.Report.Format == "" {
// for polict report, default report format is NOT JSON
err := reportoutput.ReportPolicies(report, logger, config)
if err != nil {
return fmt.Errorf("error generating report %w", err)
}
return nil
}

switch config.Report.Format {
case flag.FormatJSON:
case "", flag.FormatJSON:
// default report format for is JSON
err := reportoutput.ReportJSON(report, logger, config)
if err != nil {
return fmt.Errorf("error generating report %w", err)
Expand Down
4 changes: 2 additions & 2 deletions pkg/commands/process/settings/policies/logger_leaks.rego
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ high[item] {

location = data_type.locations[_]
item := {
"category": category.name,
"category_group": category.group_name,
"filename": location.filename
}
}
Expand All @@ -34,7 +34,7 @@ critical[item] {

location = data_type.locations[_]
item := {
"category": category.name,
"category_group": category.group_name,
"filename": location.filename
}
}
2 changes: 1 addition & 1 deletion pkg/flag/report_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ var (
Name: "format",
ConfigName: "report.format",
Shorthand: "f",
Value: FormatJSON,
Value: "",
Usage: "Specify report format (json, yaml)",
}
ReportFlag = Flag{
Expand Down
70 changes: 59 additions & 11 deletions pkg/report/output/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"encoding/json"
"errors"
"fmt"
"strings"

"github.com/TwiN/go-color"
"github.com/bearer/curio/pkg/commands/process/settings"
"github.com/bearer/curio/pkg/flag"
"github.com/bearer/curio/pkg/report/output/dataflow"
Expand All @@ -19,6 +21,36 @@ import (

var ErrUndefinedFormat = errors.New("undefined output format")

func ReportPolicies(report types.Report, output *zerolog.Event, config settings.Config) error {
outputPolicies, err := getPolicyReportOutput(report, config)
if err != nil {
return err
}

outputStr := &strings.Builder{}
outputStr.WriteString("===============================")

for _, policyBreach := range outputPolicies[settings.LevelCritical] {
writePolicyBreachToOutput(outputStr, policyBreach, settings.LevelCritical, color.Red)
}

for _, policyBreach := range outputPolicies[settings.LevelHigh] {
writePolicyBreachToOutput(outputStr, policyBreach, settings.LevelHigh, color.Yellow)
}

for _, policyBreach := range outputPolicies[settings.LevelMedium] {
writePolicyBreachToOutput(outputStr, policyBreach, settings.LevelMedium, color.Cyan)
}

for _, policyBreach := range outputPolicies[settings.LevelLow] {
writePolicyBreachToOutput(outputStr, policyBreach, settings.LevelLow, color.Blue)
}

output.Msg(outputStr.String())

return nil
}

func ReportJSON(report types.Report, output *zerolog.Event, config settings.Config) error {
outputDetections, err := getReportOutput(report, config)
if err != nil {
Expand Down Expand Up @@ -63,17 +95,7 @@ func getReportOutput(report types.Report, config settings.Config) (any, error) {
return dataflow.GetOutput(detections, config, false)

} else if config.Report.Report == flag.ReportPolicies {
detections, err := detectors.GetOutput(report)
if err != nil {
return nil, err
}

dataflow, err := dataflow.GetOutput(detections, config, true)
if err != nil {
return nil, err
}

return policies.GetOutput(dataflow, config)
return getPolicyReportOutput(report, config)
} else if config.Report.Report == flag.ReportStats {
lineOfCodeOutput, err := stats.GoclocDetectorOutput(config.Scan.Target)
if err != nil {
Expand All @@ -95,3 +117,29 @@ func getReportOutput(report types.Report, config settings.Config) (any, error) {

return nil, ErrUndefinedFormat
}

func getPolicyReportOutput(report types.Report, config settings.Config) (map[string][]policies.PolicyResult, error) {
detections, err := detectors.GetOutput(report)
if err != nil {
return nil, err
}

dataflow, err := dataflow.GetOutput(detections, config, true)
if err != nil {
return nil, err
}

return policies.GetOutput(dataflow, config)
}

func writePolicyBreachToOutput(outputStr *strings.Builder, policyBreach policies.PolicyResult, policySeverity string, displayColor string) {
outputStr.WriteString("\n")
outputStr.WriteString("\n")
outputStr.WriteString(color.With(displayColor, strings.ToUpper(policySeverity)) + ": ")
outputStr.WriteString(policyBreach.PolicyName + " policy breach with " + policyBreach.CategoryGroup + "\n")
outputStr.WriteString(policyBreach.PolicyDescription + "\n")
outputStr.WriteString("Filename: " + policyBreach.Filename)
outputStr.WriteString("\n")
outputStr.WriteString("\n")
outputStr.WriteString("===============================")
}
18 changes: 9 additions & 9 deletions pkg/report/output/policies/policies.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@ type PolicyInput struct {
}

type PolicyOutput struct {
LineNumber string `json:"line_number,omitempty"`
Filename string `json:"filename,omitempty"`
Category string `json:"category,omitempty"`
LineNumber string `json:"line_number,omitempty" yaml:"line_number,omitempty"`
Filename string `json:"filename,omitempty" yaml:"filename,omitempty"`
CategoryGroup string `json:"category_group,omitempty" yaml:"category_group,omitempty"`
}

type PolicyResult struct {
PolicyName string `json:"policy_name"`
PolicyDescription string `json:"policy_description"`
LineNumber string `json:"line_number,omitempty"`
Filename string `json:"filename,omitempty"`
Category string `json:"category,omitempty"`
PolicyName string `json:"policy_name" yaml:"policy_name"`
PolicyDescription string `json:"policy_description" yaml:"policy_description"`
LineNumber string `json:"line_number,omitempty" yaml:"line_number,omitempty"`
Filename string `json:"filename,omitempty" yaml:"filename,omitempty"`
CategoryGroup string `json:"category_group,omitempty" yaml:"category_group,omitempty"`
}

func GetOutput(dataflow *dataflow.DataFlow, config settings.Config) (map[string][]PolicyResult, error) {
Expand Down Expand Up @@ -89,7 +89,7 @@ func GetOutput(dataflow *dataflow.DataFlow, config settings.Config) (map[string]
PolicyName: policy.Name,
PolicyDescription: policy.Description,
Filename: policyOutput.Filename,
Category: policyOutput.Category,
CategoryGroup: policyOutput.CategoryGroup,
}

result[severity] = append(result[severity], policyResult)
Expand Down

0 comments on commit 10e2312

Please sign in to comment.