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  }