Skip to content

Commit

Permalink
clean: Refactor tool command [TAROT-2333]
Browse files Browse the repository at this point in the history
  • Loading branch information
afsmeira authored Oct 9, 2023
1 parent df87acc commit df5089a
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 88 deletions.
5 changes: 5 additions & 0 deletions cmd/tool/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// The `codacy-trivy` application, or tool, executes a Trivy analysis on the provided source code files.
//
// The analysis returns a set of results to `stdout` (according to Codacy tools specifications),
// which correspond to violations of `codacy-trivy` rules.
package main
23 changes: 23 additions & 0 deletions cmd/tool/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package main

import "fmt"

const packageName string = "codacy-trivy/tool"

// ToolError is the error returned when failing to run the tool.
type ToolError struct {
// msg is the error message explaining what operation failed.
msg string
// w is the underlying error.
w error
}

func (e ToolError) Error() string {
if e.w == nil {
return fmt.Sprintf("%s: %s", packageName, e.msg)
}
return fmt.Sprintf("%s: %s\n%s", packageName, e.msg, e.w.Error())
}
func (e ToolError) Unwrap() error {
return e.w
}
90 changes: 2 additions & 88 deletions cmd/tool/main.go
Original file line number Diff line number Diff line change
@@ -1,96 +1,10 @@
package main

import (
"bytes"
"errors"
"fmt"
"os"
"path"

"github.com/aquasecurity/trivy/pkg/fanal/secret"
codacy "github.com/codacy/codacy-engine-golang-seed/v5"
"github.com/samber/lo"
)

const (
sourceConfigFileName = "trivy.yaml"
secretRuleID = "secret"
)

func readConfiguration(tool codacy.Tool, sourceFolder string) ([]codacy.Pattern, error) {
// if no patterns, try to use configuration from source code
// otherwise default configuration file
if len(tool.Patterns) == 0 {
sourceConfigFileContent, err := configurationFromSourceCode(sourceFolder)
if err != nil {
return nil, err
}
return sourceConfigFileContent, nil
}

return tool.Patterns, nil
}

func configurationFromSourceCode(sourceFolder string) ([]codacy.Pattern, error) {
path.Join(sourceFolder, sourceConfigFileName)
// TODO: Avoid parsing the configuration file and pass it to the tool if it exists
return nil, nil
}

func runTrivy(patterns []codacy.Pattern, files []string, sourceDir string) ([]codacy.Issue, error) {
var secretDetectionEnabled = lo.SomeBy(patterns, func(p codacy.Pattern) bool {
return p.PatternID == secretRuleID
})
if !secretDetectionEnabled {
return []codacy.Issue{}, nil
}

scanner := secret.NewScanner(&secret.Config{})

var results []codacy.Issue

for _, f := range files {
content, err := os.ReadFile(path.Join(sourceDir, f))
if err != nil {
return nil, errors.New("Error reading file: " + err.Error())
}
content = bytes.ReplaceAll(content, []byte("\r"), []byte(""))
secrets := scanner.Scan(secret.ScanArgs{
FilePath: f,
Content: content,
})
for _, result := range secrets.Findings {
results = append(results, codacy.Issue{
File: f,
Message: fmt.Sprintf("Possible hardcoded secret: %s", result.Title),
PatternID: secretRuleID,
Line: result.StartLine,
})
}
}

return results, nil
}

type TrivyImplementation struct {
}

func (i TrivyImplementation) Run(tool codacy.Tool, sourceDir string) ([]codacy.Issue, error) {
patterns, err := readConfiguration(tool, sourceDir)
if err != nil {
return nil, errors.New("Error reading configuration: " + err.Error())
}

results, err := runTrivy(patterns, tool.Files, sourceDir)
if err != nil {
return nil, errors.New("Error running Trivy: " + err.Error())
}

return results, nil
}

func main() {
implementation := TrivyImplementation{}

codacy.StartTool(implementation)
codacyTrivy := &CodacyTrivy{}
codacy.StartTool(codacyTrivy)
}
63 changes: 63 additions & 0 deletions cmd/tool/tool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package main

import (
"bytes"
"fmt"
"os"
"path"

"github.com/aquasecurity/trivy/pkg/fanal/secret"
codacy "github.com/codacy/codacy-engine-golang-seed/v5"
"github.com/samber/lo"
)

const secretRuleID string = "secret"

type CodacyTrivy struct{}

// https://github.com/uber-go/guide/blob/master/style.md#verify-interface-compliance
var _ codacy.ToolImplementation = (*CodacyTrivy)(nil)

func (t CodacyTrivy) Run(tool codacy.Tool, sourceDir string) ([]codacy.Issue, error) {
if len(tool.Patterns) == 0 {
// TODO Use configuration from source code or default configuration file.
return []codacy.Issue{}, nil
}

return run(tool.Patterns, tool.Files, sourceDir)
}

func run(patterns []codacy.Pattern, files []string, sourceDir string) ([]codacy.Issue, error) {
var secretDetectionEnabled = lo.SomeBy(patterns, func(p codacy.Pattern) bool {
return p.PatternID == secretRuleID
})
if !secretDetectionEnabled {
return []codacy.Issue{}, nil
}

scanner := secret.NewScanner(&secret.Config{})

results := []codacy.Issue{}

for _, f := range files {
content, err := os.ReadFile(path.Join(sourceDir, f))
if err != nil {
return nil, ToolError{msg: fmt.Sprintf("Failed to read source file %s", f), w: err}
}
content = bytes.ReplaceAll(content, []byte("\r"), []byte(""))

secrets := scanner.Scan(secret.ScanArgs{FilePath: f, Content: content})
for _, result := range secrets.Findings {
results = append(
results,
codacy.Issue{
File: f,
Message: fmt.Sprintf("Possible hardcoded secret: %s", result.Title),
PatternID: secretRuleID,
Line: result.StartLine,
},
)
}
}
return results, nil
}

0 comments on commit df5089a

Please sign in to comment.