Compare commits

...

10 Commits

Author SHA1 Message Date
afdesk
fa8a8ba7dc fix(server): use a new db worker for hot updates (#2581)
Co-authored-by: knqyf263 <knqyf263@gmail.com>
2022-07-25 17:26:08 +03:00
DmitriyLewen
769ed554b0 docs: add trivy with download-db-only flag to Air-Gapped Environment (#2583) 2022-07-25 16:50:26 +03:00
DmitriyLewen
5f9a963ef6 docs: split commands to download db for different versions of oras (#2582) 2022-07-25 15:19:04 +03:00
Alexander Lauster
d93a997800 feat(report): export exitcode for license checks (#2564)
Also export the exit code for license checks 
fixes #2562
2022-07-25 14:26:12 +03:00
afdesk
f9be138aab fix: cli can use lowercase for severities (#2565) 2022-07-25 14:25:16 +03:00
Teppei Fukuda
c7f0bc92ae fix: allow subcommands with TRIVY_RUN_AS_PLUGIN (#2577) 2022-07-25 11:27:47 +03:00
MaineK00n
c2f3731873 fix: add missing types in TypeOSes and TypeLanguages in analyzer (#2569) 2022-07-24 17:24:13 +03:00
saso
7b4f2dc72f fix: enable some features of the wasm runtime (#2575) 2022-07-24 08:31:54 +03:00
Denys Mazhar
84677903a6 fix(k8s): no error logged if trivy can't get docker image in kubernetes mode (#2521)
* Enable k8s logging and increase log level of the image scan errors

* Rework errors reporting

* Rework GetErrors method into printErrors

Print errors during report writing

* Increase log level for scan errors logging
2022-07-21 15:34:47 -03:00
saso
e1e02d785f docs(sbom): improve sbom attestation documentation (#2566) 2022-07-21 17:54:21 +03:00
19 changed files with 136 additions and 51 deletions

View File

@@ -11,7 +11,7 @@ on:
pull_request:
env:
GO_VERSION: "1.18"
TINYGO_VERSION: "0.23.0"
TINYGO_VERSION: "0.24.0"
jobs:
test:
name: Test

View File

@@ -1,8 +1,14 @@
package main
import (
"context"
"os"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy/pkg/commands"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/plugin"
)
var (
@@ -10,8 +16,26 @@ var (
)
func main() {
app := commands.NewApp(version)
if err := app.Execute(); err != nil {
if err := run(); err != nil {
log.Fatal(err)
}
}
func run() error {
// Trivy behaves as the specified plugin.
if runAsPlugin := os.Getenv("TRIVY_RUN_AS_PLUGIN"); runAsPlugin != "" {
if !plugin.IsPredefined(runAsPlugin) {
return xerrors.Errorf("unknown plugin: %s", runAsPlugin)
}
if err := plugin.RunWithArgs(context.Background(), runAsPlugin, os.Args); err != nil {
return xerrors.Errorf("plugin error: %w", err)
}
return nil
}
app := commands.NewApp(version)
if err := app.Execute(); err != nil {
return err
}
return nil
}

View File

@@ -1,4 +1,4 @@
FROM squidfunk/mkdocs-material:8.2.10
FROM squidfunk/mkdocs-material:8.3.9
## If you want to see exactly the same version as is published to GitHub pages
## use a private image for insiders, which requires authentication.

View File

@@ -11,13 +11,13 @@ mergedeep==1.3.4
mike==1.1.2
mkdocs==1.3.0
mkdocs-macros-plugin==0.7.0
mkdocs-material==8.2.10
mkdocs-material==8.3.9
mkdocs-material-extensions==1.0.3
mkdocs-minify-plugin==0.5.0
mkdocs-redirects==1.0.4
packaging==21.3
Pygments==2.11.2
pymdown-extensions==9.3
Pygments==2.12.0
pymdown-extensions==9.5
pyparsing==3.0.8
python-dateutil==2.8.2
PyYAML==6.0

View File

@@ -5,14 +5,34 @@ Trivy can be used in air-gapped environments. Note that an allowlist is [here][a
## Air-Gapped Environment for vulnerabilities
### Download the vulnerability database
At first, you need to download the vulnerability database for use in air-gapped environments.
Please follow [oras installation instruction][oras].
=== "Trivy"
Download `db.tar.gz`:
```
TRIVY_TEMP_DIR=$(mktemp -d)
trivy --cache-dir $TRIVY_TEMP_DIR image --download-db-only
tar -cf ./db.tar.gz -C $TRIVY_TEMP_DIR/db metadata.json trivy.db
rm -rf $TRIVY_TEMP_DIR
```
```
$ oras pull ghcr.io/aquasecurity/trivy-db:2 -a
```
=== "oras >= v0.13.0"
At first, you need to download the vulnerability database for use in air-gapped environments.
Please follow [oras installation instruction][oras].
Download `db.tar.gz`:
```
$ oras pull ghcr.io/aquasecurity/trivy-db:2
```
=== "oras < v0.13.0"
At first, you need to download the vulnerability database for use in air-gapped environments.
Please follow [oras installation instruction][oras].
Download `db.tar.gz`:
```
$ oras pull -a ghcr.io/aquasecurity/trivy-db:2
```
### Transfer the DB file into the air-gapped environment
The way of transfer depends on the environment.

View File

@@ -13,8 +13,8 @@ Cosign can generate key pairs and use them for signing and verification. Read mo
In the following example, Trivy generates an SBOM in the spdx format, and then Cosign attaches an attestation of the SBOM to a container image with a local key pair.
```
$ trivy image --format spdx -o predicate <IMAGE>
$ cosign attest --key /path/to/cosign.key --type spdx --predicate predicate <IMAGE>
$ trivy image --format spdx -o sbom.spdx <IMAGE>
$ cosign attest --key /path/to/cosign.key --type spdx --predicate sbom.spdx <IMAGE>
```
Then, you can verify attestations on the image.
@@ -27,12 +27,12 @@ You can also create attestations of other formatted SBOM.
```
# spdx-json
$ trivy image --format spdx-json -o predicate <IMAGE>
$ cosign attest --key /path/to/cosign.key --type spdx --predicate predicate <IMAGE>
$ trivy image --format spdx-json -o sbom.spdx.json <IMAGE>
$ cosign attest --key /path/to/cosign.key --type spdx --predicate sbom.spdx.json <IMAGE>
# cyclonedx
$ trivy image --format cyclonedx -o predicate <IMAGE>
$ cosign attest --key /path/to/cosign.key --type https://cyclonedx.org/schema --predicate predicate <IMAGE>
$ trivy image --format cyclonedx -o sbom.cdx.json <IMAGE>
$ cosign attest --key /path/to/cosign.key --type https://cyclonedx.org/schema --predicate sbom.cdx.json <IMAGE>
```
## Keyless signing
@@ -40,8 +40,8 @@ $ cosign attest --key /path/to/cosign.key --type https://cyclonedx.org/schema --
You can use Cosign to sign without keys by authenticating with an OpenID Connect protocol supported by sigstore (Google, GitHub, or Microsoft).
```
$ trivy image --format spdx -o predicate <IMAGE>
$ COSIGN_EXPERIMENTAL=1 cosign attest --type spdx --predicate predicate <IMAGE>
$ trivy image --format spdx -o sbom.spdx <IMAGE>
$ COSIGN_EXPERIMENTAL=1 cosign attest --type spdx --predicate sbom.spdx <IMAGE>
```
You can verify attestations.

View File

@@ -276,6 +276,6 @@ $ trivy image --format template --template "@/usr/local/share/trivy/templates/ht
[new-json]: https://github.com/aquasecurity/trivy/discussions/1050
[action]: https://github.com/aquasecurity/trivy-action
[asff]: https://github.com/aquasecurity/trivy/blob/main/docs/advanced/integrations/aws-security-hub.md
[asff]: https://github.com/aquasecurity/trivy/blob/main/docs/docs/integrations/aws-security-hub.md
[sarif]: https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/managing-results-from-code-scanning
[sprig]: http://masterminds.github.io/sprig/

View File

@@ -138,6 +138,7 @@ theme:
- navigation.tabs
- navigation.tabs.sticky
- navigation.sections
- content.tabs.link
markdown_extensions:
- pymdownx.highlight
@@ -145,7 +146,8 @@ markdown_extensions:
- admonition
- footnotes
- attr_list
- pymdownx.tabbed
- pymdownx.tabbed:
alternate_style: true
- def_list
- pymdownx.details
- pymdownx.emoji:

View File

@@ -68,15 +68,6 @@ func SetOut(out io.Writer) {
func NewApp(version string) *cobra.Command {
globalFlags := flag.NewGlobalFlagGroup()
rootCmd := NewRootCommand(version, globalFlags)
if runAsPlugin := os.Getenv("TRIVY_RUN_AS_PLUGIN"); runAsPlugin != "" {
rootCmd.RunE = func(cmd *cobra.Command, args []string) error {
return plugin.RunWithArgs(cmd.Context(), runAsPlugin, args)
}
rootCmd.DisableFlagParsing = true
return rootCmd
}
rootCmd.AddCommand(
NewImageCommand(globalFlags),
NewFilesystemCommand(globalFlags),

View File

@@ -149,15 +149,16 @@ func (c *Client) Download(ctx context.Context, dst string) error {
log.Logger.Debug("no metadata file")
}
if err := c.populateOCIArtifact(); err != nil {
art, err := c.initOCIArtifact()
if err != nil {
return xerrors.Errorf("OCI artifact error: %w", err)
}
if err := c.artifact.Download(ctx, db.Dir(dst)); err != nil {
if err = art.Download(ctx, db.Dir(dst)); err != nil {
return xerrors.Errorf("database download error: %w", err)
}
if err := c.updateDownloadedAt(dst); err != nil {
if err = c.updateDownloadedAt(dst); err != nil {
return xerrors.Errorf("failed to update downloaded_at: %w", err)
}
return nil
@@ -182,14 +183,15 @@ func (c *Client) updateDownloadedAt(dst string) error {
return nil
}
func (c *Client) populateOCIArtifact() error {
if c.artifact == nil {
repo := fmt.Sprintf("%s:%d", c.dbRepository, db.SchemaVersion)
art, err := oci.NewArtifact(repo, dbMediaType, c.quiet, c.insecureSkipTLSVerify)
if err != nil {
return xerrors.Errorf("OCI artifact error: %w", err)
}
c.artifact = art
func (c *Client) initOCIArtifact() (*oci.Artifact, error) {
if c.artifact != nil {
return c.artifact, nil
}
return nil
repo := fmt.Sprintf("%s:%d", c.dbRepository, db.SchemaVersion)
art, err := oci.NewArtifact(repo, dbMediaType, c.quiet, c.insecureSkipTLSVerify)
if err != nil {
return nil, xerrors.Errorf("OCI artifact error: %w", err)
}
return art, nil
}

View File

@@ -104,16 +104,17 @@ const (
var (
// TypeOSes has all OS-related analyzers
TypeOSes = []Type{
TypeAlpine, TypeAmazon, TypeDebian, TypePhoton, TypeCentOS,
TypeOSRelease, TypeAlpine, TypeAmazon, TypeCBLMariner, TypeDebian, TypePhoton, TypeCentOS,
TypeRocky, TypeAlma, TypeFedora, TypeOracle, TypeRedHatBase, TypeSUSE, TypeUbuntu,
TypeApk, TypeDpkg, TypeRpm,
TypeApk, TypeDpkg, TypeDpkgLicense, TypeRpm, TypeRpmqa,
TypeApkRepo,
}
// TypeLanguages has all language analyzers
TypeLanguages = []Type{
TypeBundler, TypeGemSpec, TypeCargo, TypeComposer, TypeJar, TypePom,
TypeNpmPkgLock, TypeNodePkg, TypeYarn, TypePnpm, TypeNuget, TypePythonPkg, TypePip, TypePipenv,
TypePoetry, TypeGoBinary, TypeGoMod,
TypeNpmPkgLock, TypeNodePkg, TypeYarn, TypePnpm, TypeNuget, TypeDotNetDeps,
TypePythonPkg, TypePip, TypePipenv, TypePoetry, TypeGoBinary, TypeGoMod,
}
// TypeLockfiles has all lock file analyzers

View File

@@ -220,7 +220,7 @@ func splitSeverity(severity []string) []dbTypes.Severity {
var severities []dbTypes.Severity
for _, s := range severity {
sev, err := dbTypes.NewSeverity(s)
sev, err := dbTypes.NewSeverity(strings.ToUpper(s))
if err != nil {
log.Logger.Warnf("unknown severity option: %s", err)
continue

View File

@@ -43,6 +43,18 @@ func TestReportFlagGroup_ToOptions(t *testing.T) {
Output: os.Stdout,
},
},
{
name: "happy path with a low case severity",
fields: fields{
severities: "critical",
},
want: flag.ReportOptions{
Output: os.Stdout,
Severities: []dbTypes.Severity{
dbTypes.SeverityCritical,
},
},
},
{
name: "happy path with an unknown severity",
fields: fields{

View File

@@ -71,6 +71,7 @@ func run(ctx context.Context, opts flag.Options, cluster string, artifacts []*ar
if err != nil {
return xerrors.Errorf("k8s scan error: %w", err)
}
if err := report.Write(r, report.Option{
Format: opts.Format,
Report: opts.ReportFormat,

View File

@@ -14,6 +14,7 @@ import (
"github.com/aquasecurity/trivy-kubernetes/pkg/artifacts"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types"
)
@@ -129,6 +130,8 @@ type Writer interface {
// Write writes the results in the give format
func Write(report Report, option Option, securityChecks []string, showEmpty bool) error {
report.printErrors()
switch option.Format {
case jsonFormat:
jwriter := JSONWriter{Output: option.Output, Report: option.Report}
@@ -220,3 +223,17 @@ func CreateResource(artifact *artifacts.Artifact, report types.Report, err error
return r
}
func (r Report) printErrors() {
for _, resource := range r.Vulnerabilities {
if resource.Error != "" {
log.Logger.Errorf("Error during vulnerabilities scan: %s", resource.Error)
}
}
for _, resource := range r.Misconfigurations {
if resource.Error != "" {
log.Logger.Errorf("Error during misconfiguration scan: %s", resource.Error)
}
}
}

View File

@@ -97,7 +97,7 @@ func (s *Scanner) scanVulns(ctx context.Context, artifact *artifacts.Artifact) (
imageReport, err := s.runner.ScanImage(ctx, s.opts)
if err != nil {
log.Logger.Debugf("failed to scan image %s: %s", image, err)
log.Logger.Warnf("failed to scan image %s: %s", image, err)
resources = append(resources, report.CreateResource(artifact, imageReport, err))
continue
}

View File

@@ -84,8 +84,15 @@ type Manager struct {
func NewManager(ctx context.Context) (*Manager, error) {
m := &Manager{}
// The runtime must enable the following features because Tinygo uses these features to build.
// cf. https://github.com/tinygo-org/tinygo/blob/b65447c7d567eea495805656f45472cc3c483e03/targets/wasi.json#L4
c := wazero.NewRuntimeConfig().
WithFeatureBulkMemoryOperations(true).
WithFeatureNonTrappingFloatToIntConversion(true).
WithFeatureSignExtensionOps(true)
// Create a new WebAssembly Runtime.
m.runtime = wazero.NewRuntime()
m.runtime = wazero.NewRuntimeWithConfig(c)
// Load WASM modules in local
if err := m.loadModules(ctx); err != nil {

View File

@@ -293,6 +293,11 @@ func RunWithArgs(ctx context.Context, url string, args []string) error {
return nil
}
func IsPredefined(name string) bool {
_, ok := officialPlugins[name]
return ok
}
func loadMetadata(dir string) (Plugin, error) {
filePath := filepath.Join(dir, configFile)
f, err := os.Open(filePath)

View File

@@ -114,6 +114,9 @@ func (results Results) Failed() bool {
if len(r.Secrets) > 0 {
return true
}
if len(r.Licenses) > 0 {
return true
}
}
return false
}