mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 15:50:15 -08:00
refactor: rename scanner to service (#8584)
This commit is contained in:
@@ -8,7 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/post"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/post"
|
||||
)
|
||||
|
||||
func TestModule(t *testing.T) {
|
||||
|
||||
@@ -12,97 +12,100 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner"
|
||||
"github.com/aquasecurity/trivy/pkg/scan"
|
||||
)
|
||||
|
||||
//////////////
|
||||
// Standalone
|
||||
//////////////
|
||||
|
||||
// initializeImageScanner is for container image scanning in standalone mode
|
||||
// initializeImageScanService is for container image scanning in standalone mode
|
||||
// e.g. dockerd, container registry, podman, etc.
|
||||
func initializeImageScanner(ctx context.Context, imageName string, imageOpt types.ImageOptions, cacheOptions cache.Options, artifactOption artifact.Option) (
|
||||
scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.StandaloneDockerSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
func initializeImageScanService(ctx context.Context, imageName string, imageOpt types.ImageOptions, cacheOptions cache.Options, artifactOption artifact.Option) (
|
||||
scan.Service, func(), error) {
|
||||
wire.Build(scan.StandaloneDockerSet)
|
||||
return scan.Service{}, nil, nil
|
||||
}
|
||||
|
||||
// initializeArchiveScanner is for container image archive scanning in standalone mode
|
||||
// initializeArchiveScanService is for container image archive scanning in standalone mode
|
||||
// e.g. docker save -o alpine.tar alpine:3.15
|
||||
func initializeArchiveScanner(ctx context.Context, filePath string, cacheOptions cache.Options, artifactOption artifact.Option) (
|
||||
scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.StandaloneArchiveSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
func initializeArchiveScanService(ctx context.Context, filePath string, cacheOptions cache.Options, artifactOption artifact.Option) (
|
||||
scan.Service, func(), error) {
|
||||
wire.Build(scan.StandaloneArchiveSet)
|
||||
return scan.Service{}, nil, nil
|
||||
}
|
||||
|
||||
// initializeFilesystemScanner is for filesystem scanning in standalone mode
|
||||
func initializeFilesystemScanner(ctx context.Context, path string, cacheOptions cache.Options, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.StandaloneFilesystemSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
// initializeFilesystemScanService is for filesystem scanning in standalone mode
|
||||
func initializeFilesystemScanService(ctx context.Context, path string, cacheOptions cache.Options, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
wire.Build(scan.StandaloneFilesystemSet)
|
||||
return scan.Service{}, nil, nil
|
||||
}
|
||||
|
||||
func initializeRepositoryScanner(ctx context.Context, url string, cacheOptions cache.Options, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.StandaloneRepositorySet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
// initializeRepositoryScanService is for repository scanning in standalone mode
|
||||
func initializeRepositoryScanService(ctx context.Context, url string, cacheOptions cache.Options, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
wire.Build(scan.StandaloneRepositorySet)
|
||||
return scan.Service{}, nil, nil
|
||||
}
|
||||
|
||||
func initializeSBOMScanner(ctx context.Context, filePath string, cacheOptions cache.Options, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.StandaloneSBOMSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
// initializeSBOMScanService is for sbom scanning in standalone mode
|
||||
func initializeSBOMScanService(ctx context.Context, filePath string, cacheOptions cache.Options, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
wire.Build(scan.StandaloneSBOMSet)
|
||||
return scan.Service{}, nil, nil
|
||||
}
|
||||
|
||||
func initializeVMScanner(ctx context.Context, filePath string, cacheOptions cache.Options, artifactOption artifact.Option) (
|
||||
scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.StandaloneVMSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
// initializeVMScanService is for vm scanning in standalone mode
|
||||
func initializeVMScanService(ctx context.Context, filePath string, cacheOptions cache.Options, artifactOption artifact.Option) (
|
||||
scan.Service, func(), error) {
|
||||
wire.Build(scan.StandaloneVMSet)
|
||||
return scan.Service{}, nil, nil
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Client/Server
|
||||
/////////////////
|
||||
|
||||
// initializeRemoteImageScanner is for container image scanning in client/server mode
|
||||
// initializeRemoteImageScanService is for container image scanning in client/server mode
|
||||
// e.g. dockerd, container registry, podman, etc.
|
||||
func initializeRemoteImageScanner(ctx context.Context, imageName string, remoteCacheOptions cache.RemoteOptions,
|
||||
remoteScanOptions client.ScannerOption, imageOpt types.ImageOptions, artifactOption artifact.Option) (
|
||||
scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.RemoteDockerSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
func initializeRemoteImageScanService(ctx context.Context, imageName string, remoteCacheOptions cache.RemoteOptions,
|
||||
remoteScanOptions client.ServiceOption, imageOpt types.ImageOptions, artifactOption artifact.Option) (
|
||||
scan.Service, func(), error) {
|
||||
wire.Build(scan.RemoteDockerSet)
|
||||
return scan.Service{}, nil, nil
|
||||
}
|
||||
|
||||
// initializeRemoteArchiveScanner is for container image archive scanning in client/server mode
|
||||
// initializeRemoteArchiveScanService is for container image archive scanning in client/server mode
|
||||
// e.g. docker save -o alpine.tar alpine:3.15
|
||||
func initializeRemoteArchiveScanner(ctx context.Context, filePath string, remoteCacheOptions cache.RemoteOptions,
|
||||
remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.RemoteArchiveSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
func initializeRemoteArchiveScanService(ctx context.Context, filePath string, remoteCacheOptions cache.RemoteOptions,
|
||||
remoteScanOptions client.ServiceOption, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
wire.Build(scan.RemoteArchiveSet)
|
||||
return scan.Service{}, nil, nil
|
||||
}
|
||||
|
||||
// initializeRemoteFilesystemScanner is for filesystem scanning in client/server mode
|
||||
func initializeRemoteFilesystemScanner(ctx context.Context, path string, remoteCacheOptions cache.RemoteOptions,
|
||||
remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.RemoteFilesystemSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
// initializeRemoteFilesystemScanService is for filesystem scanning in client/server mode
|
||||
func initializeRemoteFilesystemScanService(ctx context.Context, path string, remoteCacheOptions cache.RemoteOptions,
|
||||
remoteScanOptions client.ServiceOption, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
wire.Build(scan.RemoteFilesystemSet)
|
||||
return scan.Service{}, nil, nil
|
||||
}
|
||||
|
||||
// initializeRemoteRepositoryScanner is for repository scanning in client/server mode
|
||||
func initializeRemoteRepositoryScanner(ctx context.Context, url string, remoteCacheOptions cache.RemoteOptions,
|
||||
remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (
|
||||
scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.RemoteRepositorySet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
// initializeRemoteRepositoryScanService is for repository scanning in client/server mode
|
||||
func initializeRemoteRepositoryScanService(ctx context.Context, url string, remoteCacheOptions cache.RemoteOptions,
|
||||
remoteScanOptions client.ServiceOption, artifactOption artifact.Option) (
|
||||
scan.Service, func(), error) {
|
||||
wire.Build(scan.RemoteRepositorySet)
|
||||
return scan.Service{}, nil, nil
|
||||
}
|
||||
|
||||
// initializeRemoteSBOMScanner is for sbom scanning in client/server mode
|
||||
func initializeRemoteSBOMScanner(ctx context.Context, path string, remoteCacheOptions cache.RemoteOptions,
|
||||
remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.RemoteSBOMSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
// initializeRemoteSBOMScanService is for sbom scanning in client/server mode
|
||||
func initializeRemoteSBOMScanService(ctx context.Context, path string, remoteCacheOptions cache.RemoteOptions,
|
||||
remoteScanOptions client.ServiceOption, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
wire.Build(scan.RemoteSBOMSet)
|
||||
return scan.Service{}, nil, nil
|
||||
}
|
||||
|
||||
// initializeRemoteVMScanner is for vm scanning in client/server mode
|
||||
func initializeRemoteVMScanner(ctx context.Context, path string, remoteCacheOptions cache.RemoteOptions,
|
||||
remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
wire.Build(scanner.RemoteVMSet)
|
||||
return scanner.Scanner{}, nil, nil
|
||||
// initializeRemoteVMScanService is for vm scanning in client/server mode
|
||||
func initializeRemoteVMScanService(ctx context.Context, path string, remoteCacheOptions cache.RemoteOptions,
|
||||
remoteScanOptions client.ServiceOption, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
wire.Build(scan.RemoteVMSet)
|
||||
return scan.Service{}, nil, nil
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
pkgReport "github.com/aquasecurity/trivy/pkg/report"
|
||||
"github.com/aquasecurity/trivy/pkg/result"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner"
|
||||
"github.com/aquasecurity/trivy/pkg/scan"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/version/doc"
|
||||
)
|
||||
@@ -50,8 +50,8 @@ var (
|
||||
SkipScan = errors.New("skip subsequent processes")
|
||||
)
|
||||
|
||||
// InitializeScanner defines the initialize function signature of scanner
|
||||
type InitializeScanner func(context.Context, ScannerConfig) (scanner.Scanner, func(), error)
|
||||
// InitializeScanService defines the initialize function signature of scan service
|
||||
type InitializeScanService func(context.Context, ScannerConfig) (scan.Service, func(), error)
|
||||
|
||||
type ScannerConfig struct {
|
||||
// e.g. image name and file path
|
||||
@@ -62,7 +62,7 @@ type ScannerConfig struct {
|
||||
RemoteCacheOptions cache.RemoteOptions
|
||||
|
||||
// Client/Server options
|
||||
ServerOption client.ScannerOption
|
||||
ServerOption client.ServiceOption
|
||||
|
||||
// Artifact options
|
||||
ArtifactOption artifact.Option
|
||||
@@ -90,8 +90,8 @@ type Runner interface {
|
||||
}
|
||||
|
||||
type runner struct {
|
||||
initializeScanner InitializeScanner
|
||||
dbOpen bool
|
||||
initializeScanService InitializeScanService
|
||||
dbOpen bool
|
||||
|
||||
// WASM modules
|
||||
module *module.Manager
|
||||
@@ -99,11 +99,11 @@ type runner struct {
|
||||
|
||||
type RunnerOption func(*runner)
|
||||
|
||||
// WithInitializeScanner takes a custom scanner initialization function.
|
||||
// WithInitializeService takes a custom service initialization function.
|
||||
// It is useful when Trivy is imported as a library.
|
||||
func WithInitializeScanner(f InitializeScanner) RunnerOption {
|
||||
func WithInitializeService(f InitializeScanService) RunnerOption {
|
||||
return func(r *runner) {
|
||||
r.initializeScanner = f
|
||||
r.initializeScanService = f
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,20 +158,20 @@ func (r *runner) ScanImage(ctx context.Context, opts flag.Options) (types.Report
|
||||
// Disable the lock file scanning
|
||||
opts.DisabledAnalyzers = analyzer.TypeLockfiles
|
||||
|
||||
var s InitializeScanner
|
||||
var s InitializeScanService
|
||||
switch {
|
||||
case opts.Input != "" && opts.ServerAddr == "":
|
||||
// Scan image tarball in standalone mode
|
||||
s = archiveStandaloneScanner
|
||||
s = archiveStandaloneScanService
|
||||
case opts.Input != "" && opts.ServerAddr != "":
|
||||
// Scan image tarball in client/server mode
|
||||
s = archiveRemoteScanner
|
||||
s = archiveRemoteScanService
|
||||
case opts.Input == "" && opts.ServerAddr == "":
|
||||
// Scan container image in standalone mode
|
||||
s = imageStandaloneScanner
|
||||
s = imageStandaloneScanService
|
||||
case opts.Input == "" && opts.ServerAddr != "":
|
||||
// Scan container image in client/server mode
|
||||
s = imageRemoteScanner
|
||||
s = imageRemoteScanService
|
||||
}
|
||||
|
||||
return r.scanArtifact(ctx, opts, s)
|
||||
@@ -193,13 +193,13 @@ func (r *runner) ScanRootfs(ctx context.Context, opts flag.Options) (types.Repor
|
||||
}
|
||||
|
||||
func (r *runner) scanFS(ctx context.Context, opts flag.Options) (types.Report, error) {
|
||||
var s InitializeScanner
|
||||
var s InitializeScanService
|
||||
if opts.ServerAddr == "" {
|
||||
// Scan filesystem in standalone mode
|
||||
s = filesystemStandaloneScanner
|
||||
s = filesystemStandaloneScanService
|
||||
} else {
|
||||
// Scan filesystem in client/server mode
|
||||
s = filesystemRemoteScanner
|
||||
s = filesystemRemoteScanService
|
||||
}
|
||||
|
||||
return r.scanArtifact(ctx, opts, s)
|
||||
@@ -213,25 +213,25 @@ func (r *runner) ScanRepository(ctx context.Context, opts flag.Options) (types.R
|
||||
opts.DisabledAnalyzers = append(analyzer.TypeIndividualPkgs, analyzer.TypeOSes...)
|
||||
opts.DisabledAnalyzers = append(opts.DisabledAnalyzers, analyzer.TypeSBOM)
|
||||
|
||||
var s InitializeScanner
|
||||
var s InitializeScanService
|
||||
if opts.ServerAddr == "" {
|
||||
// Scan repository in standalone mode
|
||||
s = repositoryStandaloneScanner
|
||||
s = repositoryStandaloneScanService
|
||||
} else {
|
||||
// Scan repository in client/server mode
|
||||
s = repositoryRemoteScanner
|
||||
s = repositoryRemoteScanService
|
||||
}
|
||||
return r.scanArtifact(ctx, opts, s)
|
||||
}
|
||||
|
||||
func (r *runner) ScanSBOM(ctx context.Context, opts flag.Options) (types.Report, error) {
|
||||
var s InitializeScanner
|
||||
var s InitializeScanService
|
||||
if opts.ServerAddr == "" {
|
||||
// Scan cycloneDX in standalone mode
|
||||
s = sbomStandaloneScanner
|
||||
s = sbomStandaloneScanService
|
||||
} else {
|
||||
// Scan cycloneDX in client/server mode
|
||||
s = sbomRemoteScanner
|
||||
s = sbomRemoteScanService
|
||||
}
|
||||
|
||||
return r.scanArtifact(ctx, opts, s)
|
||||
@@ -241,23 +241,23 @@ func (r *runner) ScanVM(ctx context.Context, opts flag.Options) (types.Report, e
|
||||
// TODO: Does VM scan disable lock file..?
|
||||
opts.DisabledAnalyzers = analyzer.TypeLockfiles
|
||||
|
||||
var s InitializeScanner
|
||||
var s InitializeScanService
|
||||
if opts.ServerAddr == "" {
|
||||
// Scan virtual machine in standalone mode
|
||||
s = vmStandaloneScanner
|
||||
s = vmStandaloneScanService
|
||||
} else {
|
||||
// Scan virtual machine in client/server mode
|
||||
s = vmRemoteScanner
|
||||
s = vmRemoteScanService
|
||||
}
|
||||
|
||||
return r.scanArtifact(ctx, opts, s)
|
||||
}
|
||||
|
||||
func (r *runner) scanArtifact(ctx context.Context, opts flag.Options, initializeScanner InitializeScanner) (types.Report, error) {
|
||||
if r.initializeScanner != nil {
|
||||
initializeScanner = r.initializeScanner
|
||||
func (r *runner) scanArtifact(ctx context.Context, opts flag.Options, initializeService InitializeScanService) (types.Report, error) {
|
||||
if r.initializeScanService != nil {
|
||||
initializeService = r.initializeScanService
|
||||
}
|
||||
report, err := r.scan(ctx, opts, initializeScanner)
|
||||
report, err := r.scan(ctx, opts, initializeService)
|
||||
if err != nil {
|
||||
return types.Report{}, xerrors.Errorf("scan error: %w", err)
|
||||
}
|
||||
@@ -614,14 +614,14 @@ func (r *runner) initScannerConfig(ctx context.Context, opts flag.Options) (Scan
|
||||
}, scanOptions, nil
|
||||
}
|
||||
|
||||
func (r *runner) scan(ctx context.Context, opts flag.Options, initializeScanner InitializeScanner) (types.Report, error) {
|
||||
func (r *runner) scan(ctx context.Context, opts flag.Options, initializeService InitializeScanService) (types.Report, error) {
|
||||
scannerConfig, scanOptions, err := r.initScannerConfig(ctx, opts)
|
||||
if err != nil {
|
||||
return types.Report{}, err
|
||||
}
|
||||
s, cleanup, err := initializeScanner(ctx, scannerConfig)
|
||||
s, cleanup, err := initializeService(ctx, scannerConfig)
|
||||
if err != nil {
|
||||
return types.Report{}, xerrors.Errorf("unable to initialize a scanner: %w", err)
|
||||
return types.Report{}, xerrors.Errorf("unable to initialize a scan service: %w", err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
|
||||
@@ -5,121 +5,120 @@ import (
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/scanner"
|
||||
"github.com/aquasecurity/trivy/pkg/scan"
|
||||
)
|
||||
|
||||
// imageStandaloneScanner initializes a container image scanner in standalone mode
|
||||
// imageStandaloneScanService initializes a container image scan service in standalone mode
|
||||
// $ trivy image alpine:3.15
|
||||
func imageStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||
s, cleanup, err := initializeImageScanner(ctx, conf.Target, conf.ArtifactOption.ImageOption, conf.CacheOptions, conf.ArtifactOption)
|
||||
func imageStandaloneScanService(ctx context.Context, conf ScannerConfig) (scan.Service, func(), error) {
|
||||
s, cleanup, err := initializeImageScanService(ctx, conf.Target, conf.ArtifactOption.ImageOption, conf.CacheOptions, conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize an image scanner: %w", err)
|
||||
return scan.Service{}, func() {}, xerrors.Errorf("unable to initialize an image scan service: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
// archiveStandaloneScanner initializes an image archive scanner in standalone mode
|
||||
// archiveStandaloneScanService initializes an image archive scan srevice in standalone mode
|
||||
// $ trivy image --input alpine.tar
|
||||
func archiveStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||
s, cleanup, err := initializeArchiveScanner(ctx, conf.Target, conf.CacheOptions, conf.ArtifactOption)
|
||||
func archiveStandaloneScanService(ctx context.Context, conf ScannerConfig) (scan.Service, func(), error) {
|
||||
s, cleanup, err := initializeArchiveScanService(ctx, conf.Target, conf.CacheOptions, conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize the archive scanner: %w", err)
|
||||
return scan.Service{}, func() {}, xerrors.Errorf("unable to initialize the archive scan service: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
// imageRemoteScanner initializes a container image scanner in client/server mode
|
||||
// imageRemoteScanService initializes a container image scan service in client/server mode
|
||||
// $ trivy image --server localhost:4954 alpine:3.15
|
||||
func imageRemoteScanner(ctx context.Context, conf ScannerConfig) (
|
||||
scanner.Scanner, func(), error) {
|
||||
s, cleanup, err := initializeRemoteImageScanner(ctx, conf.Target, conf.RemoteCacheOptions, conf.ServerOption,
|
||||
func imageRemoteScanService(ctx context.Context, conf ScannerConfig) (scan.Service, func(), error) {
|
||||
s, cleanup, err := initializeRemoteImageScanService(ctx, conf.Target, conf.RemoteCacheOptions, conf.ServerOption,
|
||||
conf.ArtifactOption.ImageOption, conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, xerrors.Errorf("unable to initialize a remote image scanner: %w", err)
|
||||
return scan.Service{}, nil, xerrors.Errorf("unable to initialize a remote image scan service: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
// archiveRemoteScanner initializes an image archive scanner in client/server mode
|
||||
// archiveRemoteScanService initializes an image archive scan service in client/server mode
|
||||
// $ trivy image --server localhost:4954 --input alpine.tar
|
||||
func archiveRemoteScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||
func archiveRemoteScanService(ctx context.Context, conf ScannerConfig) (scan.Service, func(), error) {
|
||||
// Scan tar file
|
||||
s, cleanup, err := initializeRemoteArchiveScanner(ctx, conf.Target, conf.RemoteCacheOptions, conf.ServerOption, conf.ArtifactOption)
|
||||
s, cleanup, err := initializeRemoteArchiveScanService(ctx, conf.Target, conf.RemoteCacheOptions, conf.ServerOption, conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, xerrors.Errorf("unable to initialize the remote archive scanner: %w", err)
|
||||
return scan.Service{}, nil, xerrors.Errorf("unable to initialize the remote archive scan service: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
// filesystemStandaloneScanner initializes a filesystem scanner in standalone mode
|
||||
func filesystemStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||
s, cleanup, err := initializeFilesystemScanner(ctx, conf.Target, conf.CacheOptions, conf.ArtifactOption)
|
||||
// filesystemStandaloneScanService initializes a filesystem scan service in standalone mode
|
||||
func filesystemStandaloneScanService(ctx context.Context, conf ScannerConfig) (scan.Service, func(), error) {
|
||||
s, cleanup, err := initializeFilesystemScanService(ctx, conf.Target, conf.CacheOptions, conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a filesystem scanner: %w", err)
|
||||
return scan.Service{}, func() {}, xerrors.Errorf("unable to initialize a filesystem scan service: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
// filesystemRemoteScanner initializes a filesystem scanner in client/server mode
|
||||
func filesystemRemoteScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||
s, cleanup, err := initializeRemoteFilesystemScanner(ctx, conf.Target, conf.RemoteCacheOptions, conf.ServerOption, conf.ArtifactOption)
|
||||
// filesystemRemoteScanService initializes a filesystem scan service in client/server mode
|
||||
func filesystemRemoteScanService(ctx context.Context, conf ScannerConfig) (scan.Service, func(), error) {
|
||||
s, cleanup, err := initializeRemoteFilesystemScanService(ctx, conf.Target, conf.RemoteCacheOptions, conf.ServerOption, conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a remote filesystem scanner: %w", err)
|
||||
return scan.Service{}, func() {}, xerrors.Errorf("unable to initialize a remote filesystem scan service: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
// repositoryStandaloneScanner initializes a repository scanner in standalone mode
|
||||
func repositoryStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||
s, cleanup, err := initializeRepositoryScanner(ctx, conf.Target, conf.CacheOptions, conf.ArtifactOption)
|
||||
// repositoryStandaloneScanService initializes a repository scan service in standalone mode
|
||||
func repositoryStandaloneScanService(ctx context.Context, conf ScannerConfig) (scan.Service, func(), error) {
|
||||
s, cleanup, err := initializeRepositoryScanService(ctx, conf.Target, conf.CacheOptions, conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a repository scanner: %w", err)
|
||||
return scan.Service{}, func() {}, xerrors.Errorf("unable to initialize a repository scan service: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
// repositoryRemoteScanner initializes a repository scanner in client/server mode
|
||||
func repositoryRemoteScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||
s, cleanup, err := initializeRemoteRepositoryScanner(ctx, conf.Target, conf.RemoteCacheOptions, conf.ServerOption,
|
||||
// repositoryRemoteScanService initializes a repository scan service in client/server mode
|
||||
func repositoryRemoteScanService(ctx context.Context, conf ScannerConfig) (scan.Service, func(), error) {
|
||||
s, cleanup, err := initializeRemoteRepositoryScanService(ctx, conf.Target, conf.RemoteCacheOptions, conf.ServerOption,
|
||||
conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a remote repository scanner: %w", err)
|
||||
return scan.Service{}, func() {}, xerrors.Errorf("unable to initialize a remote repository scan service: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
// sbomStandaloneScanner initializes a SBOM scanner in standalone mode
|
||||
func sbomStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||
s, cleanup, err := initializeSBOMScanner(ctx, conf.Target, conf.CacheOptions, conf.ArtifactOption)
|
||||
// sbomStandaloneScanService initializes a SBOM scan service in standalone mode
|
||||
func sbomStandaloneScanService(ctx context.Context, conf ScannerConfig) (scan.Service, func(), error) {
|
||||
s, cleanup, err := initializeSBOMScanService(ctx, conf.Target, conf.CacheOptions, conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a cycloneDX scanner: %w", err)
|
||||
return scan.Service{}, func() {}, xerrors.Errorf("unable to initialize a cycloneDX scan service: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
// sbomRemoteScanner initializes a SBOM scanner in client/server mode
|
||||
func sbomRemoteScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||
s, cleanup, err := initializeRemoteSBOMScanner(ctx, conf.Target, conf.RemoteCacheOptions, conf.ServerOption, conf.ArtifactOption)
|
||||
// sbomRemoteScanService initializes a SBOM scan service in client/server mode
|
||||
func sbomRemoteScanService(ctx context.Context, conf ScannerConfig) (scan.Service, func(), error) {
|
||||
s, cleanup, err := initializeRemoteSBOMScanService(ctx, conf.Target, conf.RemoteCacheOptions, conf.ServerOption, conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a remote cycloneDX scanner: %w", err)
|
||||
return scan.Service{}, func() {}, xerrors.Errorf("unable to initialize a remote cycloneDX scan service: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
// vmStandaloneScanner initializes a VM scanner in standalone mode
|
||||
func vmStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||
s, cleanup, err := initializeVMScanner(ctx, conf.Target, conf.CacheOptions, conf.ArtifactOption)
|
||||
// vmStandaloneScanService initializes a VM scan service in standalone mode
|
||||
func vmStandaloneScanService(ctx context.Context, conf ScannerConfig) (scan.Service, func(), error) {
|
||||
s, cleanup, err := initializeVMScanService(ctx, conf.Target, conf.CacheOptions, conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a vm scanner: %w", err)
|
||||
return scan.Service{}, func() {}, xerrors.Errorf("unable to initialize a vm scan service: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
// vmRemoteScanner initializes a VM scanner in client/server mode
|
||||
func vmRemoteScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||
s, cleanup, err := initializeRemoteVMScanner(ctx, conf.Target, conf.RemoteCacheOptions, conf.ServerOption, conf.ArtifactOption)
|
||||
// vmRemoteScanService initializes a VM scan service in client/server mode
|
||||
func vmRemoteScanService(ctx context.Context, conf ScannerConfig) (scan.Service, func(), error) {
|
||||
s, cleanup, err := initializeRemoteVMScanService(ctx, conf.Target, conf.RemoteCacheOptions, conf.ServerOption, conf.ArtifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a remote vm scanner: %w", err)
|
||||
return scan.Service{}, func() {}, xerrors.Errorf("unable to initialize a remote vm scan service: %w", err)
|
||||
}
|
||||
return s, cleanup, nil
|
||||
}
|
||||
|
||||
@@ -21,185 +21,188 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/walker"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/vulnerability"
|
||||
)
|
||||
|
||||
// Injectors from inject.go:
|
||||
|
||||
// initializeImageScanner is for container image scanning in standalone mode
|
||||
// initializeImageScanService is for container image scanning in standalone mode
|
||||
// e.g. dockerd, container registry, podman, etc.
|
||||
func initializeImageScanner(ctx context.Context, imageName string, imageOpt types.ImageOptions, cacheOptions cache.Options, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
func initializeImageScanService(ctx context.Context, imageName string, imageOpt types.ImageOptions, cacheOptions cache.Options, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
cacheCache, cleanup, err := cache.New(cacheOptions)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
applierApplier := applier.NewApplier(cacheCache)
|
||||
ospkgScanner := ospkg.NewScanner()
|
||||
scanner := ospkg.NewScanner()
|
||||
langpkgScanner := langpkg.NewScanner()
|
||||
config := db.Config{}
|
||||
client := vulnerability.NewClient(config)
|
||||
localScanner := local.NewScanner(applierApplier, ospkgScanner, langpkgScanner, client)
|
||||
service := local.NewService(applierApplier, scanner, langpkgScanner, client)
|
||||
typesImage, cleanup2, err := image.NewContainerImage(ctx, imageName, imageOpt)
|
||||
if err != nil {
|
||||
cleanup()
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
artifactArtifact, err := image2.NewArtifact(typesImage, cacheCache, artifactOption)
|
||||
if err != nil {
|
||||
cleanup2()
|
||||
cleanup()
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(localScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
scanService := scan.NewService(service, artifactArtifact)
|
||||
return scanService, func() {
|
||||
cleanup2()
|
||||
cleanup()
|
||||
}, nil
|
||||
}
|
||||
|
||||
// initializeArchiveScanner is for container image archive scanning in standalone mode
|
||||
// initializeArchiveScanService is for container image archive scanning in standalone mode
|
||||
// e.g. docker save -o alpine.tar alpine:3.15
|
||||
func initializeArchiveScanner(ctx context.Context, filePath string, cacheOptions cache.Options, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
func initializeArchiveScanService(ctx context.Context, filePath string, cacheOptions cache.Options, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
cacheCache, cleanup, err := cache.New(cacheOptions)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
applierApplier := applier.NewApplier(cacheCache)
|
||||
ospkgScanner := ospkg.NewScanner()
|
||||
scanner := ospkg.NewScanner()
|
||||
langpkgScanner := langpkg.NewScanner()
|
||||
config := db.Config{}
|
||||
client := vulnerability.NewClient(config)
|
||||
localScanner := local.NewScanner(applierApplier, ospkgScanner, langpkgScanner, client)
|
||||
service := local.NewService(applierApplier, scanner, langpkgScanner, client)
|
||||
typesImage, err := image.NewArchiveImage(filePath)
|
||||
if err != nil {
|
||||
cleanup()
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
artifactArtifact, err := image2.NewArtifact(typesImage, cacheCache, artifactOption)
|
||||
if err != nil {
|
||||
cleanup()
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(localScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
scanService := scan.NewService(service, artifactArtifact)
|
||||
return scanService, func() {
|
||||
cleanup()
|
||||
}, nil
|
||||
}
|
||||
|
||||
// initializeFilesystemScanner is for filesystem scanning in standalone mode
|
||||
func initializeFilesystemScanner(ctx context.Context, path string, cacheOptions cache.Options, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
// initializeFilesystemScanService is for filesystem scanning in standalone mode
|
||||
func initializeFilesystemScanService(ctx context.Context, path string, cacheOptions cache.Options, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
cacheCache, cleanup, err := cache.New(cacheOptions)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
applierApplier := applier.NewApplier(cacheCache)
|
||||
ospkgScanner := ospkg.NewScanner()
|
||||
scanner := ospkg.NewScanner()
|
||||
langpkgScanner := langpkg.NewScanner()
|
||||
config := db.Config{}
|
||||
client := vulnerability.NewClient(config)
|
||||
localScanner := local.NewScanner(applierApplier, ospkgScanner, langpkgScanner, client)
|
||||
service := local.NewService(applierApplier, scanner, langpkgScanner, client)
|
||||
fs := walker.NewFS()
|
||||
artifactArtifact, err := local2.NewArtifact(path, cacheCache, fs, artifactOption)
|
||||
if err != nil {
|
||||
cleanup()
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(localScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
scanService := scan.NewService(service, artifactArtifact)
|
||||
return scanService, func() {
|
||||
cleanup()
|
||||
}, nil
|
||||
}
|
||||
|
||||
func initializeRepositoryScanner(ctx context.Context, url string, cacheOptions cache.Options, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
// initializeRepositoryScanService is for repository scanning in standalone mode
|
||||
func initializeRepositoryScanService(ctx context.Context, url string, cacheOptions cache.Options, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
cacheCache, cleanup, err := cache.New(cacheOptions)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
applierApplier := applier.NewApplier(cacheCache)
|
||||
ospkgScanner := ospkg.NewScanner()
|
||||
scanner := ospkg.NewScanner()
|
||||
langpkgScanner := langpkg.NewScanner()
|
||||
config := db.Config{}
|
||||
client := vulnerability.NewClient(config)
|
||||
localScanner := local.NewScanner(applierApplier, ospkgScanner, langpkgScanner, client)
|
||||
service := local.NewService(applierApplier, scanner, langpkgScanner, client)
|
||||
fs := walker.NewFS()
|
||||
artifactArtifact, cleanup2, err := repo.NewArtifact(url, cacheCache, fs, artifactOption)
|
||||
if err != nil {
|
||||
cleanup()
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(localScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
scanService := scan.NewService(service, artifactArtifact)
|
||||
return scanService, func() {
|
||||
cleanup2()
|
||||
cleanup()
|
||||
}, nil
|
||||
}
|
||||
|
||||
func initializeSBOMScanner(ctx context.Context, filePath string, cacheOptions cache.Options, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
// initializeSBOMScanService is for sbom scanning in standalone mode
|
||||
func initializeSBOMScanService(ctx context.Context, filePath string, cacheOptions cache.Options, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
cacheCache, cleanup, err := cache.New(cacheOptions)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
applierApplier := applier.NewApplier(cacheCache)
|
||||
ospkgScanner := ospkg.NewScanner()
|
||||
scanner := ospkg.NewScanner()
|
||||
langpkgScanner := langpkg.NewScanner()
|
||||
config := db.Config{}
|
||||
client := vulnerability.NewClient(config)
|
||||
localScanner := local.NewScanner(applierApplier, ospkgScanner, langpkgScanner, client)
|
||||
service := local.NewService(applierApplier, scanner, langpkgScanner, client)
|
||||
artifactArtifact, err := sbom.NewArtifact(filePath, cacheCache, artifactOption)
|
||||
if err != nil {
|
||||
cleanup()
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(localScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
scanService := scan.NewService(service, artifactArtifact)
|
||||
return scanService, func() {
|
||||
cleanup()
|
||||
}, nil
|
||||
}
|
||||
|
||||
func initializeVMScanner(ctx context.Context, filePath string, cacheOptions cache.Options, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
// initializeVMScanService is for vm scanning in standalone mode
|
||||
func initializeVMScanService(ctx context.Context, filePath string, cacheOptions cache.Options, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
cacheCache, cleanup, err := cache.New(cacheOptions)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
applierApplier := applier.NewApplier(cacheCache)
|
||||
ospkgScanner := ospkg.NewScanner()
|
||||
scanner := ospkg.NewScanner()
|
||||
langpkgScanner := langpkg.NewScanner()
|
||||
config := db.Config{}
|
||||
client := vulnerability.NewClient(config)
|
||||
localScanner := local.NewScanner(applierApplier, ospkgScanner, langpkgScanner, client)
|
||||
service := local.NewService(applierApplier, scanner, langpkgScanner, client)
|
||||
walkerVM := walker.NewVM()
|
||||
artifactArtifact, err := vm.NewArtifact(filePath, cacheCache, walkerVM, artifactOption)
|
||||
if err != nil {
|
||||
cleanup()
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(localScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
scanService := scan.NewService(service, artifactArtifact)
|
||||
return scanService, func() {
|
||||
cleanup()
|
||||
}, nil
|
||||
}
|
||||
|
||||
// initializeRemoteImageScanner is for container image scanning in client/server mode
|
||||
// initializeRemoteImageScanService is for container image scanning in client/server mode
|
||||
// e.g. dockerd, container registry, podman, etc.
|
||||
func initializeRemoteImageScanner(ctx context.Context, imageName string, remoteCacheOptions cache.RemoteOptions, remoteScanOptions client.ScannerOption, imageOpt types.ImageOptions, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
func initializeRemoteImageScanService(ctx context.Context, imageName string, remoteCacheOptions cache.RemoteOptions, remoteScanOptions client.ServiceOption, imageOpt types.ImageOptions, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
v := _wireValue
|
||||
clientScanner := client.NewScanner(remoteScanOptions, v...)
|
||||
service := client.NewService(remoteScanOptions, v...)
|
||||
typesImage, cleanup, err := image.NewContainerImage(ctx, imageName, imageOpt)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
remoteCache := cache.NewRemoteCache(remoteCacheOptions)
|
||||
artifactArtifact, err := image2.NewArtifact(typesImage, remoteCache, artifactOption)
|
||||
if err != nil {
|
||||
cleanup()
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(clientScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
scanService := scan.NewService(service, artifactArtifact)
|
||||
return scanService, func() {
|
||||
cleanup()
|
||||
}, nil
|
||||
}
|
||||
@@ -208,81 +211,81 @@ var (
|
||||
_wireValue = []client.Option(nil)
|
||||
)
|
||||
|
||||
// initializeRemoteArchiveScanner is for container image archive scanning in client/server mode
|
||||
// initializeRemoteArchiveScanService is for container image archive scanning in client/server mode
|
||||
// e.g. docker save -o alpine.tar alpine:3.15
|
||||
func initializeRemoteArchiveScanner(ctx context.Context, filePath string, remoteCacheOptions cache.RemoteOptions, remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
func initializeRemoteArchiveScanService(ctx context.Context, filePath string, remoteCacheOptions cache.RemoteOptions, remoteScanOptions client.ServiceOption, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
v := _wireValue
|
||||
clientScanner := client.NewScanner(remoteScanOptions, v...)
|
||||
service := client.NewService(remoteScanOptions, v...)
|
||||
typesImage, err := image.NewArchiveImage(filePath)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
remoteCache := cache.NewRemoteCache(remoteCacheOptions)
|
||||
artifactArtifact, err := image2.NewArtifact(typesImage, remoteCache, artifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(clientScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
scanService := scan.NewService(service, artifactArtifact)
|
||||
return scanService, func() {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// initializeRemoteFilesystemScanner is for filesystem scanning in client/server mode
|
||||
func initializeRemoteFilesystemScanner(ctx context.Context, path string, remoteCacheOptions cache.RemoteOptions, remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
// initializeRemoteFilesystemScanService is for filesystem scanning in client/server mode
|
||||
func initializeRemoteFilesystemScanService(ctx context.Context, path string, remoteCacheOptions cache.RemoteOptions, remoteScanOptions client.ServiceOption, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
v := _wireValue
|
||||
clientScanner := client.NewScanner(remoteScanOptions, v...)
|
||||
service := client.NewService(remoteScanOptions, v...)
|
||||
remoteCache := cache.NewRemoteCache(remoteCacheOptions)
|
||||
fs := walker.NewFS()
|
||||
artifactArtifact, err := local2.NewArtifact(path, remoteCache, fs, artifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(clientScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
scanService := scan.NewService(service, artifactArtifact)
|
||||
return scanService, func() {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// initializeRemoteRepositoryScanner is for repository scanning in client/server mode
|
||||
func initializeRemoteRepositoryScanner(ctx context.Context, url string, remoteCacheOptions cache.RemoteOptions, remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
// initializeRemoteRepositoryScanService is for repository scanning in client/server mode
|
||||
func initializeRemoteRepositoryScanService(ctx context.Context, url string, remoteCacheOptions cache.RemoteOptions, remoteScanOptions client.ServiceOption, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
v := _wireValue
|
||||
clientScanner := client.NewScanner(remoteScanOptions, v...)
|
||||
service := client.NewService(remoteScanOptions, v...)
|
||||
remoteCache := cache.NewRemoteCache(remoteCacheOptions)
|
||||
fs := walker.NewFS()
|
||||
artifactArtifact, cleanup, err := repo.NewArtifact(url, remoteCache, fs, artifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(clientScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
scanService := scan.NewService(service, artifactArtifact)
|
||||
return scanService, func() {
|
||||
cleanup()
|
||||
}, nil
|
||||
}
|
||||
|
||||
// initializeRemoteSBOMScanner is for sbom scanning in client/server mode
|
||||
func initializeRemoteSBOMScanner(ctx context.Context, path string, remoteCacheOptions cache.RemoteOptions, remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
// initializeRemoteSBOMScanService is for sbom scanning in client/server mode
|
||||
func initializeRemoteSBOMScanService(ctx context.Context, path string, remoteCacheOptions cache.RemoteOptions, remoteScanOptions client.ServiceOption, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
v := _wireValue
|
||||
clientScanner := client.NewScanner(remoteScanOptions, v...)
|
||||
service := client.NewService(remoteScanOptions, v...)
|
||||
remoteCache := cache.NewRemoteCache(remoteCacheOptions)
|
||||
artifactArtifact, err := sbom.NewArtifact(path, remoteCache, artifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(clientScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
scanService := scan.NewService(service, artifactArtifact)
|
||||
return scanService, func() {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// initializeRemoteVMScanner is for vm scanning in client/server mode
|
||||
func initializeRemoteVMScanner(ctx context.Context, path string, remoteCacheOptions cache.RemoteOptions, remoteScanOptions client.ScannerOption, artifactOption artifact.Option) (scanner.Scanner, func(), error) {
|
||||
// initializeRemoteVMScanService is for vm scanning in client/server mode
|
||||
func initializeRemoteVMScanService(ctx context.Context, path string, remoteCacheOptions cache.RemoteOptions, remoteScanOptions client.ServiceOption, artifactOption artifact.Option) (scan.Service, func(), error) {
|
||||
v := _wireValue
|
||||
clientScanner := client.NewScanner(remoteScanOptions, v...)
|
||||
service := client.NewService(remoteScanOptions, v...)
|
||||
remoteCache := cache.NewRemoteCache(remoteCacheOptions)
|
||||
walkerVM := walker.NewVM()
|
||||
artifactArtifact, err := vm.NewArtifact(path, remoteCache, walkerVM, artifactOption)
|
||||
if err != nil {
|
||||
return scanner.Scanner{}, nil, err
|
||||
return scan.Service{}, nil, err
|
||||
}
|
||||
scannerScanner := scanner.NewScanner(clientScanner, artifactArtifact)
|
||||
return scannerScanner, func() {
|
||||
scanService := scan.NewService(service, artifactArtifact)
|
||||
return scanService, func() {
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
osver "github.com/aquasecurity/trivy/pkg/detector/ospkg/version"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
osver "github.com/aquasecurity/trivy/pkg/detector/ospkg/version"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
osver "github.com/aquasecurity/trivy/pkg/detector/ospkg/version"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
osver "github.com/aquasecurity/trivy/pkg/detector/ospkg/version"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/chainguard"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
osver "github.com/aquasecurity/trivy/pkg/detector/ospkg/version"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
osver "github.com/aquasecurity/trivy/pkg/detector/ospkg/version"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
osver "github.com/aquasecurity/trivy/pkg/detector/ospkg/version"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
osver "github.com/aquasecurity/trivy/pkg/detector/ospkg/version"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
osver "github.com/aquasecurity/trivy/pkg/detector/ospkg/version"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
osver "github.com/aquasecurity/trivy/pkg/detector/ospkg/version"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
osver "github.com/aquasecurity/trivy/pkg/detector/ospkg/version"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/wolfi"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
)
|
||||
|
||||
const archiveVersion = 1
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/purl"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
xslices "github.com/aquasecurity/trivy/pkg/x/slices"
|
||||
)
|
||||
|
||||
@@ -541,8 +541,8 @@ func (o *Options) RemoteCacheOpts() cache.RemoteOptions {
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Options) ClientScannerOpts() client.ScannerOption {
|
||||
return client.ScannerOption{
|
||||
func (o *Options) ClientScannerOpts() client.ServiceOption {
|
||||
return client.ServiceOption{
|
||||
RemoteURL: o.ServerAddr,
|
||||
CustomHeaders: o.CustomHeaders,
|
||||
Insecure: o.Insecure,
|
||||
|
||||
@@ -6,25 +6,25 @@ import (
|
||||
"github.com/google/wire"
|
||||
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scan"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/local"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
// ScanSuperSet binds the dependencies for k8s
|
||||
var ScanSuperSet = wire.NewSet(
|
||||
local.SuperSet,
|
||||
wire.Bind(new(scanner.Driver), new(local.Scanner)),
|
||||
wire.Bind(new(scan.Backend), new(local.Service)),
|
||||
NewScanKubernetes,
|
||||
)
|
||||
|
||||
// ScanKubernetes implements the scanner
|
||||
type ScanKubernetes struct {
|
||||
localScanner local.Scanner
|
||||
localScanner local.Service
|
||||
}
|
||||
|
||||
// NewScanKubernetes is the factory method for scanner
|
||||
func NewScanKubernetes(s local.Scanner) *ScanKubernetes {
|
||||
func NewScanKubernetes(s local.Service) *ScanKubernetes {
|
||||
return &ScanKubernetes{localScanner: s}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/purl"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/cyclonedx"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/local"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/applier"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/vulnerability"
|
||||
)
|
||||
|
||||
@@ -24,7 +24,7 @@ func initializeScanK8s(localArtifactCache cache.LocalArtifactCache) *ScanKuberne
|
||||
langpkgScanner := langpkg.NewScanner()
|
||||
config := db.Config{}
|
||||
client := vulnerability.NewClient(config)
|
||||
localScanner := local.NewScanner(applierApplier, scanner, langpkgScanner, client)
|
||||
scanKubernetes := NewScanKubernetes(localScanner)
|
||||
service := local.NewService(applierApplier, scanner, langpkgScanner, client)
|
||||
scanKubernetes := NewScanKubernetes(service)
|
||||
return scanKubernetes
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
tapi "github.com/aquasecurity/trivy/pkg/module/api"
|
||||
"github.com/aquasecurity/trivy/pkg/module/serialize"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/post"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/post"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/utils/fsutils"
|
||||
)
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||
"github.com/aquasecurity/trivy/pkg/module"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/post"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/post"
|
||||
)
|
||||
|
||||
func TestManager_Register(t *testing.T) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/dependency"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/aquasecurity/tml"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -30,22 +30,22 @@ func WithRPCClient(c rpc.Scanner) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// ScannerOption holds options for RPC client
|
||||
type ScannerOption struct {
|
||||
// ServiceOption holds options for RPC client
|
||||
type ServiceOption struct {
|
||||
RemoteURL string
|
||||
Insecure bool
|
||||
CustomHeaders http.Header
|
||||
PathPrefix string
|
||||
}
|
||||
|
||||
// Scanner implements the RPC scanner
|
||||
type Scanner struct {
|
||||
// Service implements the RPC client for remote scanning
|
||||
type Service struct {
|
||||
customHeaders http.Header
|
||||
client rpc.Scanner
|
||||
}
|
||||
|
||||
// NewScanner is the factory method to return RPC Scanner
|
||||
func NewScanner(scannerOptions ScannerOption, opts ...Option) Scanner {
|
||||
// NewService is the factory method to return RPC Service
|
||||
func NewService(scannerOptions ServiceOption, opts ...Option) Service {
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: scannerOptions.Insecure}
|
||||
httpClient := &http.Client{Transport: tr}
|
||||
@@ -61,14 +61,14 @@ func NewScanner(scannerOptions ScannerOption, opts ...Option) Scanner {
|
||||
opt(o)
|
||||
}
|
||||
|
||||
return Scanner{
|
||||
return Service{
|
||||
customHeaders: scannerOptions.CustomHeaders,
|
||||
client: o.rpcClient,
|
||||
}
|
||||
}
|
||||
|
||||
// Scan scans the image
|
||||
func (s Scanner) Scan(ctx context.Context, target, artifactKey string, blobKeys []string, opts types.ScanOptions) (types.Results, ftypes.OS, error) {
|
||||
func (s Service) Scan(ctx context.Context, target, artifactKey string, blobKeys []string, opts types.ScanOptions) (types.Results, ftypes.OS, error) {
|
||||
ctx = WithCustomHeaders(ctx, s.customHeaders)
|
||||
|
||||
// Convert to the rpc struct
|
||||
|
||||
@@ -195,7 +195,7 @@ func TestScanner_Scan(t *testing.T) {
|
||||
}))
|
||||
client := rpc.NewScannerJSONClient(ts.URL, ts.Client())
|
||||
|
||||
s := NewScanner(ScannerOption{CustomHeaders: tt.customHeaders}, WithRPCClient(client))
|
||||
s := NewService(ServiceOption{CustomHeaders: tt.customHeaders}, WithRPCClient(client))
|
||||
|
||||
gotResults, gotOS, err := s.Scan(t.Context(), tt.args.target, tt.args.imageID, tt.args.layerIDs, tt.args.options)
|
||||
|
||||
@@ -240,7 +240,7 @@ func TestScanner_ScanServerInsecure(t *testing.T) {
|
||||
},
|
||||
},
|
||||
})
|
||||
s := NewScanner(ScannerOption{Insecure: tt.insecure}, WithRPCClient(c))
|
||||
s := NewService(ServiceOption{Insecure: tt.insecure}, WithRPCClient(c))
|
||||
_, _, err := s.Scan(t.Context(), "dummy", "", nil, types.ScanOptions{})
|
||||
|
||||
if tt.wantErr != "" {
|
||||
|
||||
@@ -13,29 +13,30 @@ import (
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scan"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/local"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
xstrings "github.com/aquasecurity/trivy/pkg/x/strings"
|
||||
rpcCache "github.com/aquasecurity/trivy/rpc/cache"
|
||||
rpcScanner "github.com/aquasecurity/trivy/rpc/scanner"
|
||||
)
|
||||
|
||||
// ScanSuperSet binds the dependencies for server
|
||||
// ScanSuperSet binds the dependencies for the server implementation.
|
||||
var ScanSuperSet = wire.NewSet(
|
||||
local.SuperSet,
|
||||
wire.Bind(new(scanner.Driver), new(local.Scanner)),
|
||||
wire.Bind(new(scan.Backend), new(local.Service)),
|
||||
NewScanServer,
|
||||
)
|
||||
|
||||
// ScanServer implements the scanner
|
||||
// ScanServer implements the scanner service.
|
||||
// It uses local.Service as its backend to perform various types of security scanning.
|
||||
type ScanServer struct {
|
||||
localScanner scanner.Driver
|
||||
local scan.Backend
|
||||
}
|
||||
|
||||
// NewScanServer is the factory method for scanner
|
||||
func NewScanServer(s scanner.Driver) *ScanServer {
|
||||
return &ScanServer{localScanner: s}
|
||||
// NewScanServer creates a new ScanServer instance with the specified backend implementation.
|
||||
func NewScanServer(s scan.Backend) *ScanServer {
|
||||
return &ScanServer{local: s}
|
||||
}
|
||||
|
||||
// Log and return an error
|
||||
@@ -47,7 +48,7 @@ func teeError(err error) error {
|
||||
// Scan scans and return response
|
||||
func (s *ScanServer) Scan(ctx context.Context, in *rpcScanner.ScanRequest) (*rpcScanner.ScanResponse, error) {
|
||||
options := s.ToOptions(in.Options)
|
||||
results, os, err := s.localScanner.Scan(ctx, in.Target, in.ArtifactId, in.BlobIds, options)
|
||||
results, os, err := s.local.Scan(ctx, in.Target, in.ArtifactId, in.BlobIds, options)
|
||||
if err != nil {
|
||||
return nil, teeError(xerrors.Errorf("failed scan, %s: %w", in.Target, err))
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/applier"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/vulnerability"
|
||||
rpcCache "github.com/aquasecurity/trivy/rpc/cache"
|
||||
@@ -53,7 +53,7 @@ func TestScanServer_Scan(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
fixtures: []string{"../..//scanner/local/testdata/fixtures/happy.yaml"},
|
||||
fixtures: []string{"../../scan/local/testdata/fixtures/happy.yaml"},
|
||||
setUpCache: func(t *testing.T) cache.Cache {
|
||||
c := cache.NewMemoryCache()
|
||||
require.NoError(t, c.PutArtifact("sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", ftypes.ArtifactInfo{
|
||||
@@ -150,7 +150,7 @@ func TestScanServer_Scan(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
fixtures: []string{"../../scanner/local/testdata/fixtures/sad.yaml"},
|
||||
fixtures: []string{"../../scan/local/testdata/fixtures/sad.yaml"},
|
||||
setUpCache: func(t *testing.T) cache.Cache {
|
||||
c := cache.NewMemoryCache()
|
||||
require.NoError(t, c.PutArtifact("sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a", ftypes.ArtifactInfo{
|
||||
@@ -197,7 +197,7 @@ func TestScanServer_Scan(t *testing.T) {
|
||||
|
||||
// Create scanner
|
||||
applier := applier.NewApplier(c)
|
||||
scanner := local.NewScanner(applier, ospkg.NewScanner(), langpkg.NewScanner(), vulnerability.NewClient(db.Config{}))
|
||||
scanner := local.NewService(applier, ospkg.NewScanner(), langpkg.NewScanner(), vulnerability.NewClient(db.Config{}))
|
||||
s := NewScanServer(scanner)
|
||||
|
||||
got, err := s.Scan(t.Context(), tt.args.in)
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/applier"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/vulnerability"
|
||||
)
|
||||
|
||||
@@ -24,7 +24,7 @@ func initializeScanServer(localArtifactCache cache.LocalArtifactCache) *ScanServ
|
||||
langpkgScanner := langpkg.NewScanner()
|
||||
config := db.Config{}
|
||||
client := vulnerability.NewClient(config)
|
||||
localScanner := local.NewScanner(applierApplier, scanner, langpkgScanner, client)
|
||||
scanServer := NewScanServer(localScanner)
|
||||
service := local.NewService(applierApplier, scanner, langpkgScanner, client)
|
||||
scanServer := NewScanServer(service)
|
||||
return scanServer
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/purl"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom/core"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/iac/rego"
|
||||
"github.com/aquasecurity/trivy/pkg/licensing"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/post"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/post"
|
||||
"github.com/aquasecurity/trivy/pkg/set"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/vulnerability"
|
||||
@@ -38,21 +38,21 @@ var SuperSet = wire.NewSet(
|
||||
applier.NewApplier,
|
||||
ospkg.NewScanner,
|
||||
langpkg.NewScanner,
|
||||
NewScanner,
|
||||
NewService,
|
||||
)
|
||||
|
||||
// Scanner implements the OspkgDetector and LibraryDetector
|
||||
type Scanner struct {
|
||||
// Service implements the OspkgDetector and LibraryDetector
|
||||
type Service struct {
|
||||
applier applier.Applier
|
||||
osPkgScanner ospkg.Scanner
|
||||
langPkgScanner langpkg.Scanner
|
||||
vulnClient vulnerability.Client
|
||||
}
|
||||
|
||||
// NewScanner is the factory method for Scanner
|
||||
func NewScanner(a applier.Applier, osPkgScanner ospkg.Scanner, langPkgScanner langpkg.Scanner,
|
||||
vulnClient vulnerability.Client) Scanner {
|
||||
return Scanner{
|
||||
// NewService is the factory method for Scanner
|
||||
func NewService(a applier.Applier, osPkgScanner ospkg.Scanner, langPkgScanner langpkg.Scanner,
|
||||
vulnClient vulnerability.Client) Service {
|
||||
return Service{
|
||||
applier: a,
|
||||
osPkgScanner: osPkgScanner,
|
||||
langPkgScanner: langPkgScanner,
|
||||
@@ -61,7 +61,7 @@ func NewScanner(a applier.Applier, osPkgScanner ospkg.Scanner, langPkgScanner la
|
||||
}
|
||||
|
||||
// Scan scans the artifact and return results.
|
||||
func (s Scanner) Scan(ctx context.Context, targetName, artifactKey string, blobKeys []string, options types.ScanOptions) (
|
||||
func (s Service) Scan(ctx context.Context, targetName, artifactKey string, blobKeys []string, options types.ScanOptions) (
|
||||
types.Results, ftypes.OS, error) {
|
||||
detail, err := s.applier.ApplyLayers(artifactKey, blobKeys)
|
||||
switch {
|
||||
@@ -112,7 +112,7 @@ func (s Scanner) Scan(ctx context.Context, targetName, artifactKey string, blobK
|
||||
return s.ScanTarget(ctx, target, options)
|
||||
}
|
||||
|
||||
func (s Scanner) ScanTarget(ctx context.Context, target types.ScanTarget, options types.ScanOptions) (types.Results, ftypes.OS, error) {
|
||||
func (s Service) ScanTarget(ctx context.Context, target types.ScanTarget, options types.ScanOptions) (types.Results, ftypes.OS, error) {
|
||||
var results types.Results
|
||||
|
||||
// Filter packages according to the options
|
||||
@@ -157,7 +157,7 @@ func (s Scanner) ScanTarget(ctx context.Context, target types.ScanTarget, option
|
||||
return results, target.OS, nil
|
||||
}
|
||||
|
||||
func (s Scanner) scanVulnerabilities(ctx context.Context, target types.ScanTarget, options types.ScanOptions) (
|
||||
func (s Service) scanVulnerabilities(ctx context.Context, target types.ScanTarget, options types.ScanOptions) (
|
||||
types.Results, bool, error) {
|
||||
if !options.Scanners.AnyEnabled(types.SBOMScanner, types.VulnerabilityScanner) {
|
||||
return nil, false, nil
|
||||
@@ -190,7 +190,7 @@ func (s Scanner) scanVulnerabilities(ctx context.Context, target types.ScanTarge
|
||||
return results, eosl, nil
|
||||
}
|
||||
|
||||
func (s Scanner) misconfsToResults(misconfs []ftypes.Misconfiguration, options types.ScanOptions) types.Results {
|
||||
func (s Service) misconfsToResults(misconfs []ftypes.Misconfiguration, options types.ScanOptions) types.Results {
|
||||
if !ShouldScanMisconfigOrRbac(options.Scanners) &&
|
||||
!options.ImageConfigScanners.Enabled(types.MisconfigScanner) {
|
||||
return nil
|
||||
@@ -200,7 +200,7 @@ func (s Scanner) misconfsToResults(misconfs []ftypes.Misconfiguration, options t
|
||||
}
|
||||
|
||||
// MisconfsToResults is exported for trivy-plugin-aqua purposes only
|
||||
func (s Scanner) MisconfsToResults(misconfs []ftypes.Misconfiguration) types.Results {
|
||||
func (s Service) MisconfsToResults(misconfs []ftypes.Misconfiguration) types.Results {
|
||||
log.Info("Detected config files", log.Int("num", len(misconfs)))
|
||||
var results types.Results
|
||||
for _, misconf := range misconfs {
|
||||
@@ -233,7 +233,7 @@ func (s Scanner) MisconfsToResults(misconfs []ftypes.Misconfiguration) types.Res
|
||||
return results
|
||||
}
|
||||
|
||||
func (s Scanner) secretsToResults(secrets []ftypes.Secret, options types.ScanOptions) types.Results {
|
||||
func (s Service) secretsToResults(secrets []ftypes.Secret, options types.ScanOptions) types.Results {
|
||||
if !options.Scanners.Enabled(types.SecretScanner) {
|
||||
return nil
|
||||
}
|
||||
@@ -253,7 +253,7 @@ func (s Scanner) secretsToResults(secrets []ftypes.Secret, options types.ScanOpt
|
||||
return results
|
||||
}
|
||||
|
||||
func (s Scanner) scanLicenses(target types.ScanTarget, options types.ScanOptions) types.Results {
|
||||
func (s Service) scanLicenses(target types.ScanTarget, options types.ScanOptions) types.Results {
|
||||
if !options.Scanners.Enabled(types.LicenseScanner) {
|
||||
return nil
|
||||
}
|
||||
@@ -277,7 +277,7 @@ func (s Scanner) scanLicenses(target types.ScanTarget, options types.ScanOptions
|
||||
return results
|
||||
}
|
||||
|
||||
func (s Scanner) scanOSPackageLicenses(packages []ftypes.Package, scanner licensing.Scanner) *types.Result {
|
||||
func (s Service) scanOSPackageLicenses(packages []ftypes.Package, scanner licensing.Scanner) *types.Result {
|
||||
if len(packages) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -295,7 +295,7 @@ func (s Scanner) scanOSPackageLicenses(packages []ftypes.Package, scanner licens
|
||||
}
|
||||
}
|
||||
|
||||
func (s Scanner) scanApplicationLicenses(apps []ftypes.Application, scanner licensing.Scanner) []types.Result {
|
||||
func (s Service) scanApplicationLicenses(apps []ftypes.Application, scanner licensing.Scanner) []types.Result {
|
||||
var results []types.Result
|
||||
|
||||
for _, app := range apps {
|
||||
@@ -329,7 +329,7 @@ func (s Scanner) scanApplicationLicenses(apps []ftypes.Application, scanner lice
|
||||
return results
|
||||
}
|
||||
|
||||
func (s Scanner) scanFileLicenses(licenses []ftypes.LicenseFile, scanner licensing.Scanner, options types.ScanOptions) *types.Result {
|
||||
func (s Service) scanFileLicenses(licenses []ftypes.LicenseFile, scanner licensing.Scanner, options types.ScanOptions) *types.Result {
|
||||
if !options.LicenseFull {
|
||||
return nil
|
||||
}
|
||||
@@ -15,8 +15,8 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/applier"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/vulnerability"
|
||||
)
|
||||
@@ -1244,7 +1244,7 @@ func TestScanner_Scan(t *testing.T) {
|
||||
|
||||
c := tt.setupCache(t)
|
||||
a := applier.NewApplier(c)
|
||||
s := NewScanner(a, ospkg.NewScanner(), langpkg.NewScanner(), vulnerability.NewClient(db.Config{}))
|
||||
s := NewService(a, ospkg.NewScanner(), langpkg.NewScanner(), vulnerability.NewClient(db.Config{}))
|
||||
|
||||
gotResults, gotOS, err := s.Scan(t.Context(), tt.args.target, "", tt.args.layerIDs, tt.args.options)
|
||||
if tt.wantErr != "" {
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/post"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/post"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package scanner
|
||||
package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/report"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/local"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
@@ -35,8 +35,8 @@ var StandaloneSuperSet = wire.NewSet(
|
||||
wire.Bind(new(cache.LocalArtifactCache), new(cache.Cache)),
|
||||
|
||||
local.SuperSet,
|
||||
wire.Bind(new(Driver), new(local.Scanner)),
|
||||
NewScanner,
|
||||
wire.Bind(new(Backend), new(local.Service)),
|
||||
NewService,
|
||||
)
|
||||
|
||||
// StandaloneDockerSet binds docker dependencies
|
||||
@@ -87,10 +87,10 @@ var RemoteSuperSet = wire.NewSet(
|
||||
cache.NewRemoteCache,
|
||||
wire.Bind(new(cache.ArtifactCache), new(*cache.RemoteCache)), // No need for LocalArtifactCache
|
||||
|
||||
client.NewScanner,
|
||||
client.NewService,
|
||||
wire.Value([]client.Option(nil)),
|
||||
wire.Bind(new(Driver), new(client.Scanner)),
|
||||
NewScanner,
|
||||
wire.Bind(new(Backend), new(client.Service)),
|
||||
NewService,
|
||||
)
|
||||
|
||||
// RemoteFilesystemSet binds filesystem dependencies for client/server mode
|
||||
@@ -131,28 +131,36 @@ var RemoteArchiveSet = wire.NewSet(
|
||||
RemoteSuperSet,
|
||||
)
|
||||
|
||||
// Scanner implements the Artifact and Driver operations
|
||||
type Scanner struct {
|
||||
driver Driver
|
||||
// Service is the main service that coordinates security scanning operations.
|
||||
// It uses either local.Service or remote.Service as its backend implementation.
|
||||
type Service struct {
|
||||
backend Backend
|
||||
artifact artifact.Artifact
|
||||
}
|
||||
|
||||
// Driver defines operations of scanner
|
||||
type Driver interface {
|
||||
// Backend defines the interface for security scanning implementations.
|
||||
// It can be either local.Service for standalone scanning or remote.Service
|
||||
// for client/server mode scanning. The backend handles various types of
|
||||
// security scanning including vulnerability, misconfiguration, secret,
|
||||
// and license scanning.
|
||||
type Backend interface {
|
||||
Scan(ctx context.Context, target, artifactKey string, blobKeys []string, options types.ScanOptions) (
|
||||
results types.Results, osFound ftypes.OS, err error)
|
||||
}
|
||||
|
||||
// NewScanner is the factory method of Scanner
|
||||
func NewScanner(driver Driver, ar artifact.Artifact) Scanner {
|
||||
return Scanner{
|
||||
driver: driver,
|
||||
// NewService creates a new Service instance with the specified backend implementation
|
||||
// and artifact handler.
|
||||
func NewService(backend Backend, ar artifact.Artifact) Service {
|
||||
return Service{
|
||||
backend: backend,
|
||||
artifact: ar,
|
||||
}
|
||||
}
|
||||
|
||||
// ScanArtifact scans the artifacts and returns results
|
||||
func (s Scanner) ScanArtifact(ctx context.Context, options types.ScanOptions) (types.Report, error) {
|
||||
// ScanArtifact performs security scanning on the specified artifact.
|
||||
// It first inspects the artifact to gather necessary information,
|
||||
// then delegates the actual scanning to the configured backend implementation.
|
||||
func (s Service) ScanArtifact(ctx context.Context, options types.ScanOptions) (types.Report, error) {
|
||||
artifactInfo, err := s.artifact.Inspect(ctx)
|
||||
if err != nil {
|
||||
return types.Report{}, xerrors.Errorf("failed analysis: %w", err)
|
||||
@@ -164,7 +172,7 @@ func (s Scanner) ScanArtifact(ctx context.Context, options types.ScanOptions) (t
|
||||
}
|
||||
}()
|
||||
|
||||
results, osFound, err := s.driver.Scan(ctx, artifactInfo.Name, artifactInfo.ID, artifactInfo.BlobIDs, options)
|
||||
results, osFound, err := s.backend.Scan(ctx, artifactInfo.Name, artifactInfo.ID, artifactInfo.BlobIDs, options)
|
||||
if err != nil {
|
||||
return types.Report{}, xerrors.Errorf("scan failed: %w", err)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package scanner
|
||||
package scan
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -19,9 +19,9 @@ import (
|
||||
image2 "github.com/aquasecurity/trivy/pkg/fanal/artifact/image"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/image"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/langpkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/local"
|
||||
"github.com/aquasecurity/trivy/pkg/scan/ospkg"
|
||||
tTypes "github.com/aquasecurity/trivy/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/vulnerability"
|
||||
)
|
||||
@@ -216,8 +216,8 @@ func TestScanner_ScanArtifact(t *testing.T) {
|
||||
|
||||
// Create scanner
|
||||
applier := applier.NewApplier(c)
|
||||
scanner := local.NewScanner(applier, ospkg.NewScanner(), langpkg.NewScanner(), vulnerability.NewClient(db.Config{}))
|
||||
s := NewScanner(scanner, artifact)
|
||||
scanner := local.NewService(applier, ospkg.NewScanner(), langpkg.NewScanner(), vulnerability.NewClient(db.Config{}))
|
||||
s := NewService(scanner, artifact)
|
||||
|
||||
ctx := clock.With(t.Context(), time.Date(2021, 8, 25, 12, 20, 30, 5, time.UTC))
|
||||
got, err := s.ScanArtifact(ctx, tt.args.options)
|
||||
Reference in New Issue
Block a user