mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-05 20:40:16 -08:00
214 lines
5.7 KiB
Go
214 lines
5.7 KiB
Go
package flag
|
|
|
|
import (
|
|
"crypto/x509"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/spf13/cobra"
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/aquasecurity/trivy/pkg/cache"
|
|
"github.com/aquasecurity/trivy/pkg/log"
|
|
)
|
|
|
|
var (
|
|
ConfigFileFlag = Flag[string]{
|
|
Name: "config",
|
|
ConfigName: "config",
|
|
Shorthand: "c",
|
|
Default: "trivy.yaml",
|
|
Usage: "config path",
|
|
Persistent: true,
|
|
}
|
|
ShowVersionFlag = Flag[bool]{
|
|
Name: "version",
|
|
ConfigName: "version",
|
|
Shorthand: "v",
|
|
Usage: "show version",
|
|
Persistent: true,
|
|
}
|
|
QuietFlag = Flag[bool]{
|
|
Name: "quiet",
|
|
ConfigName: "quiet",
|
|
Shorthand: "q",
|
|
Usage: "suppress progress bar and log output",
|
|
Persistent: true,
|
|
TelemetrySafe: true,
|
|
}
|
|
DebugFlag = Flag[bool]{
|
|
Name: "debug",
|
|
ConfigName: "debug",
|
|
Shorthand: "d",
|
|
Usage: "debug mode",
|
|
Persistent: true,
|
|
TelemetrySafe: true,
|
|
}
|
|
InsecureFlag = Flag[bool]{
|
|
Name: "insecure",
|
|
ConfigName: "insecure",
|
|
Usage: "allow insecure server connections",
|
|
Persistent: true,
|
|
TelemetrySafe: true,
|
|
}
|
|
CACertFlag = Flag[string]{
|
|
Name: "cacert",
|
|
ConfigName: "cacert",
|
|
Usage: "Path to PEM-encoded CA certificate file",
|
|
Persistent: true,
|
|
}
|
|
TimeoutFlag = Flag[time.Duration]{
|
|
Name: "timeout",
|
|
ConfigName: "timeout",
|
|
Default: time.Second * 300, // 5 mins
|
|
Usage: "timeout",
|
|
Persistent: true,
|
|
TelemetrySafe: true,
|
|
}
|
|
CacheDirFlag = Flag[string]{
|
|
Name: "cache-dir",
|
|
ConfigName: "cache.dir",
|
|
Default: cache.DefaultDir(),
|
|
Usage: "cache directory",
|
|
Persistent: true,
|
|
}
|
|
GenerateDefaultConfigFlag = Flag[bool]{
|
|
Name: "generate-default-config",
|
|
ConfigName: "generate-default-config",
|
|
Usage: "write the default config to trivy-default.yaml",
|
|
Persistent: true,
|
|
}
|
|
TraceHTTPFlag = Flag[bool]{
|
|
Name: "trace-http",
|
|
ConfigName: "trace.http",
|
|
Usage: "[DANGEROUS] enable HTTP request/response trace logging (may expose sensitive data)",
|
|
Persistent: true,
|
|
TelemetrySafe: true,
|
|
Internal: true, // Hidden from help output, intended for maintainer debugging only
|
|
}
|
|
)
|
|
|
|
// GlobalFlagGroup composes global flags
|
|
type GlobalFlagGroup struct {
|
|
ConfigFile *Flag[string]
|
|
ShowVersion *Flag[bool] // spf13/cobra can't override the logic of version printing like VersionPrinter in urfave/cli. -v needs to be defined ourselves.
|
|
Quiet *Flag[bool]
|
|
Debug *Flag[bool]
|
|
Insecure *Flag[bool]
|
|
CACert *Flag[string]
|
|
Timeout *Flag[time.Duration]
|
|
CacheDir *Flag[string]
|
|
GenerateDefaultConfig *Flag[bool]
|
|
TraceHTTP *Flag[bool]
|
|
}
|
|
|
|
// GlobalOptions defines flags and other configuration parameters for all the subcommands
|
|
type GlobalOptions struct {
|
|
ConfigFile string
|
|
ShowVersion bool
|
|
Quiet bool
|
|
Debug bool
|
|
Insecure bool
|
|
CACerts *x509.CertPool
|
|
Timeout time.Duration
|
|
CacheDir string
|
|
GenerateDefaultConfig bool
|
|
TraceHTTP bool
|
|
}
|
|
|
|
func NewGlobalFlagGroup() *GlobalFlagGroup {
|
|
return &GlobalFlagGroup{
|
|
ConfigFile: ConfigFileFlag.Clone(),
|
|
ShowVersion: ShowVersionFlag.Clone(),
|
|
Quiet: QuietFlag.Clone(),
|
|
Debug: DebugFlag.Clone(),
|
|
Insecure: InsecureFlag.Clone(),
|
|
CACert: CACertFlag.Clone(),
|
|
Timeout: TimeoutFlag.Clone(),
|
|
CacheDir: CacheDirFlag.Clone(),
|
|
GenerateDefaultConfig: GenerateDefaultConfigFlag.Clone(),
|
|
TraceHTTP: TraceHTTPFlag.Clone(),
|
|
}
|
|
}
|
|
|
|
func (f *GlobalFlagGroup) Name() string {
|
|
return "Global"
|
|
}
|
|
|
|
func (f *GlobalFlagGroup) Flags() []Flagger {
|
|
return []Flagger{
|
|
f.ConfigFile,
|
|
f.ShowVersion,
|
|
f.Quiet,
|
|
f.Debug,
|
|
f.Insecure,
|
|
f.CACert,
|
|
f.Timeout,
|
|
f.CacheDir,
|
|
f.GenerateDefaultConfig,
|
|
f.TraceHTTP,
|
|
}
|
|
}
|
|
|
|
func (f *GlobalFlagGroup) AddFlags(cmd *cobra.Command) {
|
|
for _, flag := range f.Flags() {
|
|
flag.Add(cmd)
|
|
}
|
|
}
|
|
|
|
func (f *GlobalFlagGroup) Bind(cmd *cobra.Command) error {
|
|
for _, flag := range f.Flags() {
|
|
if err := flag.Bind(cmd); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (f *GlobalFlagGroup) ToOptions(opts *Options) error {
|
|
// Keep TRIVY_NON_SSL for backward compatibility
|
|
insecure := f.Insecure.Value() || os.Getenv("TRIVY_NON_SSL") != ""
|
|
caCerts, err := loadRootCAs(f.CACert.Value())
|
|
if err != nil {
|
|
return xerrors.Errorf("failed to load root CA certificates: %w", err)
|
|
}
|
|
|
|
log.Debug("Cache dir", log.String("dir", f.CacheDir.Value()))
|
|
|
|
opts.GlobalOptions = GlobalOptions{
|
|
ConfigFile: f.ConfigFile.Value(),
|
|
ShowVersion: f.ShowVersion.Value(),
|
|
Quiet: f.Quiet.Value(),
|
|
Debug: f.Debug.Value(),
|
|
Insecure: insecure,
|
|
CACerts: caCerts,
|
|
Timeout: f.Timeout.Value(),
|
|
CacheDir: f.CacheDir.Value(),
|
|
GenerateDefaultConfig: f.GenerateDefaultConfig.Value(),
|
|
TraceHTTP: f.TraceHTTP.Value(),
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// loadRootCAs builds a cert pool from the system pool and the provided PEM bundle.
|
|
// Returns nil if caCertPath is empty or on failure.
|
|
func loadRootCAs(caCertPath string) (*x509.CertPool, error) {
|
|
if caCertPath == "" {
|
|
return nil, nil
|
|
}
|
|
|
|
rootCAs, err := x509.SystemCertPool()
|
|
if err != nil || rootCAs == nil {
|
|
rootCAs = x509.NewCertPool()
|
|
}
|
|
|
|
pem, err := os.ReadFile(caCertPath)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to read root CA certificate: %w", err)
|
|
}
|
|
if ok := rootCAs.AppendCertsFromPEM(pem); !ok {
|
|
return nil, xerrors.Errorf("failed to append CA bundle")
|
|
}
|
|
return rootCAs, nil
|
|
}
|