github.com/seilagamo/poc-lava-release@v0.3.3-rc3/cmd/lava/internal/scan/scan.go (about) 1 // Copyright 2023 Adevinta 2 3 // Package scan implements the scan command. 4 package scan 5 6 import ( 7 "errors" 8 "fmt" 9 "os" 10 "time" 11 12 "github.com/fatih/color" 13 14 "github.com/seilagamo/poc-lava-release/cmd/lava/internal/base" 15 "github.com/seilagamo/poc-lava-release/internal/config" 16 "github.com/seilagamo/poc-lava-release/internal/engine" 17 "github.com/seilagamo/poc-lava-release/internal/metrics" 18 "github.com/seilagamo/poc-lava-release/internal/report" 19 ) 20 21 // CmdScan represents the scan command. 22 var CmdScan = &base.Command{ 23 UsageLine: "scan [flags]", 24 Short: "run scan", 25 Long: ` 26 Run a scan using the provided config file. 27 28 The -c flag allows to specify a configuration file. By default, "lava 29 scan" looks for a configuration file with the name "lava.yaml" in the 30 current directory. 31 32 The -forcecolor flag forces colorized output. By default, colorized 33 output is disabled in the following cases: 34 35 - Lava is not executed from a terminal. 36 - Lava is executed from a "dumb" terminal. 37 - The NO_COLOR environment variable is set (regardless of its value). 38 39 The exit code of the command depends on the highest severity among all 40 the vulnerabilities that have been found. 41 42 - 104: Critical severity vulnerabilities found 43 - 103: High severity vulnerabilities found 44 - 102: Medium severity vulnerabilities found 45 - 101: Low severity vulnerabilities found 46 - 100: Informational vulnerabilities found 47 - 2: Syntax error 48 - 1: Command error 49 - 0: No vulnerabilities found 50 51 Those vulnerabilities that has been excluded in the configuration are 52 not considered in the computation of the exit code. In other words, 53 vulnerabilities with a severity that is lower than "report.severity" 54 and vulnerabilities that match any "report.exclusions" rules are 55 ignored. 56 `, 57 } 58 59 var ( 60 cfgfile = CmdScan.Flag.String("c", "lava.yaml", "config file") 61 forceColor = CmdScan.Flag.Bool("forcecolor", false, "force colorized output") 62 ) 63 64 func init() { 65 CmdScan.Run = run // Break initialization cycle. 66 } 67 68 // osExit is used by tests to capture the exit code. 69 var osExit = os.Exit 70 71 // run is the entry point of the scan command. 72 func run(args []string) error { 73 if len(args) > 0 { 74 return errors.New("too many arguments") 75 } 76 77 if *forceColor { 78 color.NoColor = false 79 } 80 81 startTime := time.Now() 82 metrics.Collect("start_time", startTime) 83 84 cfg, err := config.ParseFile(*cfgfile) 85 if err != nil { 86 return fmt.Errorf("parse config file: %w", err) 87 } 88 89 metrics.Collect("config_version", cfg.LavaVersion) 90 metrics.Collect("checktype_urls", cfg.ChecktypeURLs) 91 metrics.Collect("targets", cfg.Targets) 92 metrics.Collect("severity", cfg.ReportConfig.Severity) 93 metrics.Collect("exclusion_count", len(cfg.ReportConfig.Exclusions)) 94 95 base.LogLevel.Set(cfg.LogLevel) 96 er, err := engine.Run(cfg.ChecktypeURLs, cfg.Targets, cfg.AgentConfig) 97 if err != nil { 98 return fmt.Errorf("engine run: %w", err) 99 } 100 101 rw, err := report.NewWriter(cfg.ReportConfig) 102 if err != nil { 103 return fmt.Errorf("new writer: %w", err) 104 } 105 defer rw.Close() 106 107 exitCode, err := rw.Write(er) 108 if err != nil { 109 return fmt.Errorf("render report: %w", err) 110 } 111 112 metrics.Collect("exit_code", exitCode) 113 metrics.Collect("duration", time.Since(startTime).Seconds()) 114 115 if cfg.ReportConfig.Metrics != "" { 116 if err = metrics.WriteFile(cfg.ReportConfig.Metrics); err != nil { 117 return fmt.Errorf("write metrics: %w", err) 118 } 119 } 120 121 osExit(int(exitCode)) 122 123 return nil 124 }