mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-19 10:42:43 -08:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43362b2832 | ||
|
|
db2d0c2e9b | ||
|
|
922d493159 | ||
|
|
c4811c3104 | ||
|
|
0ec840b3b4 | ||
|
|
0b96d08877 | ||
|
|
7abd41609f | ||
|
|
fcc193b7d1 | ||
|
|
44d74a7d8a | ||
|
|
4189855fc1 | ||
|
|
77f1abc17d | ||
|
|
96d58ccd1b | ||
|
|
823374b578 | ||
|
|
b127c1c8a7 | ||
|
|
b1ea09d901 | ||
|
|
8c1c3df232 | ||
|
|
cee08c38f4 | ||
|
|
bc8f613ba6 | ||
|
|
af584a8517 | ||
|
|
1805a956a3 | ||
|
|
b9eddafe71 | ||
|
|
bdd1266087 |
@@ -1,3 +1,5 @@
|
||||
version: 2.1
|
||||
|
||||
defaults: &defaults
|
||||
docker :
|
||||
- image: aquasec/trivy-ci:latest
|
||||
@@ -5,7 +7,7 @@ defaults: &defaults
|
||||
CGO_ENABLED: "0"
|
||||
|
||||
jobs:
|
||||
test:
|
||||
unit-test:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
@@ -22,6 +24,15 @@ jobs:
|
||||
- run:
|
||||
name: Test
|
||||
command: make test
|
||||
integration-test:
|
||||
<<: *defaults
|
||||
parameters:
|
||||
docker_version:
|
||||
type: string
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker:
|
||||
version: << parameters.docker_version >>
|
||||
- run:
|
||||
name: Integration Test
|
||||
command: make test-integration
|
||||
@@ -54,12 +65,14 @@ jobs:
|
||||
- run:
|
||||
name: Create deb repository
|
||||
command: ci/deploy-deb.sh
|
||||
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
release:
|
||||
jobs:
|
||||
- test
|
||||
jobs:
|
||||
- unit-test
|
||||
- integration-test:
|
||||
docker_version: 18.09.3
|
||||
- release:
|
||||
filters:
|
||||
branches:
|
||||
|
||||
25
README.md
25
README.md
@@ -44,6 +44,7 @@ A Simple and Comprehensive Vulnerability Scanner for Containers, Suitable for CI
|
||||
- [Client/Server](#client--server)
|
||||
- [Server](#server)
|
||||
- [Client](#client)
|
||||
- [Authentication](#authentication)
|
||||
- [Continuous Integration (CI)](#continuous-integration-ci)
|
||||
- [Travis CI](#travis-ci)
|
||||
- [CircleCI](#circleci)
|
||||
@@ -76,7 +77,7 @@ See [here](#continuous-integration-ci) for details.
|
||||
# Features
|
||||
|
||||
- Detect comprehensive vulnerabilities
|
||||
- OS packages (Alpine, **Red Hat Universal Base Image**, Red Hat Enterprise Linux, CentOS, Oracle Linux, Debian, Ubuntu, Amazon Linux 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 and Cargo)
|
||||
- Simple
|
||||
- Specify only an image name
|
||||
@@ -94,6 +95,8 @@ See [here](#continuous-integration-ci) for details.
|
||||
- **Suitable for CI** such as Travis CI, CircleCI, Jenkins, etc.
|
||||
- See [CI Example](#continuous-integration-ci)
|
||||
|
||||
Please see [LICENSE](https://github.com/aquasecurity/trivy/blob/master/LICENSE) for Trivy licensing information. Note that Trivy uses vulnerability information from a variety of sources, some of which are licensed for non-commercial use only.
|
||||
|
||||
# Installation
|
||||
|
||||
## RHEL/CentOS
|
||||
@@ -1098,6 +1101,12 @@ $ trivy server --listen localhost:8080
|
||||
2019-12-12T15:17:56.707+0200 INFO Listening localhost:8080...
|
||||
```
|
||||
|
||||
If you want to accept a connection from outside, you have to specify `0.0.0.0` or your ip address, not `localhost`.
|
||||
|
||||
```
|
||||
$ trivy server --listen 0.0.0.0:8080
|
||||
```
|
||||
|
||||
### Client
|
||||
Then, specify the remote address.
|
||||
```
|
||||
@@ -1124,6 +1133,15 @@ Total: 3 (UNKNOWN: 0, LOW: 1, MEDIUM: 2, HIGH: 0, CRITICAL: 0)
|
||||
```
|
||||
</details>
|
||||
|
||||
### Authentication
|
||||
|
||||
```
|
||||
$ trivy server --listen localhost:8080 --token dummy
|
||||
```
|
||||
|
||||
```
|
||||
$ trivy client --remote http://localhost:8080 --token dummy alpine:3.10
|
||||
```
|
||||
|
||||
### Deprecated options
|
||||
|
||||
@@ -1296,11 +1314,14 @@ The unfixed/unfixable vulnerabilities mean that the patch has not yet been provi
|
||||
| CentOS | 6, 7 | Installed by yum/rpm | YES |
|
||||
| Oracle Linux | 5, 6, 7, 8 | Installed by yum/rpm | NO |
|
||||
| Amazon Linux | 1, 2 | Installed by yum/rpm | NO |
|
||||
| openSUSE Leap | 42, 15 | Installed by zypper/rpm | NO |
|
||||
| SUSE Enterprise Linux | 11, 12, 15 | Installed by zypper/rpm | NO |
|
||||
| Photon OS | 1.0, 2.0, 3.0 | Installed by tdnf/yum/rpm | NO |
|
||||
| Debian GNU/Linux | wheezy, jessie, stretch, buster | Installed by apt/apt-get/dpkg | YES |
|
||||
| Ubuntu | 12.04, 14.04, 16.04, 18.04, 18.10, 19.04 | Installed by apt/apt-get/dpkg | YES |
|
||||
| Distroless | Any | Installed by apt/apt-get/dpkg | YES |
|
||||
|
||||
RHEL, CentOS, Oracle Linux and Amazon Linux package information is stored in a binary format, and Trivy uses the `rpm` executable to parse this information when scanning an image based on RHEL or CentOS. The Trivy container image includes `rpm`, and the installers include it as a dependency. If you installed the `trivy` binary using `wget` or `curl`, or if you build it from source, you will also need to ensure that `rpm` is available.
|
||||
RHEL, CentOS, Oracle Linux, SUSE, Amazon Linux and Photon OS package information is stored in a binary format, and Trivy uses the `rpm` executable to parse this information when scanning an image based on RHEL or CentOS. The Trivy container image includes `rpm`, and the installers include it as a dependency. If you installed the `trivy` binary using `wget` or `curl`, or if you build it from source, you will also need to ensure that `rpm` is available.
|
||||
|
||||
Distroless: https://github.com/GoogleContainerTools/distroless
|
||||
|
||||
|
||||
19
go.mod
19
go.mod
@@ -3,13 +3,16 @@ module github.com/aquasecurity/trivy
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/aquasecurity/fanal v0.0.0-20191104115841-1a8ced6845b7
|
||||
github.com/aquasecurity/fanal v0.0.0-20200112144021-9a35ce3bd793
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20191120190201-a6645984b409
|
||||
github.com/briandowns/spinner v0.0.0-20190319032542-ac46072a5a91
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20191226181755-d6cabf5bc5d1
|
||||
github.com/caarlos0/env/v6 v6.0.0
|
||||
github.com/genuinetools/reg v0.16.1
|
||||
github.com/golang/protobuf v1.3.1
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible
|
||||
github.com/cheggaaa/pb/v3 v3.0.3
|
||||
github.com/docker/docker v0.0.0-20180924202107-a9c061deec0f
|
||||
github.com/genuinetools/reg v0.16.0
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d // indirect
|
||||
github.com/golang/protobuf v1.3.2
|
||||
github.com/google/go-github/v28 v28.1.1
|
||||
github.com/google/wire v0.3.0
|
||||
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d
|
||||
@@ -20,17 +23,15 @@ require (
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/twitchtv/twirp v5.9.0+incompatible
|
||||
github.com/urfave/cli v1.20.0
|
||||
go.etcd.io/bbolt v1.3.3 // indirect
|
||||
go.uber.org/atomic v1.5.1 // indirect
|
||||
go.uber.org/multierr v1.4.0 // indirect
|
||||
go.uber.org/zap v1.13.0
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529
|
||||
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421
|
||||
golang.org/x/sys v0.0.0-20191020152052-9984515f0562 // indirect
|
||||
golang.org/x/tools v0.0.0-20191121040551-947d4aa89328 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.28
|
||||
gopkg.in/yaml.v2 v2.2.4 // indirect
|
||||
k8s.io/utils v0.0.0-20191010214722-8d271d903fe4
|
||||
)
|
||||
|
||||
replace github.com/genuinetools/reg => github.com/tomoyamachi/reg v0.16.1-0.20190706172545-2a2250fd7c00
|
||||
|
||||
160
go.sum
160
go.sum
@@ -8,15 +8,15 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/GoogleCloudPlatform/docker-credential-gcr v1.5.0 h1:wykTgKwhVr2t2qs+xI020s6W5dt614QqCHV+7W9dg64=
|
||||
github.com/GoogleCloudPlatform/docker-credential-gcr v1.5.0/go.mod h1:BB1eHdMLYEFuFdBlRMb0N7YGVdM5s6Pt0njxgvfbGGs=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA=
|
||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||
github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc=
|
||||
github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
|
||||
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
|
||||
@@ -27,59 +27,58 @@ 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/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/aquasecurity/fanal v0.0.0-20190819081512-f04452b627c6/go.mod h1:enEz4FFetw4XAbkffaYgyCVq1556R9Ry+noqT4rq9BE=
|
||||
github.com/aquasecurity/fanal v0.0.0-20191104115841-1a8ced6845b7 h1:CbCusMPZOgrbqiCWEFbWcmBBonllFpMJhtXp9WkyNVQ=
|
||||
github.com/aquasecurity/fanal v0.0.0-20191104115841-1a8ced6845b7/go.mod h1:dD1Ny21eY5FSDyERfUIMwdgYhg6Lnw611VOwDHmTSoQ=
|
||||
github.com/aquasecurity/fanal v0.0.0-20200112144021-9a35ce3bd793 h1:wPGD5cu66RvwRkNULAqOAMbNWFjmYSCJ/mqHJ5rYBN0=
|
||||
github.com/aquasecurity/fanal v0.0.0-20200112144021-9a35ce3bd793/go.mod h1:S2D937GMywJzh6KiLQEyt/0yqmfAngUFvuQ9UmkIZSw=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b h1:55Ulc/gvfWm4ylhVaR7MxOwujRjA6et7KhmUbSgUFf4=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b/go.mod h1:BpNTD9vHfrejKsED9rx04ldM1WIbeyXGYxUrqTVwxVQ=
|
||||
github.com/aquasecurity/trivy v0.1.6/go.mod h1:5hobyhxLzDtxruHzPxpND2PUKOssvGUdE9BocpJUwo4=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20191120190201-a6645984b409 h1:RrFBrw3qZXH/AIEtEYF1WgYhXae3VPPaaPIJic5p1gw=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20191120190201-a6645984b409/go.mod h1:vYzX1UhX0o29E+/nuFJTgUJBM5UA7I/NftnbBcYyYRE=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20191226181755-d6cabf5bc5d1 h1:IVXoVH8ejJuBdxgH/+er2WjBxc0tqIGuBCqI5aWW3A0=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20191226181755-d6cabf5bc5d1/go.mod h1:Uf9bXd50zTHtWTP7+7u5+OFCPtUVrmsS4v0RXd7E5lw=
|
||||
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/araddon/dateparse v0.0.0-20190426192744-0d74ffceef83 h1:ukTLOeMC0aVxbJWVg6hOsVJ0VPIo8w++PbNsze/pqF8=
|
||||
github.com/araddon/dateparse v0.0.0-20190426192744-0d74ffceef83/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI=
|
||||
github.com/aws/aws-sdk-go v1.19.11 h1:tqaTGER6Byw3QvsjGW0p018U2UOqaJPeJuzoaF7jjoQ=
|
||||
github.com/aws/aws-sdk-go v1.19.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.25.31 h1:14mdh3HsTgRekePPkYcCbAaEXJknc3mN7f4XfsiMMDA=
|
||||
github.com/aws/aws-sdk-go v1.25.31/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/briandowns/spinner v0.0.0-20190319032542-ac46072a5a91 h1:GMmnK0dvr0Sf0gx3DvTbln0c8DE07B7sPVD9dgHOqo4=
|
||||
github.com/briandowns/spinner v0.0.0-20190319032542-ac46072a5a91/go.mod h1:hw/JEQBIE+c/BLI4aKM8UU8v+ZqrD3h7HC27kKt8JQU=
|
||||
github.com/caarlos0/env/v6 v6.0.0 h1:NZt6FAoB8ieKO5lEwRdwCzYxWFx7ZYF2R7UcoyaWtyc=
|
||||
github.com/caarlos0/env/v6 v6.0.0/go.mod h1:+wdyOmtjoZIW2GJOc2OYa5NoOFuWD/bIpWqm30NgtRk=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cheggaaa/pb/v3 v3.0.3 h1:8WApbyUmgMOz7WIxJVNK0IRDcRfAmTxcEdi0TuxjdP4=
|
||||
github.com/cheggaaa/pb/v3 v3.0.3/go.mod h1:Pp35CDuiEpHa/ZLGCtBbM6CBwMstv1bJlG884V+73Yc=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/containerd/containerd v1.2.9 h1:6tyNjBmAMG47QuFPIT9LgiiexoVxC6qpTGR+eD0R0Z8=
|
||||
github.com/containerd/containerd v1.2.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/continuity v0.0.0-20180921161001-7f53d412b9eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6 h1:NmTXa/uVnDyp0TY5MKi197+3HWcnYWfnHGyaFthlnGw=
|
||||
github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/coreos/clair v0.0.0-20180919182544-44ae4bc9590a/go.mod h1:uXhHPWAoRqw0jJc2f8RrPCwRhIo9otQ8OEWUFtpCiwA=
|
||||
github.com/coreos/clair v2.0.1-0.20190910143208-94150ab1f4ac+incompatible/go.mod h1:uXhHPWAoRqw0jJc2f8RrPCwRhIo9otQ8OEWUFtpCiwA=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
|
||||
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/docker/cli v0.0.0-20180920165730-54c19e67f69c h1:QlAVcyoF7QQVN7zV+xYBjgwtRVlRU3WCTCpb2mcqQrM=
|
||||
github.com/docker/cli v0.0.0-20180920165730-54c19e67f69c/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v0.0.0-20190913211141-95327f4e6241 h1:btTBgRvrdoe+b7NfX/7PnUbiXzGceLCt09QZkg1bgqA=
|
||||
github.com/docker/cli v0.0.0-20190913211141-95327f4e6241/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v0.0.0-20180920194744-16128bbac47f/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v0.0.0-20180924202107-a9c061deec0f h1:W4fbqg0JUwy6lLesoJaV/rE0fwAmtdtinMa64X1CEh0=
|
||||
github.com/docker/docker v0.0.0-20180924202107-a9c061deec0f/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v1.4.2-0.20190916154449-92cc603036dd h1:kDIT0qjvLHbdL86aa+VteVpVZOR7coIyIejM/o3CwOo=
|
||||
github.com/docker/docker v1.4.2-0.20190916154449-92cc603036dd/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-ce v0.0.0-20180924210327-f53bd8bb8e43 h1:gZ4lWixV821UVbYtr+oz1ZPCHkbtE+ivfmHyZRgyl2Y=
|
||||
github.com/docker/docker-ce v0.0.0-20180924210327-f53bd8bb8e43/go.mod h1:l1FUGRYBvbjnZ8MS6A2xOji4aZFlY/Qmgz7p4oXH7ac=
|
||||
github.com/docker/docker-credential-helpers v0.6.1/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||
github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=
|
||||
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||
github.com/docker/docker-credential-helpers v0.6.2 h1:CrW9H1VMf3a4GrtyAi7IUJjkJVpwBBpX0+mvkvYJaus=
|
||||
github.com/docker/docker-credential-helpers v0.6.2/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||
github.com/docker/go-connections v0.0.0-20180821093606-97c2040d34df/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82 h1:X0fj836zx99zFu83v/M79DuBn84IL/Syx1SY6Y5ZEMA=
|
||||
github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
|
||||
@@ -100,43 +99,40 @@ github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM=
|
||||
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fernet/fernet-go v0.0.0-20180830025343-9eac43b88a5e/go.mod h1:2H9hjfbpSMHwY503FclkV/lZTBh2YlOmLLSda12uL8c=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/genuinetools/pkg v0.0.0-20180910213200-1c141f661797/go.mod h1:XTcrCYlXPxnxL2UpnwuRn7tcaTn9HAhxFoFJucootk8=
|
||||
github.com/genuinetools/pkg v0.0.0-20181022210355-2fcf164d37cb/go.mod h1:XTcrCYlXPxnxL2UpnwuRn7tcaTn9HAhxFoFJucootk8=
|
||||
github.com/genuinetools/reg v0.16.0/go.mod h1:12Fe9EIvK3dG/qWhNk5e9O96I8SGmCKLsJ8GsXUbk+Y=
|
||||
github.com/genuinetools/reg v0.16.1 h1:nZiceimcvxEVtWKSmPtRhEkl2TrxDhrbmYEAbTkKXvo=
|
||||
github.com/genuinetools/reg v0.16.1/go.mod h1:EgA+w+hj3rMsn5zBV5jdWIGsLAsoFIcSy0QlxAXsm5Q=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/gliderlabs/ssh v0.1.3 h1:cBU46h1lYQk5f2Z+jZbewFKy+1zzE2aUX/ilcPDAm9M=
|
||||
github.com/gliderlabs/ssh v0.1.3/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE=
|
||||
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo=
|
||||
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
@@ -154,10 +150,8 @@ github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.11.1/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/gorilla/mux v1.7.1 h1:Dw4jY2nghMMRsh1ol8dv1axHkDwMQK2DHerMNJsIpJU=
|
||||
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
@@ -173,6 +167,7 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e h1:RgQk53JHp/Cjunrr1WlsXSZpqXn+uREuHvUVcK82CV8=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/knqyf263/berkeleydb v0.0.0-20190501065933-fafe01fb9662/go.mod h1:bu1CcN4tUtoRcI/B/RFHhxMNKFHVq/c3SV+UTyduoXg=
|
||||
@@ -187,6 +182,8 @@ github.com/knqyf263/nested v0.0.1 h1:Sv26CegUMhjt19zqbBKntjwESdxe5hxVPSk0+AKjdUc
|
||||
github.com/knqyf263/nested v0.0.1/go.mod h1:zwhsIhMkBg90DTOJQvxPkKIypEHPYkgWHs4gybdlUmk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
@@ -205,30 +202,30 @@ github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-jsonpointer v0.0.0-20180225143300-37667080efed h1:fCWISZq4YN4ulCJx7x0KB15rqxLEe3mtNJL8cSOGKZU=
|
||||
github.com/mattn/go-jsonpointer v0.0.0-20180225143300-37667080efed/go.mod h1:SDJ4hurDYyQ9/7nc+eCYtXqdufgK4Cq9TJlwPklqEYA=
|
||||
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.6 h1:V2iyH+aX9C5fsYCpK60U8BYIvmhqxuOL3JZcqc1NB7k=
|
||||
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE=
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/olekukonko/tablewriter v0.0.2-0.20190607075207-195002e6e56a h1:0LD5FJGQpEyD78OdhX97W75RjYmMjfLPp1ePrk5URxs=
|
||||
github.com/olekukonko/tablewriter v0.0.2-0.20190607075207-195002e6e56a/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2 h1:QhPf3A2AZW3tTGvHPg0TA+CR3oHbVLlXUhlghqISp1I=
|
||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y=
|
||||
@@ -246,40 +243,43 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.0.0-20180924113449-f69c853d21c1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20180920065004-418d78d0b9a7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/httpfs v0.0.0-20181222201310-74dc9339e414/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/simplereach/timeutils v1.2.0/go.mod h1:VVbQDfN/FHRZa1LSqcwo4kNZ62OOyqLLGQKYB3pB0Q8=
|
||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
|
||||
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
|
||||
@@ -291,6 +291,8 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/tomoyamachi/reg v0.16.1-0.20190706172545-2a2250fd7c00 h1:0e4vRd9YqnQBIAIAE39jLKDWffRfJWxloyWwcaMAQho=
|
||||
github.com/tomoyamachi/reg v0.16.1-0.20190706172545-2a2250fd7c00/go.mod h1:RQE7h2jyIxekQZ24/wad0c9RGP+KSq4XzHh7h83ALi8=
|
||||
github.com/twitchtv/twirp v5.9.0+incompatible h1:KBCo4NYCpE9alO1HAEcgninDnw/0AhPT1rZnHkkSqi8=
|
||||
github.com/twitchtv/twirp v5.9.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
@@ -300,8 +302,6 @@ github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70
|
||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||
go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
@@ -321,7 +321,6 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5 h1:bselrhR0Or1vomJZC8ZIjWtbDmn9OYFLX5Ik9alpJpE=
|
||||
@@ -329,7 +328,6 @@ golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaE
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -340,17 +338,17 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180925072008-f04abc6bdfa7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 h1:p9xBe/w/OzkeYVKm234g55gMdD1nSIooTir5kV11kfA=
|
||||
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191108221443-4ba9e2ef068c h1:SRpq/kuj/xNci/RdvEs+RSvpfxqvLAzTKuKGlzoGdZQ=
|
||||
golang.org/x/net v0.0.0-20191108221443-4ba9e2ef068c/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 h1:Wo7BWFiOk0QRFMLYMqJGFMd9CgUAcGx7V+qEg/h5IBI=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -358,13 +356,11 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180925112736-b09afc3d579e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -373,19 +369,24 @@ golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191020152052-9984515f0562 h1:wOweSabW7qssfcg63CEDHHA4zyoqRlGU6eYV7IUMCq0=
|
||||
golang.org/x/sys v0.0.0-20191020152052-9984515f0562/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190506115046-ca7f33d4116e h1:bq5BY1tGuaK8HxuwN6pT6kWgTVLeJ5KwuyBpsl1CZL4=
|
||||
golang.org/x/sys v0.0.0-20190506115046-ca7f33d4116e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 h1:ZBzSG/7F4eNKz2L3GE9o300RX0Az1Bw5HF7PDraD+qU=
|
||||
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
@@ -393,7 +394,7 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190503185657-3b6f9c0030f7/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
|
||||
@@ -411,17 +412,16 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
|
||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180924164928-221a8d4f7494/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107 h1:xtNn7qFlagY2mQNFHMSRPjT2RkOV4OXM7P5TVy9xATo=
|
||||
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.15.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 h1:nfPFGzJkUDX6uBmpN/pSw7MbOAWegH5QDQuoXFHedLg=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
@@ -430,9 +430,7 @@ gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/src-d/go-billy.v4 v4.2.1/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk=
|
||||
gopkg.in/src-d/go-billy.v4 v4.3.0 h1:KtlZ4c1OWbIs4jCv5ZXrTqG8EQocr0g/d4DjNg70aek=
|
||||
gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk=
|
||||
@@ -444,21 +442,19 @@ gopkg.in/src-d/go-git.v4 v4.10.0/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYC
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE=
|
||||
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/utils v0.0.0-20191010214722-8d271d903fe4 h1:Gi+/O1saihwDqnlmC8Vhv1M5Sp4+rbOmK9TbsLn8ZEA=
|
||||
k8s.io/utils v0.0.0-20191010214722-8d271d903fe4/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
|
||||
@@ -20,13 +20,15 @@ import (
|
||||
|
||||
func TestClientServer(t *testing.T) {
|
||||
type args struct {
|
||||
Version string
|
||||
IgnoreUnfixed bool
|
||||
Severity []string
|
||||
IgnoreIDs []string
|
||||
Input string
|
||||
ClientToken string
|
||||
ServerToken string
|
||||
Version string
|
||||
IgnoreUnfixed bool
|
||||
Severity []string
|
||||
IgnoreIDs []string
|
||||
Input string
|
||||
ClientToken string
|
||||
ClientTokenHeader string
|
||||
ServerToken string
|
||||
ServerTokenHeader string
|
||||
}
|
||||
cases := []struct {
|
||||
name string
|
||||
@@ -45,10 +47,12 @@ func TestClientServer(t *testing.T) {
|
||||
{
|
||||
name: "alpine 3.10 integration with token",
|
||||
testArgs: args{
|
||||
Version: "dev",
|
||||
Input: "testdata/fixtures/alpine-310.tar.gz",
|
||||
ClientToken: "token",
|
||||
ServerToken: "token",
|
||||
Version: "dev",
|
||||
Input: "testdata/fixtures/alpine-310.tar.gz",
|
||||
ClientToken: "token",
|
||||
ClientTokenHeader: "Trivy-Token",
|
||||
ServerToken: "token",
|
||||
ServerTokenHeader: "Trivy-Token",
|
||||
},
|
||||
golden: "testdata/alpine-310.json.golden",
|
||||
},
|
||||
@@ -257,13 +261,67 @@ func TestClientServer(t *testing.T) {
|
||||
},
|
||||
golden: "testdata/oraclelinux-8-slim.json.golden",
|
||||
},
|
||||
{
|
||||
name: "opensuse leap 15.1 integration",
|
||||
testArgs: args{
|
||||
Version: "dev",
|
||||
Input: "testdata/fixtures/opensuse-leap-151.tar.gz",
|
||||
},
|
||||
golden: "testdata/opensuse-leap-151.json.golden",
|
||||
},
|
||||
{
|
||||
name: "opensuse leap 42.3 integration",
|
||||
testArgs: args{
|
||||
Version: "dev",
|
||||
Input: "testdata/fixtures/opensuse-leap-423.tar.gz",
|
||||
},
|
||||
golden: "testdata/opensuse-leap-423.json.golden",
|
||||
},
|
||||
{
|
||||
name: "photon 1.0 integration",
|
||||
testArgs: args{
|
||||
Version: "dev",
|
||||
Input: "testdata/fixtures/photon-10.tar.gz",
|
||||
},
|
||||
golden: "testdata/photon-10.json.golden",
|
||||
},
|
||||
{
|
||||
name: "photon 2.0 integration",
|
||||
testArgs: args{
|
||||
Version: "dev",
|
||||
Input: "testdata/fixtures/photon-20.tar.gz",
|
||||
},
|
||||
golden: "testdata/photon-20.json.golden",
|
||||
},
|
||||
{
|
||||
name: "photon 3.0 integration",
|
||||
testArgs: args{
|
||||
Version: "dev",
|
||||
Input: "testdata/fixtures/photon-30.tar.gz",
|
||||
},
|
||||
golden: "testdata/photon-30.json.golden",
|
||||
},
|
||||
{
|
||||
name: "invalid token",
|
||||
testArgs: args{
|
||||
Version: "dev",
|
||||
Input: "testdata/fixtures/distroless-base.tar.gz",
|
||||
ClientToken: "invalidtoken",
|
||||
ServerToken: "token",
|
||||
Version: "dev",
|
||||
Input: "testdata/fixtures/distroless-base.tar.gz",
|
||||
ClientToken: "invalidtoken",
|
||||
ClientTokenHeader: "Trivy-Token",
|
||||
ServerToken: "token",
|
||||
ServerTokenHeader: "Trivy-Token",
|
||||
},
|
||||
wantErr: "twirp error unauthenticated: invalid token",
|
||||
},
|
||||
{
|
||||
name: "invalid token header",
|
||||
testArgs: args{
|
||||
Version: "dev",
|
||||
Input: "testdata/fixtures/distroless-base.tar.gz",
|
||||
ClientToken: "valid-token",
|
||||
ClientTokenHeader: "Trivy-Token",
|
||||
ServerToken: "valid-token",
|
||||
ServerTokenHeader: "Invalid",
|
||||
},
|
||||
wantErr: "twirp error unauthenticated: invalid token",
|
||||
},
|
||||
@@ -283,7 +341,7 @@ func TestClientServer(t *testing.T) {
|
||||
// Setup CLI App
|
||||
app := internal.NewApp(c.testArgs.Version)
|
||||
app.Writer = ioutil.Discard
|
||||
osArgs := setupServer(addr, c.testArgs.ServerToken, cacheDir)
|
||||
osArgs := setupServer(addr, c.testArgs.ServerToken, c.testArgs.ServerTokenHeader, cacheDir)
|
||||
|
||||
// Run Trivy server
|
||||
require.NoError(t, app.Run(osArgs), c.name)
|
||||
@@ -297,7 +355,7 @@ func TestClientServer(t *testing.T) {
|
||||
app.Writer = ioutil.Discard
|
||||
|
||||
osArgs, outputFile, cleanup := setupClient(t, c.testArgs.IgnoreUnfixed, c.testArgs.Severity,
|
||||
c.testArgs.IgnoreIDs, addr, c.testArgs.ClientToken, c.testArgs.Input, cacheDir, c.golden)
|
||||
c.testArgs.IgnoreIDs, addr, c.testArgs.ClientToken, c.testArgs.ClientTokenHeader, c.testArgs.Input, cacheDir, c.golden)
|
||||
defer cleanup()
|
||||
|
||||
// Run Trivy client
|
||||
@@ -322,16 +380,16 @@ func TestClientServer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func setupServer(addr, token, cacheDir string) []string {
|
||||
func setupServer(addr, token, tokenHeader, cacheDir string) []string {
|
||||
osArgs := []string{"trivy", "server", "--skip-update", "--cache-dir", cacheDir, "--listen", addr}
|
||||
if token != "" {
|
||||
osArgs = append(osArgs, []string{"--token", token}...)
|
||||
osArgs = append(osArgs, []string{"--token", token, "--token-header", tokenHeader}...)
|
||||
}
|
||||
return osArgs
|
||||
}
|
||||
|
||||
func setupClient(t *testing.T, ignoreUnfixed bool, severity, ignoreIDs []string,
|
||||
addr, token, input, cacheDir, golden string) ([]string, string, func()) {
|
||||
addr, token, tokenHeader, input, cacheDir, golden string) ([]string, string, func()) {
|
||||
t.Helper()
|
||||
osArgs := []string{"trivy", "client", "--cache-dir", cacheDir,
|
||||
"--format", "json", "--remote", "http://" + addr}
|
||||
@@ -355,7 +413,7 @@ func setupClient(t *testing.T, ignoreUnfixed bool, severity, ignoreIDs []string,
|
||||
osArgs = append(osArgs, []string{"--ignorefile", trivyIgnore}...)
|
||||
}
|
||||
if token != "" {
|
||||
osArgs = append(osArgs, []string{"--token", token}...)
|
||||
osArgs = append(osArgs, []string{"--token", token, "--token-header", tokenHeader}...)
|
||||
}
|
||||
if input != "" {
|
||||
osArgs = append(osArgs, []string{"--input", input}...)
|
||||
|
||||
318
integration/docker_engine_test.go
Normal file
318
integration/docker_engine_test.go
Normal file
@@ -0,0 +1,318 @@
|
||||
// +build integration
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/aquasecurity/trivy/internal"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRun_WithDockerEngine(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
imageTag string
|
||||
invalidImage bool
|
||||
ignoreUnfixed bool
|
||||
severity []string
|
||||
ignoreIDs []string
|
||||
testfile string
|
||||
expectedOutputFile string
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "happy path, valid image path, alpine:3.10",
|
||||
imageTag: "alpine:3.10",
|
||||
expectedOutputFile: "testdata/alpine-310.json.golden",
|
||||
testfile: "testdata/fixtures/alpine-310.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, alpine:3.10, ignore unfixed",
|
||||
ignoreUnfixed: true,
|
||||
imageTag: "alpine:3.10",
|
||||
expectedOutputFile: "testdata/alpine-310-ignore-unfixed.json.golden",
|
||||
testfile: "testdata/fixtures/alpine-310.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, alpine:3.10, ignore unfixed, with medium and high severity",
|
||||
ignoreUnfixed: true,
|
||||
severity: []string{"MEDIUM", "HIGH"},
|
||||
imageTag: "alpine:3.10",
|
||||
expectedOutputFile: "testdata/alpine-310-medium-high.json.golden",
|
||||
testfile: "testdata/fixtures/alpine-310.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, alpine:3.10, with .trivyignore",
|
||||
imageTag: "alpine:3.10",
|
||||
ignoreIDs: []string{"CVE-2019-1549", "CVE-2019-1563"},
|
||||
expectedOutputFile: "testdata/alpine-310-ignore-cveids.json.golden",
|
||||
testfile: "testdata/fixtures/alpine-310.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, alpine:3.9",
|
||||
imageTag: "alpine:3.9",
|
||||
expectedOutputFile: "testdata/alpine-39.json.golden",
|
||||
testfile: "testdata/fixtures/alpine-39.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, amazonlinux:1",
|
||||
imageTag: "amazonlinux:1",
|
||||
expectedOutputFile: "testdata/amazon-1.json.golden",
|
||||
testfile: "testdata/fixtures/amazon-1.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, amazonlinux:2",
|
||||
imageTag: "amazonlinux:2",
|
||||
expectedOutputFile: "testdata/amazon-2.json.golden",
|
||||
testfile: "testdata/fixtures/amazon-2.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, centos:6",
|
||||
imageTag: "centos:6",
|
||||
expectedOutputFile: "testdata/centos-6.json.golden",
|
||||
testfile: "testdata/fixtures/centos-6.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, centos:6",
|
||||
imageTag: "centos:6",
|
||||
expectedOutputFile: "testdata/centos-6.json.golden",
|
||||
testfile: "testdata/fixtures/centos-6.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, centos:7",
|
||||
imageTag: "centos:7",
|
||||
expectedOutputFile: "testdata/centos-7.json.golden",
|
||||
testfile: "testdata/fixtures/centos-7.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, centos:7, with --ignore-unfixed option",
|
||||
imageTag: "centos:7",
|
||||
ignoreUnfixed: true,
|
||||
expectedOutputFile: "testdata/centos-7-ignore-unfixed.json.golden",
|
||||
testfile: "testdata/fixtures/centos-7.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, centos:7, with --ignore-unfixed option, with low and high severity",
|
||||
imageTag: "centos:7",
|
||||
ignoreUnfixed: true,
|
||||
severity: []string{"LOW", "HIGH"},
|
||||
expectedOutputFile: "testdata/centos-7-low-high.json.golden",
|
||||
testfile: "testdata/fixtures/centos-7.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, debian:buster",
|
||||
imageTag: "debian:buster",
|
||||
expectedOutputFile: "testdata/debian-buster.json.golden",
|
||||
testfile: "testdata/fixtures/debian-buster.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, debian:buster, with --ignore-unfixed option",
|
||||
ignoreUnfixed: true,
|
||||
imageTag: "debian:buster",
|
||||
expectedOutputFile: "testdata/debian-buster-ignore-unfixed.json.golden",
|
||||
testfile: "testdata/fixtures/debian-buster.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, debian:stretch",
|
||||
imageTag: "debian:stretch",
|
||||
expectedOutputFile: "testdata/debian-stretch.json.golden",
|
||||
testfile: "testdata/fixtures/debian-stretch.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, distroless:base",
|
||||
imageTag: "gcr.io/distroless/base:latest",
|
||||
expectedOutputFile: "testdata/distroless-base.json.golden",
|
||||
testfile: "testdata/fixtures/distroless-base.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, distroless:base",
|
||||
imageTag: "gcr.io/distroless/base:latest",
|
||||
expectedOutputFile: "testdata/distroless-base.json.golden",
|
||||
testfile: "testdata/fixtures/distroless-base.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, distroless:base, with --ignore-unfixed option",
|
||||
imageTag: "gcr.io/distroless/base:latest",
|
||||
ignoreUnfixed: true,
|
||||
expectedOutputFile: "testdata/distroless-base-ignore-unfixed.json.golden",
|
||||
testfile: "testdata/fixtures/distroless-base.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, distroless:python2.7",
|
||||
imageTag: "gcr.io/distroless/python2.7:latest",
|
||||
expectedOutputFile: "testdata/distroless-python27.json.golden",
|
||||
testfile: "testdata/fixtures/distroless-python27.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, oraclelinux:6-slim",
|
||||
imageTag: "oraclelinux:6-slim",
|
||||
expectedOutputFile: "testdata/oraclelinux-6-slim.json.golden",
|
||||
testfile: "testdata/fixtures/oraclelinux-6-slim.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, oraclelinux:7-slim",
|
||||
imageTag: "oraclelinux:7-slim",
|
||||
expectedOutputFile: "testdata/oraclelinux-7-slim.json.golden",
|
||||
testfile: "testdata/fixtures/oraclelinux-7-slim.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, oraclelinux:8-slim",
|
||||
imageTag: "oraclelinux:8-slim",
|
||||
expectedOutputFile: "testdata/oraclelinux-8-slim.json.golden",
|
||||
testfile: "testdata/fixtures/oraclelinux-8-slim.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, ubuntu:16.04",
|
||||
imageTag: "ubuntu:16.04",
|
||||
expectedOutputFile: "testdata/ubuntu-1604.json.golden",
|
||||
testfile: "testdata/fixtures/ubuntu-1604.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, ubuntu:18.04",
|
||||
imageTag: "ubuntu:18.04",
|
||||
expectedOutputFile: "testdata/ubuntu-1804.json.golden",
|
||||
testfile: "testdata/fixtures/ubuntu-1804.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, ubuntu:18.04, with --ignore-unfixed option",
|
||||
imageTag: "ubuntu:18.04",
|
||||
ignoreUnfixed: true,
|
||||
expectedOutputFile: "testdata/ubuntu-1804-ignore-unfixed.json.golden",
|
||||
testfile: "testdata/fixtures/ubuntu-1804.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, registry.redhat.io/ubi7",
|
||||
imageTag: "registry.redhat.io/ubi7",
|
||||
expectedOutputFile: "testdata/ubi-7.json.golden",
|
||||
testfile: "testdata/fixtures/ubi-7.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, opensuse leap 15.1",
|
||||
imageTag: "opensuse/leap:latest",
|
||||
expectedOutputFile: "testdata/opensuse-leap-151.json.golden",
|
||||
testfile: "testdata/fixtures/opensuse-leap-151.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, opensuse leap 42.3",
|
||||
imageTag: "opensuse/leap:42.3",
|
||||
expectedOutputFile: "testdata/opensuse-leap-423.json.golden",
|
||||
testfile: "testdata/fixtures/opensuse-leap-423.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, photon 1.0",
|
||||
imageTag: "photon:1.0-20190823",
|
||||
expectedOutputFile: "testdata/photon-10.json.golden",
|
||||
testfile: "testdata/fixtures/photon-10.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, photon 2.0",
|
||||
imageTag: "photon:2.0-20190726",
|
||||
expectedOutputFile: "testdata/photon-20.json.golden",
|
||||
testfile: "testdata/fixtures/photon-20.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "happy path, valid image path, photon 3.0",
|
||||
imageTag: "photon:3.0-20190823",
|
||||
expectedOutputFile: "testdata/photon-30.json.golden",
|
||||
testfile: "testdata/fixtures/photon-30.tar.gz",
|
||||
},
|
||||
{
|
||||
name: "sad path, invalid image",
|
||||
invalidImage: true,
|
||||
testfile: "badimage:latest",
|
||||
expectedError: "error in image scan: failed to analyze image: failed to extract files: failed to get the v2 manifest: Get https://registry-1.docker.io/v2/library/badimage/manifests/latest: http: non-successful response (status=401 body=\"{\\\"errors\\\":[{\\\"code\\\":\\\"UNAUTHORIZED\\\",\\\"message\\\":\\\"authentication required\\\",\\\"detail\\\":[{\\\"Type\\\":\\\"repository\\\",\\\"Class\\\":\\\"\\\",\\\"Name\\\":\\\"library/badimage\\\",\\\"Action\\\":\\\"pull\\\"}]}]}\\n\")",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Copy DB file
|
||||
cacheDir := gunzipDB()
|
||||
defer os.RemoveAll(cacheDir)
|
||||
|
||||
ctx := context.Background()
|
||||
defer ctx.Done()
|
||||
|
||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||
require.NoError(t, err, tc.name)
|
||||
|
||||
if !tc.invalidImage {
|
||||
testfile, err := os.Open(tc.testfile)
|
||||
require.NoError(t, err, tc.name)
|
||||
|
||||
// ensure image doesnt already exists
|
||||
_, _ = cli.ImageRemove(ctx, tc.testfile, types.ImageRemoveOptions{
|
||||
Force: true,
|
||||
PruneChildren: true,
|
||||
})
|
||||
|
||||
// load image into docker engine
|
||||
_, err = cli.ImageLoad(ctx, testfile, true)
|
||||
require.NoError(t, err, tc.name)
|
||||
|
||||
// tag our image to something unique
|
||||
err = cli.ImageTag(ctx, tc.imageTag, tc.testfile)
|
||||
require.NoError(t, err, tc.name)
|
||||
}
|
||||
|
||||
of, err := ioutil.TempFile("", "integration-docker-engine-output-file-*")
|
||||
require.NoError(t, err, tc.name)
|
||||
defer os.Remove(of.Name())
|
||||
|
||||
// run trivy
|
||||
app := internal.NewApp("dev")
|
||||
trivyArgs := []string{"trivy", "--skip-update", "--cache-dir", cacheDir, "--format=json"}
|
||||
if tc.ignoreUnfixed {
|
||||
trivyArgs = append(trivyArgs, "--ignore-unfixed")
|
||||
}
|
||||
if len(tc.severity) != 0 {
|
||||
trivyArgs = append(trivyArgs,
|
||||
[]string{"--severity", strings.Join(tc.severity, ",")}...,
|
||||
)
|
||||
}
|
||||
if len(tc.ignoreIDs) != 0 {
|
||||
trivyIgnore := ".trivyignore"
|
||||
err := ioutil.WriteFile(trivyIgnore, []byte(strings.Join(tc.ignoreIDs, "\n")), 0444)
|
||||
assert.NoError(t, err, "failed to write .trivyignore")
|
||||
defer os.Remove(trivyIgnore)
|
||||
}
|
||||
if !tc.invalidImage {
|
||||
trivyArgs = append(trivyArgs, "--output", of.Name())
|
||||
}
|
||||
trivyArgs = append(trivyArgs, tc.testfile)
|
||||
|
||||
err = app.Run(trivyArgs)
|
||||
switch {
|
||||
case tc.expectedError != "":
|
||||
assert.Equal(t, tc.expectedError, err.Error(), tc.name)
|
||||
default:
|
||||
assert.NoError(t, err, tc.name)
|
||||
}
|
||||
|
||||
if !tc.invalidImage {
|
||||
// check for vulnerability output info
|
||||
got, err := ioutil.ReadAll(of)
|
||||
assert.NoError(t, err, tc.name)
|
||||
want, err := ioutil.ReadFile(tc.expectedOutputFile)
|
||||
assert.NoError(t, err, tc.name)
|
||||
assert.JSONEq(t, string(want), string(got), tc.name)
|
||||
|
||||
// cleanup
|
||||
_, err = cli.ImageRemove(ctx, tc.testfile, types.ImageRemoveOptions{
|
||||
Force: true,
|
||||
PruneChildren: true,
|
||||
})
|
||||
assert.NoError(t, err, tc.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -291,6 +291,56 @@ func TestRun_WithTar(t *testing.T) {
|
||||
},
|
||||
golden: "testdata/oraclelinux-8-slim.json.golden",
|
||||
},
|
||||
{
|
||||
name: "opensuse leap 15.1 integration",
|
||||
testArgs: args{
|
||||
Version: "dev",
|
||||
SkipUpdate: true,
|
||||
Format: "json",
|
||||
Input: "testdata/fixtures/opensuse-leap-151.tar.gz",
|
||||
},
|
||||
golden: "testdata/opensuse-leap-151.json.golden",
|
||||
},
|
||||
{
|
||||
name: "opensuse leap 42.3 integration",
|
||||
testArgs: args{
|
||||
Version: "dev",
|
||||
SkipUpdate: true,
|
||||
Format: "json",
|
||||
Input: "testdata/fixtures/opensuse-leap-423.tar.gz",
|
||||
},
|
||||
golden: "testdata/opensuse-leap-423.json.golden",
|
||||
},
|
||||
{
|
||||
name: "photon 1.0 integration",
|
||||
testArgs: args{
|
||||
Version: "dev",
|
||||
SkipUpdate: true,
|
||||
Format: "json",
|
||||
Input: "testdata/fixtures/photon-10.tar.gz",
|
||||
},
|
||||
golden: "testdata/photon-10.json.golden",
|
||||
},
|
||||
{
|
||||
name: "photon 2.0 integration",
|
||||
testArgs: args{
|
||||
Version: "dev",
|
||||
SkipUpdate: true,
|
||||
Format: "json",
|
||||
Input: "testdata/fixtures/photon-20.tar.gz",
|
||||
},
|
||||
golden: "testdata/photon-20.json.golden",
|
||||
},
|
||||
{
|
||||
name: "photon 3.0 integration",
|
||||
testArgs: args{
|
||||
Version: "dev",
|
||||
SkipUpdate: true,
|
||||
Format: "json",
|
||||
Input: "testdata/fixtures/photon-30.tar.gz",
|
||||
},
|
||||
golden: "testdata/photon-30.json.golden",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
|
||||
103
integration/testdata/opensuse-leap-151.json.golden
vendored
Normal file
103
integration/testdata/opensuse-leap-151.json.golden
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
[
|
||||
{
|
||||
"Target": "testdata/fixtures/opensuse-leap-151.tar.gz (opensuse.leap 15.1)",
|
||||
"Vulnerabilities": [
|
||||
{
|
||||
"VulnerabilityID": "openSUSE-SU-2019:2596-1",
|
||||
"PkgName": "cpio",
|
||||
"InstalledVersion": "2.12-lp151.2.68",
|
||||
"FixedVersion": "2.12-lp151.3.3.1",
|
||||
"Title": "Security update for cpio",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-11/msg00076.html",
|
||||
"https://www.suse.com/support/security/rating/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "openSUSE-SU-2019:2611-1",
|
||||
"PkgName": "libidn2-0",
|
||||
"InstalledVersion": "2.0.4-lp151.2.3",
|
||||
"FixedVersion": "2.2.0-lp151.3.3.1",
|
||||
"Title": "Security update for libidn2",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-12/msg00009.html",
|
||||
"https://www.suse.com/support/security/rating/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "openSUSE-SU-2019:2551-1",
|
||||
"PkgName": "libncurses6",
|
||||
"InstalledVersion": "6.1-lp151.5.41",
|
||||
"FixedVersion": "6.1-lp151.6.3.1",
|
||||
"Title": "Security update for ncurses",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-11/msg00059.html",
|
||||
"https://www.suse.com/support/security/rating/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "openSUSE-SU-2019:2689-1",
|
||||
"PkgName": "libssh4",
|
||||
"InstalledVersion": "0.8.7-lp151.2.3.1",
|
||||
"FixedVersion": "0.8.7-lp151.2.6.1",
|
||||
"Title": "Security update for libssh",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-12/msg00033.html",
|
||||
"https://www.suse.com/support/security/rating/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "openSUSE-SU-2019:2612-1",
|
||||
"PkgName": "libxml2-2",
|
||||
"InstalledVersion": "2.9.7-lp151.5.3.1",
|
||||
"FixedVersion": "2.9.7-lp151.5.6.1",
|
||||
"Title": "Security update for libxml2",
|
||||
"Severity": "UNKNOWN",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-12/msg00010.html",
|
||||
"https://www.suse.com/support/security/rating/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "openSUSE-SU-2019:2551-1",
|
||||
"PkgName": "ncurses-utils",
|
||||
"InstalledVersion": "6.1-lp151.5.41",
|
||||
"FixedVersion": "6.1-lp151.6.3.1",
|
||||
"Title": "Security update for ncurses",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-11/msg00059.html",
|
||||
"https://www.suse.com/support/security/rating/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "openSUSE-SU-2019:2672-1",
|
||||
"PkgName": "permissions",
|
||||
"InstalledVersion": "20181116-lp151.4.6.1",
|
||||
"FixedVersion": "20181116-lp151.4.9.1",
|
||||
"Title": "Security update for permissions",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-12/msg00024.html",
|
||||
"https://www.suse.com/support/security/rating/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "openSUSE-SU-2019:2551-1",
|
||||
"PkgName": "terminfo-base",
|
||||
"InstalledVersion": "6.1-lp151.5.41",
|
||||
"FixedVersion": "6.1-lp151.6.3.1",
|
||||
"Title": "Security update for ncurses",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-11/msg00059.html",
|
||||
"https://www.suse.com/support/security/rating/"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
6
integration/testdata/opensuse-leap-423.json.golden
vendored
Normal file
6
integration/testdata/opensuse-leap-423.json.golden
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
[
|
||||
{
|
||||
"Target": "testdata/fixtures/opensuse-leap-423.tar.gz (opensuse.leap 42.3)",
|
||||
"Vulnerabilities": null
|
||||
}
|
||||
]
|
||||
@@ -162,5 +162,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
]
|
||||
@@ -855,5 +855,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
]
|
||||
@@ -3,4 +3,4 @@
|
||||
"Target": "testdata/fixtures/oraclelinux-8-slim.tar.gz (oracle 8.0)",
|
||||
"Vulnerabilities": null
|
||||
}
|
||||
]
|
||||
]
|
||||
61
integration/testdata/photon-10.json.golden
vendored
Normal file
61
integration/testdata/photon-10.json.golden
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
[
|
||||
{
|
||||
"Target": "testdata/fixtures/photon-10.tar.gz (photon 1.0)",
|
||||
"Vulnerabilities": [
|
||||
{
|
||||
"VulnerabilityID": "CVE-2012-6711",
|
||||
"PkgName": "bash",
|
||||
"InstalledVersion": "4.3.48-3.ph1",
|
||||
"FixedVersion": "4.3.48-4.ph1",
|
||||
"Title": "bash: heap-based buffer overflow during echo of unsupported characters",
|
||||
"Description": "A heap-based buffer overflow exists in GNU Bash before 4.3 when wide characters, not supported by the current locale set in the LC_CTYPE environment variable, are printed through the echo built-in function. A local attacker, who can provide data to print through the \"echo -e\" built-in function, may use this flaw to crash a script or execute code with the privileges of the bash process. This occurs because ansicstr() in lib/sh/strtrans.c mishandles u32cconv().",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"http://git.savannah.gnu.org/cgit/bash.git/commit/?h=devel\u0026id=863d31ae775d56b785dc5b0105b6d251515d81d5",
|
||||
"http://www.securityfocus.com/bid/108824",
|
||||
"https://bugzilla.redhat.com/show_bug.cgi?id=1721071",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-6711"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-1563",
|
||||
"PkgName": "openssl",
|
||||
"InstalledVersion": "1.0.2s-1.ph1",
|
||||
"FixedVersion": "1.0.2t-1.ph1",
|
||||
"Title": "openssl: information disclosure in PKCS7_dataDecode and CMS_decrypt_set1_pkey",
|
||||
"Description": "In situations where an attacker receives automated notification of the success or failure of a decryption attempt an attacker, after sending a very large number of messages to be decrypted, can recover a CMS/PKCS7 transported encryption key or decrypt any RSA encrypted message that was encrypted with the public RSA key, using a Bleichenbacher padding oracle attack. Applications are not affected if they use a certificate together with the private RSA key to the CMS_decrypt or PKCS7_decrypt functions to select the correct recipient info to decrypt. Fixed in OpenSSL 1.1.1d (Affected 1.1.1-1.1.1c). Fixed in OpenSSL 1.1.0l (Affected 1.1.0-1.1.0k). Fixed in OpenSSL 1.0.2t (Affected 1.0.2-1.0.2s).",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"http://packetstormsecurity.com/files/154467/Slackware-Security-Advisory-openssl-Updates.html",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-1563",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=08229ad838c50f644d7e928e2eef147b4308ad64",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=631f94db0065c78181ca9ba5546ebc8bb3884b97",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=e21f8cf78a125cd3c8c0d1a1a6c8bb0b901f893f",
|
||||
"https://seclists.org/bugtraq/2019/Sep/25",
|
||||
"https://security.netapp.com/advisory/ntap-20190919-0002/",
|
||||
"https://www.openssl.org/news/secadv/20190910.txt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-1547",
|
||||
"PkgName": "openssl",
|
||||
"InstalledVersion": "1.0.2s-1.ph1",
|
||||
"FixedVersion": "1.0.2t-1.ph1",
|
||||
"Title": "openssl: side-channel weak encryption vulnerability",
|
||||
"Description": "Normally in OpenSSL EC groups always have a co-factor present and this is used in side channel resistant code paths. However, in some cases, it is possible to construct a group using explicit parameters (instead of using a named curve). In those cases it is possible that such a group does not have the cofactor present. This can occur even where all the parameters match a known named curve. If such a curve is used then OpenSSL falls back to non-side channel resistant code paths which may result in full key recovery during an ECDSA signature operation. In order to be vulnerable an attacker would have to have the ability to time the creation of a large number of signatures where explicit parameters with no co-factor present are in use by an application using libcrypto. For the avoidance of doubt libssl is not vulnerable because explicit parameters are never used. Fixed in OpenSSL 1.1.1d (Affected 1.1.1-1.1.1c). Fixed in OpenSSL 1.1.0l (Affected 1.1.0-1.1.0k). Fixed in OpenSSL 1.0.2t (Affected 1.0.2-1.0.2s).",
|
||||
"Severity": "LOW",
|
||||
"References": [
|
||||
"http://packetstormsecurity.com/files/154467/Slackware-Security-Advisory-openssl-Updates.html",
|
||||
"https://arxiv.org/abs/1909.01785",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-1547",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=21c856b75d81eff61aa63b4f036bb64a85bf6d46",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=30c22fa8b1d840036b8e203585738df62a03cec8",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=7c1709c2da5414f5b6133d00a03fc8c5bf996c7a",
|
||||
"https://seclists.org/bugtraq/2019/Sep/25",
|
||||
"https://security.netapp.com/advisory/ntap-20190919-0002/",
|
||||
"https://www.openssl.org/news/secadv/20190910.txt"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
227
integration/testdata/photon-20.json.golden
vendored
Normal file
227
integration/testdata/photon-20.json.golden
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
[
|
||||
{
|
||||
"Target": "testdata/fixtures/photon-20.tar.gz (photon 2.0)",
|
||||
"Vulnerabilities": [
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-5481",
|
||||
"PkgName": "curl",
|
||||
"InstalledVersion": "7.59.0-7.ph2",
|
||||
"FixedVersion": "7.59.0-9.ph2",
|
||||
"Title": "curl: double free due to subsequent call of realloc()",
|
||||
"Description": "Double-free vulnerability in the FTP-kerberos code in cURL 7.52.0 to 7.65.3.",
|
||||
"Severity": "HIGH",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00048.html",
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00055.html",
|
||||
"https://curl.haxx.se/docs/CVE-2019-5481.html",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/RGDVKSLY5JUNJRLYRUA6CXGQ2LM63XC3/",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/UA7KDM2WPM5CJDDGOEGFV6SSGD2J7RNT/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-5482",
|
||||
"PkgName": "curl",
|
||||
"InstalledVersion": "7.59.0-7.ph2",
|
||||
"FixedVersion": "7.59.0-9.ph2",
|
||||
"Title": "curl: heap buffer overflow in function tftp_receive_packet()",
|
||||
"Description": "Heap buffer overflow in the TFTP protocol handler in cURL 7.19.4 to 7.65.3.",
|
||||
"Severity": "HIGH",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00048.html",
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00055.html",
|
||||
"https://curl.haxx.se/docs/CVE-2019-5482.html",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5482",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/RGDVKSLY5JUNJRLYRUA6CXGQ2LM63XC3/",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/UA7KDM2WPM5CJDDGOEGFV6SSGD2J7RNT/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2018-16890",
|
||||
"PkgName": "curl",
|
||||
"InstalledVersion": "7.59.0-7.ph2",
|
||||
"FixedVersion": "7.59.0-8.ph2",
|
||||
"Title": "curl: NTLM type-2 heap out-of-bounds buffer read",
|
||||
"Description": "libcurl versions from 7.36.0 to before 7.64.0 is vulnerable to a heap buffer out-of-bounds read. The function handling incoming NTLM type-2 messages (`lib/vauth/ntlm.c:ntlm_decode_type2_target`) does not validate incoming data correctly and is subject to an integer overflow vulnerability. Using that overflow, a malicious or broken NTLM server could trick libcurl to accept a bad length + offset combination that would lead to a buffer read out-of-bounds.",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"http://www.securityfocus.com/bid/106947",
|
||||
"https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2018-16890",
|
||||
"https://cert-portal.siemens.com/productcert/pdf/ssa-436177.pdf",
|
||||
"https://curl.haxx.se/docs/CVE-2018-16890.html",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-16890",
|
||||
"https://lists.apache.org/thread.html/8338a0f605bdbb3a6098bb76f666a95fc2b2f53f37fa1ecc89f1146f@%3Cdevnull.infra.apache.org%3E",
|
||||
"https://security.netapp.com/advisory/ntap-20190315-0001/",
|
||||
"https://usn.ubuntu.com/3882-1/",
|
||||
"https://www.debian.org/security/2019/dsa-4386",
|
||||
"https://www.oracle.com/technetwork/security-advisory/cpuapr2019-5072813.html",
|
||||
"https://www.oracle.com/technetwork/security-advisory/cpujul2019-5072835.html"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-5481",
|
||||
"PkgName": "curl-libs",
|
||||
"InstalledVersion": "7.59.0-7.ph2",
|
||||
"FixedVersion": "7.59.0-9.ph2",
|
||||
"Title": "curl: double free due to subsequent call of realloc()",
|
||||
"Description": "Double-free vulnerability in the FTP-kerberos code in cURL 7.52.0 to 7.65.3.",
|
||||
"Severity": "HIGH",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00048.html",
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00055.html",
|
||||
"https://curl.haxx.se/docs/CVE-2019-5481.html",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/RGDVKSLY5JUNJRLYRUA6CXGQ2LM63XC3/",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/UA7KDM2WPM5CJDDGOEGFV6SSGD2J7RNT/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-5482",
|
||||
"PkgName": "curl-libs",
|
||||
"InstalledVersion": "7.59.0-7.ph2",
|
||||
"FixedVersion": "7.59.0-9.ph2",
|
||||
"Title": "curl: heap buffer overflow in function tftp_receive_packet()",
|
||||
"Description": "Heap buffer overflow in the TFTP protocol handler in cURL 7.19.4 to 7.65.3.",
|
||||
"Severity": "HIGH",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00048.html",
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00055.html",
|
||||
"https://curl.haxx.se/docs/CVE-2019-5482.html",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5482",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/RGDVKSLY5JUNJRLYRUA6CXGQ2LM63XC3/",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/UA7KDM2WPM5CJDDGOEGFV6SSGD2J7RNT/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2018-16890",
|
||||
"PkgName": "curl-libs",
|
||||
"InstalledVersion": "7.59.0-7.ph2",
|
||||
"FixedVersion": "7.59.0-8.ph2",
|
||||
"Title": "curl: NTLM type-2 heap out-of-bounds buffer read",
|
||||
"Description": "libcurl versions from 7.36.0 to before 7.64.0 is vulnerable to a heap buffer out-of-bounds read. The function handling incoming NTLM type-2 messages (`lib/vauth/ntlm.c:ntlm_decode_type2_target`) does not validate incoming data correctly and is subject to an integer overflow vulnerability. Using that overflow, a malicious or broken NTLM server could trick libcurl to accept a bad length + offset combination that would lead to a buffer read out-of-bounds.",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"http://www.securityfocus.com/bid/106947",
|
||||
"https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2018-16890",
|
||||
"https://cert-portal.siemens.com/productcert/pdf/ssa-436177.pdf",
|
||||
"https://curl.haxx.se/docs/CVE-2018-16890.html",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-16890",
|
||||
"https://lists.apache.org/thread.html/8338a0f605bdbb3a6098bb76f666a95fc2b2f53f37fa1ecc89f1146f@%3Cdevnull.infra.apache.org%3E",
|
||||
"https://security.netapp.com/advisory/ntap-20190315-0001/",
|
||||
"https://usn.ubuntu.com/3882-1/",
|
||||
"https://www.debian.org/security/2019/dsa-4386",
|
||||
"https://www.oracle.com/technetwork/security-advisory/cpuapr2019-5072813.html",
|
||||
"https://www.oracle.com/technetwork/security-advisory/cpujul2019-5072835.html"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-5094",
|
||||
"PkgName": "e2fsprogs-libs",
|
||||
"InstalledVersion": "1.43.4-2.ph2",
|
||||
"FixedVersion": "1.43.4-3.ph2",
|
||||
"Description": "An exploitable code execution vulnerability exists in the quota file functionality of E2fsprogs 1.45.3. A specially crafted ext4 partition can cause an out-of-bounds write on the heap, resulting in code execution. An attacker can corrupt a partition to trigger this vulnerability.",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5094",
|
||||
"https://lists.debian.org/debian-lts-announce/2019/09/msg00029.html",
|
||||
"https://seclists.org/bugtraq/2019/Sep/58",
|
||||
"https://talosintelligence.com/vulnerability_reports/TALOS-2019-0887",
|
||||
"https://usn.ubuntu.com/4142-2/",
|
||||
"https://www.debian.org/security/2019/dsa-4535"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2018-20843",
|
||||
"PkgName": "expat-libs",
|
||||
"InstalledVersion": "2.2.4-1.ph2",
|
||||
"FixedVersion": "2.2.4-2.ph2",
|
||||
"Title": "expat: large number of colons in input makes parser consume high amount of resources, leading to DoS",
|
||||
"Description": "In libexpat in Expat before 2.2.7, XML input including XML names that contain a large number of colons could make the XML parser consume a high amount of RAM and CPU resources while processing (enough to be usable for denial-of-service attacks).",
|
||||
"Severity": "HIGH",
|
||||
"References": [
|
||||
"https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=5226",
|
||||
"https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=931031",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-20843",
|
||||
"https://github.com/libexpat/libexpat/blob/R_2_2_7/expat/Changes",
|
||||
"https://github.com/libexpat/libexpat/issues/186",
|
||||
"https://github.com/libexpat/libexpat/pull/262",
|
||||
"https://github.com/libexpat/libexpat/pull/262/commits/11f8838bf99ea0a6f0b76f9760c43704d00c4ff6",
|
||||
"https://lists.debian.org/debian-lts-announce/2019/06/msg00028.html",
|
||||
"https://seclists.org/bugtraq/2019/Jun/39",
|
||||
"https://security.netapp.com/advisory/ntap-20190703-0001/",
|
||||
"https://usn.ubuntu.com/4040-1/",
|
||||
"https://usn.ubuntu.com/4040-2/",
|
||||
"https://www.debian.org/security/2019/dsa-4472"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-13115",
|
||||
"PkgName": "libssh2",
|
||||
"InstalledVersion": "1.8.2-1.ph2",
|
||||
"FixedVersion": "1.9.0-1.ph2",
|
||||
"Title": "libssh2: integer overflow in kex_method_diffie_hellman_group_exchange_sha256_key_exchange in kex.c leads to out-of-bounds write",
|
||||
"Description": "In libssh2 before 1.9.0, kex_method_diffie_hellman_group_exchange_sha256_key_exchange in kex.c has an integer overflow that could lead to an out-of-bounds read in the way packets are read from the server. A remote attacker who compromises a SSH server may be able to disclose sensitive information or cause a denial of service condition on the client system when a user connects to the server. This is related to an _libssh2_check_length mistake, and is different from the various issues fixed in 1.8.1, such as CVE-2019-3855.",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"https://blog.semmle.com/libssh2-integer-overflow/",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-13115",
|
||||
"https://github.com/libssh2/libssh2/compare/02ecf17...42d37aa",
|
||||
"https://github.com/libssh2/libssh2/pull/350",
|
||||
"https://libssh2.org/changes.html",
|
||||
"https://lists.debian.org/debian-lts-announce/2019/07/msg00024.html"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-1563",
|
||||
"PkgName": "openssl",
|
||||
"InstalledVersion": "1.0.2s-1.ph2",
|
||||
"FixedVersion": "1.0.2t-1.ph2",
|
||||
"Title": "openssl: information disclosure in PKCS7_dataDecode and CMS_decrypt_set1_pkey",
|
||||
"Description": "In situations where an attacker receives automated notification of the success or failure of a decryption attempt an attacker, after sending a very large number of messages to be decrypted, can recover a CMS/PKCS7 transported encryption key or decrypt any RSA encrypted message that was encrypted with the public RSA key, using a Bleichenbacher padding oracle attack. Applications are not affected if they use a certificate together with the private RSA key to the CMS_decrypt or PKCS7_decrypt functions to select the correct recipient info to decrypt. Fixed in OpenSSL 1.1.1d (Affected 1.1.1-1.1.1c). Fixed in OpenSSL 1.1.0l (Affected 1.1.0-1.1.0k). Fixed in OpenSSL 1.0.2t (Affected 1.0.2-1.0.2s).",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"http://packetstormsecurity.com/files/154467/Slackware-Security-Advisory-openssl-Updates.html",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-1563",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=08229ad838c50f644d7e928e2eef147b4308ad64",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=631f94db0065c78181ca9ba5546ebc8bb3884b97",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=e21f8cf78a125cd3c8c0d1a1a6c8bb0b901f893f",
|
||||
"https://seclists.org/bugtraq/2019/Sep/25",
|
||||
"https://security.netapp.com/advisory/ntap-20190919-0002/",
|
||||
"https://www.openssl.org/news/secadv/20190910.txt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-1547",
|
||||
"PkgName": "openssl",
|
||||
"InstalledVersion": "1.0.2s-1.ph2",
|
||||
"FixedVersion": "1.0.2t-1.ph2",
|
||||
"Title": "openssl: side-channel weak encryption vulnerability",
|
||||
"Description": "Normally in OpenSSL EC groups always have a co-factor present and this is used in side channel resistant code paths. However, in some cases, it is possible to construct a group using explicit parameters (instead of using a named curve). In those cases it is possible that such a group does not have the cofactor present. This can occur even where all the parameters match a known named curve. If such a curve is used then OpenSSL falls back to non-side channel resistant code paths which may result in full key recovery during an ECDSA signature operation. In order to be vulnerable an attacker would have to have the ability to time the creation of a large number of signatures where explicit parameters with no co-factor present are in use by an application using libcrypto. For the avoidance of doubt libssl is not vulnerable because explicit parameters are never used. Fixed in OpenSSL 1.1.1d (Affected 1.1.1-1.1.1c). Fixed in OpenSSL 1.1.0l (Affected 1.1.0-1.1.0k). Fixed in OpenSSL 1.0.2t (Affected 1.0.2-1.0.2s).",
|
||||
"Severity": "LOW",
|
||||
"References": [
|
||||
"http://packetstormsecurity.com/files/154467/Slackware-Security-Advisory-openssl-Updates.html",
|
||||
"https://arxiv.org/abs/1909.01785",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-1547",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=21c856b75d81eff61aa63b4f036bb64a85bf6d46",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=30c22fa8b1d840036b8e203585738df62a03cec8",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=7c1709c2da5414f5b6133d00a03fc8c5bf996c7a",
|
||||
"https://seclists.org/bugtraq/2019/Sep/25",
|
||||
"https://security.netapp.com/advisory/ntap-20190919-0002/",
|
||||
"https://www.openssl.org/news/secadv/20190910.txt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-16168",
|
||||
"PkgName": "sqlite-libs",
|
||||
"InstalledVersion": "3.27.2-3.ph2",
|
||||
"FixedVersion": "3.27.2-5.ph2",
|
||||
"Description": "In SQLite through 3.29.0, whereLoopAddBtreeIndex in sqlite3.c can crash a browser or other application because of missing validation of a sqlite_stat1 sz field, aka a \"severe division by zero in the query planner.\"",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"https://security.netapp.com/advisory/ntap-20190926-0003/",
|
||||
"https://www.mail-archive.com/sqlite-users@mailinglists.sqlite.org/msg116312.html",
|
||||
"https://www.sqlite.org/src/info/e4598ecbdd18bd82945f6029013296690e719a62",
|
||||
"https://www.sqlite.org/src/timeline?c=98357d8c1263920b"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
142
integration/testdata/photon-30.json.golden
vendored
Normal file
142
integration/testdata/photon-30.json.golden
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
[
|
||||
{
|
||||
"Target": "testdata/fixtures/photon-30.tar.gz (photon 3.0)",
|
||||
"Vulnerabilities": [
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-5481",
|
||||
"PkgName": "curl",
|
||||
"InstalledVersion": "7.61.1-4.ph3",
|
||||
"FixedVersion": "7.61.1-5.ph3",
|
||||
"Title": "curl: double free due to subsequent call of realloc()",
|
||||
"Description": "Double-free vulnerability in the FTP-kerberos code in cURL 7.52.0 to 7.65.3.",
|
||||
"Severity": "HIGH",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00048.html",
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00055.html",
|
||||
"https://curl.haxx.se/docs/CVE-2019-5481.html",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/RGDVKSLY5JUNJRLYRUA6CXGQ2LM63XC3/",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/UA7KDM2WPM5CJDDGOEGFV6SSGD2J7RNT/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-5482",
|
||||
"PkgName": "curl",
|
||||
"InstalledVersion": "7.61.1-4.ph3",
|
||||
"FixedVersion": "7.61.1-5.ph3",
|
||||
"Title": "curl: heap buffer overflow in function tftp_receive_packet()",
|
||||
"Description": "Heap buffer overflow in the TFTP protocol handler in cURL 7.19.4 to 7.65.3.",
|
||||
"Severity": "HIGH",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00048.html",
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00055.html",
|
||||
"https://curl.haxx.se/docs/CVE-2019-5482.html",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5482",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/RGDVKSLY5JUNJRLYRUA6CXGQ2LM63XC3/",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/UA7KDM2WPM5CJDDGOEGFV6SSGD2J7RNT/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-5481",
|
||||
"PkgName": "curl-libs",
|
||||
"InstalledVersion": "7.61.1-4.ph3",
|
||||
"FixedVersion": "7.61.1-5.ph3",
|
||||
"Title": "curl: double free due to subsequent call of realloc()",
|
||||
"Description": "Double-free vulnerability in the FTP-kerberos code in cURL 7.52.0 to 7.65.3.",
|
||||
"Severity": "HIGH",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00048.html",
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00055.html",
|
||||
"https://curl.haxx.se/docs/CVE-2019-5481.html",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/RGDVKSLY5JUNJRLYRUA6CXGQ2LM63XC3/",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/UA7KDM2WPM5CJDDGOEGFV6SSGD2J7RNT/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-5482",
|
||||
"PkgName": "curl-libs",
|
||||
"InstalledVersion": "7.61.1-4.ph3",
|
||||
"FixedVersion": "7.61.1-5.ph3",
|
||||
"Title": "curl: heap buffer overflow in function tftp_receive_packet()",
|
||||
"Description": "Heap buffer overflow in the TFTP protocol handler in cURL 7.19.4 to 7.65.3.",
|
||||
"Severity": "HIGH",
|
||||
"References": [
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00048.html",
|
||||
"http://lists.opensuse.org/opensuse-security-announce/2019-09/msg00055.html",
|
||||
"https://curl.haxx.se/docs/CVE-2019-5482.html",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5482",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/RGDVKSLY5JUNJRLYRUA6CXGQ2LM63XC3/",
|
||||
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/UA7KDM2WPM5CJDDGOEGFV6SSGD2J7RNT/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-5094",
|
||||
"PkgName": "e2fsprogs-libs",
|
||||
"InstalledVersion": "1.44.3-2.ph3",
|
||||
"FixedVersion": "1.44.3-3.ph3",
|
||||
"Description": "An exploitable code execution vulnerability exists in the quota file functionality of E2fsprogs 1.45.3. A specially crafted ext4 partition can cause an out-of-bounds write on the heap, resulting in code execution. An attacker can corrupt a partition to trigger this vulnerability.",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5094",
|
||||
"https://lists.debian.org/debian-lts-announce/2019/09/msg00029.html",
|
||||
"https://seclists.org/bugtraq/2019/Sep/58",
|
||||
"https://talosintelligence.com/vulnerability_reports/TALOS-2019-0887",
|
||||
"https://usn.ubuntu.com/4142-2/",
|
||||
"https://www.debian.org/security/2019/dsa-4535"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-1563",
|
||||
"PkgName": "openssl",
|
||||
"InstalledVersion": "1.0.2s-1.ph3",
|
||||
"FixedVersion": "1.0.2t-1.ph3",
|
||||
"Title": "openssl: information disclosure in PKCS7_dataDecode and CMS_decrypt_set1_pkey",
|
||||
"Description": "In situations where an attacker receives automated notification of the success or failure of a decryption attempt an attacker, after sending a very large number of messages to be decrypted, can recover a CMS/PKCS7 transported encryption key or decrypt any RSA encrypted message that was encrypted with the public RSA key, using a Bleichenbacher padding oracle attack. Applications are not affected if they use a certificate together with the private RSA key to the CMS_decrypt or PKCS7_decrypt functions to select the correct recipient info to decrypt. Fixed in OpenSSL 1.1.1d (Affected 1.1.1-1.1.1c). Fixed in OpenSSL 1.1.0l (Affected 1.1.0-1.1.0k). Fixed in OpenSSL 1.0.2t (Affected 1.0.2-1.0.2s).",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"http://packetstormsecurity.com/files/154467/Slackware-Security-Advisory-openssl-Updates.html",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-1563",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=08229ad838c50f644d7e928e2eef147b4308ad64",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=631f94db0065c78181ca9ba5546ebc8bb3884b97",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=e21f8cf78a125cd3c8c0d1a1a6c8bb0b901f893f",
|
||||
"https://seclists.org/bugtraq/2019/Sep/25",
|
||||
"https://security.netapp.com/advisory/ntap-20190919-0002/",
|
||||
"https://www.openssl.org/news/secadv/20190910.txt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-1547",
|
||||
"PkgName": "openssl",
|
||||
"InstalledVersion": "1.0.2s-1.ph3",
|
||||
"FixedVersion": "1.0.2t-1.ph3",
|
||||
"Title": "openssl: side-channel weak encryption vulnerability",
|
||||
"Description": "Normally in OpenSSL EC groups always have a co-factor present and this is used in side channel resistant code paths. However, in some cases, it is possible to construct a group using explicit parameters (instead of using a named curve). In those cases it is possible that such a group does not have the cofactor present. This can occur even where all the parameters match a known named curve. If such a curve is used then OpenSSL falls back to non-side channel resistant code paths which may result in full key recovery during an ECDSA signature operation. In order to be vulnerable an attacker would have to have the ability to time the creation of a large number of signatures where explicit parameters with no co-factor present are in use by an application using libcrypto. For the avoidance of doubt libssl is not vulnerable because explicit parameters are never used. Fixed in OpenSSL 1.1.1d (Affected 1.1.1-1.1.1c). Fixed in OpenSSL 1.1.0l (Affected 1.1.0-1.1.0k). Fixed in OpenSSL 1.0.2t (Affected 1.0.2-1.0.2s).",
|
||||
"Severity": "LOW",
|
||||
"References": [
|
||||
"http://packetstormsecurity.com/files/154467/Slackware-Security-Advisory-openssl-Updates.html",
|
||||
"https://arxiv.org/abs/1909.01785",
|
||||
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-1547",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=21c856b75d81eff61aa63b4f036bb64a85bf6d46",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=30c22fa8b1d840036b8e203585738df62a03cec8",
|
||||
"https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=7c1709c2da5414f5b6133d00a03fc8c5bf996c7a",
|
||||
"https://seclists.org/bugtraq/2019/Sep/25",
|
||||
"https://security.netapp.com/advisory/ntap-20190919-0002/",
|
||||
"https://www.openssl.org/news/secadv/20190910.txt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-16168",
|
||||
"PkgName": "sqlite-libs",
|
||||
"InstalledVersion": "3.27.2-3.ph3",
|
||||
"FixedVersion": "3.27.2-5.ph3",
|
||||
"Description": "In SQLite through 3.29.0, whereLoopAddBtreeIndex in sqlite3.c can crash a browser or other application because of missing validation of a sqlite_stat1 sz field, aka a \"severe division by zero in the query planner.\"",
|
||||
"Severity": "MEDIUM",
|
||||
"References": [
|
||||
"https://security.netapp.com/advisory/ntap-20190926-0003/",
|
||||
"https://www.mail-archive.com/sqlite-users@mailinglists.sqlite.org/msg116312.html",
|
||||
"https://www.sqlite.org/src/info/e4598ecbdd18bd82945f6029013296690e719a62",
|
||||
"https://www.sqlite.org/src/timeline?c=98357d8c1263920b"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
BIN
integration/testdata/trivy.db.gz
vendored
BIN
integration/testdata/trivy.db.gz
vendored
Binary file not shown.
@@ -4,15 +4,14 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aquasecurity/trivy/internal/client"
|
||||
"github.com/aquasecurity/trivy/internal/server"
|
||||
|
||||
"github.com/aquasecurity/trivy/internal/standalone"
|
||||
"github.com/aquasecurity/trivy/pkg/vulnerability"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
"github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/internal/client"
|
||||
"github.com/aquasecurity/trivy/internal/server"
|
||||
"github.com/aquasecurity/trivy/internal/standalone"
|
||||
"github.com/aquasecurity/trivy/pkg/utils"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/aquasecurity/trivy/pkg/vulnerability"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -115,7 +114,7 @@ var (
|
||||
cacheDirFlag = cli.StringFlag{
|
||||
Name: "cache-dir",
|
||||
Value: utils.DefaultCacheDir(),
|
||||
Usage: "use as cache directory, but image cache is stored in /path/to/cache/fanal",
|
||||
Usage: "cache directory",
|
||||
EnvVar: "TRIVY_CACHE_DIR",
|
||||
}
|
||||
|
||||
@@ -144,6 +143,13 @@ var (
|
||||
Usage: "for authentication",
|
||||
EnvVar: "TRIVY_TOKEN",
|
||||
}
|
||||
|
||||
tokenHeader = cli.StringFlag{
|
||||
Name: "token-header",
|
||||
Value: "Trivy-Token",
|
||||
Usage: "specify a header name for token",
|
||||
EnvVar: "TRIVY_TOKEN_HEADER",
|
||||
}
|
||||
)
|
||||
|
||||
func NewApp(version string) *cli.App {
|
||||
@@ -243,12 +249,18 @@ func NewClientCommand() cli.Command {
|
||||
|
||||
// original flags
|
||||
token,
|
||||
tokenHeader,
|
||||
cli.StringFlag{
|
||||
Name: "remote",
|
||||
Value: "http://localhost:4954",
|
||||
Usage: "server address",
|
||||
EnvVar: "TRIVY_REMOTE",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "custom-headers",
|
||||
Usage: "custom headers",
|
||||
EnvVar: "TRIVY_CUSTOM_HEADERS",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -269,6 +281,7 @@ func NewServerCommand() cli.Command {
|
||||
|
||||
// original flags
|
||||
token,
|
||||
tokenHeader,
|
||||
cli.StringFlag{
|
||||
Name: "listen",
|
||||
Value: "localhost:4954",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -12,7 +13,6 @@ import (
|
||||
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/utils"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -37,8 +37,11 @@ type Config struct {
|
||||
IgnoreUnfixed bool
|
||||
ExitCode int
|
||||
|
||||
RemoteAddr string
|
||||
Token string
|
||||
RemoteAddr string
|
||||
token string
|
||||
tokenHeader string
|
||||
customHeaders []string
|
||||
CustomHeaders http.Header
|
||||
|
||||
// these variables are generated by Init()
|
||||
ImageName string
|
||||
@@ -77,8 +80,10 @@ func New(c *cli.Context) (Config, error) {
|
||||
IgnoreUnfixed: c.Bool("ignore-unfixed"),
|
||||
ExitCode: c.Int("exit-code"),
|
||||
|
||||
RemoteAddr: c.String("remote"),
|
||||
Token: c.String("token"),
|
||||
RemoteAddr: c.String("remote"),
|
||||
token: c.String("token"),
|
||||
tokenHeader: c.String("token-header"),
|
||||
customHeaders: c.StringSlice("custom-headers"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -86,9 +91,11 @@ func (c *Config) Init() (err error) {
|
||||
c.Severities = c.splitSeverity(c.severities)
|
||||
c.VulnType = strings.Split(c.vulnType, ",")
|
||||
c.AppVersion = c.context.App.Version
|
||||
c.CustomHeaders = splitCustomHeaders(c.customHeaders)
|
||||
|
||||
if c.Quiet {
|
||||
utils.Quiet = true
|
||||
// add token to custom headers
|
||||
if c.token != "" {
|
||||
c.CustomHeaders.Set(c.tokenHeader, c.token)
|
||||
}
|
||||
|
||||
// --clear-cache doesn't conduct the scan
|
||||
@@ -140,3 +147,16 @@ func (c *Config) splitSeverity(severity string) []dbTypes.Severity {
|
||||
}
|
||||
return severities
|
||||
}
|
||||
|
||||
func splitCustomHeaders(headers []string) http.Header {
|
||||
result := make(http.Header)
|
||||
for _, header := range headers {
|
||||
// e.g. x-api-token:XXX
|
||||
s := strings.SplitN(header, ":", 2)
|
||||
if len(s) != 2 {
|
||||
continue
|
||||
}
|
||||
result.Set(s[0], s[1])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ package config
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -83,6 +85,8 @@ func TestConfig_Init(t *testing.T) {
|
||||
onlyUpdate string
|
||||
refresh bool
|
||||
autoRefresh bool
|
||||
token string
|
||||
tokenHeader string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -95,20 +99,27 @@ func TestConfig_Init(t *testing.T) {
|
||||
{
|
||||
name: "happy path",
|
||||
fields: fields{
|
||||
severities: "CRITICAL",
|
||||
vulnType: "os",
|
||||
Quiet: true,
|
||||
severities: "CRITICAL",
|
||||
vulnType: "os",
|
||||
Quiet: true,
|
||||
token: "foobar",
|
||||
tokenHeader: "Trivy-Token",
|
||||
},
|
||||
args: []string{"alpine:3.10"},
|
||||
want: Config{
|
||||
AppVersion: "0.0.0",
|
||||
Severities: []dbTypes.Severity{dbTypes.SeverityCritical},
|
||||
severities: "CRITICAL",
|
||||
ImageName: "alpine:3.10",
|
||||
VulnType: []string{"os"},
|
||||
vulnType: "os",
|
||||
Output: os.Stdout,
|
||||
Quiet: true,
|
||||
AppVersion: "0.0.0",
|
||||
Severities: []dbTypes.Severity{dbTypes.SeverityCritical},
|
||||
severities: "CRITICAL",
|
||||
ImageName: "alpine:3.10",
|
||||
VulnType: []string{"os"},
|
||||
vulnType: "os",
|
||||
Output: os.Stdout,
|
||||
Quiet: true,
|
||||
token: "foobar",
|
||||
tokenHeader: "Trivy-Token",
|
||||
CustomHeaders: http.Header{
|
||||
"Trivy-Token": []string{"foobar"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -122,13 +133,14 @@ func TestConfig_Init(t *testing.T) {
|
||||
"unknown severity option: unknown severity: INVALID",
|
||||
},
|
||||
want: Config{
|
||||
AppVersion: "0.0.0",
|
||||
Severities: []dbTypes.Severity{dbTypes.SeverityCritical, dbTypes.SeverityUnknown},
|
||||
severities: "CRITICAL,INVALID",
|
||||
ImageName: "centos:7",
|
||||
VulnType: []string{"os", "library"},
|
||||
vulnType: "os,library",
|
||||
Output: os.Stdout,
|
||||
AppVersion: "0.0.0",
|
||||
Severities: []dbTypes.Severity{dbTypes.SeverityCritical, dbTypes.SeverityUnknown},
|
||||
severities: "CRITICAL,INVALID",
|
||||
ImageName: "centos:7",
|
||||
VulnType: []string{"os", "library"},
|
||||
vulnType: "os,library",
|
||||
Output: os.Stdout,
|
||||
CustomHeaders: make(http.Header),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -143,13 +155,14 @@ func TestConfig_Init(t *testing.T) {
|
||||
"You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed",
|
||||
},
|
||||
want: Config{
|
||||
AppVersion: "0.0.0",
|
||||
Severities: []dbTypes.Severity{dbTypes.SeverityLow},
|
||||
severities: "LOW",
|
||||
ImageName: "gcr.io/distroless/base",
|
||||
VulnType: []string{"os", "library"},
|
||||
vulnType: "os,library",
|
||||
Output: os.Stdout,
|
||||
AppVersion: "0.0.0",
|
||||
Severities: []dbTypes.Severity{dbTypes.SeverityLow},
|
||||
severities: "LOW",
|
||||
ImageName: "gcr.io/distroless/base",
|
||||
VulnType: []string{"os", "library"},
|
||||
vulnType: "os,library",
|
||||
Output: os.Stdout,
|
||||
CustomHeaders: make(http.Header),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -200,6 +213,8 @@ func TestConfig_Init(t *testing.T) {
|
||||
ExitCode: tt.fields.ExitCode,
|
||||
ImageName: tt.fields.ImageName,
|
||||
Output: tt.fields.Output,
|
||||
token: tt.fields.token,
|
||||
tokenHeader: tt.fields.tokenHeader,
|
||||
}
|
||||
|
||||
err := c.Init()
|
||||
@@ -227,3 +242,32 @@ func TestConfig_Init(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_splitCustomHeaders(t *testing.T) {
|
||||
type args struct {
|
||||
headers []string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want http.Header
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
args: args{
|
||||
headers: []string{"x-api-token:foo bar", "Authorization:user:password"},
|
||||
},
|
||||
want: http.Header{
|
||||
"X-Api-Token": []string{"foo bar"},
|
||||
"Authorization": []string{"user:password"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := splitCustomHeaders(tt.args.headers); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("splitCustomHeaders() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"github.com/aquasecurity/fanal/cache"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client/library"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner"
|
||||
@@ -10,7 +11,8 @@ import (
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
func initializeScanner(ospkgToken ospkg.Token, libToken library.Token, ospkgURL ospkg.RemoteURL, libURL library.RemoteURL) scanner.Scanner {
|
||||
func initializeScanner(cacheClient cache.Cache, ospkgCustomHeaders ospkg.CustomHeaders, libraryCustomHeaders library.CustomHeaders,
|
||||
ospkgURL ospkg.RemoteURL, libURL library.RemoteURL) scanner.Scanner {
|
||||
wire.Build(scanner.ClientSet)
|
||||
return scanner.Scanner{}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@ import (
|
||||
"github.com/urfave/cli"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/fanal/cache"
|
||||
"github.com/aquasecurity/trivy/internal/client/config"
|
||||
"github.com/aquasecurity/trivy/internal/operation"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/report"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client/library"
|
||||
@@ -35,17 +37,23 @@ func run(c config.Config) (err error) {
|
||||
|
||||
// configure cache dir
|
||||
utils.SetCacheDir(c.CacheDir)
|
||||
cacheClient := cache.Initialize(c.CacheDir)
|
||||
cacheOperation := operation.NewCache(cacheClient)
|
||||
log.Logger.Debugf("cache dir: %s", utils.CacheDir())
|
||||
|
||||
if c.ClearCache {
|
||||
return cacheOperation.ClearImages()
|
||||
}
|
||||
|
||||
scanOptions := types.ScanOptions{
|
||||
VulnType: c.VulnType,
|
||||
Timeout: c.Timeout,
|
||||
RemoteURL: c.RemoteAddr,
|
||||
Token: c.Token,
|
||||
}
|
||||
log.Logger.Debugf("Vulnerability type: %s", scanOptions.VulnType)
|
||||
|
||||
scanner := initializeScanner(ospkg.Token(c.Token), library.Token(c.Token),
|
||||
scanner := initializeScanner(cacheClient,
|
||||
ospkg.CustomHeaders(c.CustomHeaders), library.CustomHeaders(c.CustomHeaders),
|
||||
ospkg.RemoteURL(c.RemoteAddr), library.RemoteURL(c.RemoteAddr))
|
||||
results, err := scanner.ScanImage(c.ImageName, c.Input, scanOptions)
|
||||
if err != nil {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"github.com/aquasecurity/fanal/cache"
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client/library"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client/ospkg"
|
||||
@@ -17,14 +18,14 @@ import (
|
||||
|
||||
// Injectors from inject.go:
|
||||
|
||||
func initializeScanner(ospkgToken ospkg.Token, libToken library.Token, ospkgURL ospkg.RemoteURL, libURL library.RemoteURL) scanner.Scanner {
|
||||
func initializeScanner(cacheClient cache.Cache, ospkgCustomHeaders ospkg.CustomHeaders, libraryCustomHeaders library.CustomHeaders, ospkgURL ospkg.RemoteURL, libURL library.RemoteURL) scanner.Scanner {
|
||||
osDetector := ospkg.NewProtobufClient(ospkgURL)
|
||||
detector := ospkg.NewDetector(ospkgToken, osDetector)
|
||||
detector := ospkg.NewDetector(ospkgCustomHeaders, osDetector)
|
||||
ospkgScanner := ospkg2.NewScanner(detector)
|
||||
libDetector := library.NewProtobufClient(libURL)
|
||||
libraryDetector := library.NewDetector(libToken, libDetector)
|
||||
libraryDetector := library.NewDetector(libraryCustomHeaders, libDetector)
|
||||
libraryScanner := library2.NewScanner(libraryDetector)
|
||||
scannerScanner := scanner.NewScanner(ospkgScanner, libraryScanner)
|
||||
scannerScanner := scanner.NewScanner(cacheClient, ospkgScanner, libraryScanner)
|
||||
return scannerScanner
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
func initializeDBClient() db.Client {
|
||||
func initializeDBClient(quiet bool) db.Client {
|
||||
wire.Build(db.SuperSet)
|
||||
return db.Client{}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/google/wire"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/fanal/cache"
|
||||
@@ -12,27 +13,47 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/utils"
|
||||
)
|
||||
|
||||
func Reset() (err error) {
|
||||
log.Logger.Info("Resetting...")
|
||||
if err = cache.Clear(); err != nil {
|
||||
return xerrors.New("failed to remove image layer cache")
|
||||
var SuperSet = wire.NewSet(
|
||||
cache.Initialize,
|
||||
NewCache,
|
||||
)
|
||||
|
||||
type Cache struct {
|
||||
client cache.Cache
|
||||
}
|
||||
|
||||
func NewCache(client cache.Cache) Cache {
|
||||
return Cache{client: client}
|
||||
}
|
||||
|
||||
func (c Cache) Reset() (err error) {
|
||||
if err := c.ClearDB(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.ClearImages(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c Cache) ClearDB() (err error) {
|
||||
log.Logger.Info("Removing DB file...")
|
||||
if err = os.RemoveAll(utils.CacheDir()); err != nil {
|
||||
return xerrors.New("failed to remove cache")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ClearCache() error {
|
||||
func (c Cache) ClearImages() error {
|
||||
log.Logger.Info("Removing image caches...")
|
||||
if err := cache.Clear(); err != nil {
|
||||
if err := c.client.Clear(); err != nil {
|
||||
return xerrors.New("failed to remove image layer cache")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DownloadDB(appVersion, cacheDir string, light, skipUpdate bool) error {
|
||||
client := initializeDBClient()
|
||||
func DownloadDB(appVersion, cacheDir string, quiet, light, skipUpdate bool) error {
|
||||
client := initializeDBClient(quiet)
|
||||
ctx := context.Background()
|
||||
needsUpdate, err := client.NeedsUpdate(ctx, appVersion, light, skipUpdate)
|
||||
if err != nil {
|
||||
@@ -44,6 +65,7 @@ func DownloadDB(appVersion, cacheDir string, light, skipUpdate bool) error {
|
||||
if err = db.Close(); err != nil {
|
||||
return xerrors.Errorf("failed db close: %w", err)
|
||||
}
|
||||
log.Logger.Info("Downloading DB...")
|
||||
if err := client.Download(ctx, cacheDir, light); err != nil {
|
||||
return xerrors.Errorf("failed to download vulnerability DB: %w", err)
|
||||
}
|
||||
|
||||
@@ -9,15 +9,17 @@ import (
|
||||
db2 "github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/github"
|
||||
"github.com/aquasecurity/trivy/pkg/indicator"
|
||||
"k8s.io/utils/clock"
|
||||
)
|
||||
|
||||
// Injectors from inject.go:
|
||||
|
||||
func initializeDBClient() db.Client {
|
||||
func initializeDBClient(quiet bool) db.Client {
|
||||
config := db2.Config{}
|
||||
client := github.NewClient()
|
||||
progressBar := indicator.NewProgressBar(quiet)
|
||||
realClock := clock.RealClock{}
|
||||
dbClient := db.NewClient(config, client, realClock)
|
||||
dbClient := db.NewClient(config, client, progressBar, realClock)
|
||||
return dbClient
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@ package config
|
||||
import (
|
||||
"github.com/urfave/cli"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/utils"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -17,8 +15,9 @@ type Config struct {
|
||||
DownloadDBOnly bool
|
||||
SkipUpdate bool
|
||||
|
||||
Listen string
|
||||
Token string
|
||||
Listen string
|
||||
Token string
|
||||
TokenHeader string
|
||||
|
||||
// these variables are generated by Init()
|
||||
AppVersion string
|
||||
@@ -38,6 +37,7 @@ func New(c *cli.Context) Config {
|
||||
SkipUpdate: c.Bool("skip-update"),
|
||||
Listen: c.String("listen"),
|
||||
Token: c.String("token"),
|
||||
TokenHeader: c.String("token-header"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,8 +48,5 @@ func (c *Config) Init() (err error) {
|
||||
|
||||
c.AppVersion = c.context.App.Version
|
||||
|
||||
// A server always suppresses a progress bar
|
||||
utils.Quiet = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/server"
|
||||
"github.com/urfave/cli"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/internal/operation"
|
||||
"github.com/aquasecurity/trivy/internal/server/config"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/server"
|
||||
"github.com/aquasecurity/trivy/pkg/utils"
|
||||
"github.com/urfave/cli"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
func Run(ctx *cli.Context) error {
|
||||
@@ -30,8 +30,10 @@ func run(c config.Config) (err error) {
|
||||
utils.SetCacheDir(c.CacheDir)
|
||||
log.Logger.Debugf("cache dir: %s", utils.CacheDir())
|
||||
|
||||
// server doesn't have image cache
|
||||
cacheOperation := operation.NewCache(nil)
|
||||
if c.Reset {
|
||||
return operation.Reset()
|
||||
return cacheOperation.ClearDB()
|
||||
}
|
||||
|
||||
if err = db.Init(c.CacheDir); err != nil {
|
||||
@@ -39,7 +41,7 @@ func run(c config.Config) (err error) {
|
||||
}
|
||||
|
||||
// download the database file
|
||||
if err = operation.DownloadDB(c.AppVersion, c.CacheDir, false, c.SkipUpdate); err != nil {
|
||||
if err = operation.DownloadDB(c.AppVersion, c.CacheDir, true, false, c.SkipUpdate); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/utils"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -109,10 +108,6 @@ func (c *Config) Init() (err error) {
|
||||
c.VulnType = strings.Split(c.vulnType, ",")
|
||||
c.AppVersion = c.context.App.Version
|
||||
|
||||
if c.Quiet || c.NoProgress {
|
||||
utils.Quiet = true
|
||||
}
|
||||
|
||||
// --clear-cache, --download-db-only and --reset don't conduct the scan
|
||||
if c.ClearCache || c.DownloadDBOnly || c.Reset {
|
||||
return nil
|
||||
|
||||
@@ -3,12 +3,19 @@
|
||||
package standalone
|
||||
|
||||
import (
|
||||
"github.com/aquasecurity/fanal/cache"
|
||||
"github.com/aquasecurity/trivy/internal/operation"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner"
|
||||
"github.com/aquasecurity/trivy/pkg/vulnerability"
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
func initializeScanner() scanner.Scanner {
|
||||
func initializeCacheClient(cacheDir string) (operation.Cache, error) {
|
||||
wire.Build(operation.SuperSet)
|
||||
return operation.Cache{}, nil
|
||||
}
|
||||
|
||||
func initializeScanner(c cache.Cache) scanner.Scanner {
|
||||
wire.Build(scanner.StandaloneSet)
|
||||
return scanner.Scanner{}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
l "log"
|
||||
"os"
|
||||
|
||||
"github.com/aquasecurity/fanal/cache"
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/internal/operation"
|
||||
"github.com/aquasecurity/trivy/internal/standalone/config"
|
||||
@@ -35,14 +36,15 @@ func run(c config.Config) (err error) {
|
||||
|
||||
// configure cache dir
|
||||
utils.SetCacheDir(c.CacheDir)
|
||||
cacheClient := cache.Initialize(c.CacheDir)
|
||||
cacheOperation := operation.NewCache(cacheClient)
|
||||
log.Logger.Debugf("cache dir: %s", utils.CacheDir())
|
||||
|
||||
if c.Reset {
|
||||
return operation.Reset()
|
||||
return cacheOperation.Reset()
|
||||
}
|
||||
|
||||
if c.ClearCache {
|
||||
return operation.ClearCache()
|
||||
return cacheOperation.ClearImages()
|
||||
}
|
||||
|
||||
if err = db.Init(c.CacheDir); err != nil {
|
||||
@@ -50,7 +52,8 @@ func run(c config.Config) (err error) {
|
||||
}
|
||||
|
||||
// download the database file
|
||||
if err = operation.DownloadDB(c.AppVersion, c.CacheDir, c.Light, c.SkipUpdate); err != nil {
|
||||
noProgress := c.Quiet || c.NoProgress
|
||||
if err = operation.DownloadDB(c.AppVersion, c.CacheDir, noProgress, c.Light, c.SkipUpdate); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -64,7 +67,7 @@ func run(c config.Config) (err error) {
|
||||
}
|
||||
log.Logger.Debugf("Vulnerability type: %s", scanOptions.VulnType)
|
||||
|
||||
scanner := initializeScanner()
|
||||
scanner := initializeScanner(cacheClient)
|
||||
results, err := scanner.ScanImage(c.ImageName, c.Input, scanOptions)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error in image scan: %w", err)
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
package standalone
|
||||
|
||||
import (
|
||||
"github.com/aquasecurity/fanal/cache"
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/internal/operation"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/library"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner"
|
||||
@@ -17,13 +19,19 @@ import (
|
||||
|
||||
// Injectors from inject.go:
|
||||
|
||||
func initializeScanner() scanner.Scanner {
|
||||
func initializeCacheClient(cacheDir string) (operation.Cache, error) {
|
||||
cacheCache := cache.Initialize(cacheDir)
|
||||
operationCache := operation.NewCache(cacheCache)
|
||||
return operationCache, nil
|
||||
}
|
||||
|
||||
func initializeScanner(c cache.Cache) scanner.Scanner {
|
||||
detector := ospkg.Detector{}
|
||||
ospkgScanner := ospkg2.NewScanner(detector)
|
||||
driverFactory := library.DriverFactory{}
|
||||
libraryDetector := library.NewDetector(driverFactory)
|
||||
libraryScanner := library2.NewScanner(libraryDetector)
|
||||
scannerScanner := scanner.NewScanner(ospkgScanner, libraryScanner)
|
||||
scannerScanner := scanner.NewScanner(c, ospkgScanner, libraryScanner)
|
||||
return scannerScanner
|
||||
}
|
||||
|
||||
|
||||
30
pkg/db/db.go
30
pkg/db/db.go
@@ -13,8 +13,8 @@ import (
|
||||
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/github"
|
||||
"github.com/aquasecurity/trivy/pkg/indicator"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -23,11 +23,21 @@ const (
|
||||
)
|
||||
|
||||
var SuperSet = wire.NewSet(
|
||||
// indicator.ProgressBar
|
||||
indicator.NewProgressBar,
|
||||
|
||||
// clock.Clock
|
||||
wire.Struct(new(clock.RealClock)),
|
||||
wire.Bind(new(clock.Clock), new(clock.RealClock)),
|
||||
|
||||
// db.Config
|
||||
wire.Struct(new(db.Config)),
|
||||
|
||||
// github.Client
|
||||
github.NewClient,
|
||||
wire.Bind(new(github.Operation), new(github.Client)),
|
||||
|
||||
// db.Client
|
||||
NewClient,
|
||||
wire.Bind(new(Operation), new(Client)),
|
||||
)
|
||||
@@ -44,13 +54,15 @@ type dbOperation interface {
|
||||
type Client struct {
|
||||
dbc dbOperation
|
||||
githubClient github.Operation
|
||||
pb indicator.ProgressBar
|
||||
clock clock.Clock
|
||||
}
|
||||
|
||||
func NewClient(dbc db.Config, githubClient github.Operation, clock clock.Clock) Client {
|
||||
func NewClient(dbc db.Config, githubClient github.Operation, pb indicator.ProgressBar, clock clock.Clock) Client {
|
||||
return Client{
|
||||
dbc: dbc,
|
||||
githubClient: githubClient,
|
||||
pb: pb,
|
||||
clock: clock,
|
||||
}
|
||||
}
|
||||
@@ -102,23 +114,21 @@ func (c Client) NeedsUpdate(ctx context.Context, cliVersion string, light, skip
|
||||
|
||||
func (c Client) Download(ctx context.Context, cacheDir string, light bool) error {
|
||||
dbFile := fullDB
|
||||
message := " Downloading Full DB file..."
|
||||
if light {
|
||||
dbFile = lightDB
|
||||
message = " Downloading Lightweight DB file..."
|
||||
}
|
||||
|
||||
spinner := utils.NewSpinner(message)
|
||||
spinner.Start()
|
||||
defer spinner.Stop()
|
||||
|
||||
rc, err := c.githubClient.DownloadDB(ctx, dbFile)
|
||||
rc, size, err := c.githubClient.DownloadDB(ctx, dbFile)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to download vulnerability DB: %w", err)
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
gr, err := gzip.NewReader(rc)
|
||||
bar := c.pb.Start(int64(size))
|
||||
barReader := bar.NewProxyReader(rc)
|
||||
defer bar.Finish()
|
||||
|
||||
gr, err := gzip.NewReader(barReader)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("invalid gzip file: %w", err)
|
||||
}
|
||||
|
||||
@@ -3,12 +3,13 @@ package db
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/indicator"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
@@ -208,30 +209,21 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestClient_Download(t *testing.T) {
|
||||
type downloadDBOutput struct {
|
||||
fileName string
|
||||
err error
|
||||
}
|
||||
type downloadDB struct {
|
||||
input string
|
||||
output downloadDBOutput
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
light bool
|
||||
downloadDB []downloadDB
|
||||
downloadDB []github.DownloadDBExpectation
|
||||
expectedContent []byte
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
light: false,
|
||||
downloadDB: []downloadDB{
|
||||
downloadDB: []github.DownloadDBExpectation{
|
||||
{
|
||||
input: fullDB,
|
||||
output: downloadDBOutput{
|
||||
fileName: "testdata/test.db.gz",
|
||||
Args: github.DownloadDBInput{FileName: fullDB},
|
||||
ReturnArgs: github.DownloadDBOutput{
|
||||
FileName: "testdata/test.db.gz",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -239,11 +231,11 @@ func TestClient_Download(t *testing.T) {
|
||||
{
|
||||
name: "DownloadDB returns an error",
|
||||
light: false,
|
||||
downloadDB: []downloadDB{
|
||||
downloadDB: []github.DownloadDBExpectation{
|
||||
{
|
||||
input: fullDB,
|
||||
output: downloadDBOutput{
|
||||
err: xerrors.New("download failed"),
|
||||
Args: github.DownloadDBInput{FileName: fullDB},
|
||||
ReturnArgs: github.DownloadDBOutput{
|
||||
Err: xerrors.New("download failed"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -252,11 +244,11 @@ func TestClient_Download(t *testing.T) {
|
||||
{
|
||||
name: "invalid gzip",
|
||||
light: false,
|
||||
downloadDB: []downloadDB{
|
||||
downloadDB: []github.DownloadDBExpectation{
|
||||
{
|
||||
input: fullDB,
|
||||
output: downloadDBOutput{
|
||||
fileName: "testdata/invalid.db.gz",
|
||||
Args: github.DownloadDBInput{FileName: fullDB},
|
||||
ReturnArgs: github.DownloadDBOutput{
|
||||
FileName: "testdata/invalid.db.gz",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -269,19 +261,8 @@ func TestClient_Download(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
mockGitHubClient := new(github.MockClient)
|
||||
for _, dd := range tc.downloadDB {
|
||||
var rc io.ReadCloser
|
||||
if dd.output.fileName != "" {
|
||||
f, err := os.Open(dd.output.fileName)
|
||||
assert.NoError(t, err, tc.name)
|
||||
rc = f
|
||||
}
|
||||
|
||||
mockGitHubClient.On("DownloadDB", mock.Anything, dd.input).Return(
|
||||
rc, dd.output.err,
|
||||
)
|
||||
}
|
||||
mockGitHubClient, err := github.NewMockClient(tc.downloadDB)
|
||||
require.NoError(t, err, tc.name)
|
||||
|
||||
dir, err := ioutil.TempDir("", "db")
|
||||
require.NoError(t, err, tc.name)
|
||||
@@ -290,7 +271,8 @@ func TestClient_Download(t *testing.T) {
|
||||
err = db.Init(dir)
|
||||
require.NoError(t, err, tc.name)
|
||||
|
||||
client := NewClient(db.Config{}, mockGitHubClient, nil)
|
||||
pb := indicator.NewProgressBar(true)
|
||||
client := NewClient(db.Config{}, mockGitHubClient, pb, nil)
|
||||
ctx := context.Background()
|
||||
err = client.Download(ctx, dir, tc.light)
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ var (
|
||||
"3.8": time.Date(2020, 5, 1, 23, 59, 59, 0, time.UTC),
|
||||
"3.9": time.Date(2020, 11, 1, 23, 59, 59, 0, time.UTC),
|
||||
"3.10": time.Date(2021, 5, 1, 23, 59, 59, 0, time.UTC),
|
||||
"3.11": time.Date(2021, 11, 1, 23, 59, 59, 0, time.UTC),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/detector/ospkg/amazon"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/ospkg/debian"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/ospkg/oracle"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/ospkg/photon"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/ospkg/redhat"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/ospkg/suse"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/ospkg/ubuntu"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/google/wire"
|
||||
@@ -68,6 +70,12 @@ func newDriver(osFamily, osName string) Driver {
|
||||
d = amazon.NewScanner()
|
||||
case fos.Oracle:
|
||||
d = oracle.NewScanner()
|
||||
case fos.OpenSUSELeap:
|
||||
d = suse.NewScanner(suse.OpenSUSE)
|
||||
case fos.SLES:
|
||||
d = suse.NewScanner(suse.SUSEEnterpriseLinux)
|
||||
case fos.Photon:
|
||||
d = photon.NewScanner()
|
||||
default:
|
||||
log.Logger.Warnf("unsupported os : %s", osFamily)
|
||||
return nil
|
||||
|
||||
68
pkg/detector/ospkg/photon/photon.go
Normal file
68
pkg/detector/ospkg/photon/photon.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package photon
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/photon"
|
||||
version "github.com/knqyf263/go-rpm-version"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/fanal/analyzer"
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
|
||||
"k8s.io/utils/clock"
|
||||
)
|
||||
|
||||
var (
|
||||
eolDates = map[string]time.Time{}
|
||||
)
|
||||
|
||||
type Scanner struct {
|
||||
vs dbTypes.VulnSrc
|
||||
clock clock.Clock
|
||||
}
|
||||
|
||||
func NewScanner() *Scanner {
|
||||
return &Scanner{
|
||||
vs: photon.NewVulnSrc(),
|
||||
clock: clock.RealClock{},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Scanner) Detect(osVer string, pkgs []analyzer.Package) ([]types.DetectedVulnerability, error) {
|
||||
log.Logger.Info("Detecting Photon Linux vulnerabilities...")
|
||||
log.Logger.Debugf("Photon Linux: os version: %s", osVer)
|
||||
log.Logger.Debugf("Photon Linux: the number of packages: %d", len(pkgs))
|
||||
|
||||
var vulns []types.DetectedVulnerability
|
||||
for _, pkg := range pkgs {
|
||||
advisories, err := s.vs.Get(osVer, pkg.SrcName)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to get Photon Linux advisory: %w", err)
|
||||
}
|
||||
|
||||
installed := utils.FormatVersion(pkg)
|
||||
installedVersion := version.NewVersion(installed)
|
||||
for _, adv := range advisories {
|
||||
fixedVersion := version.NewVersion(adv.FixedVersion)
|
||||
vuln := types.DetectedVulnerability{
|
||||
VulnerabilityID: adv.VulnerabilityID,
|
||||
PkgName: pkg.Name,
|
||||
InstalledVersion: installed,
|
||||
}
|
||||
if installedVersion.LessThan(fixedVersion) {
|
||||
vuln.FixedVersion = adv.FixedVersion
|
||||
vulns = append(vulns, vuln)
|
||||
}
|
||||
}
|
||||
}
|
||||
return vulns, nil
|
||||
}
|
||||
|
||||
func (s *Scanner) IsSupportedVersion(osFamily, osVer string) bool {
|
||||
return true
|
||||
}
|
||||
128
pkg/detector/ospkg/suse/suse.go
Normal file
128
pkg/detector/ospkg/suse/suse.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package suse
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/aquasecurity/fanal/analyzer"
|
||||
fos "github.com/aquasecurity/fanal/analyzer/os"
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
susecvrf "github.com/aquasecurity/trivy-db/pkg/vulnsrc/suse-cvrf"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/utils"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
version "github.com/knqyf263/go-rpm-version"
|
||||
"golang.org/x/xerrors"
|
||||
"k8s.io/utils/clock"
|
||||
)
|
||||
|
||||
var (
|
||||
slesEolDates = map[string]time.Time{
|
||||
// Source: https://www.suse.com/lifecycle/
|
||||
"10": time.Date(2007, 12, 31, 23, 59, 59, 0, time.UTC),
|
||||
"10.1": time.Date(2008, 11, 30, 23, 59, 59, 0, time.UTC),
|
||||
"10.2": time.Date(2010, 4, 11, 23, 59, 59, 0, time.UTC),
|
||||
"10.3": time.Date(2011, 10, 11, 23, 59, 59, 0, time.UTC),
|
||||
"10.4": time.Date(2013, 7, 31, 23, 59, 59, 0, time.UTC),
|
||||
"11": time.Date(2010, 12, 31, 23, 59, 59, 0, time.UTC),
|
||||
"11.1": time.Date(2012, 8, 31, 23, 59, 59, 0, time.UTC),
|
||||
"11.2": time.Date(2014, 1, 31, 23, 59, 59, 0, time.UTC),
|
||||
"11.3": time.Date(2016, 1, 31, 23, 59, 59, 0, time.UTC),
|
||||
"11.4": time.Date(2019, 3, 31, 23, 59, 59, 0, time.UTC),
|
||||
"12": time.Date(2016, 6, 30, 23, 59, 59, 0, time.UTC),
|
||||
"12.1": time.Date(2017, 5, 31, 23, 59, 59, 0, time.UTC),
|
||||
"12.2": time.Date(2018, 3, 31, 23, 59, 59, 0, time.UTC),
|
||||
"12.3": time.Date(2019, 1, 30, 23, 59, 59, 0, time.UTC),
|
||||
// 6 months after SLES12 SP5 release
|
||||
// "12.4": time.Date(2024, 10, 31, 23, 59, 59, 0, time.UTC),
|
||||
"15": time.Date(2019, 12, 31, 23, 59, 59, 0, time.UTC),
|
||||
// 6 months after SLES 15 SP2 release
|
||||
// "15.1": time.Date(2028, 7, 31, 23, 59, 59, 0, time.UTC),
|
||||
}
|
||||
|
||||
opensuseEolDates = map[string]time.Time{
|
||||
// Source: https://en.opensuse.org/Lifetime
|
||||
"42.1": time.Date(2017, 5, 17, 23, 59, 59, 0, time.UTC),
|
||||
"42.2": time.Date(2018, 1, 26, 23, 59, 59, 0, time.UTC),
|
||||
"42.3": time.Date(2019, 6, 30, 23, 59, 59, 0, time.UTC),
|
||||
"15.0": time.Date(2019, 12, 3, 23, 59, 59, 0, time.UTC),
|
||||
"15.1": time.Date(2020, 11, 30, 23, 59, 59, 0, time.UTC),
|
||||
"15.2": time.Date(2021, 11, 30, 23, 59, 59, 0, time.UTC),
|
||||
}
|
||||
)
|
||||
|
||||
type Scanner struct {
|
||||
vs dbTypes.VulnSrc
|
||||
clock clock.Clock
|
||||
family string
|
||||
}
|
||||
|
||||
type SUSEType int
|
||||
|
||||
const (
|
||||
SUSEEnterpriseLinux SUSEType = iota
|
||||
OpenSUSE
|
||||
)
|
||||
|
||||
func NewScanner(t SUSEType) *Scanner {
|
||||
switch t {
|
||||
case SUSEEnterpriseLinux:
|
||||
return &Scanner{
|
||||
vs: susecvrf.NewVulnSrc(susecvrf.SUSEEnterpriseLinux),
|
||||
clock: clock.RealClock{},
|
||||
}
|
||||
case OpenSUSE:
|
||||
return &Scanner{
|
||||
vs: susecvrf.NewVulnSrc(susecvrf.OpenSUSE),
|
||||
clock: clock.RealClock{},
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Scanner) Detect(osVer string, pkgs []analyzer.Package) ([]types.DetectedVulnerability, error) {
|
||||
log.Logger.Info("Detecting SUSE vulnerabilities...")
|
||||
log.Logger.Debugf("SUSE: os version: %s", osVer)
|
||||
log.Logger.Debugf("SUSE: the number of packages: %d", len(pkgs))
|
||||
|
||||
var vulns []types.DetectedVulnerability
|
||||
for _, pkg := range pkgs {
|
||||
advisories, err := s.vs.Get(osVer, pkg.SrcName)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to get SUSE advisory: %w", err)
|
||||
}
|
||||
|
||||
installed := utils.FormatVersion(pkg)
|
||||
installedVersion := version.NewVersion(installed)
|
||||
for _, adv := range advisories {
|
||||
fixedVersion := version.NewVersion(adv.FixedVersion)
|
||||
vuln := types.DetectedVulnerability{
|
||||
VulnerabilityID: adv.VulnerabilityID,
|
||||
PkgName: pkg.Name,
|
||||
InstalledVersion: installed,
|
||||
}
|
||||
if installedVersion.LessThan(fixedVersion) {
|
||||
vuln.FixedVersion = adv.FixedVersion
|
||||
vulns = append(vulns, vuln)
|
||||
}
|
||||
}
|
||||
}
|
||||
return vulns, nil
|
||||
}
|
||||
|
||||
func (s *Scanner) IsSupportedVersion(osFamily, osVer string) bool {
|
||||
var eolDate time.Time
|
||||
var ok bool
|
||||
|
||||
if osFamily == fos.SLES {
|
||||
eolDate, ok = slesEolDates[osVer]
|
||||
} else if osFamily == fos.OpenSUSELeap {
|
||||
eolDate, ok = opensuseEolDates[osVer]
|
||||
}
|
||||
|
||||
if !ok {
|
||||
log.Logger.Warnf("This OS version is not on the EOL list: %s %s", osFamily, osVer)
|
||||
return false
|
||||
}
|
||||
|
||||
return s.clock.Now().Before(eolDate)
|
||||
}
|
||||
92
pkg/detector/ospkg/suse/suse_test.go
Normal file
92
pkg/detector/ospkg/suse/suse_test.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package suse
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
susecvrf "github.com/aquasecurity/trivy-db/pkg/vulnsrc/suse-cvrf"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
|
||||
"k8s.io/utils/clock"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
log.InitLogger(false, false)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestScanner_IsSupportedVersion(t *testing.T) {
|
||||
vectors := map[string]struct {
|
||||
clock clock.Clock
|
||||
osFamily string
|
||||
osVersion string
|
||||
distribution susecvrf.Distribution
|
||||
expected bool
|
||||
}{
|
||||
"opensuse.leap42.3": {
|
||||
clock: clocktesting.NewFakeClock(time.Date(2019, 5, 31, 23, 59, 59, 0, time.UTC)),
|
||||
osFamily: "opensuse.leap",
|
||||
osVersion: "42.3",
|
||||
distribution: susecvrf.OpenSUSE,
|
||||
expected: true,
|
||||
},
|
||||
"opensuse.leap15": {
|
||||
clock: clocktesting.NewFakeClock(time.Date(2019, 5, 31, 23, 59, 59, 0, time.UTC)),
|
||||
osFamily: "opensuse.leap",
|
||||
osVersion: "15.0",
|
||||
distribution: susecvrf.OpenSUSE,
|
||||
expected: true,
|
||||
},
|
||||
"opensuse.leap15.1": {
|
||||
clock: clocktesting.NewFakeClock(time.Date(2019, 5, 31, 23, 59, 59, 0, time.UTC)),
|
||||
osFamily: "opensuse.leap",
|
||||
osVersion: "15.1",
|
||||
distribution: susecvrf.OpenSUSE,
|
||||
expected: true,
|
||||
},
|
||||
"opensuse.leap15.1-sametime": {
|
||||
clock: clocktesting.NewFakeClock(time.Date(2020, 11, 30, 23, 59, 59, 0, time.UTC)),
|
||||
osFamily: "opensuse.leap",
|
||||
osVersion: "15.1",
|
||||
distribution: susecvrf.OpenSUSE,
|
||||
expected: false,
|
||||
},
|
||||
"sles12.3": {
|
||||
clock: clocktesting.NewFakeClock(time.Date(2019, 5, 31, 23, 59, 59, 0, time.UTC)),
|
||||
osFamily: "suse linux enterprise server",
|
||||
osVersion: "12.3",
|
||||
distribution: susecvrf.SUSEEnterpriseLinux,
|
||||
expected: false,
|
||||
},
|
||||
"sles15": {
|
||||
clock: clocktesting.NewFakeClock(time.Date(2019, 5, 31, 23, 59, 59, 0, time.UTC)),
|
||||
osFamily: "suse linux enterprise server",
|
||||
osVersion: "15",
|
||||
distribution: susecvrf.SUSEEnterpriseLinux,
|
||||
expected: true,
|
||||
},
|
||||
"unknown": {
|
||||
clock: clocktesting.NewFakeClock(time.Date(2019, 5, 31, 23, 59, 59, 0, time.UTC)),
|
||||
osFamily: "oracle",
|
||||
osVersion: "unknown",
|
||||
distribution: susecvrf.SUSEEnterpriseLinux,
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for testName, v := range vectors {
|
||||
s := &Scanner{
|
||||
vs: susecvrf.NewVulnSrc(v.distribution),
|
||||
clock: v.clock,
|
||||
}
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
actual := s.IsSupportedVersion(v.osFamily, v.osVersion)
|
||||
if actual != v.expected {
|
||||
t.Errorf("[%s] got %v, want %v", testName, actual, v.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
@@ -42,7 +43,7 @@ func (r Repository) DownloadAsset(ctx context.Context, id int64) (io.ReadCloser,
|
||||
}
|
||||
|
||||
type Operation interface {
|
||||
DownloadDB(ctx context.Context, fileName string) (io.ReadCloser, error)
|
||||
DownloadDB(ctx context.Context, fileName string) (io.ReadCloser, int, error)
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
@@ -72,11 +73,11 @@ func NewClient() Client {
|
||||
}
|
||||
}
|
||||
|
||||
func (c Client) DownloadDB(ctx context.Context, fileName string) (io.ReadCloser, error) {
|
||||
func (c Client) DownloadDB(ctx context.Context, fileName string) (io.ReadCloser, int, error) {
|
||||
options := github.ListOptions{}
|
||||
releases, _, err := c.Repository.ListReleases(ctx, &options)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to list releases: %w", err)
|
||||
return nil, 0, xerrors.Errorf("failed to list releases: %w", err)
|
||||
}
|
||||
|
||||
sort.Slice(releases, func(i, j int) bool {
|
||||
@@ -91,37 +92,42 @@ func (c Client) DownloadDB(ctx context.Context, fileName string) (io.ReadCloser,
|
||||
}
|
||||
|
||||
for _, asset := range release.Assets {
|
||||
rc, err := c.downloadAsset(ctx, asset, fileName)
|
||||
rc, size, err := c.downloadAsset(ctx, asset, fileName)
|
||||
if err != nil {
|
||||
log.Logger.Debug(err)
|
||||
continue
|
||||
}
|
||||
return rc, nil
|
||||
return rc, size, nil
|
||||
}
|
||||
|
||||
}
|
||||
return nil, xerrors.New("DB file not found")
|
||||
return nil, 0, xerrors.New("DB file not found")
|
||||
}
|
||||
|
||||
func (c Client) downloadAsset(ctx context.Context, asset github.ReleaseAsset, fileName string) (io.ReadCloser, error) {
|
||||
func (c Client) downloadAsset(ctx context.Context, asset github.ReleaseAsset, fileName string) (io.ReadCloser, int, error) {
|
||||
log.Logger.Debugf("asset name: %s", asset.GetName())
|
||||
if asset.GetName() != fileName {
|
||||
return nil, xerrors.New("file name doesn't match")
|
||||
return nil, 0, xerrors.New("file name doesn't match")
|
||||
}
|
||||
|
||||
rc, url, err := c.Repository.DownloadAsset(ctx, asset.GetID())
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("unable to download the asset: %w", err)
|
||||
return nil, 0, xerrors.Errorf("unable to download the asset: %w", err)
|
||||
}
|
||||
|
||||
if rc != nil {
|
||||
return rc, nil
|
||||
return rc, asset.GetSize(), nil
|
||||
}
|
||||
|
||||
log.Logger.Debugf("asset URL: %s", url)
|
||||
resp, err := http.Get(url)
|
||||
if err != nil || resp.StatusCode != http.StatusOK {
|
||||
return nil, xerrors.Errorf("unable to download the asset via URL: %w", err)
|
||||
return nil, 0, xerrors.Errorf("unable to download the asset via URL: %w", err)
|
||||
}
|
||||
return resp.Body, nil
|
||||
|
||||
size, err := strconv.Atoi(resp.Header.Get("Content-Length"))
|
||||
if err != nil {
|
||||
return nil, 0, xerrors.Errorf("invalid size: %w", err)
|
||||
}
|
||||
return resp.Body, size, nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package github
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
@@ -11,15 +12,46 @@ type MockClient struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (_m *MockClient) DownloadDB(ctx context.Context, fileName string) (io.ReadCloser, error) {
|
||||
type DownloadDBInput struct {
|
||||
FileName string
|
||||
}
|
||||
type DownloadDBOutput struct {
|
||||
FileName string
|
||||
Size int
|
||||
Err error
|
||||
}
|
||||
type DownloadDBExpectation struct {
|
||||
Args DownloadDBInput
|
||||
ReturnArgs DownloadDBOutput
|
||||
}
|
||||
|
||||
func NewMockClient(downloadDBExpectations []DownloadDBExpectation) (*MockClient, error) {
|
||||
mockDetector := new(MockClient)
|
||||
for _, e := range downloadDBExpectations {
|
||||
var rc io.ReadCloser
|
||||
if e.ReturnArgs.FileName != "" {
|
||||
f, err := os.Open(e.ReturnArgs.FileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rc = f
|
||||
}
|
||||
|
||||
mockDetector.On("DownloadDB", mock.Anything, e.Args.FileName).Return(
|
||||
rc, e.ReturnArgs.Size, e.ReturnArgs.Err)
|
||||
}
|
||||
return mockDetector, nil
|
||||
}
|
||||
|
||||
func (_m *MockClient) DownloadDB(ctx context.Context, fileName string) (io.ReadCloser, int, error) {
|
||||
ret := _m.Called(ctx, fileName)
|
||||
ret0 := ret.Get(0)
|
||||
if ret0 == nil {
|
||||
return nil, ret.Error(1)
|
||||
return nil, ret.Int(1), ret.Error(2)
|
||||
}
|
||||
rc, ok := ret0.(io.ReadCloser)
|
||||
if !ok {
|
||||
return nil, ret.Error(1)
|
||||
return nil, ret.Int(1), ret.Error(2)
|
||||
}
|
||||
return rc, ret.Error(1)
|
||||
return rc, ret.Int(1), ret.Error(2)
|
||||
}
|
||||
|
||||
@@ -451,7 +451,7 @@ func TestClient_DownloadDB(t *testing.T) {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
rc, err := client.DownloadDB(ctx, tc.fileName)
|
||||
rc, _, err := client.DownloadDB(ctx, tc.fileName)
|
||||
|
||||
switch {
|
||||
case tc.expectedError != nil:
|
||||
|
||||
40
pkg/indicator/progress.go
Normal file
40
pkg/indicator/progress.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package indicator
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/cheggaaa/pb/v3"
|
||||
)
|
||||
|
||||
type ProgressBar struct {
|
||||
quiet bool
|
||||
}
|
||||
|
||||
func NewProgressBar(quiet bool) ProgressBar {
|
||||
return ProgressBar{quiet: quiet}
|
||||
}
|
||||
|
||||
func (p ProgressBar) Start(total int64) Bar {
|
||||
if p.quiet {
|
||||
return Bar{}
|
||||
}
|
||||
bar := pb.Full.Start64(total)
|
||||
return Bar{bar: bar}
|
||||
}
|
||||
|
||||
type Bar struct {
|
||||
bar *pb.ProgressBar
|
||||
}
|
||||
|
||||
func (b Bar) NewProxyReader(r io.Reader) io.Reader {
|
||||
if b.bar == nil {
|
||||
return r
|
||||
}
|
||||
return b.bar.NewProxyReader(r)
|
||||
}
|
||||
func (b Bar) Finish() {
|
||||
if b.bar == nil {
|
||||
return
|
||||
}
|
||||
b.bar.Finish()
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
type Results []Result
|
||||
|
||||
type Result struct {
|
||||
FileName string `json:"Target"`
|
||||
Target string `json:"Target"`
|
||||
Vulnerabilities []types.DetectedVulnerability `json:"Vulnerabilities"`
|
||||
}
|
||||
|
||||
@@ -101,8 +101,8 @@ func (tw TableWriter) write(result Result) {
|
||||
results = append(results, r)
|
||||
}
|
||||
|
||||
fmt.Printf("\n%s\n", result.FileName)
|
||||
fmt.Println(strings.Repeat("=", len(result.FileName)))
|
||||
fmt.Printf("\n%s\n", result.Target)
|
||||
fmt.Println(strings.Repeat("=", len(result.Target)))
|
||||
fmt.Printf("Total: %d (%s)\n\n", len(result.Vulnerabilities), strings.Join(results, ", "))
|
||||
|
||||
if len(result.Vulnerabilities) == 0 {
|
||||
|
||||
@@ -117,7 +117,7 @@ func TestReportWriter_Table(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
inputResults := report.Results{
|
||||
{
|
||||
FileName: "foo",
|
||||
Target: "foo",
|
||||
Vulnerabilities: tc.detectedVulns,
|
||||
},
|
||||
}
|
||||
@@ -151,7 +151,7 @@ func TestReportWriter_JSON(t *testing.T) {
|
||||
},
|
||||
expectedJSON: report.Results{
|
||||
report.Result{
|
||||
FileName: "foojson",
|
||||
Target: "foojson",
|
||||
Vulnerabilities: []types.DetectedVulnerability{
|
||||
{
|
||||
VulnerabilityID: "123",
|
||||
@@ -179,7 +179,7 @@ func TestReportWriter_JSON(t *testing.T) {
|
||||
|
||||
inputResults := report.Results{
|
||||
{
|
||||
FileName: "foojson",
|
||||
Target: "foojson",
|
||||
Vulnerabilities: tc.detectedVulns,
|
||||
},
|
||||
}
|
||||
@@ -236,7 +236,7 @@ func TestReportWriter_Template(t *testing.T) {
|
||||
tmplWritten := bytes.Buffer{}
|
||||
inputResults := report.Results{
|
||||
{
|
||||
FileName: "foojson",
|
||||
Target: "foojson",
|
||||
Vulnerabilities: tc.detectedVulns,
|
||||
},
|
||||
}
|
||||
|
||||
20
pkg/rpc/client/headers.go
Normal file
20
pkg/rpc/client/headers.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/twitchtv/twirp"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
func WithCustomHeaders(ctx context.Context, customHeaders http.Header) context.Context {
|
||||
// Attach the headers to a context
|
||||
ctxWithToken, err := twirp.WithHTTPRequestHeaders(ctx, customHeaders)
|
||||
if err != nil {
|
||||
log.Logger.Warnf("twirp error setting headers: %s", err)
|
||||
return ctx
|
||||
}
|
||||
return ctxWithToken
|
||||
}
|
||||
59
pkg/rpc/client/headers_test.go
Normal file
59
pkg/rpc/client/headers_test.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/twitchtv/twirp"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
_ = log.InitLogger(false, true)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestWithCustomHeaders(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
customHeaders http.Header
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want http.Header
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
customHeaders: http.Header{
|
||||
"Trivy-Token": []string{"token"},
|
||||
},
|
||||
},
|
||||
want: http.Header{
|
||||
"Trivy-Token": []string{"token"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sad path, invalid headers passed in",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
customHeaders: http.Header{
|
||||
"Content-Type": []string{"token"},
|
||||
},
|
||||
},
|
||||
want: http.Header(nil),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
gotCtx := WithCustomHeaders(tt.args.ctx, tt.args.customHeaders)
|
||||
header, _ := twirp.HTTPRequestHeaders(gotCtx)
|
||||
assert.Equal(t, tt.want, header, tt.name)
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,13 @@ import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client"
|
||||
|
||||
"github.com/google/wire"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
ptypes "github.com/aquasecurity/go-dep-parser/pkg/types"
|
||||
detector "github.com/aquasecurity/trivy/pkg/detector/library"
|
||||
r "github.com/aquasecurity/trivy/pkg/rpc"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
rpc "github.com/aquasecurity/trivy/rpc/detector"
|
||||
)
|
||||
@@ -28,22 +27,28 @@ func NewProtobufClient(remoteURL RemoteURL) rpc.LibDetector {
|
||||
return rpc.NewLibDetectorProtobufClient(string(remoteURL), &http.Client{})
|
||||
}
|
||||
|
||||
type Token string
|
||||
type CustomHeaders http.Header
|
||||
|
||||
type Detector struct {
|
||||
token Token
|
||||
client rpc.LibDetector
|
||||
customHeaders CustomHeaders
|
||||
client rpc.LibDetector
|
||||
}
|
||||
|
||||
func NewDetector(token Token, detector rpc.LibDetector) Detector {
|
||||
return Detector{token: token, client: detector}
|
||||
func NewDetector(customHeaders CustomHeaders, detector rpc.LibDetector) Detector {
|
||||
return Detector{customHeaders: customHeaders, client: detector}
|
||||
}
|
||||
|
||||
func (d Detector) Detect(filePath string, libs []ptypes.Library) ([]types.DetectedVulnerability, error) {
|
||||
ctx := client.WithToken(context.Background(), string(d.token))
|
||||
res, err := d.client.Detect(ctx, &rpc.LibDetectRequest{
|
||||
FilePath: filePath,
|
||||
Libraries: r.ConvertToRpcLibraries(libs),
|
||||
ctx := client.WithCustomHeaders(context.Background(), http.Header(d.customHeaders))
|
||||
|
||||
var res *rpc.DetectResponse
|
||||
err := r.Retry(func() error {
|
||||
var err error
|
||||
res, err = d.client.Detect(ctx, &rpc.LibDetectRequest{
|
||||
FilePath: filePath,
|
||||
Libraries: r.ConvertToRpcLibraries(libs),
|
||||
})
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to detect vulnerabilities via RPC: %w", err)
|
||||
|
||||
@@ -48,8 +48,9 @@ func TestDetectClient_Detect(t *testing.T) {
|
||||
}
|
||||
|
||||
type fields struct {
|
||||
token Token
|
||||
customHeaders CustomHeaders
|
||||
}
|
||||
|
||||
type args struct {
|
||||
filePath string
|
||||
libs []ptypes.Library
|
||||
@@ -65,7 +66,9 @@ func TestDetectClient_Detect(t *testing.T) {
|
||||
{
|
||||
name: "happy path",
|
||||
fields: fields{
|
||||
token: "token",
|
||||
customHeaders: CustomHeaders{
|
||||
"Trivy-Token": []string{"token"},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
filePath: "app/Pipfile.lock",
|
||||
@@ -141,7 +144,7 @@ func TestDetectClient_Detect(t *testing.T) {
|
||||
mockDetector.On("Detect", mock.Anything, tt.detect.input.req).Return(
|
||||
tt.detect.output.res, tt.detect.output.err)
|
||||
|
||||
d := NewDetector(tt.fields.token, mockDetector)
|
||||
d := NewDetector(tt.fields.customHeaders, mockDetector)
|
||||
got, err := d.Detect(tt.args.filePath, tt.args.libs)
|
||||
if tt.wantErr != "" {
|
||||
require.NotNil(t, err, tt.name)
|
||||
|
||||
@@ -4,14 +4,13 @@ import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client"
|
||||
|
||||
"github.com/google/wire"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/fanal/analyzer"
|
||||
detector "github.com/aquasecurity/trivy/pkg/detector/ospkg"
|
||||
r "github.com/aquasecurity/trivy/pkg/rpc"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/client"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
rpc "github.com/aquasecurity/trivy/rpc/detector"
|
||||
)
|
||||
@@ -28,23 +27,29 @@ func NewProtobufClient(remoteURL RemoteURL) rpc.OSDetector {
|
||||
return rpc.NewOSDetectorProtobufClient(string(remoteURL), &http.Client{})
|
||||
}
|
||||
|
||||
type Token string
|
||||
type CustomHeaders http.Header
|
||||
|
||||
type Detector struct {
|
||||
token Token
|
||||
client rpc.OSDetector
|
||||
customHeaders CustomHeaders
|
||||
client rpc.OSDetector
|
||||
}
|
||||
|
||||
func NewDetector(token Token, detector rpc.OSDetector) Detector {
|
||||
return Detector{token: token, client: detector}
|
||||
func NewDetector(customHeaders CustomHeaders, detector rpc.OSDetector) Detector {
|
||||
return Detector{customHeaders: customHeaders, client: detector}
|
||||
}
|
||||
|
||||
func (d Detector) Detect(osFamily, osName string, pkgs []analyzer.Package) ([]types.DetectedVulnerability, bool, error) {
|
||||
ctx := client.WithToken(context.Background(), string(d.token))
|
||||
res, err := d.client.Detect(ctx, &rpc.OSDetectRequest{
|
||||
OsFamily: osFamily,
|
||||
OsName: osName,
|
||||
Packages: r.ConvertToRpcPkgs(pkgs),
|
||||
ctx := client.WithCustomHeaders(context.Background(), http.Header(d.customHeaders))
|
||||
|
||||
var res *rpc.DetectResponse
|
||||
err := r.Retry(func() error {
|
||||
var err error
|
||||
res, err = d.client.Detect(ctx, &rpc.OSDetectRequest{
|
||||
OsFamily: osFamily,
|
||||
OsName: osName,
|
||||
Packages: r.ConvertToRpcPkgs(pkgs),
|
||||
})
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, false, xerrors.Errorf("failed to detect vulnerabilities via RPC: %w", err)
|
||||
|
||||
@@ -48,7 +48,7 @@ func TestDetectClient_Detect(t *testing.T) {
|
||||
}
|
||||
|
||||
type fields struct {
|
||||
token Token
|
||||
customHeaders CustomHeaders
|
||||
}
|
||||
type args struct {
|
||||
osFamily string
|
||||
@@ -66,7 +66,9 @@ func TestDetectClient_Detect(t *testing.T) {
|
||||
{
|
||||
name: "happy path",
|
||||
fields: fields{
|
||||
token: "token",
|
||||
customHeaders: CustomHeaders{
|
||||
"Trivy-Token": []string{"token"},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
osFamily: "alpine",
|
||||
@@ -168,7 +170,7 @@ func TestDetectClient_Detect(t *testing.T) {
|
||||
mockDetector.On("Detect", mock.Anything, tt.detect.input.req).Return(
|
||||
tt.detect.output.res, tt.detect.output.err)
|
||||
|
||||
d := NewDetector(tt.fields.token, mockDetector)
|
||||
d := NewDetector(tt.fields.customHeaders, mockDetector)
|
||||
got, _, err := d.Detect(tt.args.osFamily, tt.args.osName, tt.args.pkgs)
|
||||
if tt.wantErr != "" {
|
||||
require.NotNil(t, err, tt.name)
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/twitchtv/twirp"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
var (
|
||||
buildRequestHeaderFunc = buildRequestHeader
|
||||
)
|
||||
|
||||
func buildRequestHeader(inputHeaders map[string]string) http.Header {
|
||||
header := make(http.Header)
|
||||
for k, v := range inputHeaders {
|
||||
header.Set(k, v)
|
||||
}
|
||||
return header
|
||||
}
|
||||
|
||||
func WithToken(ctx context.Context, token string) context.Context {
|
||||
// Prepare custom header
|
||||
header := buildRequestHeaderFunc(map[string]string{"Trivy-Token": token})
|
||||
|
||||
// Attach the headers to a context
|
||||
ctxWithToken, err := twirp.WithHTTPRequestHeaders(ctx, header)
|
||||
if err != nil {
|
||||
log.Logger.Warnf("twirp error setting headers: %s", err)
|
||||
return ctx
|
||||
}
|
||||
return ctxWithToken
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/twitchtv/twirp"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
_ = log.InitLogger(false, true)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestWithToken(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
token string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
buildRequestHeaderFunc func(map[string]string) http.Header
|
||||
want http.Header
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
token: "token",
|
||||
},
|
||||
want: http.Header{
|
||||
"Trivy-Token": []string{"token"},
|
||||
},
|
||||
buildRequestHeaderFunc: buildRequestHeader,
|
||||
},
|
||||
{
|
||||
name: "sad path, invalid headers passed in",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
token: "token",
|
||||
},
|
||||
want: http.Header(nil),
|
||||
buildRequestHeaderFunc: func(m map[string]string) http.Header {
|
||||
header := make(http.Header)
|
||||
for k, v := range m {
|
||||
header.Set(k, v)
|
||||
}
|
||||
|
||||
// add an extra header that is reserved for twirp
|
||||
header.Set("Content-Type", "foobar")
|
||||
return header
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
oldbuildRequestHeaderFunc := buildRequestHeaderFunc
|
||||
defer func() {
|
||||
buildRequestHeaderFunc = oldbuildRequestHeaderFunc
|
||||
}()
|
||||
buildRequestHeaderFunc = tt.buildRequestHeaderFunc
|
||||
gotCtx := WithToken(tt.args.ctx, tt.args.token)
|
||||
header, _ := twirp.HTTPRequestHeaders(gotCtx)
|
||||
assert.Equal(t, tt.want, header, tt.name)
|
||||
}
|
||||
}
|
||||
40
pkg/rpc/retry.go
Normal file
40
pkg/rpc/retry.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/cenkalti/backoff"
|
||||
"github.com/twitchtv/twirp"
|
||||
)
|
||||
|
||||
const (
|
||||
maxRetries = 10
|
||||
)
|
||||
|
||||
func Retry(f func() error) error {
|
||||
operation := func() error {
|
||||
err := f()
|
||||
if err != nil {
|
||||
twerr, ok := err.(twirp.Error)
|
||||
if !ok {
|
||||
return backoff.Permanent(err)
|
||||
}
|
||||
if twerr.Code() == twirp.Unavailable {
|
||||
return err
|
||||
}
|
||||
return backoff.Permanent(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
b := backoff.WithMaxRetries(backoff.NewExponentialBackOff(), maxRetries)
|
||||
err := backoff.RetryNotify(operation, b, func(err error, _ time.Duration) {
|
||||
log.Logger.Warn(err)
|
||||
log.Logger.Info("Retrying HTTP request...")
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -19,7 +19,7 @@ func initializeLibServer() *library.Server {
|
||||
return &library.Server{}
|
||||
}
|
||||
|
||||
func initializeDBWorker() dbWorker {
|
||||
func initializeDBWorker(quiet bool) dbWorker {
|
||||
wire.Build(SuperSet)
|
||||
return dbWorker{}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ func ListenAndServe(addr string, c config.Config) error {
|
||||
}
|
||||
|
||||
go func() {
|
||||
worker := initializeDBWorker()
|
||||
worker := initializeDBWorker(true)
|
||||
ctx := context.Background()
|
||||
for {
|
||||
time.Sleep(1 * time.Hour)
|
||||
@@ -58,19 +58,19 @@ func ListenAndServe(addr string, c config.Config) error {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
osHandler := rpc.NewOSDetectorServer(initializeOspkgServer(), nil)
|
||||
mux.Handle(rpc.OSDetectorPathPrefix, withToken(withWaitGroup(osHandler), c.Token))
|
||||
mux.Handle(rpc.OSDetectorPathPrefix, withToken(withWaitGroup(osHandler), c.Token, c.TokenHeader))
|
||||
|
||||
libHandler := rpc.NewLibDetectorServer(initializeLibServer(), nil)
|
||||
mux.Handle(rpc.LibDetectorPathPrefix, withToken(withWaitGroup(libHandler), c.Token))
|
||||
mux.Handle(rpc.LibDetectorPathPrefix, withToken(withWaitGroup(libHandler), c.Token, c.TokenHeader))
|
||||
|
||||
log.Logger.Infof("Listening %s...", addr)
|
||||
|
||||
return http.ListenAndServe(addr, mux)
|
||||
}
|
||||
|
||||
func withToken(base http.Handler, token string) http.Handler {
|
||||
func withToken(base http.Handler, token, tokenHeader string) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if token != "" && token != r.Header.Get("Trivy-Token") {
|
||||
if token != "" && token != r.Header.Get(tokenHeader) {
|
||||
rpc.WriteError(w, twirp.NewError(twirp.Unauthenticated, "invalid token"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
library2 "github.com/aquasecurity/trivy/pkg/detector/library"
|
||||
ospkg2 "github.com/aquasecurity/trivy/pkg/detector/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/github"
|
||||
"github.com/aquasecurity/trivy/pkg/indicator"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/server/library"
|
||||
"github.com/aquasecurity/trivy/pkg/rpc/server/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/vulnerability"
|
||||
@@ -36,11 +37,12 @@ func initializeLibServer() *library.Server {
|
||||
return server
|
||||
}
|
||||
|
||||
func initializeDBWorker() dbWorker {
|
||||
func initializeDBWorker(quiet bool) dbWorker {
|
||||
config := db.Config{}
|
||||
client := github.NewClient()
|
||||
progressBar := indicator.NewProgressBar(quiet)
|
||||
realClock := clock.RealClock{}
|
||||
dbClient := db2.NewClient(config, client, realClock)
|
||||
dbClient := db2.NewClient(config, client, progressBar, realClock)
|
||||
serverDbWorker := newDBWorker(dbClient)
|
||||
return serverDbWorker
|
||||
}
|
||||
|
||||
@@ -8,8 +8,9 @@ import (
|
||||
_ "github.com/aquasecurity/fanal/analyzer/os/alpine"
|
||||
_ "github.com/aquasecurity/fanal/analyzer/os/amazonlinux"
|
||||
_ "github.com/aquasecurity/fanal/analyzer/os/debianbase"
|
||||
_ "github.com/aquasecurity/fanal/analyzer/os/opensuse"
|
||||
_ "github.com/aquasecurity/fanal/analyzer/os/photon"
|
||||
_ "github.com/aquasecurity/fanal/analyzer/os/redhatbase"
|
||||
_ "github.com/aquasecurity/fanal/analyzer/os/suse"
|
||||
_ "github.com/aquasecurity/fanal/analyzer/pkg/apk"
|
||||
_ "github.com/aquasecurity/fanal/analyzer/pkg/dpkg"
|
||||
"github.com/aquasecurity/fanal/extractor"
|
||||
|
||||
@@ -8,13 +8,16 @@ import (
|
||||
"sort"
|
||||
|
||||
"github.com/google/wire"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/report"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/fanal/analyzer"
|
||||
"github.com/aquasecurity/fanal/cache"
|
||||
"github.com/aquasecurity/fanal/extractor"
|
||||
"github.com/aquasecurity/fanal/extractor/docker"
|
||||
libDetector "github.com/aquasecurity/trivy/pkg/detector/library"
|
||||
ospkgDetector "github.com/aquasecurity/trivy/pkg/detector/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/report"
|
||||
rpcLibDetector "github.com/aquasecurity/trivy/pkg/rpc/client/library"
|
||||
rpcOSDetector "github.com/aquasecurity/trivy/pkg/rpc/client/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/scanner/library"
|
||||
@@ -23,8 +26,6 @@ import (
|
||||
ospkgScanner "github.com/aquasecurity/trivy/pkg/scanner/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/utils"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
var StandaloneSet = wire.NewSet(
|
||||
@@ -44,12 +45,13 @@ var ClientSet = wire.NewSet(
|
||||
)
|
||||
|
||||
type Scanner struct {
|
||||
cacheClient cache.Cache
|
||||
ospkgScanner ospkg.Scanner
|
||||
libScanner library.Scanner
|
||||
}
|
||||
|
||||
func NewScanner(ospkgScanner ospkg.Scanner, libScanner library.Scanner) Scanner {
|
||||
return Scanner{ospkgScanner: ospkgScanner, libScanner: libScanner}
|
||||
func NewScanner(cacheClient cache.Cache, ospkgScanner ospkg.Scanner, libScanner library.Scanner) Scanner {
|
||||
return Scanner{cacheClient: cacheClient, ospkgScanner: ospkgScanner, libScanner: libScanner}
|
||||
}
|
||||
|
||||
func (s Scanner) ScanImage(imageName, filePath string, scanOptions types.ScanOptions) (report.Results, error) {
|
||||
@@ -58,15 +60,24 @@ func (s Scanner) ScanImage(imageName, filePath string, scanOptions types.ScanOpt
|
||||
|
||||
var target string
|
||||
var files extractor.FileMap
|
||||
var ac analyzer.Config
|
||||
dockerOption, err := types.GetDockerOption()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to get docker option: %w", err)
|
||||
}
|
||||
|
||||
if imageName != "" {
|
||||
dockerOption.Timeout = scanOptions.Timeout
|
||||
}
|
||||
ext, err := docker.NewDockerExtractor(dockerOption, s.cacheClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ac = analyzer.Config{Extractor: ext}
|
||||
|
||||
if imageName != "" {
|
||||
target = imageName
|
||||
dockerOption, err := types.GetDockerOption()
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to get docker option: %w", err)
|
||||
}
|
||||
|
||||
dockerOption.Timeout = scanOptions.Timeout
|
||||
files, err = analyzer.Analyze(ctx, imageName, dockerOption)
|
||||
files, err = ac.Analyze(ctx, imageName, dockerOption)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to analyze image: %w", err)
|
||||
}
|
||||
@@ -77,7 +88,7 @@ func (s Scanner) ScanImage(imageName, filePath string, scanOptions types.ScanOpt
|
||||
return nil, xerrors.Errorf("failed to open stream: %w", err)
|
||||
}
|
||||
|
||||
files, err = analyzer.AnalyzeFile(ctx, rc)
|
||||
files, err = ac.AnalyzeFile(ctx, rc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -93,7 +104,7 @@ func (s Scanner) ScanImage(imageName, filePath string, scanOptions types.ScanOpt
|
||||
if osFamily != "" {
|
||||
imageDetail := fmt.Sprintf("%s (%s %s)", target, osFamily, osVersion)
|
||||
results = append(results, report.Result{
|
||||
FileName: imageDetail,
|
||||
Target: imageDetail,
|
||||
Vulnerabilities: osVulns,
|
||||
})
|
||||
}
|
||||
@@ -108,12 +119,12 @@ func (s Scanner) ScanImage(imageName, filePath string, scanOptions types.ScanOpt
|
||||
var libResults report.Results
|
||||
for path, vulns := range libVulns {
|
||||
libResults = append(libResults, report.Result{
|
||||
FileName: path,
|
||||
Target: path,
|
||||
Vulnerabilities: vulns,
|
||||
})
|
||||
}
|
||||
sort.Slice(libResults, func(i, j int) bool {
|
||||
return libResults[i].FileName < libResults[j].FileName
|
||||
return libResults[i].Target < libResults[j].Target
|
||||
})
|
||||
results = append(results, libResults...)
|
||||
}
|
||||
@@ -127,7 +138,7 @@ func (s Scanner) ScanFile(f *os.File) (report.Results, error) {
|
||||
return nil, xerrors.Errorf("failed to scan libraries in file: %w", err)
|
||||
}
|
||||
results := report.Results{
|
||||
{FileName: f.Name(), Vulnerabilities: vulns},
|
||||
{Target: f.Name(), Vulnerabilities: vulns},
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/briandowns/spinner"
|
||||
pb "gopkg.in/cheggaaa/pb.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
Quiet = false
|
||||
)
|
||||
|
||||
type Spinner struct {
|
||||
client *spinner.Spinner
|
||||
}
|
||||
|
||||
func NewSpinner(suffix string) *Spinner {
|
||||
if Quiet {
|
||||
return &Spinner{}
|
||||
}
|
||||
s := spinner.New(spinner.CharSets[36], 100*time.Millisecond)
|
||||
s.Suffix = suffix
|
||||
return &Spinner{client: s}
|
||||
}
|
||||
|
||||
func (s *Spinner) Start() {
|
||||
if s.client == nil {
|
||||
return
|
||||
}
|
||||
s.client.Start()
|
||||
}
|
||||
func (s *Spinner) Stop() {
|
||||
if s.client == nil {
|
||||
return
|
||||
}
|
||||
s.client.Stop()
|
||||
}
|
||||
|
||||
// TODO: Expose an interface for progressbar
|
||||
type ProgressBar struct {
|
||||
client *pb.ProgressBar
|
||||
}
|
||||
|
||||
func PbStartNew(total int) *ProgressBar {
|
||||
if Quiet {
|
||||
return &ProgressBar{}
|
||||
}
|
||||
bar := pb.StartNew(total)
|
||||
return &ProgressBar{client: bar}
|
||||
}
|
||||
|
||||
func (p *ProgressBar) Increment() {
|
||||
if p.client == nil {
|
||||
return
|
||||
}
|
||||
p.client.Increment()
|
||||
}
|
||||
func (p *ProgressBar) Finish() {
|
||||
if p.client == nil {
|
||||
return
|
||||
}
|
||||
p.client.Finish()
|
||||
}
|
||||
@@ -33,7 +33,7 @@ type Operation interface {
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
dbc db.Operations
|
||||
dbc db.Operation
|
||||
}
|
||||
|
||||
func NewClient(dbc db.Config) Client {
|
||||
|
||||
@@ -26,41 +26,26 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
func TestClient_FillInfo(t *testing.T) {
|
||||
type getSeverityOutput struct {
|
||||
severity dbTypes.Severity
|
||||
err error
|
||||
}
|
||||
type getSeverity struct {
|
||||
input string
|
||||
output getSeverityOutput
|
||||
}
|
||||
type getVulnerabilityOutput struct {
|
||||
vulnerability dbTypes.Vulnerability
|
||||
err error
|
||||
}
|
||||
type getVulnerability struct {
|
||||
input string
|
||||
output getVulnerabilityOutput
|
||||
}
|
||||
|
||||
type args struct {
|
||||
vulns []types.DetectedVulnerability
|
||||
light bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
getSeverity []getSeverity
|
||||
getVulnerability []getVulnerability
|
||||
getSeverity []db.GetSeverityExpectation
|
||||
getVulnerability []db.GetVulnerabilityExpectation
|
||||
args args
|
||||
expected []types.DetectedVulnerability
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
getVulnerability: []getVulnerability{
|
||||
getVulnerability: []db.GetVulnerabilityExpectation{
|
||||
{
|
||||
input: "CVE-2019-0001",
|
||||
output: getVulnerabilityOutput{
|
||||
vulnerability: dbTypes.Vulnerability{
|
||||
Args: db.GetVulnerabilityArgs{
|
||||
VulnerabilityID: "CVE-2019-0001",
|
||||
},
|
||||
Returns: db.GetVulnerabilityReturns{
|
||||
Vulnerability: dbTypes.Vulnerability{
|
||||
Title: "dos",
|
||||
Description: "dos vulnerability",
|
||||
Severity: dbTypes.SeverityMedium.String(),
|
||||
@@ -89,17 +74,21 @@ func TestClient_FillInfo(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "happy path with light option",
|
||||
getSeverity: []getSeverity{
|
||||
getSeverity: []db.GetSeverityExpectation{
|
||||
{
|
||||
input: "CVE-2019-0001",
|
||||
output: getSeverityOutput{
|
||||
severity: dbTypes.SeverityCritical,
|
||||
Args: db.GetSeverityArgs{
|
||||
VulnerabilityID: "CVE-2019-0001",
|
||||
},
|
||||
Returns: db.GetSeverityReturns{
|
||||
Severity: dbTypes.SeverityCritical,
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "CVE-2019-0002",
|
||||
output: getSeverityOutput{
|
||||
severity: dbTypes.SeverityHigh,
|
||||
Args: db.GetSeverityArgs{
|
||||
VulnerabilityID: "CVE-2019-0002",
|
||||
},
|
||||
Returns: db.GetSeverityReturns{
|
||||
Severity: dbTypes.SeverityHigh,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -127,11 +116,13 @@ func TestClient_FillInfo(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "GetVulnerability returns an error",
|
||||
getVulnerability: []getVulnerability{
|
||||
getVulnerability: []db.GetVulnerabilityExpectation{
|
||||
{
|
||||
input: "CVE-2019-0004",
|
||||
output: getVulnerabilityOutput{
|
||||
err: xerrors.New("failed"),
|
||||
Args: db.GetVulnerabilityArgs{
|
||||
VulnerabilityID: "CVE-2019-0004",
|
||||
},
|
||||
Returns: db.GetVulnerabilityReturns{
|
||||
Err: xerrors.New("failed"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -147,11 +138,13 @@ func TestClient_FillInfo(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "GetSeverity returns an error",
|
||||
getSeverity: []getSeverity{
|
||||
getSeverity: []db.GetSeverityExpectation{
|
||||
{
|
||||
input: "CVE-2019-0003",
|
||||
output: getSeverityOutput{
|
||||
err: xerrors.New("failed"),
|
||||
Args: db.GetSeverityArgs{
|
||||
VulnerabilityID: "CVE-2019-0003",
|
||||
},
|
||||
Returns: db.GetSeverityReturns{
|
||||
Err: xerrors.New("failed"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -174,18 +167,13 @@ func TestClient_FillInfo(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mockDBConfig := new(db.MockDBConfig)
|
||||
mockDBConfig := new(db.MockOperation)
|
||||
mockDBConfig.ApplyGetSeverityExpectations(tt.getSeverity)
|
||||
mockDBConfig.ApplyGetVulnerabilityExpectations(tt.getVulnerability)
|
||||
|
||||
c := Client{
|
||||
dbc: mockDBConfig,
|
||||
}
|
||||
for _, gs := range tt.getSeverity {
|
||||
mockDBConfig.On("GetSeverity", gs.input).Return(
|
||||
gs.output.severity, gs.output.err)
|
||||
}
|
||||
for _, gv := range tt.getVulnerability {
|
||||
mockDBConfig.On("GetVulnerability", gv.input).Return(
|
||||
gv.output.vulnerability, gv.output.err)
|
||||
}
|
||||
|
||||
c.FillInfo(tt.args.vulns, tt.args.light)
|
||||
assert.Equal(t, tt.expected, tt.args.vulns, tt.name)
|
||||
|
||||
Reference in New Issue
Block a user