Skip to content

Commit

Permalink
chore: make engine pluggable
Browse files Browse the repository at this point in the history
  • Loading branch information
didroe committed May 29, 2024
1 parent 9947948 commit ea77713
Show file tree
Hide file tree
Showing 48 changed files with 1,299 additions and 1,068 deletions.
2 changes: 1 addition & 1 deletion .envrc.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export GOOGLE_APP=''
export REDIS_INIT="true"
export GOOGLE_MAX_ATTEMPT="5"
export BEARER_EXECUTABLE_PATH="./bearer"
export GITHUB_WORKSPACE="/path/to/bearer/project"
export GITHUB_WORKSPACE="$PWD"
export SCAN_DIR=/Users/username/OWASP
export BEARER_DISABLE_VERSION_CHECK=true
export BEARER_DISABLE_DEFAULT_RULES=true
Expand Down
10 changes: 2 additions & 8 deletions cmd/bearer/bearer.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
package main

import (
"os"

"github.com/bearer/bearer/cmd/bearer/build"
"github.com/bearer/bearer/internal/commands"
"github.com/bearer/bearer/external/run"
)

func main() {
app := commands.NewApp(build.Version, build.CommitSHA)
if err := app.Execute(); err != nil {
// error messages are printed by the framework
os.Exit(1)
}
run.Run(build.Version, build.CommitSHA, run.NewEngine(run.DefaultLanguages()))
}
32 changes: 32 additions & 0 deletions external/run/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package run

import (
"os"

"github.com/bearer/bearer/internal/commands"
"github.com/bearer/bearer/internal/engine"
engineimpl "github.com/bearer/bearer/internal/engine/implementation"
"github.com/bearer/bearer/internal/languages"
"github.com/bearer/bearer/internal/scanner/language"
)

type Language = language.Language
type Engine = engine.Engine

func NewEngine(languages []Language) Engine {
return engineimpl.New(languages)
}

func DefaultLanguages() []Language {
return languages.Default()
}

func Run(version, commitSHA string, engine Engine) {
err := commands.NewApp(version, commitSHA, engine).Execute()
engine.Close()

if err != nil {
// error messages are printed by the framework
os.Exit(1)
}
}
5 changes: 3 additions & 2 deletions internal/commands/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ import (
"github.com/spf13/cobra"

"github.com/bearer/bearer/cmd/bearer/build"
"github.com/bearer/bearer/internal/engine"
)

// NewApp is the factory method to return CLI
func NewApp(version string, commitSHA string) *cobra.Command {
func NewApp(version string, commitSHA string, engine engine.Engine) *cobra.Command {
rootCmd := NewRootCommand()
rootCmd.AddCommand(
NewCompletionCommand(),
NewProcessingWorkerCommand(),
NewInitCommand(),
NewScanCommand(),
NewScanCommand(engine),
NewIgnoreCommand(),
NewVersionCommand(version, commitSHA),
)
Expand Down
60 changes: 24 additions & 36 deletions internal/commands/artifact/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import (
"github.com/bearer/bearer/internal/commands/process/filelist"
"github.com/bearer/bearer/internal/commands/process/filelist/files"
"github.com/bearer/bearer/internal/commands/process/gitrepository"
"github.com/bearer/bearer/internal/commands/process/orchestrator"
"github.com/bearer/bearer/internal/commands/process/orchestrator/work"
"github.com/bearer/bearer/internal/commands/process/settings"
settingsloader "github.com/bearer/bearer/internal/commands/process/settings/loader"
"github.com/bearer/bearer/internal/engine"
"github.com/bearer/bearer/internal/flag"
flagtypes "github.com/bearer/bearer/internal/flag/types"
"github.com/bearer/bearer/internal/report/basebranchfindings"
Expand Down Expand Up @@ -71,6 +71,7 @@ type runner struct {
scanSettings settings.Config
stats *scannerstats.Stats
gitContext *gitrepository.Context
engine engine.Engine
}

// NewRunner initializes Runner that provides scanning functionalities.
Expand All @@ -81,13 +82,15 @@ func NewRunner(
targetPath string,
goclocResult *gocloc.Result,
stats *scannerstats.Stats,
engine engine.Engine,
) (Runner, error) {
r := &runner{
scanSettings: scanSettings,
targetPath: targetPath,
goclocResult: goclocResult,
stats: stats,
gitContext: gitContext,
engine: engine,
}

scanID, err := scanid.Build(scanSettings, gitContext)
Expand Down Expand Up @@ -160,24 +163,13 @@ func (r *runner) Scan(ctx context.Context, opts flagtypes.Options) ([]files.File
return nil, nil, err
}

orchestrator, err := orchestrator.New(
work.Repository{Dir: r.targetPath},
r.scanSettings,
r.stats,
len(fileList.Files),
)
if err != nil {
return nil, nil, err
}
defer orchestrator.Close()

var baseBranchFindings *basebranchfindings.Findings
if err := repository.WithBaseBranch(func() error {
if !opts.Quiet {
outputhandler.StdErrLog(fmt.Sprintf("\nScanning base branch %s", r.gitContext.BaseBranch))
}

baseBranchFindings, err = r.scanBaseBranch(orchestrator, fileList)
baseBranchFindings, err = r.scanBaseBranch(fileList)
if err != nil {
return err
}
Expand All @@ -191,24 +183,21 @@ func (r *runner) Scan(ctx context.Context, opts flagtypes.Options) ([]files.File
return nil, nil, err
}

if err := orchestrator.Scan(r.reportPath, fileList.Files); err != nil {
if err := r.engine.Scan(r.stats, r.reportPath, r.targetPath, fileList.Files); err != nil {
return nil, nil, err
}

return fileList.Files, baseBranchFindings, nil
}

func (r *runner) scanBaseBranch(
orchestrator *orchestrator.Orchestrator,
fileList *files.List,
) (*basebranchfindings.Findings, error) {
func (r *runner) scanBaseBranch(fileList *files.List) (*basebranchfindings.Findings, error) {
result := basebranchfindings.New(fileList)

if len(fileList.BaseFiles) == 0 {
return result, nil
}

if err := orchestrator.Scan(r.reportPath+".base", fileList.BaseFiles); err != nil {
if err := r.engine.Scan(r.stats, r.reportPath+".base", r.targetPath, fileList.BaseFiles); err != nil {
return nil, err
}

Expand Down Expand Up @@ -263,7 +252,7 @@ func getIgnoredFingerprints(client *api.API, settings settings.Config, gitContex
}

// Run performs artifact scanning
func Run(ctx context.Context, opts flagtypes.Options) (err error) {
func Run(ctx context.Context, opts flagtypes.Options, engine engine.Engine) (err error) {
targetPath, err := file.CanonicalPath(opts.Target)
if err != nil {
return fmt.Errorf("failed to get absolute target: %w", err)
Expand Down Expand Up @@ -302,7 +291,7 @@ func Run(ctx context.Context, opts flagtypes.Options) (err error) {
outputhandler.StdErrLog("Loading rules")
}

scanSettings, err := settings.FromOptions(opts, versionMeta)
scanSettings, err := settingsloader.FromOptions(opts, versionMeta, engine)
scanSettings.Target = opts.Target
if err != nil {
return err
Expand All @@ -317,6 +306,10 @@ func Run(ctx context.Context, opts flagtypes.Options) (err error) {
return err
}

if err := engine.Initialize(&scanSettings); err != nil {
return fmt.Errorf("failed to initialize engine: %w", err)
}

ctx, cancel := context.WithTimeout(ctx, scanSettings.Worker.Timeout)
defer cancel()

Expand All @@ -331,7 +324,7 @@ func Run(ctx context.Context, opts flagtypes.Options) (err error) {
stats = scannerstats.New()
}

r, err := NewRunner(ctx, scanSettings, gitContext, targetPath, inputgocloc, stats)
r, err := NewRunner(ctx, scanSettings, gitContext, targetPath, inputgocloc, stats, engine)
if err != nil {
return err
}
Expand Down Expand Up @@ -407,11 +400,7 @@ func (r *runner) Report(

endTime := time.Now()

reportSupported, err := anySupportedLanguagesPresent(report.Inputgocloc, r.scanSettings)
if err != nil {
return false, err
}

reportSupported := anySupportedLanguagesPresent(r.engine, report.Inputgocloc, r.scanSettings)
if !reportSupported && r.scanSettings.Report.Report != flag.ReportPrivacy && !r.scanSettings.Scan.Quiet {
var placeholderStr *strings.Builder
placeholderStr, err = getPlaceholderOutput(reportData, report, r.scanSettings, report.Inputgocloc)
Expand All @@ -426,6 +415,7 @@ func (r *runner) Report(
formatStr, err := reportoutput.FormatOutput(
reportData,
r.scanSettings,
r.engine,
report.Inputgocloc,
startTime,
endTime,
Expand Down Expand Up @@ -463,9 +453,9 @@ func (r *runner) ReportPath() string {
return r.reportPath
}

func anySupportedLanguagesPresent(inputgocloc *gocloc.Result, config settings.Config) (bool, error) {
func anySupportedLanguagesPresent(engine engine.Engine, inputgocloc *gocloc.Result, config settings.Config) bool {
if inputgocloc == nil {
return true, nil
return true
}

ruleLanguages := make(map[string]bool)
Expand All @@ -480,16 +470,14 @@ func anySupportedLanguagesPresent(inputgocloc *gocloc.Result, config settings.Co
foundLanguages[strings.ToLower(language.Name)] = true
}

for _, supportedLanguage := range maps.Keys(settings.GetSupportedRuleLanguages()) {
_, supportedLangPresent := foundLanguages[supportedLanguage]

if supportedLangPresent && settings.GetSupportedRuleLanguages()[supportedLanguage] {
return true, nil
for _, supportedLanguage := range engine.GetLanguages() {
if _, supportedLangPresent := foundLanguages[supportedLanguage.ID()]; supportedLangPresent {
return true
}
}

log.Debug().Msg("No language found for which rules are applicable")
return false, nil
return false
}

func getPlaceholderOutput(reportData *outputtypes.ReportData, report types.Report, config settings.Config, inputgocloc *gocloc.Result) (outputStr *strings.Builder, err error) {
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func NewInitCommand() *cobra.Command {
Use: "init",
Short: "Generates a default config to `bearer.yml`",
RunE: func(cmd *cobra.Command, args []string) error {
if err := ScanFlags.BindForConfigInit(NewScanCommand()); err != nil {
if err := ScanFlags.BindForConfigInit(NewScanCommand(nil)); err != nil {
return fmt.Errorf("flag bind error: %w", err)
}

Expand Down
6 changes: 3 additions & 3 deletions internal/commands/process/orchestrator/orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (

type Orchestrator struct {
repository work.Repository
config settings.Config
config *settings.Config
maxWorkersSemaphore chan struct{}
done chan struct{}
pool *pool.Pool
Expand All @@ -33,7 +33,7 @@ type Orchestrator struct {

func New(
repository work.Repository,
config settings.Config,
config *settings.Config,
stats *stats.Stats,
estimatedFileCount int,
) (*Orchestrator, error) {
Expand Down Expand Up @@ -202,7 +202,7 @@ func (orchestrator *Orchestrator) writeFileError(reportFile *os.File, file files
orchestrator.reportMutex.Unlock()
}

func getParallel(fileCount int, config settings.Config) int {
func getParallel(fileCount int, config *settings.Config) int {
if config.Scan.Parallel != 0 {
return config.Scan.Parallel
}
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/process/orchestrator/pool/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Pool struct {
available []*Process
}

func New(config settings.Config, stats *stats.Stats) *Pool {
func New(config *settings.Config, stats *stats.Stats) *Pool {
executable, err := os.Executable()
if err != nil {
output.Fatal(fmt.Sprintf("failed to get current command executable %s", err))
Expand Down
6 changes: 3 additions & 3 deletions internal/commands/process/orchestrator/pool/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ type Process struct {
type ProcessOptions struct {
executable string
baseArguments []string
config settings.Config
config *settings.Config
}

func newProcess(options *ProcessOptions, id string) (*Process, error) {
Expand Down Expand Up @@ -88,7 +88,7 @@ func newProcess(options *ProcessOptions, id string) (*Process, error) {
return process, nil
}

func (process *Process) start(config settings.Config) error {
func (process *Process) start(config *settings.Config) error {
if err := process.command.Start(); err != nil {
close(process.exitChannel)
return err
Expand Down Expand Up @@ -201,7 +201,7 @@ func (process *Process) reduceMemoryUsage() {
}
}

func (process *Process) initialize(config settings.Config) error {
func (process *Process) initialize(config *settings.Config) error {
log.Debug().Msgf("%s initializing", process.id)
start := time.Now()
killTime := time.Now().Add(config.Worker.TimeoutWorkerOnline)
Expand Down
Loading

0 comments on commit ea77713

Please sign in to comment.