From 5a9b8c976a0064e9c194dc3e68a4419b0ec1cfa7 Mon Sep 17 00:00:00 2001 From: Erez Fishhimer Date: Mon, 12 Dec 2022 09:44:58 +0200 Subject: [PATCH] add gitleaks --- .families.yaml | 14 ++++---- Makefile | 1 + cli/cmd/root.go | 2 +- shared/pkg/families/manager.go | 4 +-- shared/pkg/families/sbom/family.go | 4 +-- shared/pkg/families/secrets/config.go | 13 ++++++-- shared/pkg/families/secrets/family.go | 46 +++++++++++++++++++++++++-- shared/pkg/families/secrets/result.go | 37 +++++++++++++++++++++ 8 files changed, 104 insertions(+), 17 deletions(-) diff --git a/.families.yaml b/.families.yaml index eb53025520..0823d6a6c6 100644 --- a/.families.yaml +++ b/.families.yaml @@ -1,5 +1,5 @@ sbom: - enabled: true + enabled: false analyzers_list: - "syft" - "gomod" @@ -26,7 +26,7 @@ sbom: token: "token" vulnerabilities: - enabled: true + enabled: false scanners_list: - "grype" inputs: @@ -63,9 +63,9 @@ secrets: inputs: - input: "/dir" input_type: "dir" - - input: "/rootfs" - input_type: "rootfs" +# - input: "/rootfs" +# input_type: "rootfs" gitleaks_config: - foo: "bar" - - + binary_path: "/usr/local/bin/gitleaks" + source: "/Users/erezf/go/src/wwwin-github.cisco.com/eti/agent" + report_path: "/tmp/report.json" diff --git a/Makefile b/Makefile index 744f229171..edc5ffbe00 100644 --- a/Makefile +++ b/Makefile @@ -128,6 +128,7 @@ check: lint test ## Run tests and linters gomod-tidy: cd backend && go mod tidy cd runtime_scan && go mod tidy + cd shared && go mod tidy .PHONY: api api: ## Generating API code diff --git a/cli/cmd/root.go b/cli/cmd/root.go index bdd12228fe..19a49c6277 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -98,7 +98,7 @@ func init() { // Here you will define your flags and configuration settings. // Cobra supports persistent flags, which, if defined here, // will be global for your application. - rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.vmclarity.yaml)") + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.vmclarity/config.yaml)") rootCmd.PersistentFlags().StringVar(&output, "output", "", "set file path output (default: stdout)") } diff --git a/shared/pkg/families/manager.go b/shared/pkg/families/manager.go index ad002298ff..b83ef9ac61 100644 --- a/shared/pkg/families/manager.go +++ b/shared/pkg/families/manager.go @@ -75,8 +75,8 @@ func New(logger *log.Entry, config *Config) *Manager { func (m *Manager) Run() (*results.Results, error) { familiesResults := results.New() - for _, analyzer := range m.families { - ret, err := analyzer.Run(familiesResults) + for _, family := range m.families { + ret, err := family.Run(familiesResults) if err != nil { return nil, err } diff --git a/shared/pkg/families/sbom/family.go b/shared/pkg/families/sbom/family.go index f902436e84..c556b4a468 100644 --- a/shared/pkg/families/sbom/family.go +++ b/shared/pkg/families/sbom/family.go @@ -27,7 +27,7 @@ import ( log "github.com/sirupsen/logrus" _interface "github.com/openclarity/vmclarity/shared/pkg/families/interface" - "github.com/openclarity/vmclarity/shared/pkg/families/results" + _results "github.com/openclarity/vmclarity/shared/pkg/families/results" ) type SBOM struct { @@ -35,7 +35,7 @@ type SBOM struct { conf Config } -func (s SBOM) Run(res *results.Results) (_interface.IsResults, error) { +func (s SBOM) Run(res *_results.Results) (_interface.IsResults, error) { s.logger.Info("SBOM Run...") if len(s.conf.Inputs) == 0 { diff --git a/shared/pkg/families/secrets/config.go b/shared/pkg/families/secrets/config.go index a79acbfa3e..304f63e790 100644 --- a/shared/pkg/families/secrets/config.go +++ b/shared/pkg/families/secrets/config.go @@ -16,9 +16,16 @@ package secrets type Config struct { - Enabled bool `yaml:"enabled" mapstructure:"enabled"` - ScannersList []string `yaml:"scanners_list" mapstructure:"scanners_list"` - Inputs []Inputs `yaml:"inputs" mapstructure:"inputs"` + Enabled bool `yaml:"enabled" mapstructure:"enabled"` + ScannersList []string `yaml:"scanners_list" mapstructure:"scanners_list"` + Inputs []Inputs `yaml:"inputs" mapstructure:"inputs"` + GitleaksConfig *GitleaksConfig `yaml:"gitleaks_config" mapstructure:"gitleaks_config"` +} + +type GitleaksConfig struct { + BinaryPath string `yaml:"binary_path" mapstructure:"binary_path"` + Source string `yaml:"source" mapstructure:"source"` + ReportPath string `yaml:"report_path" mapstructure:"report_path"` } type Inputs struct { diff --git a/shared/pkg/families/secrets/family.go b/shared/pkg/families/secrets/family.go index 132c19e05f..49be17d129 100644 --- a/shared/pkg/families/secrets/family.go +++ b/shared/pkg/families/secrets/family.go @@ -16,6 +16,13 @@ package secrets import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "os" + "os/exec" + log "github.com/sirupsen/logrus" _interface "github.com/openclarity/vmclarity/shared/pkg/families/interface" @@ -28,10 +35,45 @@ type Secrets struct { } func (s Secrets) Run(res *results.Results) (_interface.IsResults, error) { - //TODO implement me s.logger.Info("Secrets Run...") + + // validate that gitleaks binary exists + if _, err := os.Stat(s.conf.GitleaksConfig.BinaryPath); err != nil { + return nil, fmt.Errorf("failed to find binary in %v: %v", s.conf.GitleaksConfig.BinaryPath, err) + } + + // ./gitleaks detect -v --source= --no-git -r -f json --exit-code 0 + cmd := exec.Command(s.conf.GitleaksConfig.BinaryPath, "detect", fmt.Sprintf("--source=%v", s.conf.GitleaksConfig.Source), "--no-git", "-r", s.conf.GitleaksConfig.ReportPath, "-f", "json", "--exit-code", "0") + _, err := runCommand(cmd) + if err != nil { + return nil, fmt.Errorf("failed to run gitleaks command: %v", err) + } + out, err := os.ReadFile(s.conf.GitleaksConfig.ReportPath) + if err != nil { + return nil, fmt.Errorf("failed to read report file from path: %v. %v", s.conf.GitleaksConfig.ReportPath, err) + } + + log.Infof("gitleaks results: %s", out) + + var retResults Results + if err := json.Unmarshal(out, &retResults.Findings); err != nil { + return nil, err + } + s.logger.Info("Secrets Done...") - return &Results{}, nil + return &retResults, nil +} + +func runCommand(cmd *exec.Cmd) ([]byte, error) { + //cmd := exec.Command(name, arg) + var outb, errb bytes.Buffer + cmd.Stdout = &outb + cmd.Stderr = &errb + if err := cmd.Run(); err != nil { + err = errors.New(fmt.Sprintf("%v. %v", err, errb.String())) + return nil, fmt.Errorf("failed to run command: %v. %v", cmd.String(), err) + } + return outb.Bytes(), nil } // ensure types implement the requisite interfaces diff --git a/shared/pkg/families/secrets/result.go b/shared/pkg/families/secrets/result.go index 7872733de3..1022911a4b 100644 --- a/shared/pkg/families/secrets/result.go +++ b/shared/pkg/families/secrets/result.go @@ -16,6 +16,43 @@ package secrets type Results struct { + Findings []Findings +} + +type Findings struct { + Description string + StartLine int + EndLine int + StartColumn int + EndColumn int + + Line string `json:"-"` + + Match string + + // Secret contains the full content of what is matched in + // the tree-sitter query. + Secret string + + // File is the name of the file containing the finding + File string + SymlinkFile string + Commit string + + // Entropy is the shannon entropy of Value + Entropy float32 + + Author string + Email string + Date string + Message string + Tags []string + + // Rule is the name of the rule that was matched + RuleID string + + // unique identifer + Fingerprint string } func (*Results) IsResults() {}