Skip to content

Commit

Permalink
feat: better handle rule loading and infomation
Browse files Browse the repository at this point in the history
  • Loading branch information
gotbadger committed Jun 28, 2023
1 parent c8c9457 commit 5c83e96
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 8 deletions.
21 changes: 21 additions & 0 deletions pkg/commands/process/settings/ruleLoader.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"

"gopkg.in/yaml.v3"
)
Expand All @@ -24,6 +26,21 @@ func LoadRuleDefinitionsFromGitHub(ruleDefinitions map[string]RuleDefinition, fo
return tagName, err
}
defer resp.Body.Close()
headers := resp.Header

if headers.Get("x-ratelimit-remaining") == "0" {
resetString := headers.Get("x-ratelimit-reset")
unixTime, err := strconv.ParseInt(resetString, 10, 64)
if err != nil {
return tagName, fmt.Errorf("rules download is rate limited please wait until: %s", resetString)
}
tm := time.Unix(unixTime, 0)
return tagName, fmt.Errorf("rules download is rate limited please wait until: %s", tm.Format("2006-01-02 15:04:05"))
}

if resp.StatusCode != 200 {
return tagName, errors.New("rules download returned non 200 status code - could not download rules")
}

// Decode the response JSON to get the URL of the asset we want to download
type Asset struct {
Expand All @@ -40,6 +57,10 @@ func LoadRuleDefinitionsFromGitHub(ruleDefinitions map[string]RuleDefinition, fo
return tagName, err
}

if release.TagName == "" {
return tagName, errors.New("could not find valid release for rules")
}

bearerRulesDir := bearerRulesDir()
if _, err := os.Stat(bearerRulesDir); errors.Is(err, os.ErrNotExist) {
err := os.Mkdir(bearerRulesDir, os.ModePerm)
Expand Down
4 changes: 3 additions & 1 deletion pkg/commands/process/settings/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/bearer/bearer/pkg/flag"
"github.com/bearer/bearer/pkg/report/customdetectors"
"github.com/bearer/bearer/pkg/util/output"
"github.com/bearer/bearer/pkg/util/set"
"github.com/rs/zerolog/log"
"gopkg.in/yaml.v3"
Expand Down Expand Up @@ -99,7 +100,8 @@ func loadRules(

tagVersion, err := LoadRuleDefinitionsFromGitHub(definitions, foundLanguages)
if err != nil {
return result, fmt.Errorf("error loading rules: %s", err)
output.Fatal(fmt.Sprintf("Error loading rules: %s", err))
// sysexit
}

result.BearerRulesVersion = tagVersion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Summary Report
=====================================

Rules:
- 2 default rules applied (https://docs.bearer.com/reference/rules)
- 2 default rules applied (https://docs.bearer.com/reference/rules) [TEST]
- 1 custom rules applied

CRITICAL: Sensitive data sent to Rails loggers detected. [CWE-209, CWE-532]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@


Summary Report

=====================================

Zero rules found. A security report requires rules to function. Please check configuration.

21 changes: 15 additions & 6 deletions pkg/report/output/security/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ func BuildReportString(config settings.Config, results *Results, lineOfCodeOutpu
config,
)

if rulesAvailableCount == 0 {
return reportStr, false
}

failures := map[string]map[string]bool{
types.LevelCritical: make(map[string]bool),
types.LevelHigh: make(map[string]bool),
Expand Down Expand Up @@ -385,20 +389,25 @@ func writeRuleListToString(
languages map[string]*gocloc.Language,
config settings.Config,
) int {
// list rules that were run
reportStr.WriteString("\n\nRules: \n")

defaultRuleCount, customRuleCount := countRules(rules, languages, config, false)
builtInCount, _ := countRules(builtInRules, languages, config, true)
defaultRuleCount = defaultRuleCount + builtInCount
totalRuleCount := defaultRuleCount + customRuleCount

reportStr.WriteString(fmt.Sprintf(" - %d default rules applied ", defaultRuleCount))
reportStr.WriteString(color.HiBlackString("(https://docs.bearer.com/reference/rules)\n"))
if totalRuleCount == 0 {
reportStr.WriteString("\n\nZero rules found. A security report requires rules to function. Please check configuration.\n")
return 0
}
reportStr.WriteString("\n\nRules: \n")
if defaultRuleCount > 0 {
reportStr.WriteString(fmt.Sprintf(" - %d default rules applied ", defaultRuleCount))
reportStr.WriteString(color.HiBlackString(fmt.Sprintf("(https://docs.bearer.com/reference/rules) [%s]\n", config.BearerRulesVersion)))
}
if customRuleCount > 0 {
reportStr.WriteString(fmt.Sprintf(" - %d custom rules applied", customRuleCount))
}

return defaultRuleCount + customRuleCount
return totalRuleCount
}

func writeApiClientResultToString(
Expand Down
42 changes: 42 additions & 0 deletions pkg/report/output/security/security_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ func TestBuildReportString(t *testing.T) {
"warning": true,
},
})
// set rule version
config.BearerRulesVersion = "TEST"

// new rules are added
customRule := &settings.Rule{
Expand Down Expand Up @@ -68,6 +70,46 @@ func TestBuildReportString(t *testing.T) {
cupaloy.SnapshotT(t, stringBuilder.String())
}

func TestNoRulesBuildReportString(t *testing.T) {
config, err := generateConfig(flag.ReportOptions{
Report: "security",
Severity: map[string]bool{
"critical": true,
"high": true,
"medium": true,
"low": true,
"warning": true,
},
})
// set rule version
config.BearerRulesVersion = "TEST"
config.Rules = map[string]*settings.Rule{}

if err != nil {
t.Fatalf("failed to generate config:%s", err)
}

dataflow := dummyDataflow()

results, err := security.GetOutput(&dataflow, config)
if err != nil {
t.Fatalf("failed to generate security output err:%s", err)
}

dummyGoclocLanguage := gocloc.Language{}
dummyGoclocResult := gocloc.Result{
Total: &dummyGoclocLanguage,
Files: map[string]*gocloc.ClocFile{},
Languages: map[string]*gocloc.Language{
"Ruby": {},
},
MaxPathLength: 0,
}

stringBuilder, _ := security.BuildReportString(config, results, &dummyGoclocResult, &dataflow)
cupaloy.SnapshotT(t, stringBuilder.String())
}

func TestGetOutput(t *testing.T) {
config, err := generateConfig(flag.ReportOptions{
Report: "security",
Expand Down

0 comments on commit 5c83e96

Please sign in to comment.