mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-22 07:10:41 -08:00
refactor: export useful APIs (#2108)
Co-authored-by: Jose Donizetti <jdbjunior@gmail.com>
This commit is contained in:
@@ -29,7 +29,7 @@ $ trivy k8s -n default --severity CRITICAL
|
|||||||
Scan a cluster and generate a simple summary report. The only outputs currently supported are `all` and `summary`. The default report format is `summary`
|
Scan a cluster and generate a simple summary report. The only outputs currently supported are `all` and `summary`. The default report format is `summary`
|
||||||
|
|
||||||
```
|
```
|
||||||
$ trivy k8s
|
$ trivy k8s
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
96
go.mod
96
go.mod
@@ -13,7 +13,7 @@ require (
|
|||||||
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798
|
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798
|
||||||
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
|
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
|
||||||
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492
|
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492
|
||||||
github.com/aquasecurity/trivy-db v0.0.0-20220327074450-74195d9604b2
|
github.com/aquasecurity/trivy-db v0.0.0-20220510190819-8ca06716f46e
|
||||||
github.com/caarlos0/env/v6 v6.9.1
|
github.com/caarlos0/env/v6 v6.9.1
|
||||||
github.com/cenkalti/backoff v2.2.1+incompatible
|
github.com/cenkalti/backoff v2.2.1+incompatible
|
||||||
github.com/cheggaaa/pb/v3 v3.0.8
|
github.com/cheggaaa/pb/v3 v3.0.8
|
||||||
@@ -46,6 +46,7 @@ require (
|
|||||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
|
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
|
||||||
google.golang.org/protobuf v1.28.0
|
google.golang.org/protobuf v1.28.0
|
||||||
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||||
k8s.io/utils v0.0.0-20211116205334-6203023598ed
|
k8s.io/utils v0.0.0-20211116205334-6203023598ed
|
||||||
)
|
)
|
||||||
@@ -71,8 +72,6 @@ require (
|
|||||||
github.com/Microsoft/go-winio v0.5.1 // indirect
|
github.com/Microsoft/go-winio v0.5.1 // indirect
|
||||||
github.com/OneOfOne/xxhash v1.2.8 // indirect
|
github.com/OneOfOne/xxhash v1.2.8 // indirect
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
|
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
|
||||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
|
||||||
github.com/VividCortex/ewma v1.1.1 // indirect
|
github.com/VividCortex/ewma v1.1.1 // indirect
|
||||||
github.com/acomagu/bufpipe v1.0.3 // indirect
|
github.com/acomagu/bufpipe v1.0.3 // indirect
|
||||||
github.com/agext/levenshtein v1.2.3 // indirect
|
github.com/agext/levenshtein v1.2.3 // indirect
|
||||||
@@ -96,31 +95,19 @@ require (
|
|||||||
github.com/docker/docker-credential-helpers v0.6.4 // indirect
|
github.com/docker/docker-credential-helpers v0.6.4 // indirect
|
||||||
github.com/docker/go-units v0.4.0 // indirect
|
github.com/docker/go-units v0.4.0 // indirect
|
||||||
github.com/emirpasic/gods v1.12.0 // indirect
|
github.com/emirpasic/gods v1.12.0 // indirect
|
||||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
|
||||||
github.com/ghodss/yaml v1.0.0 // indirect
|
github.com/ghodss/yaml v1.0.0 // indirect
|
||||||
github.com/go-errors/errors v1.0.1 // indirect
|
|
||||||
github.com/go-git/gcfg v1.5.0 // indirect
|
github.com/go-git/gcfg v1.5.0 // indirect
|
||||||
github.com/go-git/go-billy/v5 v5.3.1 // indirect
|
github.com/go-git/go-billy/v5 v5.3.1 // indirect
|
||||||
github.com/go-git/go-git/v5 v5.4.2 // indirect
|
github.com/go-git/go-git/v5 v5.4.2 // indirect
|
||||||
github.com/go-logr/logr v1.2.3 // indirect
|
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
|
||||||
github.com/go-openapi/jsonreference v0.19.5 // indirect
|
|
||||||
github.com/go-openapi/swag v0.19.14 // indirect
|
|
||||||
github.com/gobwas/glob v0.2.3 // indirect
|
github.com/gobwas/glob v0.2.3 // indirect
|
||||||
github.com/goccy/go-yaml v1.8.2 // indirect
|
github.com/goccy/go-yaml v1.8.2 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
|
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/google/btree v1.0.1 // indirect
|
|
||||||
github.com/google/go-cmp v0.5.7 // indirect
|
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
|
||||||
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
|
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
|
||||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
|
||||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
|
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
|
||||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||||
@@ -128,11 +115,8 @@ require (
|
|||||||
github.com/hashicorp/hcl/v2 v2.12.0 // indirect
|
github.com/hashicorp/hcl/v2 v2.12.0 // indirect
|
||||||
github.com/huandu/xstrings v1.3.2 // indirect
|
github.com/huandu/xstrings v1.3.2 // indirect
|
||||||
github.com/imdario/mergo v0.3.12 // indirect
|
github.com/imdario/mergo v0.3.12 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
|
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
|
||||||
github.com/klauspost/compress v1.15.1 // indirect
|
github.com/klauspost/compress v1.15.1 // indirect
|
||||||
@@ -142,9 +126,7 @@ require (
|
|||||||
github.com/liamg/jfather v0.0.7 // indirect
|
github.com/liamg/jfather v0.0.7 // indirect
|
||||||
github.com/liamg/memoryfs v1.4.1 // indirect
|
github.com/liamg/memoryfs v1.4.1 // indirect
|
||||||
github.com/liamg/tml v0.6.0
|
github.com/liamg/tml v0.6.0
|
||||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
|
||||||
github.com/magiconair/properties v1.8.5 // indirect
|
github.com/magiconair/properties v1.8.5 // indirect
|
||||||
github.com/mailru/easyjson v0.7.6 // indirect
|
|
||||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||||
@@ -157,15 +139,11 @@ require (
|
|||||||
github.com/moby/sys/mount v0.3.0 // indirect
|
github.com/moby/sys/mount v0.3.0 // indirect
|
||||||
github.com/moby/sys/mountinfo v0.6.0 // indirect
|
github.com/moby/sys/mountinfo v0.6.0 // indirect
|
||||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
|
||||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
|
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
|
||||||
github.com/opencontainers/runc v1.1.1 // indirect
|
github.com/opencontainers/runc v1.1.1 // indirect
|
||||||
github.com/owenrumney/squealer v1.0.1-0.20220510063705-c0be93f0edea // indirect
|
github.com/owenrumney/squealer v1.0.1-0.20220510063705-c0be93f0edea // indirect
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
|
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
|
||||||
@@ -178,21 +156,17 @@ require (
|
|||||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||||
github.com/spdx/tools-golang v0.3.0
|
github.com/spdx/tools-golang v0.3.0
|
||||||
github.com/spf13/cast v1.4.1 // indirect
|
github.com/spf13/cast v1.4.1 // indirect
|
||||||
github.com/spf13/cobra v1.4.0 // indirect
|
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
|
||||||
github.com/stretchr/objx v0.3.0 // indirect
|
github.com/stretchr/objx v0.3.0 // indirect
|
||||||
github.com/ulikunitz/xz v0.5.8 // indirect
|
github.com/ulikunitz/xz v0.5.8 // indirect
|
||||||
github.com/vbatts/tar-split v0.11.2 // indirect
|
github.com/vbatts/tar-split v0.11.2 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.3.0 // indirect
|
github.com/xanzy/ssh-agent v0.3.0 // indirect
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
|
|
||||||
github.com/yashtewari/glob-intersection v0.1.0 // indirect
|
github.com/yashtewari/glob-intersection v0.1.0 // indirect
|
||||||
github.com/zclconf/go-cty v1.10.0 // indirect
|
github.com/zclconf/go-cty v1.10.0 // indirect
|
||||||
github.com/zclconf/go-cty-yaml v1.0.2 // indirect
|
github.com/zclconf/go-cty-yaml v1.0.2 // indirect
|
||||||
go.etcd.io/bbolt v1.3.6 // indirect
|
go.etcd.io/bbolt v1.3.6 // indirect
|
||||||
go.opencensus.io v0.23.0 // indirect
|
go.opencensus.io v0.23.0 // indirect
|
||||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
|
||||||
go.uber.org/atomic v1.7.0 // indirect
|
go.uber.org/atomic v1.7.0 // indirect
|
||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.6.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
|
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
|
||||||
@@ -202,7 +176,6 @@ require (
|
|||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
|
||||||
golang.org/x/tools v0.1.8 // indirect
|
golang.org/x/tools v0.1.8 // indirect
|
||||||
google.golang.org/api v0.62.0 // indirect
|
google.golang.org/api v0.62.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
@@ -210,14 +183,7 @@ require (
|
|||||||
google.golang.org/grpc v1.46.0 // indirect
|
google.golang.org/grpc v1.46.0 // indirect
|
||||||
gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect
|
gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect
|
||||||
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
|
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
k8s.io/api v0.23.6 // indirect
|
|
||||||
k8s.io/apimachinery v0.23.6 // indirect
|
|
||||||
k8s.io/cli-runtime v0.23.6 // indirect
|
|
||||||
k8s.io/client-go v0.23.6 // indirect
|
|
||||||
k8s.io/klog/v2 v2.30.0 // indirect
|
|
||||||
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
|
|
||||||
lukechampine.com/uint128 v1.1.1 // indirect
|
lukechampine.com/uint128 v1.1.1 // indirect
|
||||||
modernc.org/cc/v3 v3.35.22 // indirect
|
modernc.org/cc/v3 v3.35.22 // indirect
|
||||||
modernc.org/ccgo/v3 v3.15.1 // indirect
|
modernc.org/ccgo/v3 v3.15.1 // indirect
|
||||||
@@ -228,6 +194,51 @@ require (
|
|||||||
modernc.org/sqlite v1.14.5 // indirect
|
modernc.org/sqlite v1.14.5 // indirect
|
||||||
modernc.org/strutil v1.1.1 // indirect
|
modernc.org/strutil v1.1.1 // indirect
|
||||||
modernc.org/token v1.0.0 // indirect
|
modernc.org/token v1.0.0 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/aquasecurity/table v1.5.1
|
||||||
|
github.com/aquasecurity/trivy-kubernetes v0.1.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||||
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||||
|
github.com/alecthomas/chroma v0.10.0 // indirect
|
||||||
|
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||||
|
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||||
|
github.com/go-errors/errors v1.0.1 // indirect
|
||||||
|
github.com/go-logr/logr v1.2.3 // indirect
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
|
github.com/go-openapi/jsonreference v0.19.5 // indirect
|
||||||
|
github.com/go-openapi/swag v0.19.14 // indirect
|
||||||
|
github.com/google/btree v1.0.1 // indirect
|
||||||
|
github.com/google/go-cmp v0.5.7 // indirect
|
||||||
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
|
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||||
|
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||||
|
github.com/mailru/easyjson v0.7.6 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||||
|
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||||
|
github.com/spf13/cobra v1.4.0 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
|
||||||
|
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||||
|
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||||
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
|
k8s.io/api v0.23.6 // indirect
|
||||||
|
k8s.io/apimachinery v0.23.6 // indirect
|
||||||
|
k8s.io/cli-runtime v0.23.6 // indirect
|
||||||
|
k8s.io/client-go v0.23.6 // indirect
|
||||||
|
k8s.io/klog/v2 v2.30.0 // indirect
|
||||||
|
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
|
||||||
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
|
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
|
||||||
sigs.k8s.io/kustomize/api v0.10.1 // indirect
|
sigs.k8s.io/kustomize/api v0.10.1 // indirect
|
||||||
sigs.k8s.io/kustomize/kyaml v0.13.0 // indirect
|
sigs.k8s.io/kustomize/kyaml v0.13.0 // indirect
|
||||||
@@ -235,17 +246,6 @@ require (
|
|||||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require gopkg.in/yaml.v2 v2.4.0
|
|
||||||
|
|
||||||
require github.com/aquasecurity/trivy-kubernetes v0.1.0
|
|
||||||
|
|
||||||
require github.com/aquasecurity/table v1.5.1
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/alecthomas/chroma v0.10.0 // indirect
|
|
||||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
|
||||||
)
|
|
||||||
|
|
||||||
// To resolve CVE-2022-23648
|
// To resolve CVE-2022-23648
|
||||||
replace github.com/containerd/containerd v1.5.9 => github.com/containerd/containerd v1.5.10
|
replace github.com/containerd/containerd v1.5.9 => github.com/containerd/containerd v1.5.10
|
||||||
|
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -198,8 +198,8 @@ github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492/go.mod h1:
|
|||||||
github.com/aquasecurity/table v1.5.1 h1:y05AuHM3p4BGybbGn/XbcTX3RxpyzeTXAXYMcJve4IE=
|
github.com/aquasecurity/table v1.5.1 h1:y05AuHM3p4BGybbGn/XbcTX3RxpyzeTXAXYMcJve4IE=
|
||||||
github.com/aquasecurity/table v1.5.1/go.mod h1:1MFKrEPJ8NchM917BrVGvsqoXJo1OL1Ja7dF3PgUea4=
|
github.com/aquasecurity/table v1.5.1/go.mod h1:1MFKrEPJ8NchM917BrVGvsqoXJo1OL1Ja7dF3PgUea4=
|
||||||
github.com/aquasecurity/testdocker v0.0.0-20210911155206-e1e85f5a1516 h1:moQmzbpLo5dxHQCyEhqzizsDSNrNhn/7uRTCZzo4A1o=
|
github.com/aquasecurity/testdocker v0.0.0-20210911155206-e1e85f5a1516 h1:moQmzbpLo5dxHQCyEhqzizsDSNrNhn/7uRTCZzo4A1o=
|
||||||
github.com/aquasecurity/trivy-db v0.0.0-20220327074450-74195d9604b2 h1:q2Gza4V8uO5C1COzC2HeTbQgJIrmC6dTWaXZ8ujiWu0=
|
github.com/aquasecurity/trivy-db v0.0.0-20220510190819-8ca06716f46e h1:NLm5KWGcnkwaUR1GODPePyhNsbuFiT6lgKYcCcW9c10=
|
||||||
github.com/aquasecurity/trivy-db v0.0.0-20220327074450-74195d9604b2/go.mod h1:EwiQRdzVq6k7cKOMjkss8LjWMt2FUW7NaYwE7HfZZvk=
|
github.com/aquasecurity/trivy-db v0.0.0-20220510190819-8ca06716f46e/go.mod h1:/nULgnDeq/JMPMVwE1dmf4kWlYn++7VrM3O2naj4BHA=
|
||||||
github.com/aquasecurity/trivy-kubernetes v0.1.0 h1:eE7JSdqo83Kn87c86DcUIsPAtW0K9UnkkHEQ4sGI030=
|
github.com/aquasecurity/trivy-kubernetes v0.1.0 h1:eE7JSdqo83Kn87c86DcUIsPAtW0K9UnkkHEQ4sGI030=
|
||||||
github.com/aquasecurity/trivy-kubernetes v0.1.0/go.mod h1:9fU3sHz/wXN5ruZ5snUEJpzm2X6pUndKucv1mz9Walc=
|
github.com/aquasecurity/trivy-kubernetes v0.1.0/go.mod h1:9fU3sHz/wXN5ruZ5snUEJpzm2X6pUndKucv1mz9Walc=
|
||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
// ConfigRun runs scan on config files
|
// ConfigRun runs scan on config files
|
||||||
func ConfigRun(ctx *cli.Context) error {
|
func ConfigRun(ctx *cli.Context) error {
|
||||||
opt, err := initOption(ctx)
|
opt, err := InitOption(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("option error: %w", err)
|
return xerrors.Errorf("option error: %w", err)
|
||||||
}
|
}
|
||||||
@@ -22,9 +22,6 @@ func ConfigRun(ctx *cli.Context) error {
|
|||||||
opt.VulnType = nil
|
opt.VulnType = nil
|
||||||
opt.SecurityChecks = []string{types.SecurityCheckConfig}
|
opt.SecurityChecks = []string{types.SecurityCheckConfig}
|
||||||
|
|
||||||
// Skip downloading vulnerability DB
|
|
||||||
opt.SkipDBUpdate = true
|
|
||||||
|
|
||||||
// Run filesystem command internally
|
// Run filesystem command internally
|
||||||
return Run(ctx.Context, opt, filesystemStandaloneScanner, initCache)
|
return run(ctx.Context, opt, filesystemArtifact)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/aquasecurity/fanal/analyzer"
|
|
||||||
"github.com/aquasecurity/trivy/pkg/scanner"
|
"github.com/aquasecurity/trivy/pkg/scanner"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,39 +29,10 @@ func filesystemRemoteScanner(ctx context.Context, conf ScannerConfig) (scanner.S
|
|||||||
|
|
||||||
// FilesystemRun runs scan on filesystem for language-specific dependencies and config files
|
// FilesystemRun runs scan on filesystem for language-specific dependencies and config files
|
||||||
func FilesystemRun(ctx *cli.Context) error {
|
func FilesystemRun(ctx *cli.Context) error {
|
||||||
opt, err := initOption(ctx)
|
return Run(ctx, filesystemArtifact)
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("option error: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable the individual package scanning
|
|
||||||
opt.DisabledAnalyzers = analyzer.TypeIndividualPkgs
|
|
||||||
//opt.DisabledAnalyzers = append(opt.DisabledAnalyzers, analyzer.TypeSecret)
|
|
||||||
|
|
||||||
// client/server mode
|
|
||||||
if opt.RemoteAddr != "" {
|
|
||||||
return Run(ctx.Context, opt, filesystemRemoteScanner, initCache)
|
|
||||||
}
|
|
||||||
|
|
||||||
// standalone mode
|
|
||||||
return Run(ctx.Context, opt, filesystemStandaloneScanner, initCache)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RootfsRun runs scan on rootfs.
|
// RootfsRun runs scan on rootfs.
|
||||||
func RootfsRun(ctx *cli.Context) error {
|
func RootfsRun(ctx *cli.Context) error {
|
||||||
opt, err := initOption(ctx)
|
return Run(ctx, rootfsArtifact)
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("option error: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable the lock file scanning
|
|
||||||
opt.DisabledAnalyzers = analyzer.TypeLockfiles
|
|
||||||
|
|
||||||
// client/server mode
|
|
||||||
if opt.RemoteAddr != "" {
|
|
||||||
return Run(ctx.Context, opt, filesystemRemoteScanner, initCache)
|
|
||||||
}
|
|
||||||
|
|
||||||
// standalone mode
|
|
||||||
return Run(ctx.Context, opt, filesystemStandaloneScanner, initCache)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,13 @@ import (
|
|||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/aquasecurity/fanal/analyzer"
|
|
||||||
"github.com/aquasecurity/trivy/pkg/scanner"
|
"github.com/aquasecurity/trivy/pkg/scanner"
|
||||||
"github.com/aquasecurity/trivy/pkg/types"
|
"github.com/aquasecurity/trivy/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// imageScanner initializes a container image scanner in standalone mode
|
// imageStandaloneScanner initializes a container image scanner in standalone mode
|
||||||
// $ trivy image alpine:3.15
|
// $ trivy image alpine:3.15
|
||||||
func imageScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
func imageStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||||
dockerOpt, err := types.GetDockerOption(conf.ArtifactOption.InsecureSkipTLS)
|
dockerOpt, err := types.GetDockerOption(conf.ArtifactOption.InsecureSkipTLS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return scanner.Scanner{}, nil, err
|
return scanner.Scanner{}, nil, err
|
||||||
@@ -26,9 +25,9 @@ func imageScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, fun
|
|||||||
return s, cleanup, nil
|
return s, cleanup, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// archiveScanner initializes an image archive scanner in standalone mode
|
// archiveStandaloneScanner initializes an image archive scanner in standalone mode
|
||||||
// $ trivy image --input alpine.tar
|
// $ trivy image --input alpine.tar
|
||||||
func archiveScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
func archiveStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||||
s, err := initializeArchiveScanner(ctx, conf.Target, conf.ArtifactCache, conf.LocalArtifactCache, conf.ArtifactOption)
|
s, err := initializeArchiveScanner(ctx, conf.Target, conf.ArtifactCache, conf.LocalArtifactCache, conf.ArtifactOption)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize the archive scanner: %w", err)
|
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize the archive scanner: %w", err)
|
||||||
@@ -36,9 +35,9 @@ func archiveScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, f
|
|||||||
return s, func() {}, nil
|
return s, func() {}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// remoteImageScanner initializes a container image scanner in client/server mode
|
// imageRemoteScanner initializes a container image scanner in client/server mode
|
||||||
// $ trivy image --server localhost:4954 alpine:3.15
|
// $ trivy image --server localhost:4954 alpine:3.15
|
||||||
func remoteImageScanner(ctx context.Context, conf ScannerConfig) (
|
func imageRemoteScanner(ctx context.Context, conf ScannerConfig) (
|
||||||
scanner.Scanner, func(), error) {
|
scanner.Scanner, func(), error) {
|
||||||
// Scan an image in Docker Engine, Docker Registry, etc.
|
// Scan an image in Docker Engine, Docker Registry, etc.
|
||||||
dockerOpt, err := types.GetDockerOption(conf.ArtifactOption.InsecureSkipTLS)
|
dockerOpt, err := types.GetDockerOption(conf.ArtifactOption.InsecureSkipTLS)
|
||||||
@@ -54,9 +53,9 @@ func remoteImageScanner(ctx context.Context, conf ScannerConfig) (
|
|||||||
return s, cleanup, nil
|
return s, cleanup, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// remoteArchiveScanner initializes an image archive scanner in client/server mode
|
// archiveRemoteScanner initializes an image archive scanner in client/server mode
|
||||||
// $ trivy image --server localhost:4954 --input alpine.tar
|
// $ trivy image --server localhost:4954 --input alpine.tar
|
||||||
func remoteArchiveScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
func archiveRemoteScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||||
// Scan tar file
|
// Scan tar file
|
||||||
s, err := initializeRemoteArchiveScanner(ctx, conf.Target, conf.ArtifactCache, conf.RemoteOption, conf.ArtifactOption)
|
s, err := initializeRemoteArchiveScanner(ctx, conf.Target, conf.ArtifactCache, conf.RemoteOption, conf.ArtifactOption)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -67,43 +66,5 @@ func remoteArchiveScanner(ctx context.Context, conf ScannerConfig) (scanner.Scan
|
|||||||
|
|
||||||
// ImageRun runs scan on container image
|
// ImageRun runs scan on container image
|
||||||
func ImageRun(ctx *cli.Context) error {
|
func ImageRun(ctx *cli.Context) error {
|
||||||
opt, err := initOption(ctx)
|
return Run(ctx, containerImageArtifact)
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("option error: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable the lock file scanning
|
|
||||||
opt.DisabledAnalyzers = analyzer.TypeLockfiles
|
|
||||||
|
|
||||||
if opt.Input != "" {
|
|
||||||
return archiveImageRun(ctx.Context, opt)
|
|
||||||
}
|
|
||||||
|
|
||||||
return imageRun(ctx.Context, opt)
|
|
||||||
}
|
|
||||||
|
|
||||||
func archiveImageRun(ctx context.Context, opt Option) error {
|
|
||||||
// standalone mode
|
|
||||||
scanner := archiveScanner
|
|
||||||
|
|
||||||
if opt.RemoteAddr != "" {
|
|
||||||
// client/server mode
|
|
||||||
scanner = remoteArchiveScanner
|
|
||||||
}
|
|
||||||
|
|
||||||
// scan tar file
|
|
||||||
return Run(ctx, opt, scanner, initCache)
|
|
||||||
}
|
|
||||||
|
|
||||||
func imageRun(ctx context.Context, opt Option) error {
|
|
||||||
// standalone mode
|
|
||||||
scanner := imageScanner
|
|
||||||
|
|
||||||
if opt.RemoteAddr != "" {
|
|
||||||
// client/server mode
|
|
||||||
scanner = remoteImageScanner
|
|
||||||
}
|
|
||||||
|
|
||||||
// scan container image
|
|
||||||
return Run(ctx, opt, scanner, initCache)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,6 @@ import (
|
|||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
"github.com/aquasecurity/fanal/analyzer"
|
|
||||||
"github.com/aquasecurity/fanal/cache"
|
|
||||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
|
||||||
|
|
||||||
"github.com/aquasecurity/trivy/pkg/log"
|
"github.com/aquasecurity/trivy/pkg/log"
|
||||||
pkgReport "github.com/aquasecurity/trivy/pkg/report"
|
pkgReport "github.com/aquasecurity/trivy/pkg/report"
|
||||||
k8sReport "github.com/aquasecurity/trivy/pkg/report/k8s"
|
k8sReport "github.com/aquasecurity/trivy/pkg/report/k8s"
|
||||||
@@ -27,35 +23,29 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// K8sRun runs scan on kubernetes cluster
|
// K8sRun runs scan on kubernetes cluster
|
||||||
func K8sRun(ctx *cli.Context) error {
|
func K8sRun(cliCtx *cli.Context) error {
|
||||||
opt, err := initOption(ctx)
|
opt, err := InitOption(cliCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("option error: %w", err)
|
return xerrors.Errorf("option error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = log.InitLogger(opt.Debug, true); err != nil {
|
ctx, cancel := context.WithTimeout(cliCtx.Context, opt.Timeout)
|
||||||
return err
|
defer cancel()
|
||||||
}
|
|
||||||
|
|
||||||
cacheClient, err := initCache(opt)
|
defer func() {
|
||||||
|
if xerrors.Is(err, context.DeadlineExceeded) {
|
||||||
|
log.Logger.Warn("Increase --timeout value")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
runner, err := NewRunner(opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, errSkipScan) {
|
if errors.Is(err, SkipScan) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return xerrors.Errorf("cache error: %w", err)
|
return xerrors.Errorf("init error: %w", err)
|
||||||
}
|
|
||||||
defer cacheClient.Close()
|
|
||||||
|
|
||||||
// Disable DB update when using client/server
|
|
||||||
if opt.RemoteAddr == "" {
|
|
||||||
if err = initDB(opt); err != nil {
|
|
||||||
if errors.Is(err, errSkipScan) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return xerrors.Errorf("DB error: %w", err)
|
|
||||||
}
|
|
||||||
defer db.Close()
|
|
||||||
}
|
}
|
||||||
|
defer runner.Close()
|
||||||
|
|
||||||
cluster, err := k8s.GetCluster()
|
cluster, err := k8s.GetCluster()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -65,12 +55,12 @@ func K8sRun(ctx *cli.Context) error {
|
|||||||
trivyk8s := trivyk8s.New(cluster).Namespace(opt.KubernetesOption.Namespace)
|
trivyk8s := trivyk8s.New(cluster).Namespace(opt.KubernetesOption.Namespace)
|
||||||
|
|
||||||
// list all kubernetes scannable artifacts
|
// list all kubernetes scannable artifacts
|
||||||
k8sArtifacts, err := trivyk8s.ListArtifacts(ctx.Context)
|
k8sArtifacts, err := trivyk8s.ListArtifacts(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("get k8s artifacts error: %w", err)
|
return xerrors.Errorf("get k8s artifacts error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
report, err := k8sRun(ctx, opt, cacheClient, k8sArtifacts)
|
report, err := k8sRun(ctx, runner, opt, k8sArtifacts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("k8s scan error: %w", err)
|
return xerrors.Errorf("k8s scan error: %w", err)
|
||||||
}
|
}
|
||||||
@@ -88,40 +78,34 @@ func K8sRun(ctx *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func k8sRun(cliContext *cli.Context, opt Option, cacheClient cache.Cache, k8sArtifacts []*artifacts.Artifact) (k8sReport.Report, error) {
|
func k8sRun(ctx context.Context, runner *Runner, opt Option, artifacts []*artifacts.Artifact) (k8sReport.Report, error) {
|
||||||
ctx, cancel := context.WithTimeout(cliContext.Context, opt.Timeout)
|
opt.SecurityChecks = []string{types.SecurityCheckVulnerability, types.SecurityCheckConfig}
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// progress bar
|
// progress bar
|
||||||
bar := pb.StartNew(len(k8sArtifacts))
|
bar := pb.StartNew(len(artifacts))
|
||||||
if opt.NoProgress {
|
if opt.NoProgress {
|
||||||
bar.SetWriter(io.Discard)
|
bar.SetWriter(io.Discard)
|
||||||
}
|
}
|
||||||
defer bar.Finish()
|
defer bar.Finish()
|
||||||
|
|
||||||
// image scanner configurations
|
|
||||||
imageScannerConfig, imageScannerOptions, err := initImageScannerConfig(ctx, opt, cacheClient)
|
|
||||||
if err != nil {
|
|
||||||
return k8sReport.Report{}, xerrors.Errorf("scanner config error: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// config scanner configurations
|
|
||||||
configScannerConfig, configScannerOptions, err := initConfigScannerConfig(ctx, opt, cacheClient)
|
|
||||||
if err != nil {
|
|
||||||
return k8sReport.Report{}, xerrors.Errorf("scanner config error: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
vulns := make([]k8sReport.Resource, 0)
|
vulns := make([]k8sReport.Resource, 0)
|
||||||
misconfigs := make([]k8sReport.Resource, 0)
|
misconfigs := make([]k8sReport.Resource, 0)
|
||||||
|
|
||||||
|
// disable logs before scanning
|
||||||
|
err := log.InitLogger(opt.Debug, true)
|
||||||
|
if err != nil {
|
||||||
|
return k8sReport.Report{}, xerrors.Errorf("logger error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Loops once over all artifacts, and execute scanners as necessary. Not every artifacts has an image,
|
// Loops once over all artifacts, and execute scanners as necessary. Not every artifacts has an image,
|
||||||
// so image scanner is not always executed.
|
// so image scanner is not always executed.
|
||||||
for _, artifact := range k8sArtifacts {
|
for _, artifact := range artifacts {
|
||||||
bar.Increment()
|
bar.Increment()
|
||||||
|
|
||||||
// scan images if present
|
// scan images if present
|
||||||
for _, image := range artifact.Images {
|
for _, image := range artifact.Images {
|
||||||
imageReport, err := k8sScan(ctx, image, imageScanner, imageScannerConfig, imageScannerOptions)
|
opt.Target = image
|
||||||
|
imageReport, err := runner.ScanImage(ctx, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// add error to report
|
// add error to report
|
||||||
log.Logger.Debugf("failed to scan image %s: %s", image, err)
|
log.Logger.Debugf("failed to scan image %s: %s", image, err)
|
||||||
@@ -129,7 +113,7 @@ func k8sRun(cliContext *cli.Context, opt Option, cacheClient cache.Cache, k8sArt
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
imageReport, err = filter(ctx, opt, imageReport)
|
imageReport, err = runner.Filter(ctx, opt, imageReport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return k8sReport.Report{}, xerrors.Errorf("filter error: %w", err)
|
return k8sReport.Report{}, xerrors.Errorf("filter error: %w", err)
|
||||||
}
|
}
|
||||||
@@ -138,14 +122,21 @@ func k8sRun(cliContext *cli.Context, opt Option, cacheClient cache.Cache, k8sArt
|
|||||||
}
|
}
|
||||||
|
|
||||||
// scan configurations
|
// scan configurations
|
||||||
configReport, err := k8sScanConfig(ctx, configScannerConfig, configScannerOptions, artifact)
|
configFile, err := createTempFile(artifact)
|
||||||
|
if err != nil {
|
||||||
|
return k8sReport.Report{}, xerrors.Errorf("scan error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
opt.Target = configFile
|
||||||
|
configReport, err := runner.ScanFilesystem(ctx, opt)
|
||||||
|
removeFile(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// add error to report
|
// add error to report
|
||||||
log.Logger.Debugf("failed to scan config %s/%s: %s", artifact.Kind, artifact.Name, err)
|
log.Logger.Debugf("failed to scan config %s/%s: %s", artifact.Kind, artifact.Name, err)
|
||||||
misconfigs = append(misconfigs, newK8sResource(artifact, configReport, err))
|
misconfigs = append(misconfigs, newK8sResource(artifact, configReport, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
configReport, err = filter(ctx, opt, configReport)
|
configReport, err = runner.Filter(ctx, opt, configReport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return k8sReport.Report{}, xerrors.Errorf("filter error: %w", err)
|
return k8sReport.Report{}, xerrors.Errorf("filter error: %w", err)
|
||||||
}
|
}
|
||||||
@@ -153,6 +144,12 @@ func k8sRun(cliContext *cli.Context, opt Option, cacheClient cache.Cache, k8sArt
|
|||||||
misconfigs = append(misconfigs, newK8sResource(artifact, configReport, nil))
|
misconfigs = append(misconfigs, newK8sResource(artifact, configReport, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// enable logs after scanning
|
||||||
|
err = log.InitLogger(opt.Debug, opt.Quiet)
|
||||||
|
if err != nil {
|
||||||
|
return k8sReport.Report{}, xerrors.Errorf("logger error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return k8sReport.Report{
|
return k8sReport.Report{
|
||||||
SchemaVersion: 0,
|
SchemaVersion: 0,
|
||||||
Vulnerabilities: vulns,
|
Vulnerabilities: vulns,
|
||||||
@@ -160,58 +157,6 @@ func k8sRun(cliContext *cli.Context, opt Option, cacheClient cache.Cache, k8sArt
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initImageScannerConfig(ctx context.Context, opt Option, cacheClient cache.Cache) (ScannerConfig, types.ScanOptions, error) {
|
|
||||||
// Disable the lock file scanning
|
|
||||||
opt.DisabledAnalyzers = analyzer.TypeLockfiles
|
|
||||||
|
|
||||||
return initScannerConfig(ctx, opt, cacheClient)
|
|
||||||
}
|
|
||||||
|
|
||||||
func initConfigScannerConfig(ctx context.Context, opt Option, cacheClient cache.Cache) (ScannerConfig, types.ScanOptions, error) {
|
|
||||||
// Disable OS and language analyzers
|
|
||||||
opt.DisabledAnalyzers = append(analyzer.TypeOSes, analyzer.TypeLanguages...)
|
|
||||||
|
|
||||||
// Scan only config files
|
|
||||||
opt.VulnType = nil
|
|
||||||
opt.SecurityChecks = []string{types.SecurityCheckConfig}
|
|
||||||
|
|
||||||
// Skip downloading vulnerability DB
|
|
||||||
opt.SkipDBUpdate = true
|
|
||||||
|
|
||||||
return initScannerConfig(ctx, opt, cacheClient)
|
|
||||||
}
|
|
||||||
|
|
||||||
func k8sScanConfig(ctx context.Context, config ScannerConfig, opts types.ScanOptions, a *artifacts.Artifact) (types.Report, error) {
|
|
||||||
fileName, err := createTempFile(a)
|
|
||||||
if err != nil {
|
|
||||||
return types.Report{}, xerrors.Errorf("scan error: %w", err)
|
|
||||||
}
|
|
||||||
defer removeFile(fileName)
|
|
||||||
|
|
||||||
report, err := k8sScan(ctx, fileName, filesystemStandaloneScanner, config, opts)
|
|
||||||
if err != nil {
|
|
||||||
return types.Report{}, xerrors.Errorf("scan error: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return report, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func k8sScan(ctx context.Context, target string, initializeScanner InitializeScanner, config ScannerConfig, opts types.ScanOptions) (types.Report, error) {
|
|
||||||
config.Target = target
|
|
||||||
s, cleanup, err := initializeScanner(ctx, config)
|
|
||||||
if err != nil {
|
|
||||||
log.Logger.Debugf("unexpected error during scanning %s: %s", config.Target, err)
|
|
||||||
return types.Report{}, err
|
|
||||||
}
|
|
||||||
defer cleanup()
|
|
||||||
|
|
||||||
report, err := s.ScanArtifact(ctx, opts)
|
|
||||||
if err != nil {
|
|
||||||
return types.Report{}, xerrors.Errorf("artifact scan failed: %w", err)
|
|
||||||
}
|
|
||||||
return report, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTempFile(artifact *artifacts.Artifact) (string, error) {
|
func createTempFile(artifact *artifacts.Artifact) (string, error) {
|
||||||
filename := fmt.Sprintf("%s-%s-%s-*.yaml", artifact.Namespace, artifact.Kind, artifact.Name)
|
filename := fmt.Sprintf("%s-%s-%s-*.yaml", artifact.Namespace, artifact.Kind, artifact.Name)
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,11 @@ import (
|
|||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/aquasecurity/fanal/analyzer"
|
|
||||||
"github.com/aquasecurity/trivy/pkg/scanner"
|
"github.com/aquasecurity/trivy/pkg/scanner"
|
||||||
"github.com/aquasecurity/trivy/pkg/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// filesystemStandaloneScanner initializes a repository scanner in standalone mode
|
// filesystemStandaloneScanner initializes a repository scanner in standalone mode
|
||||||
func repositoryScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
func repositoryStandaloneScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner, func(), error) {
|
||||||
s, cleanup, err := initializeRepositoryScanner(ctx, conf.Target, conf.ArtifactCache, conf.LocalArtifactCache, conf.ArtifactOption)
|
s, cleanup, err := initializeRepositoryScanner(ctx, conf.Target, conf.ArtifactCache, conf.LocalArtifactCache, conf.ArtifactOption)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a filesystem scanner: %w", err)
|
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a filesystem scanner: %w", err)
|
||||||
@@ -22,16 +20,5 @@ func repositoryScanner(ctx context.Context, conf ScannerConfig) (scanner.Scanner
|
|||||||
|
|
||||||
// RepositoryRun runs scan on repository
|
// RepositoryRun runs scan on repository
|
||||||
func RepositoryRun(ctx *cli.Context) error {
|
func RepositoryRun(ctx *cli.Context) error {
|
||||||
opt, err := initOption(ctx)
|
return Run(ctx, repositoryArtifact)
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("option error: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not scan OS packages
|
|
||||||
opt.VulnType = []string{types.VulnTypeLibrary}
|
|
||||||
|
|
||||||
// Disable the OS analyzers and individual package analyzers
|
|
||||||
opt.DisabledAnalyzers = append(analyzer.TypeIndividualPkgs, analyzer.TypeOSes...)
|
|
||||||
|
|
||||||
return Run(ctx.Context, opt, repositoryScanner, initCache)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
@@ -25,9 +26,27 @@ import (
|
|||||||
"github.com/aquasecurity/trivy/pkg/utils"
|
"github.com/aquasecurity/trivy/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultPolicyNamespaces = []string{"appshield", "defsec", "builtin"}
|
type ArtifactType string
|
||||||
|
|
||||||
var errSkipScan = errors.New("skip subsequent processes")
|
const (
|
||||||
|
containerImageArtifact ArtifactType = "image"
|
||||||
|
filesystemArtifact ArtifactType = "fs"
|
||||||
|
rootfsArtifact ArtifactType = "rootfs"
|
||||||
|
repositoryArtifact ArtifactType = "repo"
|
||||||
|
imageArchiveArtifact ArtifactType = "archive"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultPolicyNamespaces = []string{"appshield", "defsec", "builtin"}
|
||||||
|
|
||||||
|
supportedArtifactTypes = []ArtifactType{containerImageArtifact, filesystemArtifact, rootfsArtifact,
|
||||||
|
repositoryArtifact, imageArchiveArtifact}
|
||||||
|
|
||||||
|
SkipScan = errors.New("skip subsequent processes")
|
||||||
|
)
|
||||||
|
|
||||||
|
// InitializeScanner defines the initialize function signature of scanner
|
||||||
|
type InitializeScanner func(context.Context, ScannerConfig) (scanner.Scanner, func(), error)
|
||||||
|
|
||||||
type ScannerConfig struct {
|
type ScannerConfig struct {
|
||||||
// e.g. image name and file path
|
// e.g. image name and file path
|
||||||
@@ -44,60 +63,151 @@ type ScannerConfig struct {
|
|||||||
ArtifactOption artifact.Option
|
ArtifactOption artifact.Option
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitializeScanner defines the initialize function signature of scanner
|
type Runner struct {
|
||||||
type InitializeScanner func(context.Context, ScannerConfig) (scanner.Scanner, func(), error)
|
cache cache.Cache
|
||||||
|
dbOpen bool
|
||||||
// InitCache defines cache initializer
|
|
||||||
type InitCache func(c Option) (cache.Cache, error)
|
|
||||||
|
|
||||||
// Run performs artifact scanning
|
|
||||||
func Run(ctx context.Context, opt Option, initializeScanner InitializeScanner, initCache InitCache) error {
|
|
||||||
ctx, cancel := context.WithTimeout(ctx, opt.Timeout)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err := runWithTimeout(ctx, opt, initializeScanner, initCache)
|
|
||||||
if xerrors.Is(err, context.DeadlineExceeded) {
|
|
||||||
log.Logger.Warn("Increase --timeout value")
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runWithTimeout(ctx context.Context, opt Option, initializeScanner InitializeScanner, initCache InitCache) error {
|
type runnerOption func(*Runner)
|
||||||
if err := log.InitLogger(opt.Debug, opt.Quiet); err != nil {
|
|
||||||
return err
|
// WithCacheClient takes a custom cache implementation
|
||||||
|
func WithCacheClient(c cache.Cache) runnerOption {
|
||||||
|
return func(r *Runner) {
|
||||||
|
r.cache = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRunner initializes Runner that provides scanning functionalities.
|
||||||
|
// It is possible to return SkipScan and it must be handled by caller.
|
||||||
|
func NewRunner(cliOption Option, opts ...runnerOption) (*Runner, error) {
|
||||||
|
r := &Runner{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheClient, err := initCache(opt)
|
err := log.InitLogger(cliOption.Debug, cliOption.Quiet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, errSkipScan) {
|
return nil, xerrors.Errorf("logger error: %w", err)
|
||||||
return nil
|
}
|
||||||
|
|
||||||
|
if err = r.initCache(cliOption); err != nil {
|
||||||
|
return nil, xerrors.Errorf("cache error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = r.initDB(cliOption); err != nil {
|
||||||
|
return nil, xerrors.Errorf("DB error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes everything
|
||||||
|
func (r *Runner) Close() error {
|
||||||
|
var errs error
|
||||||
|
if err := r.cache.Close(); err != nil {
|
||||||
|
errs = multierror.Append(errs, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.dbOpen {
|
||||||
|
if err := db.Close(); err != nil {
|
||||||
|
errs = multierror.Append(errs, err)
|
||||||
}
|
}
|
||||||
return xerrors.Errorf("cache error: %w", err)
|
|
||||||
}
|
}
|
||||||
defer cacheClient.Close()
|
return errs
|
||||||
|
}
|
||||||
|
|
||||||
// When scanning config files or running as client mode, it doesn't need to download the vulnerability database.
|
func (r *Runner) ScanImage(ctx context.Context, opt Option) (types.Report, error) {
|
||||||
if opt.RemoteAddr == "" && slices.Contains(opt.SecurityChecks, types.SecurityCheckVulnerability) {
|
// Disable the lock file scanning
|
||||||
if err = initDB(opt); err != nil {
|
opt.DisabledAnalyzers = analyzer.TypeLockfiles
|
||||||
if errors.Is(err, errSkipScan) {
|
|
||||||
return nil
|
var s InitializeScanner
|
||||||
}
|
switch {
|
||||||
return xerrors.Errorf("DB error: %w", err)
|
case opt.Input != "" && opt.RemoteAddr == "":
|
||||||
|
// Scan image tarball in standalone mode
|
||||||
|
s = archiveStandaloneScanner
|
||||||
|
case opt.Input != "" && opt.RemoteAddr != "":
|
||||||
|
// Scan image tarball in client/server mode
|
||||||
|
s = archiveRemoteScanner
|
||||||
|
case opt.Input == "" && opt.RemoteAddr == "":
|
||||||
|
// Scan container image in standalone mode
|
||||||
|
s = imageStandaloneScanner
|
||||||
|
case opt.Input == "" && opt.RemoteAddr != "":
|
||||||
|
// Scan container image in client/server mode
|
||||||
|
s = imageRemoteScanner
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Scan(ctx, opt, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runner) ScanFilesystem(ctx context.Context, opt Option) (types.Report, error) {
|
||||||
|
// Disable the individual package scanning
|
||||||
|
opt.DisabledAnalyzers = append(opt.DisabledAnalyzers, analyzer.TypeIndividualPkgs...)
|
||||||
|
|
||||||
|
return r.scanFS(ctx, opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runner) ScanRootfs(ctx context.Context, opt Option) (types.Report, error) {
|
||||||
|
// Disable the lock file scanning
|
||||||
|
opt.DisabledAnalyzers = append(opt.DisabledAnalyzers, analyzer.TypeLockfiles...)
|
||||||
|
|
||||||
|
return r.scanFS(ctx, opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runner) scanFS(ctx context.Context, opt Option) (types.Report, error) {
|
||||||
|
var s InitializeScanner
|
||||||
|
if opt.RemoteAddr == "" {
|
||||||
|
// Scan filesystem in standalone mode
|
||||||
|
s = filesystemStandaloneScanner
|
||||||
|
} else {
|
||||||
|
// Scan filesystem in client/server mode
|
||||||
|
s = filesystemRemoteScanner
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.Scan(ctx, opt, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runner) ScanRepository(ctx context.Context, opt Option) (types.Report, error) {
|
||||||
|
// Do not scan OS packages
|
||||||
|
opt.VulnType = []string{types.VulnTypeLibrary}
|
||||||
|
|
||||||
|
// Disable the OS analyzers and individual package analyzers
|
||||||
|
opt.DisabledAnalyzers = append(analyzer.TypeIndividualPkgs, analyzer.TypeOSes...)
|
||||||
|
|
||||||
|
return r.Scan(ctx, opt, repositoryStandaloneScanner)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runner) Scan(ctx context.Context, opt Option, initializeScanner InitializeScanner) (types.Report, error) {
|
||||||
|
report, err := scan(ctx, opt, initializeScanner, r.cache)
|
||||||
|
if err != nil {
|
||||||
|
return types.Report{}, xerrors.Errorf("scan error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return report, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runner) Filter(ctx context.Context, opt Option, report types.Report) (types.Report, error) {
|
||||||
|
resultClient := initializeResultClient()
|
||||||
|
results := report.Results
|
||||||
|
for i := range results {
|
||||||
|
// Fill vulnerability info only in standalone mode
|
||||||
|
if opt.RemoteAddr == "" {
|
||||||
|
resultClient.FillVulnerabilityInfo(results[i].Vulnerabilities, results[i].Type)
|
||||||
}
|
}
|
||||||
defer db.Close()
|
vulns, misconfSummary, misconfs, secrets, err := resultClient.Filter(ctx, results[i].Vulnerabilities, results[i].Misconfigurations, results[i].Secrets,
|
||||||
|
opt.Severities, opt.IgnoreUnfixed, opt.IncludeNonFailures, opt.IgnoreFile, opt.IgnorePolicy)
|
||||||
|
if err != nil {
|
||||||
|
return types.Report{}, xerrors.Errorf("unable to filter vulnerabilities: %w", err)
|
||||||
|
}
|
||||||
|
results[i].Vulnerabilities = vulns
|
||||||
|
results[i].Misconfigurations = misconfs
|
||||||
|
results[i].MisconfSummary = misconfSummary
|
||||||
|
results[i].Secrets = secrets
|
||||||
}
|
}
|
||||||
|
return report, nil
|
||||||
|
}
|
||||||
|
|
||||||
report, err := scan(ctx, opt, initializeScanner, cacheClient)
|
func (r *Runner) Report(opt Option, report types.Report) error {
|
||||||
if err != nil {
|
if err := pkgReport.Write(report, pkgReport.Option{
|
||||||
return xerrors.Errorf("scan error: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
report, err = filter(ctx, opt, report)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("filter error: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = pkgReport.Write(report, pkgReport.Option{
|
|
||||||
AppVersion: opt.GlobalOption.AppVersion,
|
AppVersion: opt.GlobalOption.AppVersion,
|
||||||
Format: opt.Format,
|
Format: opt.Format,
|
||||||
Output: opt.Output,
|
Output: opt.Output,
|
||||||
@@ -109,44 +219,15 @@ func runWithTimeout(ctx context.Context, opt Option, initializeScanner Initializ
|
|||||||
return xerrors.Errorf("unable to write results: %w", err)
|
return xerrors.Errorf("unable to write results: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(opt, report.Results.Failed())
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initCache(c Option) (cache.Cache, error) {
|
func (r *Runner) initDB(c Option) error {
|
||||||
// client/server mode
|
// When scanning config files or running as client mode, it doesn't need to download the vulnerability database.
|
||||||
if c.RemoteAddr != "" {
|
if c.RemoteAddr != "" || !slices.Contains(c.SecurityChecks, types.SecurityCheckVulnerability) {
|
||||||
remoteCache := tcache.NewRemoteCache(c.RemoteAddr, c.CustomHeaders, c.Insecure)
|
return nil
|
||||||
return tcache.NopCache(remoteCache), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// standalone mode
|
|
||||||
utils.SetCacheDir(c.CacheDir)
|
|
||||||
cache, err := operation.NewCache(c.CacheOption)
|
|
||||||
if err != nil {
|
|
||||||
return operation.Cache{}, xerrors.Errorf("unable to initialize the cache: %w", err)
|
|
||||||
}
|
|
||||||
log.Logger.Debugf("cache dir: %s", utils.CacheDir())
|
|
||||||
|
|
||||||
if c.Reset {
|
|
||||||
defer cache.Close()
|
|
||||||
if err = cache.Reset(); err != nil {
|
|
||||||
return operation.Cache{}, xerrors.Errorf("cache reset error: %w", err)
|
|
||||||
}
|
|
||||||
return operation.Cache{}, errSkipScan
|
|
||||||
}
|
|
||||||
if c.ClearCache {
|
|
||||||
defer cache.Close()
|
|
||||||
if err = cache.ClearArtifacts(); err != nil {
|
|
||||||
return operation.Cache{}, xerrors.Errorf("cache clear error: %w", err)
|
|
||||||
}
|
|
||||||
return operation.Cache{}, errSkipScan
|
|
||||||
}
|
|
||||||
return cache, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func initDB(c Option) error {
|
|
||||||
// download the database file
|
// download the database file
|
||||||
noProgress := c.Quiet || c.NoProgress
|
noProgress := c.Quiet || c.NoProgress
|
||||||
if err := operation.DownloadDB(c.AppVersion, c.CacheDir, c.DBRepository, noProgress, c.SkipDBUpdate); err != nil {
|
if err := operation.DownloadDB(c.AppVersion, c.CacheDir, c.DBRepository, noProgress, c.SkipDBUpdate); err != nil {
|
||||||
@@ -154,16 +235,121 @@ func initDB(c Option) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.DownloadDBOnly {
|
if c.DownloadDBOnly {
|
||||||
return errSkipScan
|
return SkipScan
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.Init(c.CacheDir); err != nil {
|
if err := db.Init(c.CacheDir); err != nil {
|
||||||
return xerrors.Errorf("error in vulnerability DB initialize: %w", err)
|
return xerrors.Errorf("error in vulnerability DB initialize: %w", err)
|
||||||
}
|
}
|
||||||
|
r.dbOpen = true
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initOption(ctx *cli.Context) (Option, error) {
|
func (r *Runner) initCache(c Option) error {
|
||||||
|
// Skip initializing cache when custom cache is passed
|
||||||
|
if r.cache != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// client/server mode
|
||||||
|
if c.RemoteAddr != "" {
|
||||||
|
remoteCache := tcache.NewRemoteCache(c.RemoteAddr, c.CustomHeaders, c.Insecure)
|
||||||
|
r.cache = tcache.NopCache(remoteCache)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// standalone mode
|
||||||
|
utils.SetCacheDir(c.CacheDir)
|
||||||
|
cache, err := operation.NewCache(c.CacheOption)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("unable to initialize the cache: %w", err)
|
||||||
|
}
|
||||||
|
log.Logger.Debugf("cache dir: %s", utils.CacheDir())
|
||||||
|
|
||||||
|
if c.Reset {
|
||||||
|
defer cache.Close()
|
||||||
|
if err = cache.Reset(); err != nil {
|
||||||
|
return xerrors.Errorf("cache reset error: %w", err)
|
||||||
|
}
|
||||||
|
return SkipScan
|
||||||
|
}
|
||||||
|
if c.ClearCache {
|
||||||
|
defer cache.Close()
|
||||||
|
if err = cache.ClearArtifacts(); err != nil {
|
||||||
|
return xerrors.Errorf("cache clear error: %w", err)
|
||||||
|
}
|
||||||
|
return SkipScan
|
||||||
|
}
|
||||||
|
|
||||||
|
r.cache = cache
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run performs artifact scanning
|
||||||
|
func Run(cliCtx *cli.Context, artifactType ArtifactType) error {
|
||||||
|
opt, err := InitOption(cliCtx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return run(cliCtx.Context, opt, artifactType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(ctx context.Context, opt Option, artifactType ArtifactType) (err error) {
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, opt.Timeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if xerrors.Is(err, context.DeadlineExceeded) {
|
||||||
|
log.Logger.Warn("Increase --timeout value")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
runner, err := NewRunner(opt)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, SkipScan) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return xerrors.Errorf("init error: %w", err)
|
||||||
|
}
|
||||||
|
defer runner.Close()
|
||||||
|
|
||||||
|
var report types.Report
|
||||||
|
switch artifactType {
|
||||||
|
case containerImageArtifact, imageArchiveArtifact:
|
||||||
|
if report, err = runner.ScanImage(ctx, opt); err != nil {
|
||||||
|
return xerrors.Errorf("image scan error: %w", err)
|
||||||
|
}
|
||||||
|
case filesystemArtifact:
|
||||||
|
if report, err = runner.ScanFilesystem(ctx, opt); err != nil {
|
||||||
|
return xerrors.Errorf("filesystem scan error: %w", err)
|
||||||
|
}
|
||||||
|
case rootfsArtifact:
|
||||||
|
if report, err = runner.ScanRootfs(ctx, opt); err != nil {
|
||||||
|
return xerrors.Errorf("rootfs scan error: %w", err)
|
||||||
|
}
|
||||||
|
case repositoryArtifact:
|
||||||
|
if report, err = runner.ScanRepository(ctx, opt); err != nil {
|
||||||
|
return xerrors.Errorf("repository scan error: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
report, err = runner.Filter(ctx, opt, report)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("filter error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = runner.Report(opt, report); err != nil {
|
||||||
|
return xerrors.Errorf("report error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(opt, report.Results.Failed())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitOption(ctx *cli.Context) (Option, error) {
|
||||||
opt, err := NewOption(ctx)
|
opt, err := NewOption(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Option{}, xerrors.Errorf("option error: %w", err)
|
return Option{}, xerrors.Errorf("option error: %w", err)
|
||||||
@@ -205,7 +391,7 @@ func disabledAnalyzers(opt Option) []analyzer.Type {
|
|||||||
return analyzers
|
return analyzers
|
||||||
}
|
}
|
||||||
|
|
||||||
func initScannerConfig(ctx context.Context, opt Option, cacheClient cache.Cache) (ScannerConfig, types.ScanOptions, error) {
|
func initScannerConfig(opt Option, cacheClient cache.Cache) (ScannerConfig, types.ScanOptions, error) {
|
||||||
target := opt.Target
|
target := opt.Target
|
||||||
if opt.Input != "" {
|
if opt.Input != "" {
|
||||||
target = opt.Input
|
target = opt.Input
|
||||||
@@ -262,7 +448,7 @@ func initScannerConfig(ctx context.Context, opt Option, cacheClient cache.Cache)
|
|||||||
func scan(ctx context.Context, opt Option, initializeScanner InitializeScanner, cacheClient cache.Cache) (
|
func scan(ctx context.Context, opt Option, initializeScanner InitializeScanner, cacheClient cache.Cache) (
|
||||||
types.Report, error) {
|
types.Report, error) {
|
||||||
|
|
||||||
scannerConfig, scanOptions, err := initScannerConfig(ctx, opt, cacheClient)
|
scannerConfig, scanOptions, err := initScannerConfig(opt, cacheClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.Report{}, err
|
return types.Report{}, err
|
||||||
}
|
}
|
||||||
@@ -280,27 +466,6 @@ func scan(ctx context.Context, opt Option, initializeScanner InitializeScanner,
|
|||||||
return report, nil
|
return report, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func filter(ctx context.Context, opt Option, report types.Report) (types.Report, error) {
|
|
||||||
resultClient := initializeResultClient()
|
|
||||||
results := report.Results
|
|
||||||
for i := range results {
|
|
||||||
// Fill vulnerability info only in standalone mode
|
|
||||||
if opt.RemoteAddr == "" {
|
|
||||||
resultClient.FillVulnerabilityInfo(results[i].Vulnerabilities, results[i].Type)
|
|
||||||
}
|
|
||||||
vulns, misconfSummary, misconfs, secrets, err := resultClient.Filter(ctx, results[i].Vulnerabilities, results[i].Misconfigurations, results[i].Secrets,
|
|
||||||
opt.Severities, opt.IgnoreUnfixed, opt.IncludeNonFailures, opt.IgnoreFile, opt.IgnorePolicy)
|
|
||||||
if err != nil {
|
|
||||||
return types.Report{}, xerrors.Errorf("unable to filter vulnerabilities: %w", err)
|
|
||||||
}
|
|
||||||
results[i].Vulnerabilities = vulns
|
|
||||||
results[i].Misconfigurations = misconfs
|
|
||||||
results[i].MisconfSummary = misconfSummary
|
|
||||||
results[i].Secrets = secrets
|
|
||||||
}
|
|
||||||
return report, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func exit(c Option, failedResults bool) {
|
func exit(c Option, failedResults bool) {
|
||||||
if c.ExitCode != 0 && failedResults {
|
if c.ExitCode != 0 && failedResults {
|
||||||
os.Exit(c.ExitCode)
|
os.Exit(c.ExitCode)
|
||||||
|
|||||||
@@ -2,61 +2,32 @@ package artifact
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"golang.org/x/exp/maps"
|
"golang.org/x/exp/slices"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/aquasecurity/fanal/analyzer"
|
|
||||||
"github.com/aquasecurity/trivy/pkg/types"
|
"github.com/aquasecurity/trivy/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ArtifactType string
|
|
||||||
|
|
||||||
const (
|
|
||||||
containerImageArtifact ArtifactType = "image"
|
|
||||||
filesystemArtifact ArtifactType = "fs"
|
|
||||||
repositoryArtifact ArtifactType = "repo"
|
|
||||||
imageArchiveArtifact ArtifactType = "archive"
|
|
||||||
)
|
|
||||||
|
|
||||||
var artifactTypes = map[ArtifactType]struct {
|
|
||||||
initializer InitializeScanner
|
|
||||||
disableAnalyzers []analyzer.Type
|
|
||||||
}{
|
|
||||||
containerImageArtifact: {
|
|
||||||
initializer: imageScanner,
|
|
||||||
disableAnalyzers: analyzer.TypeLockfiles,
|
|
||||||
},
|
|
||||||
filesystemArtifact: {
|
|
||||||
initializer: filesystemStandaloneScanner,
|
|
||||||
disableAnalyzers: analyzer.TypeIndividualPkgs,
|
|
||||||
},
|
|
||||||
repositoryArtifact: {
|
|
||||||
initializer: repositoryScanner,
|
|
||||||
disableAnalyzers: analyzer.TypeIndividualPkgs,
|
|
||||||
},
|
|
||||||
imageArchiveArtifact: {
|
|
||||||
initializer: archiveScanner,
|
|
||||||
disableAnalyzers: analyzer.TypeLockfiles,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// SbomRun runs generates sbom for image and package artifacts
|
// SbomRun runs generates sbom for image and package artifacts
|
||||||
func SbomRun(ctx *cli.Context) error {
|
func SbomRun(ctx *cli.Context) error {
|
||||||
opt, err := initOption(ctx)
|
opt, err := InitOption(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("option error: %w", err)
|
return xerrors.Errorf("option error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
artifactType := opt.SbomOption.ArtifactType
|
artifactType := ArtifactType(opt.SbomOption.ArtifactType)
|
||||||
s, ok := artifactTypes[ArtifactType(artifactType)]
|
if !slices.Contains(supportedArtifactTypes, artifactType) {
|
||||||
if !ok {
|
return xerrors.Errorf(`"--artifact-type" must be %q`, supportedArtifactTypes)
|
||||||
return xerrors.Errorf(`"--artifact-type" must be %q`, maps.Keys(artifactTypes))
|
}
|
||||||
|
|
||||||
|
// Pass the specified image archive via "--input".
|
||||||
|
if artifactType == imageArchiveArtifact {
|
||||||
|
opt.Input = opt.Target
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan the relevant dependencies
|
// Scan the relevant dependencies
|
||||||
opt.DisabledAnalyzers = s.disableAnalyzers
|
|
||||||
opt.ReportOption.VulnType = []string{types.VulnTypeOS, types.VulnTypeLibrary}
|
opt.ReportOption.VulnType = []string{types.VulnTypeOS, types.VulnTypeLibrary}
|
||||||
opt.ReportOption.SecurityChecks = []string{types.SecurityCheckVulnerability}
|
opt.ReportOption.SecurityChecks = []string{types.SecurityCheckVulnerability}
|
||||||
|
|
||||||
return Run(ctx.Context, opt, s.initializer, initCache)
|
return run(ctx.Context, opt, artifactType)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user