feat(java): support jar/war/ear (#837)

* refactor(server): remove Detect endpoint

* refactor(library): do not use interface

* refactor: add dbtest package

* test: add bolt fixtures

* feat: support jar scanning

* refactor: rename node to npm

* refactor: fix lint issues

* test(maven): remove some tests

* chore(mod): update fanal

* docs: update README

* chore(mod): update trivy-db

* fix(library/drive): add ecosystem

* fix: do not display 0 vulnerabilities

* refactor(table): split method

* Update README.md (#838)

* fix(app): increase the default value of timeout (#842)

* feat(maven): use go-mvn-version

* test(maven): update tests

* fix(scan): skip files and dirs before vulnerability detection

* fix: display log messages only once per type

* docs(README): add file suffixes

* chore(mod): update go-mvn-version

* feat(log): set go-dep-parser logger

* chore(mod): update fanal

* docs: update README

* docs(README): add java source

* test(maven): fix invalid case
This commit is contained in:
Teppei Fukuda
2021-02-14 18:19:42 +02:00
committed by GitHub
parent 3047c524d9
commit c9f22f4e55
43 changed files with 455 additions and 2695 deletions

View File

@@ -103,7 +103,7 @@ See [here](#continuous-integration-ci) for details.
- Detect comprehensive vulnerabilities - Detect comprehensive vulnerabilities
- OS packages (Alpine, **Red Hat Universal Base Image**, Red Hat Enterprise Linux, CentOS, Oracle Linux, Debian, Ubuntu, Amazon Linux, openSUSE Leap, SUSE Enterprise Linux, Photon OS and Distroless) - OS packages (Alpine, **Red Hat Universal Base Image**, Red Hat Enterprise Linux, CentOS, Oracle Linux, Debian, Ubuntu, Amazon Linux, openSUSE Leap, SUSE Enterprise Linux, Photon OS and Distroless)
- **Application dependencies** (Bundler, Composer, Pipenv, Poetry, npm, yarn, Cargo and NuGet) - **Application dependencies** (Bundler, Composer, Pipenv, Poetry, npm, yarn, Cargo, NuGet, and Maven)
- Simple - Simple
- Specify only an image name or artifact name - Specify only an image name or artifact name
- See [Quick Start](#quick-start) and [Examples](#examples) - See [Quick Start](#quick-start) and [Examples](#examples)
@@ -1763,6 +1763,8 @@ Distroless: https://github.com/GoogleContainerTools/distroless
- Cargo.lock - Cargo.lock
- .NET - .NET
- packages.lock.json - packages.lock.json
- Java
- JAR/WAR/EAR files (*.jar, *.war, and *.ear)
The path of these files does not matter. The path of these files does not matter.
@@ -1796,6 +1798,8 @@ Trivy scans a tar image with the following format.
- https://github.com/RustSec/advisory-db - https://github.com/RustSec/advisory-db
- .NET - .NET
- https://github.com/advisories?query=ecosystem%3Anuget - https://github.com/advisories?query=ecosystem%3Anuget
- Java
- https://github.com/advisories?query=ecosystem%3Amaven
# Usage # Usage
Trivy has several sub commands, image, fs, repo, client and server. Trivy has several sub commands, image, fs, repo, client and server.
@@ -1921,7 +1925,7 @@ See [here](docs/air-gap.md)
| Scanner | OS<br>Packages | Application<br>Dependencies | Easy to use | Accuracy | Suitable<br>for CI | | Scanner | OS<br>Packages | Application<br>Dependencies | Easy to use | Accuracy | Suitable<br>for CI |
| -------------- | :-------------: | :-------------------------: | :----------: | :---------: | :-----------------: | | -------------- | :-------------: | :-------------------------: | :----------: | :---------: | :-----------------: |
| Trivy | ✅ | ✅<br>(5 languages) | ⭐ ⭐ ⭐ | ⭐ ⭐ ⭐ | ⭐ ⭐ ⭐ | | Trivy | ✅ | ✅<br>(7 languages) | ⭐ ⭐ ⭐ | ⭐ ⭐ ⭐ | ⭐ ⭐ ⭐ |
| Clair | ✅ | × | ⭐ | ⭐ ⭐ | ⭐ ⭐ | | Clair | ✅ | × | ⭐ | ⭐ ⭐ | ⭐ ⭐ |
| Anchore Engine | ✅ | ✅<br>(4 languages) | ⭐ ⭐ | ⭐ ⭐ | ⭐ ⭐ ⭐ | | Anchore Engine | ✅ | ✅<br>(4 languages) | ⭐ ⭐ | ⭐ ⭐ | ⭐ ⭐ ⭐ |
| Quay | ✅ | × | ⭐ ⭐ ⭐ | ⭐ ⭐ | × | | Quay | ✅ | × | ⭐ ⭐ ⭐ | ⭐ ⭐ | × |

15
go.mod
View File

@@ -4,13 +4,13 @@ go 1.15
require ( require (
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986
github.com/aquasecurity/fanal v0.0.0-20210119051230-28c249da7cfd github.com/aquasecurity/fanal v0.0.0-20210214122859-98d76e2b3b96
github.com/aquasecurity/go-dep-parser v0.0.0-20201028043324-889d4a92b8e0 github.com/aquasecurity/go-dep-parser v0.0.0-20210214113128-b97635cfd627
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce
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-20210105160501-c5bf4e153277 github.com/aquasecurity/trivy-db v0.0.0-20210214043256-acc144af2228
github.com/caarlos0/env/v6 v6.0.0 github.com/caarlos0/env/v6 v6.0.0
github.com/cenkalti/backoff v2.2.1+incompatible github.com/cenkalti/backoff v2.2.1+incompatible
github.com/cheggaaa/pb/v3 v3.0.3 github.com/cheggaaa/pb/v3 v3.0.3
@@ -30,6 +30,7 @@ require (
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d
github.com/knqyf263/go-rpm-version v0.0.0-20170716094938-74609b86c936 github.com/knqyf263/go-rpm-version v0.0.0-20170716094938-74609b86c936
github.com/kylelemons/godebug v1.1.0 github.com/kylelemons/godebug v1.1.0
github.com/masahiro331/go-mvn-version v0.0.0-20210214074851-415aa65db8c0
github.com/mattn/go-runewidth v0.0.9 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/olekukonko/tablewriter v0.0.2-0.20190607075207-195002e6e56a github.com/olekukonko/tablewriter v0.0.2-0.20190607075207-195002e6e56a
github.com/open-policy-agent/opa v0.21.1 github.com/open-policy-agent/opa v0.21.1
@@ -37,13 +38,11 @@ require (
github.com/smartystreets/goconvey v1.6.4 // indirect github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/spf13/afero v1.2.2 github.com/spf13/afero v1.2.2
github.com/stretchr/objx v0.3.0 // indirect github.com/stretchr/objx v0.3.0 // indirect
github.com/stretchr/testify v1.6.1 github.com/stretchr/testify v1.7.0
github.com/testcontainers/testcontainers-go v0.3.1 github.com/testcontainers/testcontainers-go v0.3.1
github.com/twitchtv/twirp v5.10.1+incompatible github.com/twitchtv/twirp v5.10.1+incompatible
github.com/urfave/cli/v2 v2.3.0 github.com/urfave/cli/v2 v2.3.0
go.uber.org/atomic v1.5.1 // indirect go.uber.org/zap v1.16.0
go.uber.org/multierr v1.4.0 // indirect
go.uber.org/zap v1.13.0
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5 golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5
golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf // indirect golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf // indirect
@@ -51,6 +50,6 @@ require (
google.golang.org/protobuf v1.25.0 google.golang.org/protobuf v1.25.0
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 k8s.io/utils v0.0.0-20201110183641-67b214c5f920
) )

34
go.sum
View File

@@ -91,10 +91,10 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 h1:2a30xLN2sUZcMXl50hg+PJCIDdJgIvIbVcKqLJ/ZrtM= github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 h1:2a30xLN2sUZcMXl50hg+PJCIDdJgIvIbVcKqLJ/ZrtM=
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986/go.mod h1:NT+jyeCzXk6vXR5MTkdn4z64TgGfE5HMLC8qfj5unl8= github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986/go.mod h1:NT+jyeCzXk6vXR5MTkdn4z64TgGfE5HMLC8qfj5unl8=
github.com/aquasecurity/fanal v0.0.0-20210119051230-28c249da7cfd h1:meqa2AA+7K1r/nfNB19K2AP/v8+nemuWeQoTSqZ2R9s= github.com/aquasecurity/fanal v0.0.0-20210214122859-98d76e2b3b96 h1:5Uk/RmXp+Itbm3fLa0vg1OKBl6Z6BfxDVrJpwETYqWk=
github.com/aquasecurity/fanal v0.0.0-20210119051230-28c249da7cfd/go.mod h1:kur6SaohYhsjQLzijAdtn+X8rkTtwxawE51WyVCXLKk= github.com/aquasecurity/fanal v0.0.0-20210214122859-98d76e2b3b96/go.mod h1:8HoL/kipOrDodHh+jzGgO2/iXJoRf6roLP5qPv8Mi90=
github.com/aquasecurity/go-dep-parser v0.0.0-20201028043324-889d4a92b8e0 h1:cLH3SebzhbJ+jU1GIad8A1N8p7m7OjHhtY6JePISiVc= github.com/aquasecurity/go-dep-parser v0.0.0-20210214113128-b97635cfd627 h1:ccLbhkZ54xTmI6Q+CyBL8sll+OXIEzX0aDDjmy8pVWQ=
github.com/aquasecurity/go-dep-parser v0.0.0-20201028043324-889d4a92b8e0/go.mod h1:X42mTIRhgPalSm81Om2kD+3ydeunbC8TZtZj1bvgRo8= github.com/aquasecurity/go-dep-parser v0.0.0-20210214113128-b97635cfd627/go.mod h1:KHiF3uK6FOE1v27YK+5CWEJ1jd0OvA2Gmk8VFjT3utk=
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce h1:QgBRgJvtEOBtUXilDb1MLi1p1MWoyFDXAu5DEUl5nwM= github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce h1:QgBRgJvtEOBtUXilDb1MLi1p1MWoyFDXAu5DEUl5nwM=
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce/go.mod h1:HXgVzOPvXhVGLJs4ZKO817idqr/xhwsTcj17CLYY74s= github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce/go.mod h1:HXgVzOPvXhVGLJs4ZKO817idqr/xhwsTcj17CLYY74s=
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798 h1:eveqE9ivrt30CJ7dOajOfBavhZ4zPqHcZe/4tKp0alc= github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798 h1:eveqE9ivrt30CJ7dOajOfBavhZ4zPqHcZe/4tKp0alc=
@@ -107,8 +107,8 @@ github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 h1:rcEG5HI
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492/go.mod h1:9Beu8XsUNNfzml7WBf3QmyPToP1wm1Gj/Vc5UJKqTzU= github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492/go.mod h1:9Beu8XsUNNfzml7WBf3QmyPToP1wm1Gj/Vc5UJKqTzU=
github.com/aquasecurity/testdocker v0.0.0-20210106133225-0b17fe083674 h1:Xq/HxWFGaB4G/prC6czH/F5woB91GMCCilJxs/5DnDk= github.com/aquasecurity/testdocker v0.0.0-20210106133225-0b17fe083674 h1:Xq/HxWFGaB4G/prC6czH/F5woB91GMCCilJxs/5DnDk=
github.com/aquasecurity/testdocker v0.0.0-20210106133225-0b17fe083674/go.mod h1:psfu0MVaiTDLpNxCoNsTeILSKY2EICBwv345f3M+Ffs= github.com/aquasecurity/testdocker v0.0.0-20210106133225-0b17fe083674/go.mod h1:psfu0MVaiTDLpNxCoNsTeILSKY2EICBwv345f3M+Ffs=
github.com/aquasecurity/trivy-db v0.0.0-20210105160501-c5bf4e153277 h1:lXN72H9uNM1exUArIsN++n7b67PIaqhZON2cVWxwmpg= github.com/aquasecurity/trivy-db v0.0.0-20210214043256-acc144af2228 h1:Hl1eKVUApdGdMUNiSYWekViWccauKxscorOV2bc1cJE=
github.com/aquasecurity/trivy-db v0.0.0-20210105160501-c5bf4e153277/go.mod h1:N7CWA/vjVw78GWAdCJGhFQVqNGEA4e47a6eIWm+C/Bc= github.com/aquasecurity/trivy-db v0.0.0-20210214043256-acc144af2228/go.mod h1:N7CWA/vjVw78GWAdCJGhFQVqNGEA4e47a6eIWm+C/Bc=
github.com/aquasecurity/vuln-list-update v0.0.0-20191016075347-3d158c2bf9a2 h1:xbdUfr2KE4THsFx9CFWtWpU91lF+YhgP46moV94nYTA= github.com/aquasecurity/vuln-list-update v0.0.0-20191016075347-3d158c2bf9a2 h1:xbdUfr2KE4THsFx9CFWtWpU91lF+YhgP46moV94nYTA=
github.com/aquasecurity/vuln-list-update v0.0.0-20191016075347-3d158c2bf9a2/go.mod h1:6NhOP0CjZJL27bZZcaHECtzWdwDDm2g6yCY0QgXEGQQ= github.com/aquasecurity/vuln-list-update v0.0.0-20191016075347-3d158c2bf9a2/go.mod h1:6NhOP0CjZJL27bZZcaHECtzWdwDDm2g6yCY0QgXEGQQ=
github.com/araddon/dateparse v0.0.0-20190426192744-0d74ffceef83/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI= github.com/araddon/dateparse v0.0.0-20190426192744-0d74ffceef83/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI=
@@ -429,6 +429,8 @@ github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/masahiro331/go-mvn-version v0.0.0-20210214074851-415aa65db8c0 h1:GT77MM4NtCZv3oeOlY+Y7EANZ86/h49oqPytEKTm3f8=
github.com/masahiro331/go-mvn-version v0.0.0-20210214074851-415aa65db8c0/go.mod h1:M5wLEr5YKZ6OcOpiNGO0qPE4cd+xjUbBLlBvJGhZgWQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
@@ -584,6 +586,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/testcontainers/testcontainers-go v0.3.1 h1:KZkEKNfnlsipJblzGCz6fmzd+0DzJ3djulYrislG3Zw= github.com/testcontainers/testcontainers-go v0.3.1 h1:KZkEKNfnlsipJblzGCz6fmzd+0DzJ3djulYrislG3Zw=
github.com/testcontainers/testcontainers-go v0.3.1/go.mod h1:br7bkzIukhPSIjy07Ma3OuXjjFvl2jm7CDU0LQNsqLw= github.com/testcontainers/testcontainers-go v0.3.1/go.mod h1:br7bkzIukhPSIjy07Ma3OuXjjFvl2jm7CDU0LQNsqLw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@@ -624,18 +628,16 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/otel v0.14.0 h1:YFBEfjCk9MTjaytCNSUkp9Q8lF7QJezA06T71FbQxLQ= go.opentelemetry.io/otel v0.14.0 h1:YFBEfjCk9MTjaytCNSUkp9Q8lF7QJezA06T71FbQxLQ=
go.opentelemetry.io/otel v0.14.0/go.mod h1:vH5xEuwy7Rts0GNtsCW3HYQoZDY+OmBJ6t1bFGGlxgw= go.opentelemetry.io/otel v0.14.0/go.mod h1:vH5xEuwy7Rts0GNtsCW3HYQoZDY+OmBJ6t1bFGGlxgw=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
go.uber.org/atomic v1.5.1 h1:rsqfU5vBkVknbhUGbAUwQKR2H4ItV8tjJ+6kJX4cxHM= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -993,8 +995,8 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v0.0.0-20181223230014-1083505acf35/go.mod h1:R//lfYlUuTOTfblYI3lGoAAAebUdzjvbmQsuB7Ykd90= gotest.tools v0.0.0-20181223230014-1083505acf35/go.mod h1:R//lfYlUuTOTfblYI3lGoAAAebUdzjvbmQsuB7Ykd90=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=

View File

@@ -14,7 +14,6 @@ import (
"github.com/aquasecurity/fanal/cache" "github.com/aquasecurity/fanal/cache"
"github.com/aquasecurity/fanal/image" "github.com/aquasecurity/fanal/image"
"github.com/aquasecurity/trivy-db/pkg/db" "github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy/pkg/detector/library"
"github.com/aquasecurity/trivy/pkg/detector/ospkg" "github.com/aquasecurity/trivy/pkg/detector/ospkg"
"github.com/aquasecurity/trivy/pkg/scanner" "github.com/aquasecurity/trivy/pkg/scanner"
"github.com/aquasecurity/trivy/pkg/scanner/local" "github.com/aquasecurity/trivy/pkg/scanner/local"
@@ -28,9 +27,7 @@ import (
func initializeDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache, timeout time.Duration) (scanner.Scanner, func(), error) { func initializeDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache, timeout time.Duration) (scanner.Scanner, func(), error) {
applierApplier := applier.NewApplier(localArtifactCache) applierApplier := applier.NewApplier(localArtifactCache)
detector := ospkg.Detector{} detector := ospkg.Detector{}
driverFactory := library.DriverFactory{} localScanner := local.NewScanner(applierApplier, detector)
libraryDetector := library.NewDetector(driverFactory)
localScanner := local.NewScanner(applierApplier, detector, libraryDetector)
dockerOption, err := types.GetDockerOption(timeout) dockerOption, err := types.GetDockerOption(timeout)
if err != nil { if err != nil {
return scanner.Scanner{}, nil, err return scanner.Scanner{}, nil, err
@@ -49,9 +46,7 @@ func initializeDockerScanner(ctx context.Context, imageName string, artifactCach
func initializeArchiveScanner(ctx context.Context, filePath string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache, timeout time.Duration) (scanner.Scanner, error) { func initializeArchiveScanner(ctx context.Context, filePath string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache, timeout time.Duration) (scanner.Scanner, error) {
applierApplier := applier.NewApplier(localArtifactCache) applierApplier := applier.NewApplier(localArtifactCache)
detector := ospkg.Detector{} detector := ospkg.Detector{}
driverFactory := library.DriverFactory{} localScanner := local.NewScanner(applierApplier, detector)
libraryDetector := library.NewDetector(driverFactory)
localScanner := local.NewScanner(applierApplier, detector, libraryDetector)
imageImage, err := image.NewArchiveImage(filePath) imageImage, err := image.NewArchiveImage(filePath)
if err != nil { if err != nil {
return scanner.Scanner{}, err return scanner.Scanner{}, err
@@ -64,9 +59,7 @@ func initializeArchiveScanner(ctx context.Context, filePath string, artifactCach
func initializeFilesystemScanner(ctx context.Context, dir string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache) (scanner.Scanner, func(), error) { func initializeFilesystemScanner(ctx context.Context, dir string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache) (scanner.Scanner, func(), error) {
applierApplier := applier.NewApplier(localArtifactCache) applierApplier := applier.NewApplier(localArtifactCache)
detector := ospkg.Detector{} detector := ospkg.Detector{}
driverFactory := library.DriverFactory{} localScanner := local.NewScanner(applierApplier, detector)
libraryDetector := library.NewDetector(driverFactory)
localScanner := local.NewScanner(applierApplier, detector, libraryDetector)
artifact := local2.NewArtifact(dir, artifactCache) artifact := local2.NewArtifact(dir, artifactCache)
scannerScanner := scanner.NewScanner(localScanner, artifact) scannerScanner := scanner.NewScanner(localScanner, artifact)
return scannerScanner, func() { return scannerScanner, func() {
@@ -76,9 +69,7 @@ func initializeFilesystemScanner(ctx context.Context, dir string, artifactCache
func initializeRepositoryScanner(ctx context.Context, url string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache) (scanner.Scanner, func(), error) { func initializeRepositoryScanner(ctx context.Context, url string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache) (scanner.Scanner, func(), error) {
applierApplier := applier.NewApplier(localArtifactCache) applierApplier := applier.NewApplier(localArtifactCache)
detector := ospkg.Detector{} detector := ospkg.Detector{}
driverFactory := library.DriverFactory{} localScanner := local.NewScanner(applierApplier, detector)
libraryDetector := library.NewDetector(driverFactory)
localScanner := local.NewScanner(applierApplier, detector, libraryDetector)
artifact, cleanup, err := remote.NewArtifact(url, artifactCache) artifact, cleanup, err := remote.NewArtifact(url, artifactCache)
if err != nil { if err != nil {
return scanner.Scanner{}, nil, err return scanner.Scanner{}, nil, err

View File

@@ -8,6 +8,8 @@ import (
"testing" "testing"
"time" "time"
rpcScanner "github.com/aquasecurity/trivy/rpc/scanner"
google_protobuf "github.com/golang/protobuf/ptypes/empty" google_protobuf "github.com/golang/protobuf/ptypes/empty"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@@ -18,7 +20,6 @@ import (
"github.com/aquasecurity/fanal/types" "github.com/aquasecurity/fanal/types"
"github.com/aquasecurity/trivy/pkg/cache" "github.com/aquasecurity/trivy/pkg/cache"
rpcCache "github.com/aquasecurity/trivy/rpc/cache" rpcCache "github.com/aquasecurity/trivy/rpc/cache"
"github.com/aquasecurity/trivy/rpc/detector"
) )
type mockCacheServer struct { type mockCacheServer struct {
@@ -53,7 +54,7 @@ func (s *mockCacheServer) MissingBlobs(_ context.Context, in *rpcCache.MissingBl
func withToken(base http.Handler, token, tokenHeader string) http.Handler { func withToken(base http.Handler, token, tokenHeader string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if token != "" && token != r.Header.Get(tokenHeader) { if token != "" && token != r.Header.Get(tokenHeader) {
detector.WriteError(w, twirp.NewError(twirp.Unauthenticated, "invalid token")) rpcScanner.WriteError(w, twirp.NewError(twirp.Unauthenticated, "invalid token"))
return return
} }
base.ServeHTTP(w, r) base.ServeHTTP(w, r)

34
pkg/dbtest/db.go Normal file
View File

@@ -0,0 +1,34 @@
package dbtest
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
fixtures "github.com/aquasecurity/bolt-fixtures"
"github.com/aquasecurity/trivy-db/pkg/db"
)
// InitDB initializes testing database.
func InitDB(t *testing.T, fixtureFiles []string) string {
// Create a temp dir
dir := t.TempDir()
dbPath := db.Path(dir)
dbDir := filepath.Dir(dbPath)
err := os.MkdirAll(dbDir, 0700)
require.NoError(t, err)
// Load testdata into BoltDB
loader, err := fixtures.New(dbPath, fixtureFiles)
require.NoError(t, err)
require.NoError(t, loader.Load())
require.NoError(t, loader.Close())
// Initialize DB
require.NoError(t, db.Init(dir))
return dir
}

View File

@@ -1,7 +1,6 @@
package library_test package library_test
import ( import (
"os"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@@ -9,11 +8,11 @@ import (
"github.com/aquasecurity/trivy-db/pkg/db" "github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability" "github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
"github.com/aquasecurity/trivy/pkg/dbtest"
"github.com/aquasecurity/trivy/pkg/detector/library" "github.com/aquasecurity/trivy/pkg/detector/library"
"github.com/aquasecurity/trivy/pkg/detector/library/bundler" "github.com/aquasecurity/trivy/pkg/detector/library/bundler"
"github.com/aquasecurity/trivy/pkg/detector/library/comparer" "github.com/aquasecurity/trivy/pkg/detector/library/comparer"
"github.com/aquasecurity/trivy/pkg/types" "github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
) )
func TestAdvisory_DetectVulnerabilities(t *testing.T) { func TestAdvisory_DetectVulnerabilities(t *testing.T) {
@@ -98,8 +97,7 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
// Initialize DB // Initialize DB
dir := utils.InitTestDB(t, tt.fixtures) _ = dbtest.InitDB(t, tt.fixtures)
defer os.RemoveAll(dir)
defer db.Close() defer db.Close()
adv := library.NewAdvisory(tt.ecosystem, tt.comparer) adv := library.NewAdvisory(tt.ecosystem, tt.comparer)

View File

@@ -1,16 +1,16 @@
package bundler_test package bundler_test
import ( import (
"os"
"testing" "testing"
"github.com/aquasecurity/trivy/pkg/detector/library/bundler" "github.com/aquasecurity/trivy/pkg/detector/library/bundler"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy/pkg/dbtest"
"github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types" "github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
) )
func TestAdvisory_DetectVulnerabilities(t *testing.T) { func TestAdvisory_DetectVulnerabilities(t *testing.T) {
@@ -65,8 +65,8 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) {
log.InitLogger(false, true) log.InitLogger(false, true)
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
dir := utils.InitTestDB(t, tt.fixtures) _ = dbtest.InitDB(t, tt.fixtures)
defer os.RemoveAll(dir) defer db.Close()
a := bundler.NewAdvisory() a := bundler.NewAdvisory()
got, err := a.DetectVulnerabilities(tt.args.pkgName, tt.args.pkgVer) got, err := a.DetectVulnerabilities(tt.args.pkgName, tt.args.pkgVer)

View File

@@ -1,17 +1,16 @@
package cargo_test package cargo_test
import ( import (
"os"
"testing" "testing"
"github.com/aquasecurity/trivy/pkg/detector/library/cargo"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy/pkg/dbtest"
"github.com/aquasecurity/trivy/pkg/detector/library/cargo"
"github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types" "github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
) )
func TestAdvisory_DetectVulnerabilities(t *testing.T) { func TestAdvisory_DetectVulnerabilities(t *testing.T) {
@@ -81,8 +80,8 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) {
log.InitLogger(false, true) log.InitLogger(false, true)
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
dir := utils.InitTestDB(t, tt.fixtures) _ = dbtest.InitDB(t, tt.fixtures)
defer os.RemoveAll(dir) defer db.Close()
a := cargo.NewAdvisory() a := cargo.NewAdvisory()
got, err := a.DetectVulnerabilities(tt.args.pkgName, tt.args.pkgVer) got, err := a.DetectVulnerabilities(tt.args.pkgName, tt.args.pkgVer)

View File

@@ -1,17 +1,16 @@
package composer_test package composer_test
import ( import (
"os"
"testing" "testing"
"github.com/aquasecurity/trivy/pkg/detector/library/composer"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy/pkg/dbtest"
"github.com/aquasecurity/trivy/pkg/detector/library/composer"
"github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types" "github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
) )
func TestAdvisory_DetectVulnerabilities(t *testing.T) { func TestAdvisory_DetectVulnerabilities(t *testing.T) {
@@ -65,8 +64,8 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) {
log.InitLogger(false, true) log.InitLogger(false, true)
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
dir := utils.InitTestDB(t, tt.fixtures) _ = dbtest.InitDB(t, tt.fixtures)
defer os.RemoveAll(dir) defer db.Close()
a := composer.NewAdvisory() a := composer.NewAdvisory()
got, err := a.DetectVulnerabilities(tt.args.pkgName, tt.args.pkgVer) got, err := a.DetectVulnerabilities(tt.args.pkgName, tt.args.pkgVer)

View File

@@ -1,44 +1,15 @@
package library package library
import ( import (
"path/filepath"
"time"
"github.com/google/wire"
"golang.org/x/xerrors" "golang.org/x/xerrors"
ftypes "github.com/aquasecurity/fanal/types" ftypes "github.com/aquasecurity/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types" "github.com/aquasecurity/trivy/pkg/types"
) )
// SuperSet binds the dependencies for library scan
var SuperSet = wire.NewSet(
wire.Struct(new(DriverFactory)),
wire.Bind(new(Factory), new(DriverFactory)),
NewDetector,
wire.Bind(new(Operation), new(Detector)),
)
// Operation defines library scan operations
type Operation interface {
Detect(imageName string, filePath string, created time.Time, pkgs []ftypes.LibraryInfo) (vulns []types.DetectedVulnerability, err error)
}
// Detector implements driverFactory
type Detector struct {
driverFactory Factory
}
// NewDetector is the factory method for detector
func NewDetector(factory Factory) Detector {
return Detector{driverFactory: factory}
}
// Detect scans and returns vulnerabilities of library // Detect scans and returns vulnerabilities of library
func (d Detector) Detect(_, filePath string, _ time.Time, pkgs []ftypes.LibraryInfo) ([]types.DetectedVulnerability, error) { func Detect(libType string, pkgs []ftypes.LibraryInfo) ([]types.DetectedVulnerability, error) {
log.Logger.Debugf("Detecting library vulnerabilities, path: %s", filePath) driver, err := NewDriver(libType)
driver, err := d.driverFactory.NewDriver(filepath.Base(filePath))
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to new driver: %w", err) return nil, xerrors.Errorf("failed to new driver: %w", err)
} }
@@ -52,7 +23,6 @@ func (d Detector) Detect(_, filePath string, _ time.Time, pkgs []ftypes.LibraryI
} }
func detect(driver Driver, libs []ftypes.LibraryInfo) ([]types.DetectedVulnerability, error) { func detect(driver Driver, libs []ftypes.LibraryInfo) ([]types.DetectedVulnerability, error) {
log.Logger.Infof("Detecting %s vulnerabilities...", driver.Type())
var vulnerabilities []types.DetectedVulnerability var vulnerabilities []types.DetectedVulnerability
for _, lib := range libs { for _, lib := range libs {
vulns, err := driver.Detect(lib.Library.Name, lib.Library.Version) vulns, err := driver.Detect(lib.Library.Name, lib.Library.Version)

View File

@@ -1,10 +1,9 @@
package library package library
import ( import (
"fmt"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/aquasecurity/fanal/analyzer/library"
ecosystem "github.com/aquasecurity/trivy-db/pkg/vulnsrc/ghsa" ecosystem "github.com/aquasecurity/trivy-db/pkg/vulnsrc/ghsa"
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability" "github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
"github.com/aquasecurity/trivy/pkg/detector/library/bundler" "github.com/aquasecurity/trivy/pkg/detector/library/bundler"
@@ -12,41 +11,36 @@ import (
"github.com/aquasecurity/trivy/pkg/detector/library/comparer" "github.com/aquasecurity/trivy/pkg/detector/library/comparer"
"github.com/aquasecurity/trivy/pkg/detector/library/composer" "github.com/aquasecurity/trivy/pkg/detector/library/composer"
"github.com/aquasecurity/trivy/pkg/detector/library/ghsa" "github.com/aquasecurity/trivy/pkg/detector/library/ghsa"
"github.com/aquasecurity/trivy/pkg/detector/library/node" "github.com/aquasecurity/trivy/pkg/detector/library/maven"
"github.com/aquasecurity/trivy/pkg/detector/library/npm"
"github.com/aquasecurity/trivy/pkg/detector/library/python" "github.com/aquasecurity/trivy/pkg/detector/library/python"
"github.com/aquasecurity/trivy/pkg/types" "github.com/aquasecurity/trivy/pkg/types"
) )
// Factory defines library operations
type Factory interface {
NewDriver(filename string) (Driver, error)
}
type advisory interface { type advisory interface {
DetectVulnerabilities(string, string) ([]types.DetectedVulnerability, error) DetectVulnerabilities(string, string) ([]types.DetectedVulnerability, error)
} }
// DriverFactory implements Factory // NewDriver returns a driver according to the library type
type DriverFactory struct{} func NewDriver(libType string) (Driver, error) {
// NewDriver factory method for driver
func (d DriverFactory) NewDriver(filename string) (Driver, error) {
var driver Driver var driver Driver
switch filename { switch libType {
case "Gemfile.lock": case library.Bundler:
driver = newRubyGemsDriver() driver = newRubyGemsDriver()
case "Cargo.lock": case library.Cargo:
driver = newCargoDriver() driver = newCargoDriver()
case "composer.lock": case library.Composer:
driver = newComposerDriver() driver = newComposerDriver()
case "package-lock.json", "yarn.lock": case library.Npm, library.Yarn:
driver = newNpmDriver() driver = newNpmDriver()
case "Pipfile.lock", "poetry.lock": case library.Pipenv, library.Poetry:
driver = newPipDriver() driver = newPipDriver()
case "packages.lock.json": case library.NuGet:
driver = newNugetDriver() driver = newNugetDriver()
case library.Jar:
driver = newMavenDriver()
default: default:
return Driver{}, xerrors.New(fmt.Sprintf("unsupport filename %s", filename)) return Driver{}, xerrors.Errorf("unsupported type %s", libType)
} }
return driver, nil return driver, nil
} }
@@ -57,17 +51,17 @@ type Driver struct {
advisories []advisory advisories []advisory
} }
// NewDriver is the factory method from drier // Aggregate aggregates drivers
func NewDriver(advisories ...advisory) Driver { func Aggregate(ecosystem string, advisories ...advisory) Driver {
return Driver{advisories: advisories} return Driver{ecosystem: ecosystem, advisories: advisories}
} }
// Detect scans and returns vulnerabilities // Detect scans and returns vulnerabilities
func (d *Driver) Detect(pkgName string, pkgVer string) ([]types.DetectedVulnerability, error) { func (d *Driver) Detect(pkgName string, pkgVer string) ([]types.DetectedVulnerability, error) {
var detectedVulnerabilities []types.DetectedVulnerability var detectedVulnerabilities []types.DetectedVulnerability
uniqVulnIDMap := make(map[string]struct{}) uniqVulnIDMap := make(map[string]struct{})
for _, d := range d.advisories { for _, adv := range d.advisories {
vulns, err := d.DetectVulnerabilities(pkgName, pkgVer) vulns, err := adv.DetectVulnerabilities(pkgName, pkgVer)
if err != nil { if err != nil {
return nil, xerrors.Errorf("failed to detect vulnerabilities: %w", err) return nil, xerrors.Errorf("failed to detect vulnerabilities: %w", err)
} }
@@ -90,34 +84,41 @@ func (d *Driver) Type() string {
func newRubyGemsDriver() Driver { func newRubyGemsDriver() Driver {
c := bundler.RubyGemsComparer{} c := bundler.RubyGemsComparer{}
return NewDriver(ghsa.NewAdvisory(ecosystem.Rubygems, c), bundler.NewAdvisory(), return Aggregate(vulnerability.RubyGems, ghsa.NewAdvisory(ecosystem.Rubygems, c), bundler.NewAdvisory(),
NewAdvisory(vulnerability.RubyGems, c)) NewAdvisory(vulnerability.RubyGems, c))
} }
func newComposerDriver() Driver { func newComposerDriver() Driver {
c := comparer.GenericComparer{} c := comparer.GenericComparer{}
return NewDriver( return Aggregate(vulnerability.Composer, ghsa.NewAdvisory(ecosystem.Composer, c), composer.NewAdvisory(),
ghsa.NewAdvisory(ecosystem.Composer, c), composer.NewAdvisory(),
NewAdvisory(vulnerability.Composer, c)) NewAdvisory(vulnerability.Composer, c))
} }
func newCargoDriver() Driver { func newCargoDriver() Driver {
return NewDriver(cargo.NewAdvisory(), NewAdvisory(vulnerability.Cargo, comparer.GenericComparer{})) return Aggregate(vulnerability.Cargo, cargo.NewAdvisory(),
NewAdvisory(vulnerability.Cargo, comparer.GenericComparer{}))
} }
func newNpmDriver() Driver { func newNpmDriver() Driver {
c := node.NpmComparer{} c := npm.Comparer{}
return NewDriver(ghsa.NewAdvisory(ecosystem.Npm, c), node.NewAdvisory(), return Aggregate(vulnerability.Npm, ghsa.NewAdvisory(ecosystem.Npm, c),
NewAdvisory(vulnerability.Npm, c)) npm.NewAdvisory(), NewAdvisory(vulnerability.Npm, c))
} }
func newPipDriver() Driver { func newPipDriver() Driver {
c := comparer.GenericComparer{} c := comparer.GenericComparer{}
return NewDriver(ghsa.NewAdvisory(ecosystem.Pip, c), python.NewAdvisory(), return Aggregate(vulnerability.Pip, ghsa.NewAdvisory(ecosystem.Pip, c),
NewAdvisory(vulnerability.Pip, c)) python.NewAdvisory(), NewAdvisory(vulnerability.Pip, c))
} }
func newNugetDriver() Driver { func newNugetDriver() Driver {
c := comparer.GenericComparer{} c := comparer.GenericComparer{}
return NewDriver(ghsa.NewAdvisory(ecosystem.Nuget, c), NewAdvisory(vulnerability.NuGet, c)) return Aggregate(vulnerability.NuGet, ghsa.NewAdvisory(ecosystem.Nuget, c),
NewAdvisory(vulnerability.NuGet, c))
}
func newMavenDriver() Driver {
c := maven.Comparer{}
return Aggregate(vulnerability.Maven, ghsa.NewAdvisory(ecosystem.Maven, c),
NewAdvisory(vulnerability.Maven, c))
} }

View File

@@ -1,22 +1,19 @@
package library_test package library_test
import ( import (
"os"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
lib "github.com/aquasecurity/fanal/analyzer/library"
"github.com/aquasecurity/trivy-db/pkg/db" "github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy/pkg/dbtest"
"github.com/aquasecurity/trivy/pkg/detector/library" "github.com/aquasecurity/trivy/pkg/detector/library"
"github.com/aquasecurity/trivy/pkg/types" "github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
) )
func TestDriver_Detect(t *testing.T) { func TestDriver_Detect(t *testing.T) {
type fields struct {
fileName string
}
type args struct { type args struct {
pkgName string pkgName string
pkgVer string pkgVer string
@@ -24,7 +21,7 @@ func TestDriver_Detect(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
fixtures []string fixtures []string
fields fields libType string
args args args args
want []types.DetectedVulnerability want []types.DetectedVulnerability
wantErr string wantErr string
@@ -32,7 +29,7 @@ func TestDriver_Detect(t *testing.T) {
{ {
name: "happy path", name: "happy path",
fixtures: []string{"testdata/fixtures/php.yaml"}, fixtures: []string{"testdata/fixtures/php.yaml"},
fields: fields{fileName: "composer.lock"}, libType: lib.Composer,
args: args{ args: args{
pkgName: "symfony/symfony", pkgName: "symfony/symfony",
pkgVer: "4.2.6", pkgVer: "4.2.6",
@@ -49,7 +46,7 @@ func TestDriver_Detect(t *testing.T) {
{ {
name: "non-prefix buckets", name: "non-prefix buckets",
fixtures: []string{"testdata/fixtures/php-without-prefix.yaml"}, fixtures: []string{"testdata/fixtures/php-without-prefix.yaml"},
fields: fields{fileName: "composer.lock"}, libType: lib.Composer,
args: args{ args: args{
pkgName: "symfony/symfony", pkgName: "symfony/symfony",
pkgVer: "4.2.6", pkgVer: "4.2.6",
@@ -66,7 +63,7 @@ func TestDriver_Detect(t *testing.T) {
{ {
name: "no patched versions in the advisory", name: "no patched versions in the advisory",
fixtures: []string{"testdata/fixtures/php.yaml"}, fixtures: []string{"testdata/fixtures/php.yaml"},
fields: fields{fileName: "composer.lock"}, libType: lib.Composer,
args: args{ args: args{
pkgName: "symfony/symfony", pkgName: "symfony/symfony",
pkgVer: "4.4.6", pkgVer: "4.4.6",
@@ -83,7 +80,7 @@ func TestDriver_Detect(t *testing.T) {
{ {
name: "no vulnerable versions in the advisory", name: "no vulnerable versions in the advisory",
fixtures: []string{"testdata/fixtures/ruby.yaml"}, fixtures: []string{"testdata/fixtures/ruby.yaml"},
fields: fields{fileName: "Gemfile.lock"}, libType: lib.Bundler,
args: args{ args: args{
pkgName: "activesupport", pkgName: "activesupport",
pkgVer: "4.1.1", pkgVer: "4.1.1",
@@ -100,7 +97,7 @@ func TestDriver_Detect(t *testing.T) {
{ {
name: "no vulnerability", name: "no vulnerability",
fixtures: []string{"testdata/fixtures/php.yaml"}, fixtures: []string{"testdata/fixtures/php.yaml"},
fields: fields{fileName: "composer.lock"}, libType: lib.Composer,
args: args{ args: args{
pkgName: "symfony/symfony", pkgName: "symfony/symfony",
pkgVer: "4.4.7", pkgVer: "4.4.7",
@@ -110,12 +107,10 @@ func TestDriver_Detect(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
// Initialize DB // Initialize DB
dir := utils.InitTestDB(t, tt.fixtures) _ = dbtest.InitDB(t, tt.fixtures)
defer os.RemoveAll(dir)
defer db.Close() defer db.Close()
factory := library.DriverFactory{} driver, err := library.NewDriver(tt.libType)
driver, err := factory.NewDriver(tt.fields.fileName)
require.NoError(t, err) require.NoError(t, err)
got, err := driver.Detect(tt.args.pkgName, tt.args.pkgVer) got, err := driver.Detect(tt.args.pkgName, tt.args.pkgVer)

View File

@@ -1,18 +1,18 @@
package ghsa_test package ghsa_test
import ( import (
"os"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy-db/pkg/db"
ghsaSrc "github.com/aquasecurity/trivy-db/pkg/vulnsrc/ghsa" ghsaSrc "github.com/aquasecurity/trivy-db/pkg/vulnsrc/ghsa"
"github.com/aquasecurity/trivy/pkg/dbtest"
"github.com/aquasecurity/trivy/pkg/detector/library/comparer" "github.com/aquasecurity/trivy/pkg/detector/library/comparer"
"github.com/aquasecurity/trivy/pkg/detector/library/ghsa" "github.com/aquasecurity/trivy/pkg/detector/library/ghsa"
"github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types" "github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
) )
func TestAdvisory_DetectVulnerabilities(t *testing.T) { func TestAdvisory_DetectVulnerabilities(t *testing.T) {
@@ -103,8 +103,8 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) {
log.InitLogger(false, true) log.InitLogger(false, true)
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
dir := utils.InitTestDB(t, tt.fixtures) _ = dbtest.InitDB(t, tt.fixtures)
defer os.RemoveAll(dir) defer db.Close()
a := ghsa.NewAdvisory(tt.fields.ecosystem, tt.fields.comparer) a := ghsa.NewAdvisory(tt.fields.ecosystem, tt.fields.comparer)
got, err := a.DetectVulnerabilities(tt.args.pkgName, tt.args.pkgVer) got, err := a.DetectVulnerabilities(tt.args.pkgName, tt.args.pkgVer)

View File

@@ -0,0 +1,33 @@
package maven
import (
"golang.org/x/xerrors"
version "github.com/masahiro331/go-mvn-version"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy/pkg/detector/library/comparer"
)
// Comparer represents a comparer for maven
type Comparer struct{}
// IsVulnerable checks if the package version is vulnerable to the advisory.
func (n Comparer) IsVulnerable(ver string, advisory dbTypes.Advisory) bool {
return comparer.IsVulnerable(ver, advisory, n.matchVersion)
}
// matchVersion checks if the package version satisfies the given constraint.
func (n Comparer) matchVersion(currentVersion, constraint string) (bool, error) {
v, err := version.NewVersion(currentVersion)
if err != nil {
return false, xerrors.Errorf("maven version error (%s): %s", currentVersion, err)
}
c, err := version.NewConstraints(constraint)
if err != nil {
return false, xerrors.Errorf("maven constraint error (%s): %s", constraint, err)
}
return c.Check(v), nil
}

View File

@@ -0,0 +1,87 @@
package maven_test
import (
"testing"
"github.com/aquasecurity/trivy/pkg/detector/library/maven"
"github.com/stretchr/testify/assert"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy/pkg/log"
)
func TestComparer_IsVulnerable(t *testing.T) {
type args struct {
currentVersion string
advisory dbTypes.Advisory
}
tests := []struct {
name string
args args
want bool
}{
{
name: "happy path",
args: args{
currentVersion: "1.0.0",
advisory: dbTypes.Advisory{
VulnerableVersions: []string{"<=1.0"},
PatchedVersions: []string{">=1.1"},
},
},
want: true,
},
{
name: "final release",
args: args{
currentVersion: "1.2.3.final",
advisory: dbTypes.Advisory{
VulnerableVersions: []string{"<1.2.3"},
PatchedVersions: []string{"1.2.3"},
},
},
want: false,
},
{
name: "pre-release",
args: args{
currentVersion: "1.2.3-a1",
advisory: dbTypes.Advisory{
VulnerableVersions: []string{"<1.2.3"},
PatchedVersions: []string{">=1.2.3"},
},
},
want: true,
},
{
name: "multiple constraints",
args: args{
currentVersion: "2.0.0",
advisory: dbTypes.Advisory{
VulnerableVersions: []string{">=1.7.0 <1.7.16", ">=1.8.0 <1.8.8", ">=2.0.0 <2.0.8", ">=3.0.0-beta.1 <3.0.0-beta.7"},
PatchedVersions: []string{">=3.0.0-beta.7", ">=2.0.8 <3.0.0-beta.1", ">=1.8.8 <2.0.0", ">=1.7.16 <1.8.0"},
},
},
want: true,
},
{
name: "invalid constraint",
args: args{
currentVersion: "1.2.3",
advisory: dbTypes.Advisory{
VulnerableVersions: []string{`<1.0\.0`},
},
},
want: false,
},
}
log.InitLogger(false, false)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := maven.Comparer{}
got := c.IsVulnerable(tt.args.currentVersion, tt.args.advisory)
assert.Equal(t, tt.want, got)
})
}
}

View File

@@ -1,4 +1,4 @@
package node package npm
import ( import (
"strings" "strings"
@@ -12,7 +12,7 @@ import (
// Advisory encapsulate Node vulnerability source // Advisory encapsulate Node vulnerability source
type Advisory struct { type Advisory struct {
comparer NpmComparer comparer Comparer
vs node.VulnSrc vs node.VulnSrc
} }
@@ -20,7 +20,7 @@ type Advisory struct {
func NewAdvisory() *Advisory { func NewAdvisory() *Advisory {
return &Advisory{ return &Advisory{
vs: node.NewVulnSrc(), vs: node.NewVulnSrc(),
comparer: NpmComparer{}, comparer: Comparer{},
} }
} }

View File

@@ -1,16 +1,16 @@
package node_test package npm_test
import ( import (
"os"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy/pkg/detector/library/node" "github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy/pkg/dbtest"
"github.com/aquasecurity/trivy/pkg/detector/library/npm"
"github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types" "github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
) )
func TestAdvisory_DetectVulnerabilities(t *testing.T) { func TestAdvisory_DetectVulnerabilities(t *testing.T) {
@@ -72,10 +72,10 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) {
log.InitLogger(false, true) log.InitLogger(false, true)
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
dir := utils.InitTestDB(t, tt.fixtures) _ = dbtest.InitDB(t, tt.fixtures)
defer os.RemoveAll(dir) defer db.Close()
a := node.NewAdvisory() a := npm.NewAdvisory()
got, err := a.DetectVulnerabilities(tt.args.pkgName, tt.args.pkgVer) got, err := a.DetectVulnerabilities(tt.args.pkgName, tt.args.pkgVer)
if tt.wantErr != "" { if tt.wantErr != "" {
require.NotNil(t, err) require.NotNil(t, err)

View File

@@ -1,4 +1,4 @@
package node package npm
import ( import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
@@ -8,16 +8,16 @@ import (
"github.com/aquasecurity/trivy/pkg/detector/library/comparer" "github.com/aquasecurity/trivy/pkg/detector/library/comparer"
) )
// NpmComparer represents a comparer for npm // Comparer represents a comparer for npm
type NpmComparer struct{} type Comparer struct{}
// IsVulnerable checks if the package version is vulnerable to the advisory. // IsVulnerable checks if the package version is vulnerable to the advisory.
func (n NpmComparer) IsVulnerable(ver string, advisory dbTypes.Advisory) bool { func (n Comparer) IsVulnerable(ver string, advisory dbTypes.Advisory) bool {
return comparer.IsVulnerable(ver, advisory, n.matchVersion) return comparer.IsVulnerable(ver, advisory, n.matchVersion)
} }
// matchVersion checks if the package version satisfies the given constraint. // matchVersion checks if the package version satisfies the given constraint.
func (n NpmComparer) matchVersion(currentVersion, constraint string) (bool, error) { func (n Comparer) matchVersion(currentVersion, constraint string) (bool, error) {
v, err := npm.NewVersion(currentVersion) v, err := npm.NewVersion(currentVersion)
if err != nil { if err != nil {
return false, xerrors.Errorf("npm version error (%s): %s", currentVersion, err) return false, xerrors.Errorf("npm version error (%s): %s", currentVersion, err)

View File

@@ -1,4 +1,4 @@
package node_test package npm_test
import ( import (
"testing" "testing"
@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types" dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy/pkg/detector/library/node" "github.com/aquasecurity/trivy/pkg/detector/library/npm"
"github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/log"
) )
@@ -132,7 +132,7 @@ func TestNpmComparer_IsVulnerable(t *testing.T) {
log.InitLogger(false, false) log.InitLogger(false, false)
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
c := node.NpmComparer{} c := npm.Comparer{}
got := c.IsVulnerable(tt.args.currentVersion, tt.args.advisory) got := c.IsVulnerable(tt.args.currentVersion, tt.args.advisory)
assert.Equal(t, tt.want, got) assert.Equal(t, tt.want, got)
}) })

View File

@@ -1,16 +1,16 @@
package python_test package python_test
import ( import (
"os"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy/pkg/dbtest"
"github.com/aquasecurity/trivy/pkg/detector/library/python" "github.com/aquasecurity/trivy/pkg/detector/library/python"
"github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types" "github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
) )
func TestAdvisory_DetectVulnerabilities(t *testing.T) { func TestAdvisory_DetectVulnerabilities(t *testing.T) {
@@ -65,8 +65,8 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) {
log.InitLogger(false, true) log.InitLogger(false, true)
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
dir := utils.InitTestDB(t, tt.fixtures) _ = dbtest.InitDB(t, tt.fixtures)
defer os.RemoveAll(dir) defer db.Close()
a := python.NewAdvisory() a := python.NewAdvisory()
got, err := a.DetectVulnerabilities(tt.args.pkgName, tt.args.pkgVer) got, err := a.DetectVulnerabilities(tt.args.pkgName, tt.args.pkgVer)

View File

@@ -5,17 +5,17 @@ import (
"testing" "testing"
"time" "time"
ftypes "github.com/aquasecurity/fanal/types"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
oracleoval "github.com/aquasecurity/trivy-db/pkg/vulnsrc/oracle-oval"
"github.com/aquasecurity/trivy/pkg/log"
"k8s.io/utils/clock" "k8s.io/utils/clock"
clocktesting "k8s.io/utils/clock/testing" clocktesting "k8s.io/utils/clock/testing"
ftypes "github.com/aquasecurity/fanal/types"
"github.com/aquasecurity/trivy-db/pkg/db"
oracleoval "github.com/aquasecurity/trivy-db/pkg/vulnsrc/oracle-oval"
"github.com/aquasecurity/trivy/pkg/dbtest"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types"
) )
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
@@ -209,8 +209,8 @@ func TestScanner_Detect(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
dir := utils.InitTestDB(t, tt.fixtures) _ = dbtest.InitDB(t, tt.fixtures)
defer os.RemoveAll(dir) defer db.Close()
s := NewScanner() s := NewScanner()
got, err := s.Detect(tt.args.osVer, tt.args.pkgs) got, err := s.Detect(tt.args.osVer, tt.args.pkgs)

View File

@@ -6,6 +6,8 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"github.com/aquasecurity/go-dep-parser/pkg/log"
) )
var ( var (
@@ -19,8 +21,12 @@ func InitLogger(debug, disable bool) (err error) {
debugOption = debug debugOption = debug
Logger, err = NewLogger(debug, disable) Logger, err = NewLogger(debug, disable)
if err != nil { if err != nil {
return xerrors.Errorf("error in new logger: %w", err) return xerrors.Errorf("failed to initialize a logger: %w", err)
} }
// Set logger for go-dep-parser
log.SetLogger(Logger)
return nil return nil
} }

View File

@@ -74,13 +74,14 @@ type TableWriter struct {
// Write writes the result on standard output // Write writes the result on standard output
func (tw TableWriter) Write(results Results) error { func (tw TableWriter) Write(results Results) error {
for _, result := range results { for _, result := range results {
if len(result.Vulnerabilities) == 0 {
continue
}
tw.write(result) tw.write(result)
} }
return nil return nil
} }
// nolint: gocyclo
// TODO: refactror and fix cyclometic complexity
func (tw TableWriter) write(result Result) { func (tw TableWriter) write(result Result) {
table := tablewriter.NewWriter(tw.Output) table := tablewriter.NewWriter(tw.Output)
header := []string{"Library", "Vulnerability ID", "Severity", "Installed Version", "Fixed Version"} header := []string{"Library", "Vulnerability ID", "Severity", "Installed Version", "Fixed Version"}
@@ -88,38 +89,7 @@ func (tw TableWriter) write(result Result) {
header = append(header, "Title") header = append(header, "Title")
} }
table.SetHeader(header) table.SetHeader(header)
severityCount := tw.setRows(table, result.Vulnerabilities)
severityCount := map[string]int{}
for _, v := range result.Vulnerabilities {
severityCount[v.Severity]++
title := v.Title
if title == "" {
title = v.Description
}
splittedTitle := strings.Split(title, " ")
if len(splittedTitle) >= 12 {
title = strings.Join(splittedTitle[:12], " ") + "..."
}
if len(v.PrimaryURL) > 0 {
r := strings.NewReplacer("https://", "", "http://", "")
title = fmt.Sprintf("%s -->%s", title, r.Replace(v.PrimaryURL))
}
var row []string
if tw.Output == os.Stdout {
row = []string{v.PkgName, v.VulnerabilityID, dbTypes.ColorizeSeverity(v.Severity),
v.InstalledVersion, v.FixedVersion}
} else {
row = []string{v.PkgName, v.VulnerabilityID, v.Severity, v.InstalledVersion, v.FixedVersion}
}
if !tw.Light {
row = append(row, strings.TrimSpace(title))
}
table.Append(row)
}
var results []string var results []string
@@ -150,6 +120,41 @@ func (tw TableWriter) write(result Result) {
return return
} }
func (tw TableWriter) setRows(table *tablewriter.Table, vulns []types.DetectedVulnerability) map[string]int {
severityCount := map[string]int{}
for _, v := range vulns {
severityCount[v.Severity]++
title := v.Title
if title == "" {
title = v.Description
}
splitTitle := strings.Split(title, " ")
if len(splitTitle) >= 12 {
title = strings.Join(splitTitle[:12], " ") + "..."
}
if len(v.PrimaryURL) > 0 {
r := strings.NewReplacer("https://", "", "http://", "")
title = fmt.Sprintf("%s -->%s", title, r.Replace(v.PrimaryURL))
}
var row []string
if tw.Output == os.Stdout {
row = []string{v.PkgName, v.VulnerabilityID, dbTypes.ColorizeSeverity(v.Severity),
v.InstalledVersion, v.FixedVersion}
} else {
row = []string{v.PkgName, v.VulnerabilityID, v.Severity, v.InstalledVersion, v.FixedVersion}
}
if !tw.Light {
row = append(row, strings.TrimSpace(title))
}
table.Append(row)
}
return severityCount
}
// JSONWriter implements result Writer // JSONWriter implements result Writer
type JSONWriter struct { type JSONWriter struct {
Output io.Writer Output io.Writer

View File

@@ -4,8 +4,6 @@ package server
import ( import (
"github.com/aquasecurity/fanal/cache" "github.com/aquasecurity/fanal/cache"
"github.com/aquasecurity/trivy/pkg/rpc/server/library"
"github.com/aquasecurity/trivy/pkg/rpc/server/ospkg"
"github.com/google/wire" "github.com/google/wire"
) )
@@ -14,16 +12,6 @@ func initializeScanServer(localArtifactCache cache.LocalArtifactCache) *ScanServ
return &ScanServer{} return &ScanServer{}
} }
func initializeOspkgServer() *ospkg.Server {
wire.Build(ospkg.SuperSet)
return &ospkg.Server{}
}
func initializeLibServer() *library.Server {
wire.Build(library.SuperSet)
return &library.Server{}
}
func initializeDBWorker(cacheDir string, quiet bool) dbWorker { func initializeDBWorker(cacheDir string, quiet bool) dbWorker {
wire.Build(DBWorkerSuperSet) wire.Build(DBWorkerSuperSet)
return dbWorker{} return dbWorker{}

View File

@@ -1,47 +0,0 @@
package library
import (
"context"
"time"
"github.com/google/wire"
"golang.org/x/xerrors"
detector "github.com/aquasecurity/trivy/pkg/detector/library"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/rpc"
"github.com/aquasecurity/trivy/pkg/vulnerability"
proto "github.com/aquasecurity/trivy/rpc/detector"
)
// SuperSet binds the dependencies for library RPC server
var SuperSet = wire.NewSet(
detector.SuperSet,
vulnerability.SuperSet,
NewServer,
)
// Server is for backward compatibility
type Server struct {
detector detector.Operation
vulnClient vulnerability.Operation
}
// NewServer is the facotry method for Server
func NewServer(detector detector.Operation, vulnClient vulnerability.Operation) *Server {
return &Server{detector: detector, vulnClient: vulnClient}
}
// Detect is for backward compatibility
func (s *Server) Detect(_ context.Context, req *proto.LibDetectRequest) (res *proto.DetectResponse, err error) {
vulns, err := s.detector.Detect("", req.FilePath, time.Time{}, rpc.ConvertFromRPCLibraries(req.Libraries))
if err != nil {
err = xerrors.Errorf("failed to detect library vulnerabilities: %w", err)
log.Logger.Error(err)
return nil, err
}
s.vulnClient.FillInfo(vulns, "")
return &proto.DetectResponse{Vulnerabilities: rpc.ConvertToRPCVulns(vulns)}, nil
}

View File

@@ -1,187 +0,0 @@
package library
import (
"context"
"os"
"testing"
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
ftypes "github.com/aquasecurity/fanal/types"
ptypes "github.com/aquasecurity/go-dep-parser/pkg/types"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy-db/pkg/utils"
"github.com/aquasecurity/trivy/pkg/detector/library"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/vulnerability"
"github.com/aquasecurity/trivy/rpc/common"
proto "github.com/aquasecurity/trivy/rpc/detector"
)
func TestMain(m *testing.M) {
log.InitLogger(false, false)
code := m.Run()
os.Exit(code)
}
func TestServer_Detect(t *testing.T) {
type args struct {
req *proto.LibDetectRequest
}
tests := []struct {
name string
args args
detectExpectation library.OperationDetectExpectation
fillInfoExpectation vulnerability.OperationFillInfoExpectation
wantRes *proto.DetectResponse
wantErr string
}{
{
name: "happy path",
args: args{
req: &proto.LibDetectRequest{
ImageName: "alpine:3.10",
FilePath: "app/Pipfile.lock",
Libraries: []*common.Library{
{Name: "django", Version: "3.0.0"},
},
},
},
detectExpectation: library.OperationDetectExpectation{
Args: library.OperationDetectArgs{
FilePath: "app/Pipfile.lock",
Pkgs: []ftypes.LibraryInfo{
{
Library: ptypes.Library{Name: "django", Version: "3.0.0"},
},
},
},
Returns: library.OperationDetectReturns{
Vulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2019-0001",
PkgName: "test",
InstalledVersion: "1",
FixedVersion: "2",
Vulnerability: dbTypes.Vulnerability{
Title: "title",
Description: "description",
Severity: "MEDIUM",
References: []string{"http://example.com"},
LastModifiedDate: utils.MustTimeParse("2020-01-01T01:01:00Z"),
PublishedDate: utils.MustTimeParse("2001-01-01T01:01:00Z"),
CweIDs: []string{"CWE-78"},
},
Layer: ftypes.Layer{
Digest: "sha256:154ad0735c360b212b167f424d33a62305770a1fcfb6363882f5c436cfbd9812",
DiffID: "sha256:b2a1a2d80bf0c747a4f6b0ca6af5eef23f043fcdb1ed4f3a3e750aef2dc68079",
},
},
},
},
},
fillInfoExpectation: vulnerability.OperationFillInfoExpectation{
Args: vulnerability.OperationFillInfoArgs{
Vulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2019-0001",
PkgName: "test",
InstalledVersion: "1",
FixedVersion: "2",
Vulnerability: dbTypes.Vulnerability{
Title: "title",
Description: "description",
Severity: "MEDIUM",
References: []string{"http://example.com"},
LastModifiedDate: utils.MustTimeParse("2020-01-01T01:01:00Z"),
PublishedDate: utils.MustTimeParse("2001-01-01T01:01:00Z"),
CweIDs: []string{"CWE-78"},
},
Layer: ftypes.Layer{
Digest: "sha256:154ad0735c360b212b167f424d33a62305770a1fcfb6363882f5c436cfbd9812",
DiffID: "sha256:b2a1a2d80bf0c747a4f6b0ca6af5eef23f043fcdb1ed4f3a3e750aef2dc68079",
},
},
},
},
},
wantRes: &proto.DetectResponse{
Vulnerabilities: []*common.Vulnerability{
{
VulnerabilityId: "CVE-2019-0001",
PkgName: "test",
InstalledVersion: "1",
FixedVersion: "2",
Title: "title",
Description: "description",
Severity: common.Severity_MEDIUM,
Cvss: make(map[string]*common.CVSS),
References: []string{"http://example.com"},
LastModifiedDate: &timestamp.Timestamp{
Seconds: 1577840460,
},
PublishedDate: &timestamp.Timestamp{
Seconds: 978310860,
},
CweIds: []string{"CWE-78"},
Layer: &common.Layer{
Digest: "sha256:154ad0735c360b212b167f424d33a62305770a1fcfb6363882f5c436cfbd9812",
DiffId: "sha256:b2a1a2d80bf0c747a4f6b0ca6af5eef23f043fcdb1ed4f3a3e750aef2dc68079",
},
},
},
},
},
{
name: "Detect returns an error",
args: args{
req: &proto.LibDetectRequest{
ImageName: "alpine:3.10",
FilePath: "app/Pipfile.lock",
Libraries: []*common.Library{
{Name: "django", Version: "3.0.0"},
},
},
},
detectExpectation: library.OperationDetectExpectation{
Args: library.OperationDetectArgs{
FilePath: "app/Pipfile.lock",
Pkgs: []ftypes.LibraryInfo{
{Library: ptypes.Library{Name: "django", Version: "3.0.0"}},
},
},
Returns: library.OperationDetectReturns{
Err: xerrors.New("error"),
},
},
wantErr: "failed to detect library vulnerabilities",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockDetector := new(library.MockOperation)
mockDetector.ApplyDetectExpectation(tt.detectExpectation)
mockVulnClient := new(vulnerability.MockOperation)
mockVulnClient.ApplyFillInfoExpectation(tt.fillInfoExpectation)
s := NewServer(mockDetector, mockVulnClient)
ctx := context.TODO()
gotRes, err := s.Detect(ctx, tt.args.req)
if tt.wantErr != "" {
require.NotNil(t, err, tt.name)
assert.Contains(t, err.Error(), tt.wantErr, tt.name)
return
} else {
assert.NoError(t, err, tt.name)
}
assert.Equal(t, tt.wantRes, gotRes, tt.name)
mockDetector.AssertExpectations(t)
mockVulnClient.AssertExpectations(t)
})
}
}

View File

@@ -19,8 +19,6 @@ import (
"github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/utils" "github.com/aquasecurity/trivy/pkg/utils"
rpcCache "github.com/aquasecurity/trivy/rpc/cache" rpcCache "github.com/aquasecurity/trivy/rpc/cache"
"github.com/aquasecurity/trivy/rpc/detector"
rpcDetector "github.com/aquasecurity/trivy/rpc/detector"
rpcScanner "github.com/aquasecurity/trivy/rpc/scanner" rpcScanner "github.com/aquasecurity/trivy/rpc/scanner"
) )
@@ -75,14 +73,6 @@ func newServeMux(serverCache cache.Cache, dbUpdateWg, requestWg *sync.WaitGroup,
layerHandler := rpcCache.NewCacheServer(NewCacheServer(serverCache), nil) layerHandler := rpcCache.NewCacheServer(NewCacheServer(serverCache), nil)
mux.Handle(rpcCache.CachePathPrefix, withToken(withWaitGroup(layerHandler), token, tokenHeader)) mux.Handle(rpcCache.CachePathPrefix, withToken(withWaitGroup(layerHandler), token, tokenHeader))
// osHandler is for backward compatibility
osHandler := rpcDetector.NewOSDetectorServer(initializeOspkgServer(), nil)
mux.Handle(rpcDetector.OSDetectorPathPrefix, withToken(withWaitGroup(osHandler), token, tokenHeader))
// libHandler is for backward compatibility
libHandler := rpcDetector.NewLibDetectorServer(initializeLibServer(), nil)
mux.Handle(rpcDetector.LibDetectorPathPrefix, withToken(withWaitGroup(libHandler), token, tokenHeader))
mux.HandleFunc("/healthz", func(rw http.ResponseWriter, r *http.Request) { mux.HandleFunc("/healthz", func(rw http.ResponseWriter, r *http.Request) {
if _, err := rw.Write([]byte("ok")); err != nil { if _, err := rw.Write([]byte("ok")); err != nil {
log.Logger.Errorf("health check error: %s", err) log.Logger.Errorf("health check error: %s", err)
@@ -95,7 +85,7 @@ func newServeMux(serverCache cache.Cache, dbUpdateWg, requestWg *sync.WaitGroup,
func withToken(base http.Handler, token, tokenHeader string) http.Handler { func withToken(base http.Handler, token, tokenHeader string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if token != "" && token != r.Header.Get(tokenHeader) { if token != "" && token != r.Header.Get(tokenHeader) {
detector.WriteError(w, twirp.NewError(twirp.Unauthenticated, "invalid token")) rpcScanner.WriteError(w, twirp.NewError(twirp.Unauthenticated, "invalid token"))
return return
} }
base.ServeHTTP(w, r) base.ServeHTTP(w, r)

View File

@@ -1,47 +0,0 @@
package ospkg
import (
"context"
"time"
"github.com/google/wire"
"golang.org/x/xerrors"
detector "github.com/aquasecurity/trivy/pkg/detector/ospkg"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/rpc"
"github.com/aquasecurity/trivy/pkg/vulnerability"
proto "github.com/aquasecurity/trivy/rpc/detector"
)
// SuperSet binds dependencies for RPC server
var SuperSet = wire.NewSet(
detector.SuperSet,
vulnerability.SuperSet,
NewServer,
)
// Server is for backward compatibility
type Server struct {
detector detector.Operation
vulnClient vulnerability.Operation
}
// NewServer is the factory method to return Server
func NewServer(detector detector.Operation, vulnClient vulnerability.Operation) *Server {
return &Server{detector: detector, vulnClient: vulnClient}
}
// Detect is for backward compatibility
func (s *Server) Detect(_ context.Context, req *proto.OSDetectRequest) (res *proto.DetectResponse, err error) {
vulns, eosl, err := s.detector.Detect("", req.OsFamily, req.OsName, time.Time{}, rpc.ConvertFromRPCPkgs(req.Packages))
if err != nil {
err = xerrors.Errorf("failed to detect vulnerabilities of OS packages: %w", err)
log.Logger.Error(err)
return nil, err
}
s.vulnClient.FillInfo(vulns, "")
return &proto.DetectResponse{Vulnerabilities: rpc.ConvertToRPCVulns(vulns), Eosl: eosl}, nil
}

View File

@@ -1,167 +0,0 @@
package ospkg
import (
"context"
"os"
"testing"
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
ftypes "github.com/aquasecurity/fanal/types"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy-db/pkg/utils"
"github.com/aquasecurity/trivy/pkg/detector/ospkg"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/vulnerability"
"github.com/aquasecurity/trivy/rpc/common"
proto "github.com/aquasecurity/trivy/rpc/detector"
)
func TestMain(m *testing.M) {
_ = log.InitLogger(false, false)
code := m.Run()
os.Exit(code)
}
func TestServer_Detect(t *testing.T) {
type args struct {
req *proto.OSDetectRequest
}
tests := []struct {
name string
args args
detectExpectation ospkg.DetectExpectation
fillInfoExpectation vulnerability.OperationFillInfoExpectation
wantRes *proto.DetectResponse
wantErr string
}{
{
name: "happy path",
args: args{
req: &proto.OSDetectRequest{
OsFamily: "alpine",
OsName: "3.10.2",
Packages: []*common.Package{
{Name: "musl", Version: "1.1.22-r3"},
},
},
},
detectExpectation: ospkg.DetectExpectation{
Args: ospkg.DetectInput{
OSFamily: "alpine",
OSName: "3.10.2",
Pkgs: []ftypes.Package{
{Name: "musl", Version: "1.1.22-r3"},
},
},
ReturnArgs: ospkg.DetectOutput{
Eosl: false,
Vulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2019-0001",
PkgName: "musl",
Vulnerability: dbTypes.Vulnerability{
Severity: "HIGH",
LastModifiedDate: utils.MustTimeParse("2020-01-01T01:01:00Z"),
PublishedDate: utils.MustTimeParse("2001-01-01T01:01:00Z"),
},
Layer: ftypes.Layer{
Digest: "sha256:154ad0735c360b212b167f424d33a62305770a1fcfb6363882f5c436cfbd9812",
DiffID: "sha256:b2a1a2d80bf0c747a4f6b0ca6af5eef23f043fcdb1ed4f3a3e750aef2dc68079",
},
},
},
},
},
fillInfoExpectation: vulnerability.OperationFillInfoExpectation{
Args: vulnerability.OperationFillInfoArgs{
Vulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2019-0001",
PkgName: "musl",
Vulnerability: dbTypes.Vulnerability{
Severity: "HIGH",
LastModifiedDate: utils.MustTimeParse("2020-01-01T01:01:00Z"),
PublishedDate: utils.MustTimeParse("2001-01-01T01:01:00Z"),
},
Layer: ftypes.Layer{
Digest: "sha256:154ad0735c360b212b167f424d33a62305770a1fcfb6363882f5c436cfbd9812",
DiffID: "sha256:b2a1a2d80bf0c747a4f6b0ca6af5eef23f043fcdb1ed4f3a3e750aef2dc68079",
},
},
},
},
},
wantRes: &proto.DetectResponse{
Vulnerabilities: []*common.Vulnerability{
{
VulnerabilityId: "CVE-2019-0001",
PkgName: "musl",
Severity: common.Severity_HIGH,
Cvss: make(map[string]*common.CVSS),
Layer: &common.Layer{
Digest: "sha256:154ad0735c360b212b167f424d33a62305770a1fcfb6363882f5c436cfbd9812",
DiffId: "sha256:b2a1a2d80bf0c747a4f6b0ca6af5eef23f043fcdb1ed4f3a3e750aef2dc68079",
},
LastModifiedDate: &timestamp.Timestamp{
Seconds: 1577840460,
},
PublishedDate: &timestamp.Timestamp{
Seconds: 978310860,
},
},
},
},
},
{
name: "Detect returns an error",
args: args{
req: &proto.OSDetectRequest{
OsFamily: "alpine",
OsName: "3.10.2",
Packages: []*common.Package{
{Name: "musl", Version: "1.1.22-r3"},
},
},
},
detectExpectation: ospkg.DetectExpectation{
Args: ospkg.DetectInput{
OSFamily: "alpine",
OSName: "3.10.2",
Pkgs: []ftypes.Package{
{Name: "musl", Version: "1.1.22-r3"},
},
},
ReturnArgs: ospkg.DetectOutput{
Err: xerrors.New("error"),
},
},
wantErr: "failed to detect vulnerabilities of OS packages: error",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockDetector := ospkg.NewMockDetector([]ospkg.DetectExpectation{tt.detectExpectation})
mockVulnClient := new(vulnerability.MockOperation)
mockVulnClient.ApplyFillInfoExpectation(tt.fillInfoExpectation)
s := NewServer(mockDetector, mockVulnClient)
gotRes, err := s.Detect(context.TODO(), tt.args.req)
if tt.wantErr != "" {
require.NotNil(t, err, tt.name)
assert.Contains(t, err.Error(), tt.wantErr, tt.name)
return
} else {
assert.NoError(t, err, tt.name)
}
assert.Equal(t, tt.wantRes, gotRes, tt.name)
mockDetector.AssertExpectations(t)
mockVulnClient.AssertExpectations(t)
})
}
}

View File

@@ -10,12 +10,9 @@ import (
"github.com/aquasecurity/fanal/cache" "github.com/aquasecurity/fanal/cache"
"github.com/aquasecurity/trivy-db/pkg/db" "github.com/aquasecurity/trivy-db/pkg/db"
db2 "github.com/aquasecurity/trivy/pkg/db" db2 "github.com/aquasecurity/trivy/pkg/db"
"github.com/aquasecurity/trivy/pkg/detector/library"
"github.com/aquasecurity/trivy/pkg/detector/ospkg" "github.com/aquasecurity/trivy/pkg/detector/ospkg"
"github.com/aquasecurity/trivy/pkg/github" "github.com/aquasecurity/trivy/pkg/github"
"github.com/aquasecurity/trivy/pkg/indicator" "github.com/aquasecurity/trivy/pkg/indicator"
library2 "github.com/aquasecurity/trivy/pkg/rpc/server/library"
ospkg2 "github.com/aquasecurity/trivy/pkg/rpc/server/ospkg"
"github.com/aquasecurity/trivy/pkg/scanner/local" "github.com/aquasecurity/trivy/pkg/scanner/local"
"github.com/aquasecurity/trivy/pkg/vulnerability" "github.com/aquasecurity/trivy/pkg/vulnerability"
"github.com/spf13/afero" "github.com/spf13/afero"
@@ -27,32 +24,13 @@ import (
func initializeScanServer(localArtifactCache cache.LocalArtifactCache) *ScanServer { func initializeScanServer(localArtifactCache cache.LocalArtifactCache) *ScanServer {
applierApplier := applier.NewApplier(localArtifactCache) applierApplier := applier.NewApplier(localArtifactCache)
detector := ospkg.Detector{} detector := ospkg.Detector{}
driverFactory := library.DriverFactory{} scanner := local.NewScanner(applierApplier, detector)
libraryDetector := library.NewDetector(driverFactory)
scanner := local.NewScanner(applierApplier, detector, libraryDetector)
config := db.Config{} config := db.Config{}
client := vulnerability.NewClient(config) client := vulnerability.NewClient(config)
scanServer := NewScanServer(scanner, client) scanServer := NewScanServer(scanner, client)
return scanServer return scanServer
} }
func initializeOspkgServer() *ospkg2.Server {
detector := ospkg.Detector{}
config := db.Config{}
client := vulnerability.NewClient(config)
server := ospkg2.NewServer(detector, client)
return server
}
func initializeLibServer() *library2.Server {
driverFactory := library.DriverFactory{}
detector := library.NewDetector(driverFactory)
config := db.Config{}
client := vulnerability.NewClient(config)
server := library2.NewServer(detector, client)
return server
}
func initializeDBWorker(cacheDir string, quiet bool) dbWorker { func initializeDBWorker(cacheDir string, quiet bool) dbWorker {
config := db.Config{} config := db.Config{}
client := github.NewClient() client := github.NewClient()

View File

@@ -1,88 +0,0 @@
// Code generated by mockery v1.0.0. DO NOT EDIT.
package local
import mock "github.com/stretchr/testify/mock"
import pkgtypes "github.com/aquasecurity/trivy/pkg/types"
import time "time"
import types "github.com/aquasecurity/fanal/types"
// MockLibraryDetector is an autogenerated mock type for the LibraryDetector type
type MockLibraryDetector struct {
mock.Mock
}
type LibraryDetectorDetectArgs struct {
ImageName string
ImageNameAnything bool
FilePath string
FilePathAnything bool
Created time.Time
CreatedAnything bool
Pkgs []types.LibraryInfo
PkgsAnything bool
}
type LibraryDetectorDetectReturns struct {
DetectedVulns []pkgtypes.DetectedVulnerability
Err error
}
type LibraryDetectorDetectExpectation struct {
Args LibraryDetectorDetectArgs
Returns LibraryDetectorDetectReturns
}
func (_m *MockLibraryDetector) ApplyDetectExpectation(e LibraryDetectorDetectExpectation) {
var args []interface{}
if e.Args.ImageNameAnything {
args = append(args, mock.Anything)
} else {
args = append(args, e.Args.ImageName)
}
if e.Args.FilePathAnything {
args = append(args, mock.Anything)
} else {
args = append(args, e.Args.FilePath)
}
if e.Args.CreatedAnything {
args = append(args, mock.Anything)
} else {
args = append(args, e.Args.Created)
}
if e.Args.PkgsAnything {
args = append(args, mock.Anything)
} else {
args = append(args, e.Args.Pkgs)
}
_m.On("Detect", args...).Return(e.Returns.DetectedVulns, e.Returns.Err)
}
func (_m *MockLibraryDetector) ApplyDetectExpectations(expectations []LibraryDetectorDetectExpectation) {
for _, e := range expectations {
_m.ApplyDetectExpectation(e)
}
}
// Detect provides a mock function with given fields: imageName, filePath, created, pkgs
func (_m *MockLibraryDetector) Detect(imageName string, filePath string, created time.Time, pkgs []types.LibraryInfo) ([]pkgtypes.DetectedVulnerability, error) {
ret := _m.Called(imageName, filePath, created, pkgs)
var r0 []pkgtypes.DetectedVulnerability
if rf, ok := ret.Get(0).(func(string, string, time.Time, []types.LibraryInfo) []pkgtypes.DetectedVulnerability); ok {
r0 = rf(imageName, filePath, created, pkgs)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]pkgtypes.DetectedVulnerability)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string, string, time.Time, []types.LibraryInfo) error); ok {
r1 = rf(imageName, filePath, created, pkgs)
} else {
r1 = ret.Error(1)
}
return r0, r1
}

View File

@@ -8,6 +8,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/aquasecurity/trivy/pkg/detector/library"
"github.com/google/wire" "github.com/google/wire"
"golang.org/x/xerrors" "golang.org/x/xerrors"
@@ -16,6 +18,7 @@ import (
_ "github.com/aquasecurity/fanal/analyzer/library/bundler" _ "github.com/aquasecurity/fanal/analyzer/library/bundler"
_ "github.com/aquasecurity/fanal/analyzer/library/cargo" _ "github.com/aquasecurity/fanal/analyzer/library/cargo"
_ "github.com/aquasecurity/fanal/analyzer/library/composer" _ "github.com/aquasecurity/fanal/analyzer/library/composer"
_ "github.com/aquasecurity/fanal/analyzer/library/jar"
_ "github.com/aquasecurity/fanal/analyzer/library/npm" _ "github.com/aquasecurity/fanal/analyzer/library/npm"
_ "github.com/aquasecurity/fanal/analyzer/library/nuget" _ "github.com/aquasecurity/fanal/analyzer/library/nuget"
_ "github.com/aquasecurity/fanal/analyzer/library/pipenv" _ "github.com/aquasecurity/fanal/analyzer/library/pipenv"
@@ -33,7 +36,6 @@ import (
_ "github.com/aquasecurity/fanal/analyzer/pkg/rpm" _ "github.com/aquasecurity/fanal/analyzer/pkg/rpm"
"github.com/aquasecurity/fanal/applier" "github.com/aquasecurity/fanal/applier"
ftypes "github.com/aquasecurity/fanal/types" ftypes "github.com/aquasecurity/fanal/types"
libDetector "github.com/aquasecurity/trivy/pkg/detector/library"
ospkgDetector "github.com/aquasecurity/trivy/pkg/detector/ospkg" ospkgDetector "github.com/aquasecurity/trivy/pkg/detector/ospkg"
"github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/report" "github.com/aquasecurity/trivy/pkg/report"
@@ -47,8 +49,6 @@ var SuperSet = wire.NewSet(
wire.Bind(new(Applier), new(applier.Applier)), wire.Bind(new(Applier), new(applier.Applier)),
ospkgDetector.SuperSet, ospkgDetector.SuperSet,
wire.Bind(new(OspkgDetector), new(ospkgDetector.Detector)), wire.Bind(new(OspkgDetector), new(ospkgDetector.Detector)),
libDetector.SuperSet,
wire.Bind(new(LibraryDetector), new(libDetector.Detector)),
NewScanner, NewScanner,
) )
@@ -62,21 +62,15 @@ type OspkgDetector interface {
Detect(imageName, osFamily, osName string, created time.Time, pkgs []ftypes.Package) (detectedVulns []types.DetectedVulnerability, eosl bool, err error) Detect(imageName, osFamily, osName string, created time.Time, pkgs []ftypes.Package) (detectedVulns []types.DetectedVulnerability, eosl bool, err error)
} }
// LibraryDetector defines operation to detect library vulnerabilities
type LibraryDetector interface {
Detect(imageName, filePath string, created time.Time, pkgs []ftypes.LibraryInfo) (detectedVulns []types.DetectedVulnerability, err error)
}
// Scanner implements the OspkgDetector and LibraryDetector // Scanner implements the OspkgDetector and LibraryDetector
type Scanner struct { type Scanner struct {
applier Applier applier Applier
ospkgDetector OspkgDetector ospkgDetector OspkgDetector
libDetector LibraryDetector
} }
// NewScanner is the factory method for Scanner // NewScanner is the factory method for Scanner
func NewScanner(applier Applier, ospkgDetector OspkgDetector, libDetector LibraryDetector) Scanner { func NewScanner(applier Applier, ospkgDetector OspkgDetector) Scanner {
return Scanner{applier: applier, ospkgDetector: ospkgDetector, libDetector: libDetector} return Scanner{applier: applier, ospkgDetector: ospkgDetector}
} }
// Scan scans the local image and return results. TODO: fix cyclometic complexity // Scan scans the local image and return results. TODO: fix cyclometic complexity
@@ -156,17 +150,29 @@ func (s Scanner) scanLibrary(apps []ftypes.Application, options types.ScanOption
log.Logger.Info("Trivy skips scanning programming language libraries because no supported file was detected") log.Logger.Info("Trivy skips scanning programming language libraries because no supported file was detected")
return nil, nil return nil, nil
} }
var results report.Results
for _, app := range apps {
vulns, err := s.libDetector.Detect("", app.FilePath, time.Time{}, app.Libraries)
if err != nil {
return nil, xerrors.Errorf("failed vulnerability detection of libraries: %w", err)
}
var results report.Results
printedTypes := map[string]struct{}{}
for _, app := range apps {
if len(app.Libraries) == 0 {
continue
}
if skipped(app.FilePath, options.SkipFiles, options.SkipDirectories) { if skipped(app.FilePath, options.SkipFiles, options.SkipDirectories) {
continue continue
} }
// Prevent the same log messages from being displayed many times for the same type.
if _, ok := printedTypes[app.Type]; !ok {
log.Logger.Infof("Detecting %s vulnerabilities...", app.Type)
printedTypes[app.Type] = struct{}{}
}
log.Logger.Debugf("Detecting library vulnerabilities, type: %s, path: %s", app.Type, app.FilePath)
vulns, err := library.Detect(app.Type, app.Libraries)
if err != nil {
return nil, xerrors.Errorf("failed vulnerability detection of libraries: %w", err)
}
libReport := report.Result{ libReport := report.Result{
Target: app.FilePath, Target: app.FilePath,
Vulnerabilities: vulns, Vulnerabilities: vulns,

View File

@@ -4,6 +4,12 @@ import (
"errors" "errors"
"testing" "testing"
"github.com/aquasecurity/fanal/analyzer/library"
"github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy/pkg/dbtest"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@@ -26,9 +32,9 @@ func TestScanner_Scan(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
args args args args
fixtures []string
applyLayersExpectation ApplierApplyLayersExpectation applyLayersExpectation ApplierApplyLayersExpectation
ospkgDetectExpectations []OspkgDetectorDetectExpectation ospkgDetectExpectations []OspkgDetectorDetectExpectation
libDetectExpectations []LibraryDetectorDetectExpectation
wantResults report.Results wantResults report.Results
wantOS *ftypes.OS wantOS *ftypes.OS
wantEosl bool wantEosl bool
@@ -41,6 +47,7 @@ func TestScanner_Scan(t *testing.T) {
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{VulnType: []string{"os", "library"}}, options: types.ScanOptions{VulnType: []string{"os", "library"}},
}, },
fixtures: []string{"testdata/fixtures/happy.yaml"},
applyLayersExpectation: ApplierApplyLayersExpectation{ applyLayersExpectation: ApplierApplyLayersExpectation{
Args: ApplierApplyLayersArgs{ Args: ApplierApplyLayersArgs{
BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
@@ -62,11 +69,11 @@ func TestScanner_Scan(t *testing.T) {
}, },
Applications: []ftypes.Application{ Applications: []ftypes.Application{
{ {
Type: "bundler", Type: library.Bundler,
FilePath: "/app/Gemfile.lock", FilePath: "/app/Gemfile.lock",
Libraries: []ftypes.LibraryInfo{ Libraries: []ftypes.LibraryInfo{
{ {
Library: dtypes.Library{Name: "rails", Version: "6.0"}, Library: dtypes.Library{Name: "rails", Version: "4.0.2"},
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33", DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
}, },
@@ -108,34 +115,6 @@ func TestScanner_Scan(t *testing.T) {
}, },
}, },
}, },
libDetectExpectations: []LibraryDetectorDetectExpectation{
{
Args: LibraryDetectorDetectArgs{
FilePath: "/app/Gemfile.lock",
Pkgs: []ftypes.LibraryInfo{
{
Library: dtypes.Library{Name: "rails", Version: "6.0"},
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
},
},
},
Returns: LibraryDetectorDetectReturns{
DetectedVulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-10000",
PkgName: "rails",
InstalledVersion: "6.0",
FixedVersion: "6.1",
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
},
},
},
},
},
wantResults: report.Results{ wantResults: report.Results{
{ {
Target: "alpine:latest (alpine 3.11)", Target: "alpine:latest (alpine 3.11)",
@@ -156,10 +135,10 @@ func TestScanner_Scan(t *testing.T) {
Target: "/app/Gemfile.lock", Target: "/app/Gemfile.lock",
Vulnerabilities: []types.DetectedVulnerability{ Vulnerabilities: []types.DetectedVulnerability{
{ {
VulnerabilityID: "CVE-2020-10000", VulnerabilityID: "CVE-2014-0081",
PkgName: "rails", PkgName: "rails",
InstalledVersion: "6.0", InstalledVersion: "4.0.2",
FixedVersion: "6.1", FixedVersion: "4.0.3, 3.2.17",
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33", DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
}, },
@@ -180,6 +159,7 @@ func TestScanner_Scan(t *testing.T) {
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{VulnType: []string{"os", "library"}, ListAllPackages: true}, options: types.ScanOptions{VulnType: []string{"os", "library"}, ListAllPackages: true},
}, },
fixtures: []string{"testdata/fixtures/happy.yaml"},
applyLayersExpectation: ApplierApplyLayersExpectation{ applyLayersExpectation: ApplierApplyLayersExpectation{
Args: ApplierApplyLayersArgs{ Args: ApplierApplyLayersArgs{
BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
@@ -212,7 +192,7 @@ func TestScanner_Scan(t *testing.T) {
FilePath: "/app/Gemfile.lock", FilePath: "/app/Gemfile.lock",
Libraries: []ftypes.LibraryInfo{ Libraries: []ftypes.LibraryInfo{
{ {
Library: dtypes.Library{Name: "rails", Version: "6.0"}, Library: dtypes.Library{Name: "rails", Version: "4.0.2"},
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33", DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
}, },
@@ -261,34 +241,6 @@ func TestScanner_Scan(t *testing.T) {
}, },
}, },
}, },
libDetectExpectations: []LibraryDetectorDetectExpectation{
{
Args: LibraryDetectorDetectArgs{
FilePath: "/app/Gemfile.lock",
Pkgs: []ftypes.LibraryInfo{
{
Library: dtypes.Library{Name: "rails", Version: "6.0"},
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
},
},
},
Returns: LibraryDetectorDetectReturns{
DetectedVulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-10000",
PkgName: "rails",
InstalledVersion: "6.0",
FixedVersion: "6.1",
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
},
},
},
},
},
wantResults: report.Results{ wantResults: report.Results{
{ {
Target: "alpine:latest (alpine 3.11)", Target: "alpine:latest (alpine 3.11)",
@@ -326,7 +278,7 @@ func TestScanner_Scan(t *testing.T) {
Packages: []ftypes.Package{ Packages: []ftypes.Package{
{ {
Name: "rails", Name: "rails",
Version: "6.0", Version: "4.0.2",
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33", DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
}, },
@@ -334,10 +286,10 @@ func TestScanner_Scan(t *testing.T) {
}, },
Vulnerabilities: []types.DetectedVulnerability{ Vulnerabilities: []types.DetectedVulnerability{
{ {
VulnerabilityID: "CVE-2020-10000", VulnerabilityID: "CVE-2014-0081",
PkgName: "rails", PkgName: "rails",
InstalledVersion: "6.0", InstalledVersion: "4.0.2",
FixedVersion: "6.1", FixedVersion: "4.0.3, 3.2.17",
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33", DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
}, },
@@ -358,6 +310,7 @@ func TestScanner_Scan(t *testing.T) {
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{VulnType: []string{"os", "library"}}, options: types.ScanOptions{VulnType: []string{"os", "library"}},
}, },
fixtures: []string{"testdata/fixtures/happy.yaml"},
applyLayersExpectation: ApplierApplyLayersExpectation{ applyLayersExpectation: ApplierApplyLayersExpectation{
Args: ApplierApplyLayersArgs{ Args: ApplierApplyLayersArgs{
BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
@@ -371,7 +324,7 @@ func TestScanner_Scan(t *testing.T) {
FilePath: "/app/Gemfile.lock", FilePath: "/app/Gemfile.lock",
Libraries: []ftypes.LibraryInfo{ Libraries: []ftypes.LibraryInfo{
{ {
Library: dtypes.Library{Name: "rails", Version: "6.0"}, Library: dtypes.Library{Name: "rails", Version: "4.0.2"},
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303", DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
}, },
@@ -382,43 +335,15 @@ func TestScanner_Scan(t *testing.T) {
}, },
}, },
}, },
libDetectExpectations: []LibraryDetectorDetectExpectation{
{
Args: LibraryDetectorDetectArgs{
FilePath: "/app/Gemfile.lock",
Pkgs: []ftypes.LibraryInfo{
{
Library: dtypes.Library{Name: "rails", Version: "6.0"},
Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
},
},
},
},
Returns: LibraryDetectorDetectReturns{
DetectedVulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-10000",
PkgName: "rails",
InstalledVersion: "6.0",
FixedVersion: "6.1",
Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
},
},
},
},
},
},
wantResults: report.Results{ wantResults: report.Results{
{ {
Target: "/app/Gemfile.lock", Target: "/app/Gemfile.lock",
Vulnerabilities: []types.DetectedVulnerability{ Vulnerabilities: []types.DetectedVulnerability{
{ {
VulnerabilityID: "CVE-2020-10000", VulnerabilityID: "CVE-2014-0081",
PkgName: "rails", PkgName: "rails",
InstalledVersion: "6.0", InstalledVersion: "4.0.2",
FixedVersion: "6.1", FixedVersion: "4.0.3, 3.2.17",
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303", DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
}, },
@@ -436,6 +361,7 @@ func TestScanner_Scan(t *testing.T) {
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{VulnType: []string{"os", "library"}}, options: types.ScanOptions{VulnType: []string{"os", "library"}},
}, },
fixtures: []string{"testdata/fixtures/happy.yaml"},
applyLayersExpectation: ApplierApplyLayersExpectation{ applyLayersExpectation: ApplierApplyLayersExpectation{
Args: ApplierApplyLayersArgs{ Args: ApplierApplyLayersArgs{
BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
@@ -452,7 +378,7 @@ func TestScanner_Scan(t *testing.T) {
FilePath: "/app/Gemfile.lock", FilePath: "/app/Gemfile.lock",
Libraries: []ftypes.LibraryInfo{ Libraries: []ftypes.LibraryInfo{
{ {
Library: dtypes.Library{Name: "rails", Version: "6.0"}, Library: dtypes.Library{Name: "rails", Version: "4.0.2"},
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33", DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
}, },
@@ -475,34 +401,6 @@ func TestScanner_Scan(t *testing.T) {
}, },
}, },
}, },
libDetectExpectations: []LibraryDetectorDetectExpectation{
{
Args: LibraryDetectorDetectArgs{
FilePath: "/app/Gemfile.lock",
Pkgs: []ftypes.LibraryInfo{
{
Library: dtypes.Library{Name: "rails", Version: "6.0"},
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
},
},
},
Returns: LibraryDetectorDetectReturns{
DetectedVulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-10000",
PkgName: "rails",
InstalledVersion: "6.0",
FixedVersion: "6.1",
Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
},
},
},
},
},
},
wantResults: report.Results{ wantResults: report.Results{
{ {
Target: "alpine:latest (alpine 3.11)", Target: "alpine:latest (alpine 3.11)",
@@ -512,10 +410,10 @@ func TestScanner_Scan(t *testing.T) {
Target: "/app/Gemfile.lock", Target: "/app/Gemfile.lock",
Vulnerabilities: []types.DetectedVulnerability{ Vulnerabilities: []types.DetectedVulnerability{
{ {
VulnerabilityID: "CVE-2020-10000", VulnerabilityID: "CVE-2014-0081",
PkgName: "rails", PkgName: "rails",
InstalledVersion: "6.0", InstalledVersion: "4.0.2",
FixedVersion: "6.1", FixedVersion: "4.0.3, 3.2.17",
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33", DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33",
}, },
@@ -536,6 +434,7 @@ func TestScanner_Scan(t *testing.T) {
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{VulnType: []string{"os", "library"}}, options: types.ScanOptions{VulnType: []string{"os", "library"}},
}, },
fixtures: []string{"testdata/fixtures/happy.yaml"},
applyLayersExpectation: ApplierApplyLayersExpectation{ applyLayersExpectation: ApplierApplyLayersExpectation{
Args: ApplierApplyLayersArgs{ Args: ApplierApplyLayersArgs{
BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
@@ -552,7 +451,7 @@ func TestScanner_Scan(t *testing.T) {
FilePath: "/app/Gemfile.lock", FilePath: "/app/Gemfile.lock",
Libraries: []ftypes.LibraryInfo{ Libraries: []ftypes.LibraryInfo{
{ {
Library: dtypes.Library{Name: "rails", Version: "6.0"}, Library: dtypes.Library{Name: "rails", Version: "4.0.2"},
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303", DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
}, },
@@ -574,43 +473,15 @@ func TestScanner_Scan(t *testing.T) {
}, },
}, },
}, },
libDetectExpectations: []LibraryDetectorDetectExpectation{
{
Args: LibraryDetectorDetectArgs{
FilePath: "/app/Gemfile.lock",
Pkgs: []ftypes.LibraryInfo{
{
Library: dtypes.Library{Name: "rails", Version: "6.0"},
Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
},
},
},
},
Returns: LibraryDetectorDetectReturns{
DetectedVulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-10000",
PkgName: "rails",
InstalledVersion: "6.0",
FixedVersion: "6.1",
Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
},
},
},
},
},
},
wantResults: report.Results{ wantResults: report.Results{
{ {
Target: "/app/Gemfile.lock", Target: "/app/Gemfile.lock",
Vulnerabilities: []types.DetectedVulnerability{ Vulnerabilities: []types.DetectedVulnerability{
{ {
VulnerabilityID: "CVE-2020-10000", VulnerabilityID: "CVE-2014-0081",
PkgName: "rails", PkgName: "rails",
InstalledVersion: "6.0", InstalledVersion: "4.0.2",
FixedVersion: "6.1", FixedVersion: "4.0.3, 3.2.17",
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303", DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
}, },
@@ -631,6 +502,7 @@ func TestScanner_Scan(t *testing.T) {
layerIDs: []string{"sha256:a6d503001157aedc826853f9b67f26d35966221b158bff03849868ae4a821116"}, layerIDs: []string{"sha256:a6d503001157aedc826853f9b67f26d35966221b158bff03849868ae4a821116"},
options: types.ScanOptions{VulnType: []string{"os", "library"}}, options: types.ScanOptions{VulnType: []string{"os", "library"}},
}, },
fixtures: []string{"testdata/fixtures/happy.yaml"},
applyLayersExpectation: ApplierApplyLayersExpectation{ applyLayersExpectation: ApplierApplyLayersExpectation{
Args: ApplierApplyLayersArgs{ Args: ApplierApplyLayersArgs{
BlobIDs: []string{"sha256:a6d503001157aedc826853f9b67f26d35966221b158bff03849868ae4a821116"}, BlobIDs: []string{"sha256:a6d503001157aedc826853f9b67f26d35966221b158bff03849868ae4a821116"},
@@ -652,6 +524,7 @@ func TestScanner_Scan(t *testing.T) {
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{VulnType: []string{"library"}}, options: types.ScanOptions{VulnType: []string{"library"}},
}, },
fixtures: []string{"testdata/fixtures/happy.yaml"},
applyLayersExpectation: ApplierApplyLayersExpectation{ applyLayersExpectation: ApplierApplyLayersExpectation{
Args: ApplierApplyLayersArgs{ Args: ApplierApplyLayersArgs{
BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
@@ -671,7 +544,7 @@ func TestScanner_Scan(t *testing.T) {
FilePath: "/app/Gemfile.lock", FilePath: "/app/Gemfile.lock",
Libraries: []ftypes.LibraryInfo{ Libraries: []ftypes.LibraryInfo{
{ {
Library: dtypes.Library{Name: "rails", Version: "5.1"}, Library: dtypes.Library{Name: "rails", Version: "4.0.2"},
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:5cb2a5009179b1e78ecfef81a19756328bb266456cf9a9dbbcf9af8b83b735f0", DiffID: "sha256:5cb2a5009179b1e78ecfef81a19756328bb266456cf9a9dbbcf9af8b83b735f0",
}, },
@@ -683,7 +556,7 @@ func TestScanner_Scan(t *testing.T) {
FilePath: "/app/composer-lock.json", FilePath: "/app/composer-lock.json",
Libraries: []ftypes.LibraryInfo{ Libraries: []ftypes.LibraryInfo{
{ {
Library: dtypes.Library{Name: "laravel", Version: "6.0.0"}, Library: dtypes.Library{Name: "laravel/framework", Version: "6.0.0"},
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303", DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
}, },
@@ -694,69 +567,15 @@ func TestScanner_Scan(t *testing.T) {
}, },
}, },
}, },
libDetectExpectations: []LibraryDetectorDetectExpectation{
{
Args: LibraryDetectorDetectArgs{
FilePath: "/app/Gemfile.lock",
Pkgs: []ftypes.LibraryInfo{
{
Library: dtypes.Library{Name: "rails", Version: "5.1"},
Layer: ftypes.Layer{
DiffID: "sha256:5cb2a5009179b1e78ecfef81a19756328bb266456cf9a9dbbcf9af8b83b735f0",
},
},
},
},
Returns: LibraryDetectorDetectReturns{
DetectedVulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-11111",
PkgName: "rails",
InstalledVersion: "5.1",
FixedVersion: "5.2",
Layer: ftypes.Layer{
DiffID: "sha256:5cb2a5009179b1e78ecfef81a19756328bb266456cf9a9dbbcf9af8b83b735f0",
},
},
},
},
},
{
Args: LibraryDetectorDetectArgs{
FilePath: "/app/composer-lock.json",
Pkgs: []ftypes.LibraryInfo{
{
Library: dtypes.Library{Name: "laravel", Version: "6.0.0"},
Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
},
},
},
},
Returns: LibraryDetectorDetectReturns{
DetectedVulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-22222",
PkgName: "laravel",
InstalledVersion: "6.0.0",
FixedVersion: "6.1.0",
Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
},
},
},
},
},
},
wantResults: report.Results{ wantResults: report.Results{
{ {
Target: "/app/Gemfile.lock", Target: "/app/Gemfile.lock",
Vulnerabilities: []types.DetectedVulnerability{ Vulnerabilities: []types.DetectedVulnerability{
{ {
VulnerabilityID: "CVE-2020-11111", VulnerabilityID: "CVE-2014-0081",
PkgName: "rails", PkgName: "rails",
InstalledVersion: "5.1", InstalledVersion: "4.0.2",
FixedVersion: "5.2", FixedVersion: "4.0.3, 3.2.17",
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:5cb2a5009179b1e78ecfef81a19756328bb266456cf9a9dbbcf9af8b83b735f0", DiffID: "sha256:5cb2a5009179b1e78ecfef81a19756328bb266456cf9a9dbbcf9af8b83b735f0",
}, },
@@ -768,10 +587,10 @@ func TestScanner_Scan(t *testing.T) {
Target: "/app/composer-lock.json", Target: "/app/composer-lock.json",
Vulnerabilities: []types.DetectedVulnerability{ Vulnerabilities: []types.DetectedVulnerability{
{ {
VulnerabilityID: "CVE-2020-22222", VulnerabilityID: "CVE-2021-21263",
PkgName: "laravel", PkgName: "laravel/framework",
InstalledVersion: "6.0.0", InstalledVersion: "6.0.0",
FixedVersion: "6.1.0", FixedVersion: "8.22.1, 7.30.3, 6.20.12",
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303", DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
}, },
@@ -795,6 +614,7 @@ func TestScanner_Scan(t *testing.T) {
SkipDirectories: []string{"/usr/lib/ruby/gems"}, SkipDirectories: []string{"/usr/lib/ruby/gems"},
}, },
}, },
fixtures: []string{"testdata/fixtures/happy.yaml"},
applyLayersExpectation: ApplierApplyLayersExpectation{ applyLayersExpectation: ApplierApplyLayersExpectation{
Args: ApplierApplyLayersArgs{ Args: ApplierApplyLayersArgs{
BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
@@ -826,7 +646,7 @@ func TestScanner_Scan(t *testing.T) {
FilePath: "app/composer-lock.json", FilePath: "app/composer-lock.json",
Libraries: []ftypes.LibraryInfo{ Libraries: []ftypes.LibraryInfo{
{ {
Library: dtypes.Library{Name: "laravel", Version: "6.0.0"}, Library: dtypes.Library{Name: "laravel/framework", Version: "6.0.0"},
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303", DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
}, },
@@ -837,69 +657,15 @@ func TestScanner_Scan(t *testing.T) {
}, },
}, },
}, },
libDetectExpectations: []LibraryDetectorDetectExpectation{
{
Args: LibraryDetectorDetectArgs{
FilePath: "usr/lib/ruby/gems/2.5.0/gems/http_parser.rb-0.6.0/Gemfile.lock",
Pkgs: []ftypes.LibraryInfo{
{
Library: dtypes.Library{Name: "rails", Version: "5.1"},
Layer: ftypes.Layer{
DiffID: "sha256:5cb2a5009179b1e78ecfef81a19756328bb266456cf9a9dbbcf9af8b83b735f0",
},
},
},
},
Returns: LibraryDetectorDetectReturns{
DetectedVulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-11111",
PkgName: "rails",
InstalledVersion: "5.1",
FixedVersion: "5.2",
Layer: ftypes.Layer{
DiffID: "sha256:5cb2a5009179b1e78ecfef81a19756328bb266456cf9a9dbbcf9af8b83b735f0",
},
},
},
},
},
{
Args: LibraryDetectorDetectArgs{
FilePath: "app/composer-lock.json",
Pkgs: []ftypes.LibraryInfo{
{
Library: dtypes.Library{Name: "laravel", Version: "6.0.0"},
Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
},
},
},
},
Returns: LibraryDetectorDetectReturns{
DetectedVulns: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2020-22222",
PkgName: "laravel",
InstalledVersion: "6.0.0",
FixedVersion: "6.1.0",
Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
},
},
},
},
},
},
wantResults: report.Results{ wantResults: report.Results{
{ {
Target: "app/composer-lock.json", Target: "app/composer-lock.json",
Vulnerabilities: []types.DetectedVulnerability{ Vulnerabilities: []types.DetectedVulnerability{
{ {
VulnerabilityID: "CVE-2020-22222", VulnerabilityID: "CVE-2021-21263",
PkgName: "laravel", PkgName: "laravel/framework",
InstalledVersion: "6.0.0", InstalledVersion: "6.0.0",
FixedVersion: "6.1.0", FixedVersion: "8.22.1, 7.30.3, 6.20.12",
Layer: ftypes.Layer{ Layer: ftypes.Layer{
DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303", DiffID: "sha256:9922bc15eeefe1637b803ef2106f178152ce19a391f24aec838cbe2e48e73303",
}, },
@@ -920,6 +686,7 @@ func TestScanner_Scan(t *testing.T) {
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{VulnType: []string{"os", "library"}}, options: types.ScanOptions{VulnType: []string{"os", "library"}},
}, },
fixtures: []string{"testdata/fixtures/happy.yaml"},
applyLayersExpectation: ApplierApplyLayersExpectation{ applyLayersExpectation: ApplierApplyLayersExpectation{
Args: ApplierApplyLayersArgs{ Args: ApplierApplyLayersArgs{
BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
@@ -937,6 +704,7 @@ func TestScanner_Scan(t *testing.T) {
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{VulnType: []string{"os", "library"}}, options: types.ScanOptions{VulnType: []string{"os", "library"}},
}, },
fixtures: []string{"testdata/fixtures/happy.yaml"},
applyLayersExpectation: ApplierApplyLayersExpectation{ applyLayersExpectation: ApplierApplyLayersExpectation{
Args: ApplierApplyLayersArgs{ Args: ApplierApplyLayersArgs{
BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
@@ -982,12 +750,13 @@ func TestScanner_Scan(t *testing.T) {
wantErr: "failed to scan OS packages", wantErr: "failed to scan OS packages",
}, },
{ {
name: "sad path: libDetector.Detect returns an error", name: "sad path: library.Detect returns an error",
args: args{ args: args{
target: "alpine:latest", target: "alpine:latest",
layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
options: types.ScanOptions{VulnType: []string{"library"}}, options: types.ScanOptions{VulnType: []string{"library"}},
}, },
fixtures: []string{"testdata/fixtures/sad.yaml"},
applyLayersExpectation: ApplierApplyLayersExpectation{ applyLayersExpectation: ApplierApplyLayersExpectation{
Args: ApplierApplyLayersArgs{ Args: ApplierApplyLayersArgs{
BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
@@ -1024,24 +793,6 @@ func TestScanner_Scan(t *testing.T) {
}, },
}, },
}, },
libDetectExpectations: []LibraryDetectorDetectExpectation{
{
Args: LibraryDetectorDetectArgs{
FilePath: "/app/Gemfile.lock",
Pkgs: []ftypes.LibraryInfo{
{
Library: dtypes.Library{Name: "rails", Version: "6.0"},
Layer: ftypes.Layer{
DiffID: "sha256:9bdb2c849099a99c8ab35f6fd7469c623635e8f4479a0a5a3df61e22bae509f6",
},
},
},
},
Returns: LibraryDetectorDetectReturns{
Err: errors.New("error"),
},
},
},
wantErr: "failed to scan application libraries", wantErr: "failed to scan application libraries",
}, },
} }
@@ -1049,16 +800,16 @@ func TestScanner_Scan(t *testing.T) {
log.InitLogger(false, true) log.InitLogger(false, true)
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
_ = dbtest.InitDB(t, tt.fixtures)
defer db.Close()
applier := new(MockApplier) applier := new(MockApplier)
applier.ApplyApplyLayersExpectation(tt.applyLayersExpectation) applier.ApplyApplyLayersExpectation(tt.applyLayersExpectation)
ospkgDetector := new(MockOspkgDetector) ospkgDetector := new(MockOspkgDetector)
ospkgDetector.ApplyDetectExpectations(tt.ospkgDetectExpectations) ospkgDetector.ApplyDetectExpectations(tt.ospkgDetectExpectations)
libDetector := new(MockLibraryDetector) s := NewScanner(applier, ospkgDetector)
libDetector.ApplyDetectExpectations(tt.libDetectExpectations)
s := NewScanner(applier, ospkgDetector, libDetector)
gotResults, gotOS, gotEosl, err := s.Scan(tt.args.target, "", tt.args.layerIDs, tt.args.options) gotResults, gotOS, gotEosl, err := s.Scan(tt.args.target, "", tt.args.layerIDs, tt.args.options)
if tt.wantErr != "" { if tt.wantErr != "" {
require.NotNil(t, err, tt.name) require.NotNil(t, err, tt.name)
@@ -1074,7 +825,6 @@ func TestScanner_Scan(t *testing.T) {
applier.AssertExpectations(t) applier.AssertExpectations(t)
ospkgDetector.AssertExpectations(t) ospkgDetector.AssertExpectations(t)
libDetector.AssertExpectations(t)
}) })
} }
} }

View File

@@ -0,0 +1,28 @@
- bucket: "GitHub Security Advisory Rubygems"
pairs:
- bucket: rails
pairs:
- key: CVE-2014-0081
value:
PatchedVersions:
- "4.0.3"
- "3.2.17"
VulnerableVersions:
- ">= 4.0.0, < 4.0.3"
- ">= 3.0.0, < 3.2.17"
- bucket: "composer::GitHub Security Advisory Composer"
pairs:
- bucket: laravel/framework
pairs:
- key: CVE-2021-21263
value:
PatchedVersions:
- 8.22.1
- 7.30.3
- 6.20.12
VulnerableVersions:
- ">= 8.0.0, < 8.22.1"
- ">= 7.0.0, < 7.30.3"
- "< 6.20.12"

View File

@@ -0,0 +1,7 @@
- bucket: "ruby-advisory-db"
pairs:
- bucket: rails
pairs:
- key: CVE-2014-0081
value:
PatchedVersions: "invalid"

View File

@@ -3,17 +3,12 @@ package utils
import ( import (
"fmt" "fmt"
"io" "io"
"io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"testing"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors" "golang.org/x/xerrors"
fixtures "github.com/aquasecurity/bolt-fixtures"
"github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy/pkg/log" "github.com/aquasecurity/trivy/pkg/log"
) )
@@ -132,26 +127,3 @@ func CopyFile(src, dst string) (int64, error) {
n, err := io.Copy(destination, source) n, err := io.Copy(destination, source)
return n, err return n, err
} }
// InitTestDB is a utility function initializing BoltDB for unit testing
func InitTestDB(t *testing.T, fixtureFiles []string) string {
// Create a temp dir
dir, err := ioutil.TempDir("", "TestDB")
require.NoError(t, err)
dbPath := db.Path(dir)
dbDir := filepath.Dir(dbPath)
err = os.MkdirAll(dbDir, 0700)
require.NoError(t, err)
// Load testdata into BoltDB
loader, err := fixtures.New(dbPath, fixtureFiles)
require.NoError(t, err)
require.NoError(t, loader.Load())
require.NoError(t, loader.Close())
// Initialize DB
require.NoError(t, db.Init(dir))
return dir
}

View File

@@ -1,243 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: rpc/detector/service.proto
package detector
import (
fmt "fmt"
common "github.com/aquasecurity/trivy/rpc/common"
proto "github.com/golang/protobuf/proto"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type OSDetectRequest struct {
OsFamily string `protobuf:"bytes,1,opt,name=os_family,json=osFamily,proto3" json:"os_family,omitempty"`
OsName string `protobuf:"bytes,2,opt,name=os_name,json=osName,proto3" json:"os_name,omitempty"`
Packages []*common.Package `protobuf:"bytes,3,rep,name=packages,proto3" json:"packages,omitempty"`
ImageName string `protobuf:"bytes,4,opt,name=image_name,json=imageName,proto3" json:"image_name,omitempty"`
Created *timestamp.Timestamp `protobuf:"bytes,5,opt,name=created,proto3" json:"created,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *OSDetectRequest) Reset() { *m = OSDetectRequest{} }
func (m *OSDetectRequest) String() string { return proto.CompactTextString(m) }
func (*OSDetectRequest) ProtoMessage() {}
func (*OSDetectRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_93e16dbd737b8924, []int{0}
}
func (m *OSDetectRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_OSDetectRequest.Unmarshal(m, b)
}
func (m *OSDetectRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_OSDetectRequest.Marshal(b, m, deterministic)
}
func (m *OSDetectRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_OSDetectRequest.Merge(m, src)
}
func (m *OSDetectRequest) XXX_Size() int {
return xxx_messageInfo_OSDetectRequest.Size(m)
}
func (m *OSDetectRequest) XXX_DiscardUnknown() {
xxx_messageInfo_OSDetectRequest.DiscardUnknown(m)
}
var xxx_messageInfo_OSDetectRequest proto.InternalMessageInfo
func (m *OSDetectRequest) GetOsFamily() string {
if m != nil {
return m.OsFamily
}
return ""
}
func (m *OSDetectRequest) GetOsName() string {
if m != nil {
return m.OsName
}
return ""
}
func (m *OSDetectRequest) GetPackages() []*common.Package {
if m != nil {
return m.Packages
}
return nil
}
func (m *OSDetectRequest) GetImageName() string {
if m != nil {
return m.ImageName
}
return ""
}
func (m *OSDetectRequest) GetCreated() *timestamp.Timestamp {
if m != nil {
return m.Created
}
return nil
}
type DetectResponse struct {
Vulnerabilities []*common.Vulnerability `protobuf:"bytes,1,rep,name=vulnerabilities,proto3" json:"vulnerabilities,omitempty"`
Eosl bool `protobuf:"varint,2,opt,name=eosl,proto3" json:"eosl,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *DetectResponse) Reset() { *m = DetectResponse{} }
func (m *DetectResponse) String() string { return proto.CompactTextString(m) }
func (*DetectResponse) ProtoMessage() {}
func (*DetectResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_93e16dbd737b8924, []int{1}
}
func (m *DetectResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DetectResponse.Unmarshal(m, b)
}
func (m *DetectResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_DetectResponse.Marshal(b, m, deterministic)
}
func (m *DetectResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_DetectResponse.Merge(m, src)
}
func (m *DetectResponse) XXX_Size() int {
return xxx_messageInfo_DetectResponse.Size(m)
}
func (m *DetectResponse) XXX_DiscardUnknown() {
xxx_messageInfo_DetectResponse.DiscardUnknown(m)
}
var xxx_messageInfo_DetectResponse proto.InternalMessageInfo
func (m *DetectResponse) GetVulnerabilities() []*common.Vulnerability {
if m != nil {
return m.Vulnerabilities
}
return nil
}
func (m *DetectResponse) GetEosl() bool {
if m != nil {
return m.Eosl
}
return false
}
type LibDetectRequest struct {
FilePath string `protobuf:"bytes,1,opt,name=file_path,json=filePath,proto3" json:"file_path,omitempty"`
Libraries []*common.Library `protobuf:"bytes,2,rep,name=libraries,proto3" json:"libraries,omitempty"`
ImageName string `protobuf:"bytes,3,opt,name=image_name,json=imageName,proto3" json:"image_name,omitempty"`
Created *timestamp.Timestamp `protobuf:"bytes,4,opt,name=created,proto3" json:"created,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *LibDetectRequest) Reset() { *m = LibDetectRequest{} }
func (m *LibDetectRequest) String() string { return proto.CompactTextString(m) }
func (*LibDetectRequest) ProtoMessage() {}
func (*LibDetectRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_93e16dbd737b8924, []int{2}
}
func (m *LibDetectRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_LibDetectRequest.Unmarshal(m, b)
}
func (m *LibDetectRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_LibDetectRequest.Marshal(b, m, deterministic)
}
func (m *LibDetectRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_LibDetectRequest.Merge(m, src)
}
func (m *LibDetectRequest) XXX_Size() int {
return xxx_messageInfo_LibDetectRequest.Size(m)
}
func (m *LibDetectRequest) XXX_DiscardUnknown() {
xxx_messageInfo_LibDetectRequest.DiscardUnknown(m)
}
var xxx_messageInfo_LibDetectRequest proto.InternalMessageInfo
func (m *LibDetectRequest) GetFilePath() string {
if m != nil {
return m.FilePath
}
return ""
}
func (m *LibDetectRequest) GetLibraries() []*common.Library {
if m != nil {
return m.Libraries
}
return nil
}
func (m *LibDetectRequest) GetImageName() string {
if m != nil {
return m.ImageName
}
return ""
}
func (m *LibDetectRequest) GetCreated() *timestamp.Timestamp {
if m != nil {
return m.Created
}
return nil
}
func init() {
proto.RegisterType((*OSDetectRequest)(nil), "trivy.detector.OSDetectRequest")
proto.RegisterType((*DetectResponse)(nil), "trivy.detector.DetectResponse")
proto.RegisterType((*LibDetectRequest)(nil), "trivy.detector.LibDetectRequest")
}
func init() { proto.RegisterFile("rpc/detector/service.proto", fileDescriptor_93e16dbd737b8924) }
var fileDescriptor_93e16dbd737b8924 = []byte{
// 422 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xd1, 0x8a, 0xd3, 0x40,
0x14, 0x86, 0xc9, 0xb6, 0x76, 0xdb, 0x53, 0xd8, 0x95, 0x01, 0x31, 0x64, 0xd1, 0x2d, 0xbd, 0xea,
0xd5, 0x04, 0xbb, 0xe2, 0x03, 0x88, 0x0a, 0xca, 0xa2, 0x4b, 0x14, 0x45, 0x6f, 0xca, 0x64, 0xf6,
0x34, 0x1d, 0x36, 0xd3, 0x93, 0xce, 0x4c, 0x0a, 0x79, 0x34, 0x9f, 0xc2, 0x57, 0x92, 0x4e, 0x98,
0x6a, 0xa2, 0xe8, 0xde, 0x4d, 0xe6, 0xff, 0xcf, 0x7f, 0xce, 0xf9, 0x32, 0x90, 0x98, 0x4a, 0xa6,
0xb7, 0xe8, 0x50, 0x3a, 0x32, 0xa9, 0x45, 0xb3, 0x57, 0x12, 0x79, 0x65, 0xc8, 0x11, 0x3b, 0x73,
0x46, 0xed, 0x1b, 0x1e, 0xd4, 0xe4, 0xb2, 0x20, 0x2a, 0x4a, 0x4c, 0xbd, 0x9a, 0xd7, 0xeb, 0xd4,
0x29, 0x8d, 0xd6, 0x09, 0x5d, 0xb5, 0x05, 0xc9, 0x8b, 0x42, 0xb9, 0x4d, 0x9d, 0x73, 0x49, 0x3a,
0x15, 0xbb, 0x5a, 0x58, 0x94, 0xb5, 0x51, 0xae, 0x49, 0x7d, 0x50, 0x7a, 0x68, 0x25, 0x49, 0x6b,
0xda, 0x76, 0x1b, 0xcd, 0x7f, 0x44, 0x70, 0xfe, 0xe1, 0xe3, 0x2b, 0xdf, 0x27, 0xc3, 0x5d, 0x8d,
0xd6, 0xb1, 0x0b, 0x98, 0x90, 0x5d, 0xad, 0x85, 0x56, 0x65, 0x13, 0x47, 0xb3, 0x68, 0x31, 0xc9,
0xc6, 0x64, 0xdf, 0xf8, 0x6f, 0xf6, 0x18, 0x4e, 0xc9, 0xae, 0xb6, 0x42, 0x63, 0x7c, 0xe2, 0xa5,
0x11, 0xd9, 0xf7, 0x42, 0x23, 0x7b, 0x06, 0xe3, 0x4a, 0xc8, 0x3b, 0x51, 0xa0, 0x8d, 0x07, 0xb3,
0xc1, 0x62, 0xba, 0x7c, 0xc4, 0xdb, 0x2d, 0xda, 0xc6, 0xfc, 0xa6, 0x55, 0xb3, 0xa3, 0x8d, 0x3d,
0x01, 0x50, 0x5a, 0x14, 0xd8, 0xc6, 0x0d, 0x7d, 0xdc, 0xc4, 0xdf, 0xf8, 0xc4, 0xe7, 0x70, 0x2a,
0x0d, 0x0a, 0x87, 0xb7, 0xf1, 0x83, 0x59, 0xb4, 0x98, 0x2e, 0x13, 0xde, 0x62, 0xe0, 0x01, 0x03,
0xff, 0x14, 0x30, 0x64, 0xc1, 0x3a, 0xbf, 0x83, 0xb3, 0xb0, 0x8e, 0xad, 0x68, 0x6b, 0x91, 0xbd,
0x86, 0xf3, 0x7d, 0x5d, 0x6e, 0xd1, 0x88, 0x5c, 0x95, 0xca, 0x29, 0xb4, 0x71, 0xe4, 0x07, 0xbc,
0xe8, 0x0e, 0xf8, 0xf9, 0x37, 0x53, 0x93, 0xf5, 0x6b, 0x18, 0x83, 0x21, 0x92, 0x2d, 0xfd, 0xda,
0xe3, 0xcc, 0x9f, 0xe7, 0xdf, 0x23, 0x78, 0x78, 0xad, 0xf2, 0x3f, 0xf8, 0xad, 0x55, 0x89, 0xab,
0x4a, 0xb8, 0x4d, 0xe0, 0x77, 0xb8, 0xb8, 0x11, 0x6e, 0xc3, 0xae, 0x60, 0x52, 0xaa, 0xdc, 0x08,
0x73, 0x18, 0xe3, 0xe4, 0x6f, 0x9c, 0xae, 0xbd, 0xdc, 0x64, 0xbf, 0x7c, 0x3d, 0x50, 0x83, 0x7f,
0x80, 0x1a, 0xde, 0x1b, 0xd4, 0xf2, 0x0b, 0x40, 0xf8, 0xf3, 0x64, 0xd8, 0x5b, 0x18, 0xb5, 0x67,
0x76, 0xc9, 0xbb, 0x8f, 0x8f, 0xf7, 0xde, 0x47, 0xf2, 0xb4, 0x6f, 0xe8, 0xf2, 0x5e, 0x7e, 0x85,
0xe9, 0x91, 0x09, 0x19, 0xf6, 0xee, 0x98, 0x3c, 0xeb, 0x17, 0xf6, 0xd1, 0xfd, 0x2f, 0xfa, 0x25,
0x7c, 0x1b, 0x07, 0x29, 0x1f, 0xf9, 0xe5, 0xae, 0x7e, 0x06, 0x00, 0x00, 0xff, 0xff, 0x60, 0x68,
0xcc, 0x2b, 0x48, 0x03, 0x00, 0x00,
}

View File

@@ -1,37 +0,0 @@
// for backward compatibility
syntax = "proto3";
import "google/protobuf/timestamp.proto";
package trivy.detector;
option go_package = "detector";
import "github.com/aquasecurity/trivy/rpc/common/service.proto";
service OSDetector {
rpc Detect(OSDetectRequest) returns (DetectResponse);
}
message OSDetectRequest {
string os_family = 1;
string os_name = 2;
repeated common.Package packages = 3;
string image_name = 4;
google.protobuf.Timestamp created = 5;
}
message DetectResponse {
repeated common.Vulnerability vulnerabilities = 1;
bool eosl = 2;
}
service LibDetector {
rpc Detect(LibDetectRequest) returns (DetectResponse);
}
message LibDetectRequest {
string file_path = 1;
repeated common.Library libraries = 2;
string image_name = 3;
google.protobuf.Timestamp created = 4;
}

File diff suppressed because it is too large Load Diff