mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-21 23:00:42 -08:00
feat(cli): convert JSON reports into a different format (#4452)
Co-authored-by: Aurelien LAJOIE <aurelien.lajoie@kili-technology.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
# Reporting
|
||||
|
||||
## Supported Formats
|
||||
Trivy supports the following formats:
|
||||
|
||||
- Table
|
||||
@@ -8,7 +9,7 @@ Trivy supports the following formats:
|
||||
- Template
|
||||
- SBOM
|
||||
|
||||
## Table (Default)
|
||||
### Table (Default)
|
||||
|
||||
| Scanner | Supported |
|
||||
|:----------------:|:---------:|
|
||||
@@ -21,7 +22,7 @@ Trivy supports the following formats:
|
||||
$ trivy image -f table golang:1.12-alpine
|
||||
```
|
||||
|
||||
### Show origins of vulnerable dependencies
|
||||
#### Show origins of vulnerable dependencies
|
||||
|
||||
| Scanner | Supported |
|
||||
|:----------------:|:---------:|
|
||||
@@ -105,7 +106,7 @@ Also, **glob-parent@3.1.0** with some vulnerabilities is included through chain
|
||||
|
||||
Then, you can try to update **axios@0.21.4** and **cra-append-sw@2.7.0** to resolve vulnerabilities in **follow-redirects@1.14.6** and **glob-parent@3.1.0**.
|
||||
|
||||
## JSON
|
||||
### JSON
|
||||
|
||||
| Scanner | Supported |
|
||||
|:----------------:|:---------:|
|
||||
@@ -239,7 +240,7 @@ $ trivy image -f json -o results.json golang:1.12-alpine
|
||||
|
||||
`VulnerabilityID`, `PkgName`, `InstalledVersion`, and `Severity` in `Vulnerabilities` are always filled with values, but other fields might be empty.
|
||||
|
||||
## SARIF
|
||||
### SARIF
|
||||
| Scanner | Supported |
|
||||
|:----------------:|:---------:|
|
||||
| Vulnerability | ✓ |
|
||||
@@ -255,7 +256,7 @@ $ trivy image --format sarif -o report.sarif golang:1.12-alpine
|
||||
|
||||
This SARIF file can be uploaded to GitHub code scanning results, and there is a [Trivy GitHub Action][action] for automating this process.
|
||||
|
||||
## Template
|
||||
### Template
|
||||
|
||||
| Scanner | Supported |
|
||||
|:----------------:|:---------:|
|
||||
@@ -264,7 +265,7 @@ This SARIF file can be uploaded to GitHub code scanning results, and there is a
|
||||
| Secret | ✓ |
|
||||
| License | ✓ |
|
||||
|
||||
### Custom Template
|
||||
#### Custom Template
|
||||
|
||||
{% raw %}
|
||||
```
|
||||
@@ -301,18 +302,18 @@ Critical: 0, High: 2
|
||||
|
||||
For other features of sprig, see the official [sprig][sprig] documentation.
|
||||
|
||||
### Load templates from a file
|
||||
#### Load templates from a file
|
||||
You can load templates from a file prefixing the template path with an @.
|
||||
|
||||
```
|
||||
$ trivy image --format template --template "@/path/to/template" golang:1.12-alpine
|
||||
```
|
||||
|
||||
### Default Templates
|
||||
#### Default Templates
|
||||
|
||||
If Trivy is installed using rpm then default templates can be found at `/usr/local/share/trivy/templates`.
|
||||
|
||||
#### JUnit
|
||||
##### JUnit
|
||||
| Scanner | Supported |
|
||||
|:----------------:|:---------:|
|
||||
| Vulnerability | ✓ |
|
||||
@@ -325,7 +326,7 @@ In the following example using the template `junit.tpl` XML can be generated.
|
||||
$ trivy image --format template --template "@contrib/junit.tpl" -o junit-report.xml golang:1.12-alpine
|
||||
```
|
||||
|
||||
#### ASFF
|
||||
##### ASFF
|
||||
| Scanner | Supported |
|
||||
|:----------------:|:---------:|
|
||||
| Vulnerability | ✓ |
|
||||
@@ -335,7 +336,7 @@ $ trivy image --format template --template "@contrib/junit.tpl" -o junit-report.
|
||||
|
||||
Trivy also supports an [ASFF template for reporting findings to AWS Security Hub][asff]
|
||||
|
||||
#### HTML
|
||||
##### HTML
|
||||
| Scanner | Supported |
|
||||
|:----------------:|:---------:|
|
||||
| Vulnerability | ✓ |
|
||||
@@ -353,9 +354,34 @@ The following example shows use of default HTML template when Trivy is installed
|
||||
$ trivy image --format template --template "@/usr/local/share/trivy/templates/html.tpl" -o report.html golang:1.12-alpine
|
||||
```
|
||||
|
||||
## SBOM
|
||||
### SBOM
|
||||
See [here](../supply-chain/sbom.md) for details.
|
||||
|
||||
## Converting
|
||||
To generate multiple reports, you can generate the JSON report first and convert it to other formats with the `convert` subcommand.
|
||||
|
||||
```shell
|
||||
$ trivy image --format json -o result.json --list-all-pkgs debian:11
|
||||
$ trivy convert --format cyclonedx --output result.cdx result.json
|
||||
```
|
||||
|
||||
!!! note
|
||||
Please note that if you want to convert to a format that requires a list of packages,
|
||||
such as SBOM, you need to add the `--list-all-pkgs` flag when outputting in JSON.
|
||||
|
||||
[Filtering options](./filtering.md) such as `--severity` are also available with `convert`.
|
||||
|
||||
```shell
|
||||
# Output all severities in JSON
|
||||
$ trivy image --format json -o result.json --list-all-pkgs debian:11
|
||||
|
||||
# Output only critical issues in table format
|
||||
$ trivy convert --format table --severity CRITICAL result.json
|
||||
```
|
||||
|
||||
!!! note
|
||||
JSON reports from "trivy aws" and "trivy k8s" are not yet supported.
|
||||
|
||||
[cargo-auditable]: https://github.com/rust-secure-code/cargo-auditable/
|
||||
[action]: https://github.com/aquasecurity/trivy-action
|
||||
[asff]: ../../tutorials/integrations/aws-security-hub.md
|
||||
|
||||
@@ -45,6 +45,7 @@ trivy [global flags] command [flags] target
|
||||
|
||||
* [trivy aws](trivy_aws.md) - [EXPERIMENTAL] Scan AWS account
|
||||
* [trivy config](trivy_config.md) - Scan config files for misconfigurations
|
||||
* [trivy convert](trivy_convert.md) - Convert Trivy JSON report into a different format
|
||||
* [trivy filesystem](trivy_filesystem.md) - Scan local filesystem
|
||||
* [trivy image](trivy_image.md) - Scan a container image
|
||||
* [trivy kubernetes](trivy_kubernetes.md) - [EXPERIMENTAL] Scan kubernetes cluster
|
||||
|
||||
52
docs/docs/references/configuration/cli/trivy_convert.md
Normal file
52
docs/docs/references/configuration/cli/trivy_convert.md
Normal file
@@ -0,0 +1,52 @@
|
||||
## trivy convert
|
||||
|
||||
Convert Trivy JSON report into a different format
|
||||
|
||||
```
|
||||
trivy convert [flags] RESULT_JSON
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
# report conversion
|
||||
$ trivy image --format json --output result.json --list-all-pkgs debian:11
|
||||
$ trivy convert --format cyclonedx --output result.cdx result.json
|
||||
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--compliance string compliance report to generate
|
||||
--dependency-tree [EXPERIMENTAL] show dependency origin tree of vulnerable packages
|
||||
--exit-code int specify exit code when any security issues are found
|
||||
--exit-on-eol int exit with the specified code when the OS reaches end of service/life
|
||||
-f, --format string format (table, json, template, sarif, cyclonedx, spdx, spdx-json, github, cosign-vuln) (default "table")
|
||||
-h, --help help for convert
|
||||
--ignore-policy string specify the Rego file path to evaluate each vulnerability
|
||||
--ignorefile string specify .trivyignore file (default ".trivyignore")
|
||||
--list-all-pkgs enabling the option will output all packages regardless of vulnerability
|
||||
-o, --output string output file name
|
||||
--report string specify a report format for the output. (all,summary) (default "all")
|
||||
-s, --severity string severities of security issues to be displayed (comma separated) (default "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL")
|
||||
-t, --template string output template
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--cache-dir string cache directory (default "/path/to/cache")
|
||||
-c, --config string config path (default "trivy.yaml")
|
||||
-d, --debug debug mode
|
||||
--generate-default-config write the default config to trivy-default.yaml
|
||||
--insecure allow insecure server connections
|
||||
-q, --quiet suppress progress bar and log output
|
||||
--timeout duration timeout (default 5m0s)
|
||||
-v, --version show version
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [trivy](trivy.md) - Unified security scanner
|
||||
|
||||
@@ -3,3 +3,9 @@
|
||||
### How to pronounce the name "Trivy"?
|
||||
|
||||
`tri` is pronounced like **tri**gger, `vy` is pronounced like en**vy**.
|
||||
|
||||
### How to generate multiple reports?
|
||||
See [here](../docs/configuration/reporting.md#converting).
|
||||
|
||||
### How to run Trivy under air-gapped environment?
|
||||
See [here](../docs/advanced/air-gap.md).
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/cloud"
|
||||
"github.com/aquasecurity/trivy/pkg/cloud/aws/scanner"
|
||||
"github.com/aquasecurity/trivy/pkg/cloud/report"
|
||||
cmd "github.com/aquasecurity/trivy/pkg/commands/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/commands/operation"
|
||||
cr "github.com/aquasecurity/trivy/pkg/compliance/report"
|
||||
"github.com/aquasecurity/trivy/pkg/flag"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
@@ -147,6 +147,6 @@ func Run(ctx context.Context, opt flag.Options) error {
|
||||
return fmt.Errorf("unable to write results: %w", err)
|
||||
}
|
||||
|
||||
cmd.Exit(opt, r.Failed())
|
||||
operation.Exit(opt, r.Failed())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ const (
|
||||
tableFormat = "table"
|
||||
)
|
||||
|
||||
// Report represents a kubernetes scan report
|
||||
// Report represents an AWS scan report
|
||||
type Report struct {
|
||||
Provider string
|
||||
AccountID string
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
javadb "github.com/aquasecurity/trivy-java-db/pkg/db"
|
||||
awscommands "github.com/aquasecurity/trivy/pkg/cloud/aws/commands"
|
||||
"github.com/aquasecurity/trivy/pkg/commands/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/commands/convert"
|
||||
"github.com/aquasecurity/trivy/pkg/commands/server"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||
"github.com/aquasecurity/trivy/pkg/flag"
|
||||
@@ -106,6 +107,7 @@ func NewApp(version string) *cobra.Command {
|
||||
NewClientCommand(globalFlags),
|
||||
NewServerCommand(globalFlags),
|
||||
NewConfigCommand(globalFlags),
|
||||
NewConvertCommand(globalFlags),
|
||||
NewPluginCommand(),
|
||||
NewModuleCommand(globalFlags),
|
||||
NewKubernetesCommand(globalFlags),
|
||||
@@ -494,6 +496,47 @@ func NewRepositoryCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func NewConvertCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
convertFlags := &flag.Flags{
|
||||
ScanFlagGroup: &flag.ScanFlagGroup{},
|
||||
ReportFlagGroup: flag.NewReportFlagGroup(),
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "convert [flags] RESULT_JSON",
|
||||
Aliases: []string{"conv"},
|
||||
GroupID: groupUtility,
|
||||
Short: "Convert Trivy JSON report into a different format",
|
||||
Example: ` # report conversion
|
||||
$ trivy image --format json --output result.json --list-all-pkgs debian:11
|
||||
$ trivy convert --format cyclonedx --output result.cdx result.json
|
||||
`,
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := convertFlags.Bind(cmd); err != nil {
|
||||
return xerrors.Errorf("flag bind error: %w", err)
|
||||
}
|
||||
return validateArgs(cmd, args)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := convertFlags.Bind(cmd); err != nil {
|
||||
return xerrors.Errorf("flag bind error: %w", err)
|
||||
}
|
||||
opts, err := convertFlags.ToOptions(cmd.Version, args, globalFlags, outputWriter)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("flag error: %w", err)
|
||||
}
|
||||
|
||||
return convert.Run(cmd.Context(), opts)
|
||||
},
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
}
|
||||
cmd.SetFlagErrorFunc(flagErrorFunc)
|
||||
convertFlags.AddFlags(cmd)
|
||||
cmd.SetUsageTemplate(fmt.Sprintf(usageTemplate, convertFlags.Usages(cmd)))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// NewClientCommand returns the 'client' subcommand that is deprecated
|
||||
func NewClientCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
remoteFlags := flag.NewClientFlags()
|
||||
@@ -799,7 +842,7 @@ func NewModuleCommand(globalFlags *flag.GlobalFlagGroup) *cobra.Command {
|
||||
if err != nil {
|
||||
return xerrors.Errorf("flag error: %w", err)
|
||||
}
|
||||
return module.Install(cmd.Context(), opts.ModuleDir, repo, opts.Quiet, opts.Registry())
|
||||
return module.Install(cmd.Context(), opts.ModuleDir, repo, opts.Quiet, opts.RegistryOpts())
|
||||
},
|
||||
},
|
||||
&cobra.Command{
|
||||
|
||||
@@ -4,9 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/policy"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/spf13/viper"
|
||||
@@ -26,6 +23,7 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/misconf"
|
||||
"github.com/aquasecurity/trivy/pkg/module"
|
||||
"github.com/aquasecurity/trivy/pkg/policy"
|
||||
pkgReport "github.com/aquasecurity/trivy/pkg/report"
|
||||
"github.com/aquasecurity/trivy/pkg/result"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client"
|
||||
@@ -273,15 +271,7 @@ func (r *runner) scanArtifact(ctx context.Context, opts flag.Options, initialize
|
||||
|
||||
func (r *runner) Filter(ctx context.Context, opts flag.Options, report types.Report) (types.Report, error) {
|
||||
// Filter results
|
||||
err := result.Filter(ctx, report, result.FilterOption{
|
||||
Severities: opts.Severities,
|
||||
IgnoreUnfixed: opts.IgnoreUnfixed,
|
||||
IncludeNonFailures: opts.IncludeNonFailures,
|
||||
IgnoreFile: opts.IgnoreFile,
|
||||
PolicyFile: opts.IgnorePolicy,
|
||||
IgnoreLicenses: opts.IgnoredLicenses,
|
||||
VEXPath: opts.VEXPath,
|
||||
})
|
||||
err := result.Filter(ctx, report, opts.FilterOpts())
|
||||
if err != nil {
|
||||
return types.Report{}, xerrors.Errorf("filtering error: %w", err)
|
||||
}
|
||||
@@ -290,18 +280,7 @@ func (r *runner) Filter(ctx context.Context, opts flag.Options, report types.Rep
|
||||
}
|
||||
|
||||
func (r *runner) Report(opts flag.Options, report types.Report) error {
|
||||
if err := pkgReport.Write(report, pkgReport.Option{
|
||||
AppVersion: opts.AppVersion,
|
||||
Format: opts.Format,
|
||||
Output: opts.Output,
|
||||
Tree: opts.DependencyTree,
|
||||
Severities: opts.Severities,
|
||||
OutputTemplate: opts.Template,
|
||||
IncludeNonFailures: opts.IncludeNonFailures,
|
||||
Trace: opts.Trace,
|
||||
Report: opts.ReportFormat,
|
||||
Compliance: opts.Compliance,
|
||||
}); err != nil {
|
||||
if err := pkgReport.Write(report, opts.ReportOpts()); err != nil {
|
||||
return xerrors.Errorf("unable to write results: %w", err)
|
||||
}
|
||||
|
||||
@@ -320,7 +299,7 @@ func (r *runner) initDB(ctx context.Context, opts flag.Options) error {
|
||||
|
||||
// download the database file
|
||||
noProgress := opts.Quiet || opts.NoProgress
|
||||
if err := operation.DownloadDB(ctx, opts.AppVersion, opts.CacheDir, opts.DBRepository, noProgress, opts.SkipDBUpdate, opts.Registry()); err != nil {
|
||||
if err := operation.DownloadDB(ctx, opts.AppVersion, opts.CacheDir, opts.DBRepository, noProgress, opts.SkipDBUpdate, opts.RegistryOpts()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -475,8 +454,8 @@ func Run(ctx context.Context, opts flag.Options, targetKind TargetKind) (err err
|
||||
return xerrors.Errorf("report error: %w", err)
|
||||
}
|
||||
|
||||
exitOnEOL(opts, report.Metadata)
|
||||
Exit(opts, report.Results.Failed())
|
||||
operation.ExitOnEOL(opts, report.Metadata)
|
||||
operation.Exit(opts, report.Results.Failed())
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -661,7 +640,7 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
|
||||
|
||||
// For image scanning
|
||||
ImageOption: ftypes.ImageOptions{
|
||||
RegistryOptions: opts.Registry(),
|
||||
RegistryOptions: opts.RegistryOpts(),
|
||||
DockerOptions: ftypes.DockerOptions{
|
||||
Host: opts.DockerHost,
|
||||
},
|
||||
@@ -704,19 +683,6 @@ func scan(ctx context.Context, opts flag.Options, initializeScanner InitializeSc
|
||||
return report, nil
|
||||
}
|
||||
|
||||
func Exit(opts flag.Options, failedResults bool) {
|
||||
if opts.ExitCode != 0 && failedResults {
|
||||
os.Exit(opts.ExitCode)
|
||||
}
|
||||
}
|
||||
|
||||
func exitOnEOL(opts flag.Options, m types.Metadata) {
|
||||
if opts.ExitOnEOL != 0 && m.OS != nil && m.OS.Eosl {
|
||||
log.Logger.Errorf("Detected EOL OS: %s %s", m.OS.Family, m.OS.Name)
|
||||
os.Exit(opts.ExitOnEOL)
|
||||
}
|
||||
}
|
||||
|
||||
func canonicalVersion(ver string) string {
|
||||
if ver == devVersion {
|
||||
return ver
|
||||
|
||||
48
pkg/commands/convert/run.go
Normal file
48
pkg/commands/convert/run.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package convert
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/commands/operation"
|
||||
"github.com/aquasecurity/trivy/pkg/flag"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/report"
|
||||
"github.com/aquasecurity/trivy/pkg/result"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
func Run(ctx context.Context, opts flag.Options) (err error) {
|
||||
f, err := os.Open(opts.Target)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("file open error: %w", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var r types.Report
|
||||
if err = json.NewDecoder(f).Decode(&r); err != nil {
|
||||
return xerrors.Errorf("json decode error: %w", err)
|
||||
}
|
||||
|
||||
// "convert" supports JSON results produced by Trivy scanning other than AWS and Kubernetes
|
||||
if r.ArtifactName == "" && r.ArtifactType == "" {
|
||||
return xerrors.New("AWS and Kubernetes scanning reports are not yet supported")
|
||||
}
|
||||
|
||||
if err = result.Filter(ctx, r, opts.FilterOpts()); err != nil {
|
||||
return xerrors.Errorf("unable to filter results: %w", err)
|
||||
}
|
||||
|
||||
log.Logger.Debug("Writing report to output...")
|
||||
if err = report.Write(r, opts.ReportOpts()); err != nil {
|
||||
return xerrors.Errorf("unable to write results: %w", err)
|
||||
}
|
||||
|
||||
operation.ExitOnEOL(opts, r.Metadata)
|
||||
operation.Exit(opts, r.Results.Failed())
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -16,10 +16,11 @@ import (
|
||||
"github.com/aquasecurity/trivy-db/pkg/metadata"
|
||||
"github.com/aquasecurity/trivy/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/flag"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/policy"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/utils/fsutils"
|
||||
)
|
||||
|
||||
@@ -109,7 +110,7 @@ func (c Cache) ClearArtifacts() error {
|
||||
}
|
||||
|
||||
// DownloadDB downloads the DB
|
||||
func DownloadDB(ctx context.Context, appVersion, cacheDir, dbRepository string, quiet, skipUpdate bool, opt types.RegistryOptions) error {
|
||||
func DownloadDB(ctx context.Context, appVersion, cacheDir, dbRepository string, quiet, skipUpdate bool, opt ftypes.RegistryOptions) error {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
@@ -201,3 +202,16 @@ func GetTLSConfig(caCertPath, certPath, keyPath string) (*x509.CertPool, tls.Cer
|
||||
|
||||
return caCertPool, cert, nil
|
||||
}
|
||||
|
||||
func Exit(opts flag.Options, failedResults bool) {
|
||||
if opts.ExitCode != 0 && failedResults {
|
||||
os.Exit(opts.ExitCode)
|
||||
}
|
||||
}
|
||||
|
||||
func ExitOnEOL(opts flag.Options, m types.Metadata) {
|
||||
if opts.ExitOnEOL != 0 && m.OS != nil && m.OS.Eosl {
|
||||
log.Logger.Errorf("Detected EOL OS: %s %s", m.OS.Family, m.OS.Name)
|
||||
os.Exit(opts.ExitOnEOL)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func Run(ctx context.Context, opts flag.Options) (err error) {
|
||||
|
||||
// download the database file
|
||||
if err = operation.DownloadDB(ctx, opts.AppVersion, opts.CacheDir, opts.DBRepository,
|
||||
true, opts.SkipDBUpdate, opts.Registry()); err != nil {
|
||||
true, opts.SkipDBUpdate, opts.RegistryOpts()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -58,6 +58,6 @@ func Run(ctx context.Context, opts flag.Options) (err error) {
|
||||
m.Register()
|
||||
|
||||
server := rpcServer.NewServer(opts.AppVersion, opts.Listen, opts.CacheDir, opts.Token, opts.TokenHeader,
|
||||
opts.DBRepository, opts.Registry())
|
||||
opts.DBRepository, opts.RegistryOpts())
|
||||
return server.ListenAndServe(cache, opts.SkipDBUpdate)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/report"
|
||||
"github.com/aquasecurity/trivy/pkg/result"
|
||||
)
|
||||
|
||||
type Flag struct {
|
||||
@@ -122,8 +123,8 @@ func (o *Options) Align() {
|
||||
}
|
||||
}
|
||||
|
||||
// Registry returns options for OCI registries
|
||||
func (o *Options) Registry() ftypes.RegistryOptions {
|
||||
// RegistryOpts returns options for OCI registries
|
||||
func (o *Options) RegistryOpts() ftypes.RegistryOptions {
|
||||
return ftypes.RegistryOptions{
|
||||
Credentials: o.Credentials,
|
||||
RegistryToken: o.RegistryToken,
|
||||
@@ -133,6 +134,34 @@ func (o *Options) Registry() ftypes.RegistryOptions {
|
||||
}
|
||||
}
|
||||
|
||||
// FilterOpts returns options for filtering
|
||||
func (o *Options) FilterOpts() result.FilterOption {
|
||||
return result.FilterOption{
|
||||
Severities: o.Severities,
|
||||
IgnoreUnfixed: o.IgnoreUnfixed,
|
||||
IncludeNonFailures: o.IncludeNonFailures,
|
||||
IgnoreFile: o.IgnoreFile,
|
||||
PolicyFile: o.IgnorePolicy,
|
||||
IgnoreLicenses: o.IgnoredLicenses,
|
||||
VEXPath: o.VEXPath,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Options) ReportOpts() report.Option {
|
||||
return report.Option{
|
||||
AppVersion: o.AppVersion,
|
||||
Format: o.Format,
|
||||
Output: o.Output,
|
||||
Tree: o.DependencyTree,
|
||||
Severities: o.Severities,
|
||||
OutputTemplate: o.Template,
|
||||
IncludeNonFailures: o.IncludeNonFailures,
|
||||
Trace: o.Trace,
|
||||
Report: o.ReportFormat,
|
||||
Compliance: o.Compliance,
|
||||
}
|
||||
}
|
||||
|
||||
func addFlag(cmd *cobra.Command, flag *Flag) {
|
||||
if flag == nil || flag.Name == "" {
|
||||
return
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/aquasecurity/trivy-kubernetes/pkg/artifacts"
|
||||
"github.com/aquasecurity/trivy-kubernetes/pkg/k8s"
|
||||
cmd "github.com/aquasecurity/trivy/pkg/commands/artifact"
|
||||
"github.com/aquasecurity/trivy/pkg/commands/operation"
|
||||
cr "github.com/aquasecurity/trivy/pkg/compliance/report"
|
||||
"github.com/aquasecurity/trivy/pkg/flag"
|
||||
"github.com/aquasecurity/trivy/pkg/k8s/report"
|
||||
@@ -120,7 +121,7 @@ func (r *runner) run(ctx context.Context, artifacts []*artifacts.Artifact) error
|
||||
return xerrors.Errorf("unable to write results: %w", err)
|
||||
}
|
||||
|
||||
cmd.Exit(r.flagOpts, rpt.Failed())
|
||||
operation.Exit(r.flagOpts, rpt.Failed())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -139,6 +139,9 @@ func (m *Marshaler) Marshal(r types.Report) (*spdx.Document, error) {
|
||||
)
|
||||
|
||||
for _, result := range r.Results {
|
||||
if len(result.Packages) == 0 {
|
||||
continue
|
||||
}
|
||||
parentPackage, err := m.resultToSpdxPackage(result, r.Metadata.OS, pkgDownloadLocation)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to parse result: %w", err)
|
||||
|
||||
@@ -761,6 +761,69 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path secret",
|
||||
inputReport: types.Report{
|
||||
SchemaVersion: report.SchemaVersion,
|
||||
ArtifactName: "secret",
|
||||
ArtifactType: ftypes.ArtifactFilesystem,
|
||||
Results: types.Results{
|
||||
{
|
||||
Target: "key.pem",
|
||||
Class: types.ClassSecret,
|
||||
Secrets: []ftypes.SecretFinding{
|
||||
{
|
||||
RuleID: "private-key",
|
||||
Category: "AsymmetricPrivateKey",
|
||||
Severity: "HIGH",
|
||||
Title: "Asymmetric Private Key",
|
||||
StartLine: 1,
|
||||
EndLine: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantSBOM: &spdx.Document{
|
||||
SPDXVersion: spdx.Version,
|
||||
DataLicense: spdx.DataLicense,
|
||||
SPDXIdentifier: "DOCUMENT",
|
||||
DocumentName: "secret",
|
||||
DocumentNamespace: "http://aquasecurity.github.io/trivy/filesystem/secret-3ff14136-e09f-4df9-80ea-000000000001",
|
||||
|
||||
CreationInfo: &spdx.CreationInfo{
|
||||
Creators: []common.Creator{
|
||||
{
|
||||
Creator: "aquasecurity",
|
||||
CreatorType: "Organization",
|
||||
},
|
||||
{
|
||||
Creator: fmt.Sprintf("trivy-0.38.1"),
|
||||
CreatorType: "Tool",
|
||||
},
|
||||
},
|
||||
Created: "2021-08-25T12:20:30Z",
|
||||
},
|
||||
Packages: []*spdx.Package{
|
||||
{
|
||||
PackageName: "secret",
|
||||
PackageSPDXIdentifier: "Filesystem-5c08d34162a2c5d3",
|
||||
PackageDownloadLocation: "NONE",
|
||||
PackageAttributionTexts: []string{
|
||||
"SchemaVersion: 2",
|
||||
},
|
||||
PrimaryPackagePurpose: tspdx.PackagePurposeSource,
|
||||
},
|
||||
},
|
||||
Relationships: []*spdx.Relationship{
|
||||
{
|
||||
RefA: spdx.DocElementID{ElementRefID: "DOCUMENT"},
|
||||
RefB: spdx.DocElementID{ElementRefID: "Filesystem-5c08d34162a2c5d3"},
|
||||
Relationship: "DESCRIBES",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
clock := fake.NewFakeClock(time.Date(2021, 8, 25, 12, 20, 30, 5, time.UTC))
|
||||
|
||||
Reference in New Issue
Block a user