diff --git a/docs/docs/references/modes/client-server.md b/docs/docs/references/modes/client-server.md index 518fe45efc8a..7aa90abf0b22 100644 --- a/docs/docs/references/modes/client-server.md +++ b/docs/docs/references/modes/client-server.md @@ -2,9 +2,22 @@ Trivy has client/server mode. Trivy server has vulnerability database and Trivy client doesn't have to download vulnerability database. It is useful if you want to scan images or files at multiple locations and do not want to download the database at every location. -| Client/Server Mode | Image | Rootfs | Filesystem | Repository | Config | AWS | K8s | -|:---------------------:|:-----:|:------:|:----------:|:----------:|:------:|:---:|:---:| -| Supported | ✅ | ✅ | ✅ | ✅ | ✅ | X | X | +| Client/Server Mode | Image | Rootfs | Filesystem | Repository | Config | K8s | +|:------------------:|:-----:|:------:|:----------:|:----------:|:------:|:---:| +| Supported | ✅ | ✅ | ✅ | ✅ | - | - | + +Some scanners run on the client side, even in client/server mode. + +| Scanner | Run on Client or Server | +|:----------------:|:-----------------------:| +| Vulnerability | Server | +| Misconfiguration | Client[^1] | +| Secret | Client[^2] | +| License | Server | + +!!! note + Scanning of misconfigurations and licenses is performed on the client side (as in standalone mode). + Otherwise, the client would need to send files to the server that may contain sensitive information. ## Server At first, you need to launch Trivy server. It downloads vulnerability database automatically and continue to fetch the latest DB in the background. @@ -338,3 +351,5 @@ Returns the `200 OK` status if the request was successful. ![architecture](../../../imgs/client-server.png) +[^1]: The checks bundle is also downloaded on the client side. +[^2]: The scan result with masked secrets is sent to the server \ No newline at end of file diff --git a/pkg/commands/artifact/run.go b/pkg/commands/artifact/run.go index 6528ec2c3d36..3cd1b9af74b5 100644 --- a/pkg/commands/artifact/run.go +++ b/pkg/commands/artifact/run.go @@ -40,7 +40,6 @@ const ( TargetFilesystem TargetKind = "fs" TargetRootfs TargetKind = "rootfs" TargetRepository TargetKind = "repo" - TargetImageArchive TargetKind = "archive" TargetSBOM TargetKind = "sbom" TargetVM TargetKind = "vm" ) @@ -345,6 +344,15 @@ func Run(ctx context.Context, opts flag.Options, targetKind TargetKind) (err err } }() + if opts.ServerAddr != "" && opts.Scanners.AnyEnabled(types.MisconfigScanner, types.SecretScanner) { + log.WarnContext(ctx, + fmt.Sprintf( + "Trivy runs in client/server mode, but misconfiguration and license scanning will be done on the client side, see %s", + doc.URL("/docs/references/modes/client-server", ""), + ), + ) + } + if opts.GenerateDefaultConfig { log.Info("Writing the default config to trivy-default.yaml...") return viper.SafeWriteConfigAs("trivy-default.yaml") @@ -359,32 +367,23 @@ func Run(ctx context.Context, opts flag.Options, targetKind TargetKind) (err err } defer r.Close(ctx) - var report types.Report - switch targetKind { - case TargetContainerImage, TargetImageArchive: - if report, err = r.ScanImage(ctx, opts); err != nil { - return xerrors.Errorf("image scan error: %w", err) - } - case TargetFilesystem: - if report, err = r.ScanFilesystem(ctx, opts); err != nil { - return xerrors.Errorf("filesystem scan error: %w", err) - } - case TargetRootfs: - if report, err = r.ScanRootfs(ctx, opts); err != nil { - return xerrors.Errorf("rootfs scan error: %w", err) - } - case TargetRepository: - if report, err = r.ScanRepository(ctx, opts); err != nil { - return xerrors.Errorf("repository scan error: %w", err) - } - case TargetSBOM: - if report, err = r.ScanSBOM(ctx, opts); err != nil { - return xerrors.Errorf("sbom scan error: %w", err) - } - case TargetVM: - if report, err = r.ScanVM(ctx, opts); err != nil { - return xerrors.Errorf("vm scan error: %w", err) - } + scans := map[TargetKind]func(context.Context, flag.Options) (types.Report, error){ + TargetContainerImage: r.ScanImage, + TargetFilesystem: r.ScanFilesystem, + TargetRootfs: r.ScanRootfs, + TargetRepository: r.ScanRepository, + TargetSBOM: r.ScanSBOM, + TargetVM: r.ScanVM, + } + + scanFunction, exists := scans[targetKind] + if !exists { + return xerrors.Errorf("unknown target kind: %s", targetKind) + } + + report, err := scanFunction(ctx, opts) + if err != nil { + return xerrors.Errorf("%s scan error: %w", targetKind, err) } report, err = r.Filter(ctx, opts, report)