Compare commits

..

19 Commits

Author SHA1 Message Date
Teppei Fukuda
42043a0888 fix(client): add image name and build time (#402)
* WIP: Add imageName and BuildTime for Remote detector

Signed-off-by: Simarpreet Singh <simar@linux.com>

* wip

Signed-off-by: Simarpreet Singh <simar@linux.com>

* change name from build_time to created

* remove an unused function

* fix(library): add image_name and created_at

* fix(ospkg): add image_name and created_at

* fix(scan): add image_name and created_at

* fix(library): remove unused param

Co-authored-by: Simarpreet Singh <simar@linux.com>
2020-02-16 10:35:53 +02:00
Teppei Fukuda
246793e873 fix(redhat): use binary package name for OVAL (#393)
* fix(redhat): use binary package name for OVAL

* test(redhat): add a test

* test(imtegration): update golden files
2020-01-28 15:59:47 +02:00
Takuya N
692b0f1410 cli: append warning when --template option is ignored (#391)
* test: cli: append warning when --template option is ignored

to avoid --template is silently ignored when --format <table|json>
or no --format is passed.

Signed-off-by: Takuya Noguchi <takninnovationresearch@gmail.com>

* cli: append warning when --template option is ignored

to avoid --template is silently ignored when --format <table|json>
or no --format is passed.

Signed-off-by: Takuya Noguchi <takninnovationresearch@gmail.com>

* test: cli: append warning when --format template is ignored

when --template is not specified

Signed-off-by: Takuya Noguchi <takninnovationresearch@gmail.com>

* cli: append warning when --format template is ignored

when --template is not specified

Signed-off-by: Takuya Noguchi <takninnovationresearch@gmail.com>

Co-authored-by: Teppei Fukuda <knqyf263@gmail.com>
2020-01-28 13:32:57 +02:00
Teppei Fukuda
0629e1d731 fix(cli): reject multiple images (#392) 2020-01-28 12:02:34 +02:00
Takuya N
9707c7bcb1 Initial GitLab CI template to deeply integrated with GitLab Container Scanning (#376)
Signed-off-by: Takuya Noguchi <takninnovationresearch@gmail.com>
2020-01-26 16:08:44 +02:00
Davin Kevin
194fbef73c feat(): include GitLab template inside the docker container (#388)
Co-authored-by: Teppei Fukuda <knqyf263@gmail.com>
2020-01-26 11:09:07 +02:00
Takuya N
f7db00c1eb Modify template for GitLab Container Scanning (#387)
Signed-off-by: Takuya Noguchi <takninnovationresearch@gmail.com>
2020-01-26 10:04:27 +02:00
Teppei Fukuda
2f4b31ecc6 chore(goreleaser): bump up to 0.124.1 (#383) 2020-01-23 14:13:01 +02:00
Takuya N
9289624688 doc: Update GitLab CI example documentation (#375)
Signed-off-by: Takuya Noguchi <takninnovationresearch@gmail.com>

Co-authored-by: Teppei Fukuda <knqyf263@gmail.com>
2020-01-23 12:08:18 +02:00
Teppei Fukuda
5a8749cd5b chore: add install script (#370)
* chore: add install script

* installer: change perms to include +x

Signed-off-by: Simarpreet Singh <simar@linux.com>

Co-authored-by: Simarpreet Singh <simar@linux.com>
2020-01-19 09:13:36 +02:00
Aruneko
4a7fb525d7 fix typo in example of .gitlab-ci.yml (#373) 2020-01-17 12:16:00 +02:00
Teppei Fukuda
8888fcafa7 chore(goreleaser): change name_template to file_name_template (#369) 2020-01-14 12:30:53 +02:00
Manuel Rüger
63a8c6d26b Integrate with Gitlab Container Scanning (#367)
This PR integrates trivy with Gitlab Container Scanning and provides a
similar report. It adds the required template to the release tarball for easy
consumption.

https://docs.gitlab.com/ee/user/application_security/container_scanning/
https://gitlab.com/gitlab-org/gitlab/issues/11947
2020-01-14 11:46:14 +02:00
Teppei Fukuda
fc222bed7c chore: change a licence in goreleaser.yml (#365) 2020-01-13 12:58:22 +02:00
Manuel Rüger
6132ff93a2 template: Load template from paths (#202)
Signed-off-by: Manuel Rüger <manuel@rueg.eu>

Co-authored-by: Teppei Fukuda <knqyf263@gmail.com>
2020-01-13 11:39:02 +02:00
Manuel Rüger
87556aa741 Dockerfile: Update to alpine 3.11 (#361)
Co-authored-by: Teppei Fukuda <knqyf263@gmail.com>
2020-01-13 10:45:55 +02:00
Masahiro Fujimura
43362b2832 Fix inifinite loop when resolving dependencies of packages in Alpine (#364)
* Change fanal ref

* Fix Inifinite loop when resolving dependencies of packages in Alpine
2020-01-12 18:39:21 +02:00
Simarpreet Singh
db2d0c2e9b docker_engine_test: Add more OSes (#358)
* docker_engine_test: Add more OSes

Fixes: https://github.com/aquasecurity/trivy/issues/356

Signed-off-by: Simarpreet Singh <simar@linux.com>

* integration: Add all OSes for docker mode.

Signed-off-by: Simarpreet Singh <simar@linux.com>
2020-01-10 21:25:43 +02:00
Huang Huang
922d493159 Add EOL Date for alpine 3.11 (#359)
Ref: https://endoflife.date/alpine
2020-01-08 10:33:17 +02:00
44 changed files with 1582 additions and 263 deletions

View File

@@ -1,5 +1,5 @@
FROM alpine:3.10
FROM alpine:3.11
RUN apk --no-cache add ca-certificates git rpm
COPY trivy /usr/local/bin/trivy
COPY contrib/gitlab.tpl contrib/gitlab.tpl
ENTRYPOINT ["trivy"]

View File

@@ -32,6 +32,7 @@ A Simple and Comprehensive Vulnerability Scanner for Containers, Suitable for CI
- [Scan an image](#scan-an-image)
- [Scan an image file](#scan-an-image-file)
- [Save the results as JSON](#save-the-results-as-json)
- [Save the results using a template](#save-the-results-using-a-template)
- [Filter the vulnerabilities by severities](#filter-the-vulnerabilities-by-severities)
- [Filter the vulnerabilities by type](#filter-the-vulnerabilities-by-type)
- [Skip an update of vulnerability DB](#skip-update-of-vulnerability-db)
@@ -48,7 +49,7 @@ A Simple and Comprehensive Vulnerability Scanner for Containers, Suitable for CI
- [Continuous Integration (CI)](#continuous-integration-ci)
- [Travis CI](#travis-ci)
- [CircleCI](#circleci)
- [GitLab CI](#gitlab)
- [GitLab CI](#gitlab-ci)
- [Authorization for Private Docker Registry](#authorization-for-private-docker-registry)
- [Vulnerability Detection](#vulnerability-detection)
- [OS Packages](#os-packages)
@@ -654,6 +655,25 @@ $ trivy -f json -o results.json golang:1.12-alpine
</details>
### Save the results using a template
```
$ trivy --format template --template "{{ range . }} {{ .Target }} {{ end }}" golang:1.12-alpine
```
<details>
<summary>Result</summary>
```
2020-01-02T18:02:32.856+0100 INFO Detecting Alpine vulnerabilities...
golang:1.12-alpine (alpine 3.10.2)
```
</details>
You can load templates from a file prefixing the template path with an @.
```
$ trivy --format template --template "@/path/to/template" golang:1.12-alpine
```
### Filter the vulnerabilities by severities
```
@@ -1219,7 +1239,7 @@ workflows:
Example: https://circleci.com/gh/aquasecurity/trivy-ci-test
Repository: https://github.com/aquasecurity/trivy-ci-test
## GitLab
## GitLab CI
```
$ cat .gitlab-ci.yml
@@ -1228,7 +1248,7 @@ stages:
trivy:
stage: test
image: docker:19.03.1
image: docker:stable
services:
- name: docker:dind
entrypoint: ["env", "-u", "DOCKER_HOST"]
@@ -1238,6 +1258,7 @@ trivy:
DOCKER_DRIVER: overlay2
# See https://github.com/docker-library/docker/pull/166
DOCKER_TLS_CERTDIR: ""
IMAGE: trivy-ci-test:$CI_COMMIT_SHA
before_script:
- apk add --no-cache curl
- export VERSION=$(curl --silent "https://api.github.com/repos/aquasecurity/trivy/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
@@ -1246,13 +1267,22 @@ trivy:
- tar zxvf trivy_${VERSION}_Linux-64bit.tar.gz
allow_failure: true
script:
- docker build -t trivy-ci-test:$CI_COMMIT_SHA .
- ./trivy --exit-code 0 --cache-dir $CI_PROJECT_DIR/.trivycache/ --no-progress --severity HIGH trivy-ci-test:$CI_COMMIT_SHA
- ./trivy --exit-code 1 --severity CRITICAL --no-progress trivy-ci-test:$CI_COMMIT_SHA
# Build image
- docker build -t $IMAGE .
# Build report
- ./trivy --exit-code 0 --cache-dir .trivycache/ --no-progress --format template --template "@contrib/gitlab.tpl" -o gl-container-scanning-report.json $IMAGE
# Print report
- ./trivy --exit-code 0 --cache-dir .trivycache/ --no-progress --severity HIGH $IMAGE
# Fail on high and critical vulnerabilities
- ./trivy --exit-code 1 --cache-dir .trivycache/ --severity CRITICAL --no-progress $IMAGE
cache:
paths:
- $CI_PROJECT_DIR/.trivycache/
```
- .trivycache/
# Enables https://docs.gitlab.com/ee/user/application_security/container_scanning/ (Container Scanning report is available on GitLab EE Ultimate or GitLab.com Gold)
artifacts:
reports:
container_scanning: gl-container-scanning-report.json
```
## Authorization for Private Docker Registry

View File

@@ -3,7 +3,7 @@ FROM circleci/golang:1.13-buster
RUN sudo apt-get -y update \
&& sudo apt-get -y install rpm reprepro createrepo
ARG GORELEASER_VERSION=0.110.0
ARG GORELEASER_VERSION=0.124.1
ARG GORELEASER_ARTIFACT=goreleaser_Linux_x86_64.tar.gz
RUN wget https://github.com/goreleaser/goreleaser/releases/download/v${GORELEASER_VERSION}/${GORELEASER_ARTIFACT} \
&& sudo tar -xzf ${GORELEASER_ARTIFACT} -C /usr/bin/ goreleaser \

View File

@@ -0,0 +1,29 @@
Trivy_container_scanning:
stage: test
image:
name: alpine:3.11
variables:
# Override the GIT_STRATEGY variable in your `.gitlab-ci.yml` file and set it to `fetch` if you want to provide a `clair-whitelist.yml`
# file. See https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#overriding-the-container-scanning-template
# for details
GIT_STRATEGY: none
IMAGE: "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
allow_failure: true
before_script:
- export TRIVY_VERSION=${TRIVY_VERSION:-v0.4.3}
- apk add --no-cache curl docker-cli
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/master/contrib/install.sh | sh -s -- -b /usr/local/bin ${TRIVY_VERSION}
- curl -sSL -o /tmp/trivy-gitlab.tpl https://github.com/aquasecurity/trivy/raw/${TRIVY_VERSION}/contrib/gitlab.tpl
script:
- trivy --exit-code 0 --cache-dir .trivycache/ --no-progress --format template --template "@/tmp/trivy-gitlab.tpl" -o gl-container-scanning-report.json $IMAGE
cache:
paths:
- .trivycache/
artifacts:
reports:
container_scanning: gl-container-scanning-report.json
dependencies: []
only:
refs:
- branches

80
contrib/gitlab.tpl Normal file
View File

@@ -0,0 +1,80 @@
{{- /* Template based on https://docs.gitlab.com/ee/user/application_security/container_scanning/#reports-json-format */ -}}
{
"version": "2.3",
"vulnerabilities": [
{{- $first := true }}
{{- range . }}
{{- $target := .Target }}
{{- range .Vulnerabilities -}}
{{- if $first -}}
{{- $first = false -}}
{{ else -}}
,
{{- end }}
{
"category": "container_scanning",
"message": {{ .Title | printf "%q" }},
"description": {{ .Description | printf "%q" }},
"cve": "{{ .VulnerabilityID }}",
"severity": {{ if eq .Severity "UNKNOWN" -}}
"Unknown"
{{- else if eq .Severity "LOW" -}}
"Low"
{{- else if eq .Severity "MEDIUM" -}}
"Medium"
{{- else if eq .Severity "HIGH" -}}
"High"
{{- else if eq .Severity "CRITICAL" -}}
"Critical"
{{- else -}}
"{{ .Severity }}"
{{- end }},
"confidence": "Unknown",
"solution": {{ if .FixedVersion -}}
"Upgrade {{ .PkgName }} to {{ .FixedVersion }}"
{{- else -}}
"No solution provided"
{{- end }},
"scanner": {
"id": "trivy",
"name": "trivy"
},
"location": {
"dependency": {
"package": {
"name": "{{ .PkgName }}"
},
"version": "{{ .InstalledVersion }}"
},
{{- /* TODO: No mapping available - https://github.com/aquasecurity/trivy/issues/332 */}}
"operating_system": "Unknown",
"image": "{{ $target }}"
},
"identifiers": [
{
{{- /* TODO: Type not extractable - https://github.com/aquasecurity/trivy-db/pull/24 */}}
"type": "cve",
"name": "{{ .VulnerabilityID }}",
"value": "{{ .VulnerabilityID }}",
"url": ""
}
],
"links": [
{{- $first := true -}}
{{- range .References -}}
{{- if $first -}}
{{- $first = false }}
{{- else -}}
,
{{- end -}}
{
"url": "{{ . }}"
}
{{- end }}
]
}
{{- end -}}
{{- end }}
],
"remediations": []
}

409
contrib/install.sh Executable file
View File

@@ -0,0 +1,409 @@
#!/bin/sh
set -e
# Code generated by godownloader on 2020-01-14T10:03:29Z. DO NOT EDIT.
#
usage() {
this=$1
cat <<EOF
$this: download go binaries for aquasecurity/trivy
Usage: $this [-b] bindir [-d] [tag]
-b sets bindir or installation directory, Defaults to ./bin
-d turns on debug logging
[tag] is a tag from
https://github.com/aquasecurity/trivy/releases
If tag is missing, then the latest will be used.
Generated by godownloader
https://github.com/goreleaser/godownloader
EOF
exit 2
}
parse_args() {
#BINDIR is ./bin unless set be ENV
# over-ridden by flag below
BINDIR=${BINDIR:-./bin}
while getopts "b:dh?x" arg; do
case "$arg" in
b) BINDIR="$OPTARG" ;;
d) log_set_priority 10 ;;
h | \?) usage "$0" ;;
x) set -x ;;
esac
done
shift $((OPTIND - 1))
TAG=$1
}
# this function wraps all the destructive operations
# if a curl|bash cuts off the end of the script due to
# network, either nothing will happen or will syntax error
# out preventing half-done work
execute() {
tmpdir=$(mktemp -d)
log_debug "downloading files into ${tmpdir}"
http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}"
http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}"
hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}"
srcdir="${tmpdir}"
(cd "${tmpdir}" && untar "${TARBALL}")
test ! -d "${BINDIR}" && install -d "${BINDIR}"
for binexe in $BINARIES; do
if [ "$OS" = "windows" ]; then
binexe="${binexe}.exe"
fi
install "${srcdir}/${binexe}" "${BINDIR}/"
log_info "installed ${BINDIR}/${binexe}"
done
rm -rf "${tmpdir}"
}
get_binaries() {
case "$PLATFORM" in
darwin/386) BINARIES="trivy" ;;
darwin/amd64) BINARIES="trivy" ;;
darwin/arm64) BINARIES="trivy" ;;
darwin/armv7) BINARIES="trivy" ;;
freebsd/386) BINARIES="trivy" ;;
freebsd/amd64) BINARIES="trivy" ;;
freebsd/arm64) BINARIES="trivy" ;;
freebsd/armv7) BINARIES="trivy" ;;
linux/386) BINARIES="trivy" ;;
linux/amd64) BINARIES="trivy" ;;
linux/arm64) BINARIES="trivy" ;;
linux/armv7) BINARIES="trivy" ;;
openbsd/386) BINARIES="trivy" ;;
openbsd/amd64) BINARIES="trivy" ;;
openbsd/arm64) BINARIES="trivy" ;;
openbsd/armv7) BINARIES="trivy" ;;
*)
log_crit "platform $PLATFORM is not supported. Make sure this script is up-to-date and file request at https://github.com/${PREFIX}/issues/new"
exit 1
;;
esac
}
tag_to_version() {
if [ -z "${TAG}" ]; then
log_info "checking GitHub for latest tag"
else
log_info "checking GitHub for tag '${TAG}'"
fi
REALTAG=$(github_release "$OWNER/$REPO" "${TAG}") && true
if test -z "$REALTAG"; then
log_crit "unable to find '${TAG}' - use 'latest' or see https://github.com/${PREFIX}/releases for details"
exit 1
fi
# if version starts with 'v', remove it
TAG="$REALTAG"
VERSION=${TAG#v}
}
adjust_format() {
# change format (tar.gz or zip) based on OS
true
}
adjust_os() {
# adjust archive name based on OS
case ${OS} in
386) OS=32bit ;;
amd64) OS=64bit ;;
arm) OS=ARM ;;
arm64) OS=ARM64 ;;
darwin) OS=macOS ;;
dragonfly) OS=DragonFlyBSD ;;
freebsd) OS=FreeBSD ;;
linux) OS=Linux ;;
netbsd) OS=NetBSD ;;
openbsd) OS=OpenBSD ;;
esac
true
}
adjust_arch() {
# adjust archive name based on ARCH
case ${ARCH} in
386) ARCH=32bit ;;
amd64) ARCH=64bit ;;
arm) ARCH=ARM ;;
arm64) ARCH=ARM64 ;;
darwin) ARCH=macOS ;;
dragonfly) ARCH=DragonFlyBSD ;;
freebsd) ARCH=FreeBSD ;;
linux) ARCH=Linux ;;
netbsd) ARCH=NetBSD ;;
openbsd) ARCH=OpenBSD ;;
esac
true
}
cat /dev/null <<EOF
------------------------------------------------------------------------
https://github.com/client9/shlib - portable posix shell functions
Public domain - http://unlicense.org
https://github.com/client9/shlib/blob/master/LICENSE.md
but credit (and pull requests) appreciated.
------------------------------------------------------------------------
EOF
is_command() {
command -v "$1" >/dev/null
}
echoerr() {
echo "$@" 1>&2
}
log_prefix() {
echo "$0"
}
_logp=6
log_set_priority() {
_logp="$1"
}
log_priority() {
if test -z "$1"; then
echo "$_logp"
return
fi
[ "$1" -le "$_logp" ]
}
log_tag() {
case $1 in
0) echo "emerg" ;;
1) echo "alert" ;;
2) echo "crit" ;;
3) echo "err" ;;
4) echo "warning" ;;
5) echo "notice" ;;
6) echo "info" ;;
7) echo "debug" ;;
*) echo "$1" ;;
esac
}
log_debug() {
log_priority 7 || return 0
echoerr "$(log_prefix)" "$(log_tag 7)" "$@"
}
log_info() {
log_priority 6 || return 0
echoerr "$(log_prefix)" "$(log_tag 6)" "$@"
}
log_err() {
log_priority 3 || return 0
echoerr "$(log_prefix)" "$(log_tag 3)" "$@"
}
log_crit() {
log_priority 2 || return 0
echoerr "$(log_prefix)" "$(log_tag 2)" "$@"
}
uname_os() {
os=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$os" in
cygwin_nt*) os="windows" ;;
mingw*) os="windows" ;;
msys_nt*) os="windows" ;;
esac
echo "$os"
}
uname_arch() {
arch=$(uname -m)
case $arch in
x86_64) arch="amd64" ;;
x86) arch="386" ;;
i686) arch="386" ;;
i386) arch="386" ;;
aarch64) arch="arm64" ;;
armv5*) arch="armv5" ;;
armv6*) arch="armv6" ;;
armv7*) arch="armv7" ;;
esac
echo ${arch}
}
uname_os_check() {
os=$(uname_os)
case "$os" in
darwin) return 0 ;;
dragonfly) return 0 ;;
freebsd) return 0 ;;
linux) return 0 ;;
android) return 0 ;;
nacl) return 0 ;;
netbsd) return 0 ;;
openbsd) return 0 ;;
plan9) return 0 ;;
solaris) return 0 ;;
windows) return 0 ;;
esac
log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib"
return 1
}
uname_arch_check() {
arch=$(uname_arch)
case "$arch" in
386) return 0 ;;
amd64) return 0 ;;
arm64) return 0 ;;
armv5) return 0 ;;
armv6) return 0 ;;
armv7) return 0 ;;
ppc64) return 0 ;;
ppc64le) return 0 ;;
mips) return 0 ;;
mipsle) return 0 ;;
mips64) return 0 ;;
mips64le) return 0 ;;
s390x) return 0 ;;
amd64p32) return 0 ;;
esac
log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value. Please file bug report at https://github.com/client9/shlib"
return 1
}
untar() {
tarball=$1
case "${tarball}" in
*.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" ;;
*.tar) tar --no-same-owner -xf "${tarball}" ;;
*.zip) unzip "${tarball}" ;;
*)
log_err "untar unknown archive format for ${tarball}"
return 1
;;
esac
}
http_download_curl() {
local_file=$1
source_url=$2
header=$3
if [ -z "$header" ]; then
code=$(curl -w '%{http_code}' -sL -o "$local_file" "$source_url")
else
code=$(curl -w '%{http_code}' -sL -H "$header" -o "$local_file" "$source_url")
fi
if [ "$code" != "200" ]; then
log_debug "http_download_curl received HTTP status $code"
return 1
fi
return 0
}
http_download_wget() {
local_file=$1
source_url=$2
header=$3
if [ -z "$header" ]; then
wget -q -O "$local_file" "$source_url"
else
wget -q --header "$header" -O "$local_file" "$source_url"
fi
}
http_download() {
log_debug "http_download $2"
if is_command curl; then
http_download_curl "$@"
return
elif is_command wget; then
http_download_wget "$@"
return
fi
log_crit "http_download unable to find wget or curl"
return 1
}
http_copy() {
tmp=$(mktemp)
http_download "${tmp}" "$1" "$2" || return 1
body=$(cat "$tmp")
rm -f "${tmp}"
echo "$body"
}
github_release() {
owner_repo=$1
version=$2
test -z "$version" && version="latest"
giturl="https://github.com/${owner_repo}/releases/${version}"
json=$(http_copy "$giturl" "Accept:application/json")
test -z "$json" && return 1
version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//')
test -z "$version" && return 1
echo "$version"
}
hash_sha256() {
TARGET=${1:-/dev/stdin}
if is_command gsha256sum; then
hash=$(gsha256sum "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command sha256sum; then
hash=$(sha256sum "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command shasum; then
hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command openssl; then
hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f a
else
log_crit "hash_sha256 unable to find command to compute sha-256 hash"
return 1
fi
}
hash_sha256_verify() {
TARGET=$1
checksums=$2
if [ -z "$checksums" ]; then
log_err "hash_sha256_verify checksum file not specified in arg2"
return 1
fi
BASENAME=${TARGET##*/}
want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1)
if [ -z "$want" ]; then
log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'"
return 1
fi
got=$(hash_sha256 "$TARGET")
if [ "$want" != "$got" ]; then
log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got"
return 1
fi
}
cat /dev/null <<EOF
------------------------------------------------------------------------
End of functions from https://github.com/client9/shlib
------------------------------------------------------------------------
EOF
PROJECT_NAME="trivy"
OWNER=aquasecurity
REPO="trivy"
BINARY=trivy
FORMAT=tar.gz
OS=$(uname_os)
ARCH=$(uname_arch)
PREFIX="$OWNER/$REPO"
# use in logging routines
log_prefix() {
echo "$PREFIX"
}
PLATFORM="${OS}/${ARCH}"
GITHUB_DOWNLOAD=https://github.com/${OWNER}/${REPO}/releases/download
uname_os_check "$OS"
uname_arch_check "$ARCH"
parse_args "$@"
get_binaries
tag_to_version
adjust_format
adjust_os
adjust_arch
log_info "found version: ${VERSION} for ${TAG}/${OS}/${ARCH}"
NAME=${PROJECT_NAME}_${VERSION}_${OS}-${ARCH}
TARBALL=${NAME}.${FORMAT}
TARBALL_URL=${GITHUB_DOWNLOAD}/${TAG}/${TARBALL}
CHECKSUM=${PROJECT_NAME}_${VERSION}_checksums.txt
CHECKSUM_URL=${GITHUB_DOWNLOAD}/${TAG}/${CHECKSUM}
execute

6
go.mod
View File

@@ -3,7 +3,8 @@ module github.com/aquasecurity/trivy
go 1.13
require (
github.com/aquasecurity/fanal v0.0.0-20200105203922-a3284d4a2d11
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 // indirect
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-20191226181755-d6cabf5bc5d1
github.com/caarlos0/env/v6 v6.0.0
@@ -20,8 +21,9 @@ require (
github.com/knqyf263/go-version v1.1.1
github.com/kylelemons/godebug v1.1.0
github.com/olekukonko/tablewriter v0.0.2-0.20190607075207-195002e6e56a
github.com/prometheus/procfs v0.0.5 // indirect
github.com/stretchr/testify v1.4.0
github.com/twitchtv/twirp v5.9.0+incompatible
github.com/twitchtv/twirp v5.10.1+incompatible
github.com/urfave/cli v1.20.0
go.uber.org/atomic v1.5.1 // indirect
go.uber.org/multierr v1.4.0 // indirect

31
go.sum
View File

@@ -10,6 +10,8 @@ github.com/GoogleCloudPlatform/docker-credential-gcr v1.5.0 h1:wykTgKwhVr2t2qs+x
github.com/GoogleCloudPlatform/docker-credential-gcr v1.5.0/go.mod h1:BB1eHdMLYEFuFdBlRMb0N7YGVdM5s6Pt0njxgvfbGGs=
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/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA=
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
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=
@@ -23,14 +25,12 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5Vpd
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/miniredis/v2 v2.11.0/go.mod h1:UA48pmi7aSazcGAvcdKcBB49z521IC9VjTTRz2nIaJE=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
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-20200105203922-a3284d4a2d11 h1:TDDvXf5j45gdgbFLMQO4XDHMF2bHYKJ3CJnOy4L43So=
github.com/aquasecurity/fanal v0.0.0-20200105203922-a3284d4a2d11/go.mod h1:I+y3thuZSKnPXWqIOFDH4sk+ekiJ8V/XB71PDzhQxL8=
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=
@@ -57,9 +57,6 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH
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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
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=
@@ -88,8 +85,6 @@ 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=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
@@ -135,8 +130,6 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
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/gomodule/redigo v1.7.1-0.20190322064113-39e2c31b7ca3/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
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=
@@ -179,8 +172,6 @@ github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT
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/klauspost/compress v1.9.3 h1:hkFELABwacUEgBfiguNeQydKv3M9pawBq8o24Ypw9+M=
github.com/klauspost/compress v1.9.3/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/knqyf263/berkeleydb v0.0.0-20190501065933-fafe01fb9662/go.mod h1:bu1CcN4tUtoRcI/B/RFHhxMNKFHVq/c3SV+UTyduoXg=
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d h1:X4cedH4Kn3JPupAwwWuo4AzYp16P0OyLO9d7OnMZc/c=
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d/go.mod h1:o8sgWoz3JADecfc/cTYD92/Et1yMqMy0utV1z+VaZao=
@@ -274,6 +265,8 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ
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/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
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/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
@@ -281,8 +274,6 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
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-20181222201310-74dc9339e414/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/simar7/gokv v0.3.3-0.20191216080237-ab4446a6841b h1:2qPkc0Hnrd6IhlxioXb0RG/NBmIPx2b5y9Z1IKriuxQ=
github.com/simar7/gokv v0.3.3-0.20191216080237-ab4446a6841b/go.mod h1:jXjPspRkuCDCRTRBgfGsfXvW8ofOGh3Y+tjZvoFr7XU=
github.com/simplereach/timeutils v1.2.0/go.mod h1:VVbQDfN/FHRZa1LSqcwo4kNZ62OOyqLLGQKYB3pB0Q8=
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@@ -306,18 +297,15 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
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/twitchtv/twirp v5.10.1+incompatible h1:35js8ID9rYPKkZ0qWnuZw+q+OuCWM1GIibu1F1YImjA=
github.com/twitchtv/twirp v5.10.1+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8=
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=
github.com/yuin/gopher-lua v0.0.0-20190206043414-8bfc7677f583/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
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=
@@ -372,6 +360,7 @@ 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=
@@ -380,7 +369,6 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
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=
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -388,6 +376,7 @@ golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190412213103-97732733099d/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-20190916202348-b4ddaad3f8a3/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=

View File

@@ -33,8 +33,8 @@ nfpms:
homepage: "https://github.com/aquasecurity"
maintainer: "Teppei Fukuda <knqyf263@gmail.com>"
description: "A Fast Vulnerability Scanner for Containers"
license: "MIT"
name_template: "{{.ProjectName}}_{{.Version}}_{{.Os}}-{{.Arch}}"
license: "AGPL-3.0"
file_name_template: "{{.ProjectName}}_{{.Version}}_{{.Os}}-{{.Arch}}"
replacements:
amd64: 64bit
386: 32bit
@@ -65,6 +65,7 @@ archives:
files:
- README.md
- LICENSE
- contrib/gitlab.tpl
brews:
-
@@ -93,3 +94,5 @@ dockers:
- "--label=org.label-schema.build-date={{ .Date }}"
- "--label=org.label-schema.vcs=https://github.com/aquasecurity/trivy"
- "--label=org.label-schema.vcs-ref={{ .FullCommit }}"
extra_files:
- contrib/gitlab.tpl

View File

@@ -6,6 +6,7 @@ import (
"context"
"io/ioutil"
"os"
"strings"
"testing"
"github.com/stretchr/testify/require"
@@ -19,16 +20,211 @@ import (
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,
@@ -64,7 +260,7 @@ func TestRun_WithDockerEngine(t *testing.T) {
require.NoError(t, err, tc.name)
// tag our image to something unique
err = cli.ImageTag(ctx, "alpine:3.10", tc.testfile)
err = cli.ImageTag(ctx, tc.imageTag, tc.testfile)
require.NoError(t, err, tc.name)
}
@@ -75,6 +271,20 @@ func TestRun_WithDockerEngine(t *testing.T) {
// 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())
}

View File

@@ -12628,6 +12628,32 @@
"https://utcc.utoronto.ca/~cks/space/blog/sysadmin/TarFindingTruncateBug"
]
},
{
"VulnerabilityID": "CVE-2019-12735",
"PkgName": "vim-minimal",
"InstalledVersion": "2:7.4.629-5.el6_8.1",
"FixedVersion": "2:7.4.629-5.el6_10.2",
"Title": "vim/neovim: ':source!' command allows arbitrary command execution via modelines",
"Description": "getchar.c in Vim before 8.1.1365 and Neovim before 0.3.6 allows remote attackers to execute arbitrary OS commands via the :source! command in a modeline, as demonstrated by execute in Vim, and assert_fails or nvim_input in Neovim.",
"Severity": "CRITICAL",
"References": [
"http://lists.opensuse.org/opensuse-security-announce/2019-06/msg00031.html",
"http://lists.opensuse.org/opensuse-security-announce/2019-06/msg00036.html",
"http://lists.opensuse.org/opensuse-security-announce/2019-06/msg00037.html",
"http://www.securityfocus.com/bid/108724",
"https://bugs.debian.org/930020",
"https://bugs.debian.org/930024",
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-12735",
"https://github.com/neovim/neovim/pull/10082",
"https://github.com/numirias/security/blob/master/doc/2019-06-04_ace-vim-neovim.md",
"https://github.com/vim/vim/commit/53575521406739cf20bbe4e384d88e7dca11f040",
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/2BMDSHTF754TITC6AQJPCS5IRIDMMIM7/",
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/TRIRBC2YRGKPAWVRMZS4SZTGGCVRVZPR/",
"https://usn.ubuntu.com/4016-1/",
"https://usn.ubuntu.com/4016-2/",
"https://www.debian.org/security/2019/dsa-4467"
]
},
{
"VulnerabilityID": "CVE-2017-5953",
"PkgName": "vim-minimal",

View File

@@ -112,6 +112,32 @@
"https://usn.ubuntu.com/3816-1/",
"https://www.exploit-db.com/exploits/45714/"
]
},
{
"VulnerabilityID": "CVE-2019-12735",
"PkgName": "vim-minimal",
"InstalledVersion": "2:7.4.160-5.el7",
"FixedVersion": "2:7.4.160-6.el7_6",
"Title": "vim/neovim: ':source!' command allows arbitrary command execution via modelines",
"Description": "getchar.c in Vim before 8.1.1365 and Neovim before 0.3.6 allows remote attackers to execute arbitrary OS commands via the :source! command in a modeline, as demonstrated by execute in Vim, and assert_fails or nvim_input in Neovim.",
"Severity": "CRITICAL",
"References": [
"http://lists.opensuse.org/opensuse-security-announce/2019-06/msg00031.html",
"http://lists.opensuse.org/opensuse-security-announce/2019-06/msg00036.html",
"http://lists.opensuse.org/opensuse-security-announce/2019-06/msg00037.html",
"http://www.securityfocus.com/bid/108724",
"https://bugs.debian.org/930020",
"https://bugs.debian.org/930024",
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-12735",
"https://github.com/neovim/neovim/pull/10082",
"https://github.com/numirias/security/blob/master/doc/2019-06-04_ace-vim-neovim.md",
"https://github.com/vim/vim/commit/53575521406739cf20bbe4e384d88e7dca11f040",
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/2BMDSHTF754TITC6AQJPCS5IRIDMMIM7/",
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/TRIRBC2YRGKPAWVRMZS4SZTGGCVRVZPR/",
"https://usn.ubuntu.com/4016-1/",
"https://usn.ubuntu.com/4016-2/",
"https://www.debian.org/security/2019/dsa-4467"
]
}
]
}

View File

@@ -1708,6 +1708,32 @@
"https://lists.apache.org/thread.html/5960a34a524848cd722fd7ab7e2227eac10107b0f90d9d1e9c3caa74@%3Cuser.cassandra.apache.org%3E",
"https://security.netapp.com/advisory/ntap-20190307-0007/"
]
},
{
"VulnerabilityID": "CVE-2019-12735",
"PkgName": "vim-minimal",
"InstalledVersion": "2:7.4.160-5.el7",
"FixedVersion": "2:7.4.160-6.el7_6",
"Title": "vim/neovim: ':source!' command allows arbitrary command execution via modelines",
"Description": "getchar.c in Vim before 8.1.1365 and Neovim before 0.3.6 allows remote attackers to execute arbitrary OS commands via the :source! command in a modeline, as demonstrated by execute in Vim, and assert_fails or nvim_input in Neovim.",
"Severity": "CRITICAL",
"References": [
"http://lists.opensuse.org/opensuse-security-announce/2019-06/msg00031.html",
"http://lists.opensuse.org/opensuse-security-announce/2019-06/msg00036.html",
"http://lists.opensuse.org/opensuse-security-announce/2019-06/msg00037.html",
"http://www.securityfocus.com/bid/108724",
"https://bugs.debian.org/930020",
"https://bugs.debian.org/930024",
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-12735",
"https://github.com/neovim/neovim/pull/10082",
"https://github.com/numirias/security/blob/master/doc/2019-06-04_ace-vim-neovim.md",
"https://github.com/vim/vim/commit/53575521406739cf20bbe4e384d88e7dca11f040",
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/2BMDSHTF754TITC6AQJPCS5IRIDMMIM7/",
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/TRIRBC2YRGKPAWVRMZS4SZTGGCVRVZPR/",
"https://usn.ubuntu.com/4016-1/",
"https://usn.ubuntu.com/4016-2/",
"https://www.debian.org/security/2019/dsa-4467"
]
}
]
}

View File

@@ -11849,6 +11849,32 @@
"https://www.kernel.org/pub/linux/utils/util-linux/v2.27/v2.27-ReleaseNotes"
]
},
{
"VulnerabilityID": "CVE-2019-12735",
"PkgName": "vim-minimal",
"InstalledVersion": "2:7.4.160-5.el7",
"FixedVersion": "2:7.4.160-6.el7_6",
"Title": "vim/neovim: ':source!' command allows arbitrary command execution via modelines",
"Description": "getchar.c in Vim before 8.1.1365 and Neovim before 0.3.6 allows remote attackers to execute arbitrary OS commands via the :source! command in a modeline, as demonstrated by execute in Vim, and assert_fails or nvim_input in Neovim.",
"Severity": "CRITICAL",
"References": [
"http://lists.opensuse.org/opensuse-security-announce/2019-06/msg00031.html",
"http://lists.opensuse.org/opensuse-security-announce/2019-06/msg00036.html",
"http://lists.opensuse.org/opensuse-security-announce/2019-06/msg00037.html",
"http://www.securityfocus.com/bid/108724",
"https://bugs.debian.org/930020",
"https://bugs.debian.org/930024",
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-12735",
"https://github.com/neovim/neovim/pull/10082",
"https://github.com/numirias/security/blob/master/doc/2019-06-04_ace-vim-neovim.md",
"https://github.com/vim/vim/commit/53575521406739cf20bbe4e384d88e7dca11f040",
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/2BMDSHTF754TITC6AQJPCS5IRIDMMIM7/",
"https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/TRIRBC2YRGKPAWVRMZS4SZTGGCVRVZPR/",
"https://usn.ubuntu.com/4016-1/",
"https://usn.ubuntu.com/4016-2/",
"https://www.debian.org/security/2019/dsa-4467"
]
},
{
"VulnerabilityID": "CVE-2017-5953",
"PkgName": "vim-minimal",

View File

@@ -108,6 +108,9 @@ func (c *Config) Init() (err error) {
c.logger.Error(`trivy requires at least 1 argument or --input option`)
cli.ShowAppHelp(c.context)
return xerrors.New("arguments error")
} else if len(args) > 1 {
c.logger.Error(`multiple images cannot be specified`)
return xerrors.New("arguments error")
}
c.Output = os.Stdout

View File

@@ -165,6 +165,17 @@ func TestConfig_Init(t *testing.T) {
CustomHeaders: make(http.Header),
},
},
{
name: "sad: multiple image names",
fields: fields{
severities: "MEDIUM",
},
args: []string{"centos:7", "alpine:3.10"},
logs: []string{
"multiple images cannot be specified",
},
wantErr: "arguments error",
},
{
name: "sad: no image name",
fields: fields{

View File

@@ -37,10 +37,7 @@ func run(c config.Config) (err error) {
// configure cache dir
utils.SetCacheDir(c.CacheDir)
cacheClient, err := cache.New(c.CacheDir)
if err != nil {
return xerrors.Errorf("unable to initialize cache client: %w", err)
}
cacheClient := cache.Initialize(c.CacheDir)
cacheOperation := operation.NewCache(cacheClient)
log.Logger.Debugf("cache dir: %s", utils.CacheDir())

View File

@@ -14,7 +14,7 @@ import (
)
var SuperSet = wire.NewSet(
cache.New,
cache.Initialize,
NewCache,
)

View File

@@ -97,6 +97,16 @@ func New(c *cli.Context) (Config, error) {
}
func (c *Config) Init() (err error) {
if c.Template != "" {
if c.Format == "" {
c.logger.Warn("--template is ignored because --format template is not specified. Use --template option with --format template option.")
} else if c.Format != "template" {
c.logger.Warnf("--template is ignored because --format %s is specified. Use --template option with --format template option.", c.Format)
}
}
if c.Format == "template" && c.Template == "" {
c.logger.Warn("--format template is ignored because --template not is specified. Specify --template option when you use --format template.")
}
if c.onlyUpdate != "" || c.refresh || c.autoRefresh {
c.logger.Warn("--only-update, --refresh and --auto-refresh are unnecessary and ignored now. These commands will be removed in the next version.")
}
@@ -118,6 +128,9 @@ func (c *Config) Init() (err error) {
c.logger.Error(`trivy requires at least 1 argument or --input option`)
cli.ShowAppHelp(c.context)
return xerrors.New("arguments error")
} else if len(args) > 1 {
c.logger.Error(`multiple images cannot be specified`)
return xerrors.New("arguments error")
}
c.Output = os.Stdout

View File

@@ -168,6 +168,68 @@ func TestConfig_Init(t *testing.T) {
onlyUpdate: "alpine",
},
},
{
name: "invalid option combination: --template enabled without --format",
fields: fields{
Template: "@contrib/gitlab.tpl",
severities: "LOW",
},
args: []string{"gitlab/gitlab-ce:12.7.2-ce.0"},
logs: []string{
"--template is ignored because --format template is not specified. Use --template option with --format template option.",
},
want: Config{
AppVersion: "0.0.0",
ImageName: "gitlab/gitlab-ce:12.7.2-ce.0",
Output: os.Stdout,
Severities: []dbTypes.Severity{dbTypes.SeverityLow},
severities: "LOW",
Template: "@contrib/gitlab.tpl",
VulnType: []string{""},
},
},
{
name: "invalid option combination: --template and --format json",
fields: fields{
Format: "json",
Template: "@contrib/gitlab.tpl",
severities: "LOW",
},
args: []string{"gitlab/gitlab-ce:12.7.2-ce.0"},
logs: []string{
"--template is ignored because --format json is specified. Use --template option with --format template option.",
},
want: Config{
AppVersion: "0.0.0",
Format: "json",
ImageName: "gitlab/gitlab-ce:12.7.2-ce.0",
Output: os.Stdout,
Severities: []dbTypes.Severity{dbTypes.SeverityLow},
severities: "LOW",
Template: "@contrib/gitlab.tpl",
VulnType: []string{""},
},
},
{
name: "invalid option combination: --format template without --template",
fields: fields{
Format: "template",
severities: "LOW",
},
args: []string{"gitlab/gitlab-ce:12.7.2-ce.0"},
logs: []string{
"--format template is ignored because --template not is specified. Specify --template option when you use --format template.",
},
want: Config{
AppVersion: "0.0.0",
Format: "template",
ImageName: "gitlab/gitlab-ce:12.7.2-ce.0",
Output: os.Stdout,
Severities: []dbTypes.Severity{dbTypes.SeverityLow},
severities: "LOW",
VulnType: []string{""},
},
},
{
name: "with latest tag",
fields: fields{
@@ -204,6 +266,17 @@ func TestConfig_Init(t *testing.T) {
},
wantErr: "The --skip-update and --download-db-only option can not be specified both",
},
{
name: "sad: multiple image names",
fields: fields{
severities: "MEDIUM",
},
args: []string{"centos:7", "alpine:3.10"},
logs: []string{
"multiple images cannot be specified",
},
wantErr: "arguments error",
},
{
name: "sad: no image name",
fields: fields{

View File

@@ -1,8 +1,10 @@
package standalone
import (
"io/ioutil"
l "log"
"os"
"strings"
"github.com/aquasecurity/fanal/cache"
"github.com/aquasecurity/trivy-db/pkg/db"
@@ -36,10 +38,7 @@ func run(c config.Config) (err error) {
// configure cache dir
utils.SetCacheDir(c.CacheDir)
cacheClient, err := cache.New(c.CacheDir)
if err != nil {
return xerrors.Errorf("unable to initialize cache client: %w", err)
}
cacheClient := cache.Initialize(c.CacheDir)
cacheOperation := operation.NewCache(cacheClient)
log.Logger.Debugf("cache dir: %s", utils.CacheDir())
@@ -83,7 +82,17 @@ func run(c config.Config) (err error) {
c.Severities, c.IgnoreUnfixed, c.IgnoreFile)
}
if err = report.WriteResults(c.Format, c.Output, results, c.Template, c.Light); err != nil {
template := c.Template
if strings.HasPrefix(c.Template, "@") {
buf, err := ioutil.ReadFile(strings.TrimPrefix(c.Template, "@"))
if err != nil {
return xerrors.Errorf("Error retrieving template from path: %w", err)
}
template = string(buf)
}
if err = report.WriteResults(c.Format, c.Output, results, template, c.Light); err != nil {
return xerrors.Errorf("unable to write results: %w", err)
}

View File

@@ -20,10 +20,7 @@ import (
// Injectors from inject.go:
func initializeCacheClient(cacheDir string) (operation.Cache, error) {
cacheCache, err := cache.New(cacheDir)
if err != nil {
return operation.Cache{}, err
}
cacheCache := cache.Initialize(cacheDir)
operationCache := operation.NewCache(cacheCache)
return operationCache, nil
}

View File

@@ -2,6 +2,7 @@ package library
import (
"path/filepath"
"time"
"github.com/google/wire"
@@ -23,7 +24,7 @@ var SuperSet = wire.NewSet(
)
type Operation interface {
Detect(string, []ptypes.Library) ([]types.DetectedVulnerability, error)
Detect(string, string, time.Time, []ptypes.Library) ([]types.DetectedVulnerability, error)
}
type Detector struct {
@@ -34,7 +35,7 @@ func NewDetector(factory Factory) Detector {
return Detector{driverFactory: factory}
}
func (d Detector) Detect(filePath string, pkgs []ptypes.Library) ([]types.DetectedVulnerability, error) {
func (d Detector) Detect(_ string, filePath string, _ time.Time, pkgs []ptypes.Library) ([]types.DetectedVulnerability, error) {
log.Logger.Debugf("Detecting library vulnerabilities, path: %s", filePath)
driver := d.driverFactory.NewDriver(filepath.Base(filePath))
if driver == nil {

View File

@@ -1,6 +1,8 @@
package library
import (
"time"
ptypes "github.com/aquasecurity/go-dep-parser/pkg/types"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/stretchr/testify/mock"
@@ -11,8 +13,10 @@ type MockDetector struct {
}
type DetectInput struct {
FilePath string
Libs []ptypes.Library
ImageName string
FilePath string
Created time.Time
Libs []ptypes.Library
}
type DetectOutput struct {
Vulns []types.DetectedVulnerability
@@ -26,14 +30,14 @@ type DetectExpectation struct {
func NewMockDetector(detectExpectations []DetectExpectation) *MockDetector {
mockDetector := new(MockDetector)
for _, e := range detectExpectations {
mockDetector.On("Detect", e.Args.FilePath, e.Args.Libs).Return(
mockDetector.On("Detect", e.Args.ImageName, e.Args.FilePath, e.Args.Created, e.Args.Libs).Return(
e.ReturnArgs.Vulns, e.ReturnArgs.Err)
}
return mockDetector
}
func (_m *MockDetector) Detect(a string, b []ptypes.Library) ([]types.DetectedVulnerability, error) {
ret := _m.Called(a, b)
func (_m *MockDetector) Detect(a, b string, c time.Time, d []ptypes.Library) ([]types.DetectedVulnerability, error) {
ret := _m.Called(a, b, c, d)
ret0 := ret.Get(0)
if ret0 == nil {
return nil, ret.Error(1)

View File

@@ -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),
}
)

View File

@@ -1,6 +1,8 @@
package ospkg
import (
"time"
"github.com/aquasecurity/trivy/pkg/detector/ospkg/alpine"
"github.com/aquasecurity/trivy/pkg/detector/ospkg/amazon"
"github.com/aquasecurity/trivy/pkg/detector/ospkg/debian"
@@ -28,7 +30,7 @@ var (
)
type Operation interface {
Detect(string, string, []analyzer.Package) ([]types.DetectedVulnerability, bool, error)
Detect(string, string, string, time.Time, []analyzer.Package) ([]types.DetectedVulnerability, bool, error)
}
type Driver interface {
@@ -38,7 +40,7 @@ type Driver interface {
type Detector struct{}
func (d Detector) Detect(osFamily, osName string, pkgs []analyzer.Package) ([]types.DetectedVulnerability, bool, error) {
func (d Detector) Detect(_, osFamily, osName string, _ time.Time, pkgs []analyzer.Package) ([]types.DetectedVulnerability, bool, error) {
driver := newDriver(osFamily, osName)
if driver == nil {
return nil, false, ErrUnsupportedOS

View File

@@ -1,6 +1,8 @@
package ospkg
import (
"time"
"github.com/aquasecurity/fanal/analyzer"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/stretchr/testify/mock"
@@ -11,9 +13,11 @@ type MockDetector struct {
}
type DetectInput struct {
OSFamily string
OSName string
Pkgs []analyzer.Package
ImageName string
OSFamily string
OSName string
Created time.Time
Pkgs []analyzer.Package
}
type DetectOutput struct {
Vulns []types.DetectedVulnerability
@@ -28,14 +32,14 @@ type DetectExpectation struct {
func NewMockDetector(detectExpectations []DetectExpectation) *MockDetector {
mockDetector := new(MockDetector)
for _, e := range detectExpectations {
mockDetector.On("Detect", e.Args.OSFamily, e.Args.OSName, e.Args.Pkgs).Return(
mockDetector.On("Detect", e.Args.ImageName, e.Args.OSFamily, e.Args.OSName, e.Args.Created, e.Args.Pkgs).Return(
e.ReturnArgs.Vulns, e.ReturnArgs.Eosl, e.ReturnArgs.Err)
}
return mockDetector
}
func (_m *MockDetector) Detect(a, b string, c []analyzer.Package) ([]types.DetectedVulnerability, bool, error) {
ret := _m.Called(a, b, c)
func (_m *MockDetector) Detect(a string, b string, c string, d time.Time, e []analyzer.Package) ([]types.DetectedVulnerability, bool, error) {
ret := _m.Called(a, b, c, d, e)
ret0 := ret.Get(0)
if ret0 == nil {
return nil, false, ret.Error(2)

View File

@@ -57,25 +57,42 @@ func (s *Scanner) Detect(osVer string, pkgs []analyzer.Package) ([]types.Detecte
var vulns []types.DetectedVulnerability
for _, pkg := range pkgs {
// For Red Hat Security Data API containing only source package names
advisories, err := s.vs.Get(osVer, pkg.SrcName)
if err != nil {
return nil, xerrors.Errorf("failed to get Red Hat advisories: %w", err)
}
installed := utils.FormatSrcVersion(pkg)
installed := utils.FormatVersion(pkg)
installedVersion := version.NewVersion(installed)
for _, adv := range advisories {
fixedVersion := version.NewVersion(adv.FixedVersion)
for _, adv := range advisories {
if adv.FixedVersion != "" {
continue
}
vuln := types.DetectedVulnerability{
VulnerabilityID: adv.VulnerabilityID,
PkgName: pkg.Name,
InstalledVersion: installed,
}
vulns = append(vulns, vuln)
}
// For Red Hat OVAL containing only binary package names
advisories, err = s.vs.Get(osVer, pkg.Name)
if err != nil {
return nil, xerrors.Errorf("failed to get Red Hat advisories: %w", err)
}
for _, adv := range advisories {
fixedVersion := version.NewVersion(adv.FixedVersion)
if installedVersion.LessThan(fixedVersion) {
vuln.FixedVersion = fixedVersion.String()
vulns = append(vulns, vuln)
} else if adv.FixedVersion == "" {
vuln := types.DetectedVulnerability{
VulnerabilityID: adv.VulnerabilityID,
PkgName: pkg.Name,
InstalledVersion: installed,
FixedVersion: fixedVersion.String(),
}
vulns = append(vulns, vuln)
}
}

View File

@@ -5,7 +5,14 @@ import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"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/types"
)
func TestMain(m *testing.M) {
@@ -13,6 +20,196 @@ func TestMain(m *testing.M) {
os.Exit(m.Run())
}
func TestScanner_Detect(t *testing.T) {
type args struct {
osVer string
pkgs []analyzer.Package
}
tests := []struct {
name string
args args
get []dbTypes.GetExpectation
want []types.DetectedVulnerability
wantErr bool
}{
{
name: "happy path: src pkg name is different from bin pkg name",
args: args{
osVer: "7.6",
pkgs: []analyzer.Package{
{
Name: "vim-minimal",
Version: "7.4.160",
Release: "5.el7",
Epoch: 2,
Arch: "x86_64",
SrcName: "vim",
SrcVersion: "7.4.160",
SrcRelease: "5.el7",
SrcEpoch: 2,
},
},
},
get: []dbTypes.GetExpectation{
{
Args: dbTypes.GetArgs{
Release: "7",
PkgName: "vim",
},
Returns: dbTypes.GetReturns{
Advisories: []dbTypes.Advisory{
{
VulnerabilityID: "CVE-2017-5953",
FixedVersion: "",
},
{
VulnerabilityID: "CVE-2017-6350",
FixedVersion: "",
},
},
},
},
{
Args: dbTypes.GetArgs{
Release: "7",
PkgName: "vim-minimal",
},
Returns: dbTypes.GetReturns{
Advisories: []dbTypes.Advisory{
{
VulnerabilityID: "CVE-2019-12735",
FixedVersion: "2:7.4.160-6.el7_6",
},
},
},
},
},
want: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2017-5953",
PkgName: "vim-minimal",
InstalledVersion: "2:7.4.160-5.el7",
},
{
VulnerabilityID: "CVE-2017-6350",
PkgName: "vim-minimal",
InstalledVersion: "2:7.4.160-5.el7",
},
{
VulnerabilityID: "CVE-2019-12735",
PkgName: "vim-minimal",
InstalledVersion: "2:7.4.160-5.el7",
FixedVersion: "2:7.4.160-6.el7_6",
},
},
},
{
name: "happy path: src pkg name is the same as bin pkg name",
args: args{
osVer: "6.5",
pkgs: []analyzer.Package{
{
Name: "nss",
Version: "3.36.0",
Release: "7.1.el7_6",
Epoch: 0,
Arch: "x86_64",
SrcName: "nss",
SrcVersion: "3.36.0",
SrcRelease: "7.4.160",
SrcEpoch: 0,
},
},
},
get: []dbTypes.GetExpectation{
{
Args: dbTypes.GetArgs{
Release: "6",
PkgName: "nss",
},
Returns: dbTypes.GetReturns{
Advisories: []dbTypes.Advisory{
{
VulnerabilityID: "CVE-2015-2808",
FixedVersion: "",
},
{
VulnerabilityID: "CVE-2016-2183",
FixedVersion: "",
},
{
VulnerabilityID: "CVE-2018-12404",
FixedVersion: "3.44.0-4.el7",
},
},
},
},
},
want: []types.DetectedVulnerability{
{
VulnerabilityID: "CVE-2015-2808",
PkgName: "nss",
InstalledVersion: "3.36.0-7.1.el7_6",
},
{
VulnerabilityID: "CVE-2016-2183",
PkgName: "nss",
InstalledVersion: "3.36.0-7.1.el7_6",
},
{
VulnerabilityID: "CVE-2018-12404",
PkgName: "nss",
InstalledVersion: "3.36.0-7.1.el7_6",
FixedVersion: "3.44.0-4.el7",
},
},
},
{
name: "sad path: Get returns an error",
args: args{
osVer: "5",
pkgs: []analyzer.Package{
{
Name: "nss",
Version: "3.36.0",
Release: "7.1.el7_6",
Epoch: 0,
Arch: "x86_64",
SrcName: "nss",
SrcVersion: "3.36.0",
SrcRelease: "7.4.160",
SrcEpoch: 0,
},
},
},
get: []dbTypes.GetExpectation{
{
Args: dbTypes.GetArgs{
Release: "5",
PkgName: "nss",
},
Returns: dbTypes.GetReturns{
Err: xerrors.New("error"),
},
},
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockVs := new(dbTypes.MockVulnSrc)
mockVs.ApplyGetExpectations(tt.get)
s := &Scanner{
vs: mockVs,
}
got, err := s.Detect(tt.args.osVer, tt.args.pkgs)
require.Equal(t, tt.wantErr, err != nil)
assert.Equal(t, tt.want, got)
})
}
}
func TestScanner_IsSupportedVersion(t *testing.T) {
vectors := map[string]struct {
now time.Time

View File

@@ -3,12 +3,16 @@ package library
import (
"context"
"net/http"
"time"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/google/wire"
"golang.org/x/xerrors"
ptypes "github.com/aquasecurity/go-dep-parser/pkg/types"
depptypes "github.com/aquasecurity/go-dep-parser/pkg/types"
detector "github.com/aquasecurity/trivy/pkg/detector/library"
"github.com/aquasecurity/trivy/pkg/log"
r "github.com/aquasecurity/trivy/pkg/rpc"
"github.com/aquasecurity/trivy/pkg/rpc/client"
"github.com/aquasecurity/trivy/pkg/types"
@@ -38,15 +42,23 @@ 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) {
func (d Detector) Detect(imageName, filePath string, created time.Time, libs []depptypes.Library) ([]types.DetectedVulnerability, error) {
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{
ImageName: imageName,
FilePath: filePath,
Libraries: r.ConvertToRpcLibraries(libs),
Created: func() *timestamp.Timestamp {
t, err := ptypes.TimestampProto(created)
if err != nil {
log.Logger.Warnf("invalid timestamp: %s", err)
}
return t
}(),
})
return err
})

View File

@@ -3,14 +3,18 @@ package library
import (
"context"
"testing"
"time"
"golang.org/x/xerrors"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
ptypes "github.com/aquasecurity/go-dep-parser/pkg/types"
deptypes "github.com/aquasecurity/go-dep-parser/pkg/types"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/rpc/detector"
@@ -52,8 +56,10 @@ func TestDetectClient_Detect(t *testing.T) {
}
type args struct {
filePath string
libs []ptypes.Library
imageName string
filePath string
created time.Time
libs []deptypes.Library
}
tests := []struct {
name string
@@ -71,14 +77,22 @@ func TestDetectClient_Detect(t *testing.T) {
},
},
args: args{
filePath: "app/Pipfile.lock",
libs: []ptypes.Library{
imageName: "/tmp/alpine.tar",
filePath: "app/Pipfile.lock",
created: time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC),
libs: []deptypes.Library{
{Name: "django", Version: "3.0.0"},
},
},
detect: detect{
input: detectInput{req: &detector.LibDetectRequest{
FilePath: "app/Pipfile.lock",
ImageName: "/tmp/alpine.tar",
FilePath: "app/Pipfile.lock",
Created: func() *timestamp.Timestamp {
d := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
t, _ := ptypes.TimestampProto(d)
return t
}(),
Libraries: []*detector.Library{
{Name: "django", Version: "3.0.0"},
},
@@ -118,17 +132,25 @@ func TestDetectClient_Detect(t *testing.T) {
name: "Detect returns an error",
fields: fields{},
args: args{
filePath: "app/Pipfile.lock",
libs: []ptypes.Library{
imageName: "/tmp/alpine.tar",
filePath: "app/Pipfile.lock",
created: time.Date(2019, 2, 1, 0, 0, 0, 0, time.UTC),
libs: []deptypes.Library{
{Name: "django", Version: "3.0.0"},
},
},
detect: detect{
input: detectInput{req: &detector.LibDetectRequest{
FilePath: "app/Pipfile.lock",
ImageName: "/tmp/alpine.tar",
FilePath: "app/Pipfile.lock",
Libraries: []*detector.Library{
{Name: "django", Version: "3.0.0"},
},
Created: func() *timestamp.Timestamp {
d := time.Date(2019, 2, 1, 0, 0, 0, 0, time.UTC)
t, _ := ptypes.TimestampProto(d)
return t
}(),
},
},
output: detectOutput{
@@ -145,7 +167,7 @@ func TestDetectClient_Detect(t *testing.T) {
tt.detect.output.res, tt.detect.output.err)
d := NewDetector(tt.fields.customHeaders, mockDetector)
got, err := d.Detect(tt.args.filePath, tt.args.libs)
got, err := d.Detect(tt.args.imageName, tt.args.filePath, tt.args.created, tt.args.libs)
if tt.wantErr != "" {
require.NotNil(t, err, tt.name)
assert.Contains(t, err.Error(), tt.wantErr, tt.name)

View File

@@ -3,6 +3,12 @@ package ospkg
import (
"context"
"net/http"
"time"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/google/wire"
"golang.org/x/xerrors"
@@ -38,15 +44,23 @@ 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) {
func (d Detector) Detect(imageName, osFamily, osName string, created time.Time, pkgs []analyzer.Package) ([]types.DetectedVulnerability, bool, error) {
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,
ImageName: imageName,
OsFamily: osFamily,
OsName: osName,
Created: func() *timestamp.Timestamp {
t, err := ptypes.TimestampProto(created)
if err != nil {
log.Logger.Warnf("invalid timestamp: %s", err)
}
return t
}(),
Packages: r.ConvertToRpcPkgs(pkgs),
})
return err

View File

@@ -3,18 +3,18 @@ package ospkg
import (
"context"
"testing"
"golang.org/x/xerrors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"time"
"github.com/aquasecurity/fanal/analyzer"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/rpc/detector"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
)
type mockDetector struct {
@@ -51,9 +51,11 @@ func TestDetectClient_Detect(t *testing.T) {
customHeaders CustomHeaders
}
type args struct {
osFamily string
osName string
pkgs []analyzer.Package
imageName string
osFamily string
osName string
created time.Time
pkgs []analyzer.Package
}
tests := []struct {
name string
@@ -71,8 +73,10 @@ func TestDetectClient_Detect(t *testing.T) {
},
},
args: args{
osFamily: "alpine",
osName: "3.10.2",
imageName: "alpine:3.10.2",
osFamily: "alpine",
osName: "3.10.2",
created: time.Unix(1581498560, 0),
pkgs: []analyzer.Package{
{
Name: "openssl",
@@ -85,8 +89,13 @@ func TestDetectClient_Detect(t *testing.T) {
detect: detect{
input: detectInput{
req: &detector.OSDetectRequest{
OsFamily: "alpine",
OsName: "3.10.2",
OsFamily: "alpine",
OsName: "3.10.2",
ImageName: "alpine:3.10.2",
Created: func() *timestamp.Timestamp {
t, _ := ptypes.TimestampProto(time.Unix(1581498560, 0))
return t
}(),
Packages: []*detector.Package{
{
Name: "openssl",
@@ -131,8 +140,10 @@ func TestDetectClient_Detect(t *testing.T) {
name: "Detect returns an error",
fields: fields{},
args: args{
osFamily: "alpine",
osName: "3.10.2",
imageName: "alpine:3.10.2",
osFamily: "alpine",
osName: "3.10.2",
created: time.Unix(1581498560, 0),
pkgs: []analyzer.Package{
{
Name: "openssl",
@@ -145,8 +156,13 @@ func TestDetectClient_Detect(t *testing.T) {
detect: detect{
input: detectInput{
req: &detector.OSDetectRequest{
OsFamily: "alpine",
OsName: "3.10.2",
ImageName: "alpine:3.10.2",
OsFamily: "alpine",
OsName: "3.10.2",
Created: func() *timestamp.Timestamp {
t, _ := ptypes.TimestampProto(time.Unix(1581498560, 0))
return t
}(),
Packages: []*detector.Package{
{
Name: "openssl",
@@ -171,7 +187,7 @@ func TestDetectClient_Detect(t *testing.T) {
tt.detect.output.res, tt.detect.output.err)
d := NewDetector(tt.fields.customHeaders, mockDetector)
got, _, err := d.Detect(tt.args.osFamily, tt.args.osName, tt.args.pkgs)
got, _, err := d.Detect(tt.args.imageName, tt.args.osFamily, tt.args.osName, tt.args.created, tt.args.pkgs)
if tt.wantErr != "" {
require.NotNil(t, err, tt.name)
assert.Contains(t, err.Error(), tt.wantErr, tt.name)

View File

@@ -2,6 +2,7 @@ package library
import (
"context"
"time"
"github.com/google/wire"
"golang.org/x/xerrors"
@@ -28,8 +29,8 @@ func NewServer(detector detector.Operation, vulnClient vulnerability.Operation)
return &Server{detector: detector, vulnClient: vulnClient}
}
func (s *Server) Detect(ctx context.Context, req *proto.LibDetectRequest) (res *proto.DetectResponse, err error) {
vulns, err := s.detector.Detect(req.FilePath, rpc.ConvertFromRpcLibraries(req.Libraries))
func (s *Server) Detect(_ context.Context, req *proto.LibDetectRequest) (res *proto.DetectResponse, err error) {
vulns, err := s.detector.Detect("", req.FilePath, time.Time{}, rpc.ConvertFromRpcLibraries(req.Libraries))
if err != nil {
err = xerrors.Errorf("failed to detect library vulnerabilities: %w", err)
log.Logger.Error(err)

View File

@@ -42,7 +42,8 @@ func TestServer_Detect(t *testing.T) {
name: "happy path",
args: args{
req: &proto.LibDetectRequest{
FilePath: "app/Pipfile.lock",
ImageName: "alpine:3.10",
FilePath: "app/Pipfile.lock",
Libraries: []*proto.Library{
{Name: "django", Version: "3.0.0"},
},
@@ -91,7 +92,8 @@ func TestServer_Detect(t *testing.T) {
name: "Detect returns an error",
args: args{
req: &proto.LibDetectRequest{
FilePath: "app/Pipfile.lock",
ImageName: "alpine:3.10",
FilePath: "app/Pipfile.lock",
Libraries: []*proto.Library{
{Name: "django", Version: "3.0.0"},
},

View File

@@ -2,6 +2,7 @@ package ospkg
import (
"context"
"time"
"github.com/google/wire"
"golang.org/x/xerrors"
@@ -29,7 +30,7 @@ func NewServer(detector detector.Operation, vulnClient vulnerability.Operation)
}
func (s *Server) Detect(ctx context.Context, req *proto.OSDetectRequest) (res *proto.DetectResponse, err error) {
vulns, eosl, err := s.detector.Detect(req.OsFamily, req.OsName, rpc.ConvertFromRpcPkgs(req.Packages))
vulns, eosl, err := s.detector.Detect("", req.OsFamily, req.OsName, time.Time{}, rpc.ConvertFromRpcPkgs(req.Packages))
if err != nil {
err = xerrors.Errorf("failed to detect vulnerabilities of OS packages: %w", err)
log.Logger.Error(err)

View File

@@ -1,8 +1,7 @@
package library
import (
"io/ioutil"
"os"
"time"
detector "github.com/aquasecurity/trivy/pkg/detector/library"
@@ -27,7 +26,7 @@ func NewScanner(detector detector.Operation) Scanner {
return Scanner{detector: detector}
}
func (s Scanner) Scan(files extractor.FileMap) (map[string][]types.DetectedVulnerability, error) {
func (s Scanner) Scan(imageName string, created time.Time, files extractor.FileMap) (map[string][]types.DetectedVulnerability, error) {
results, err := analyzer.GetLibraries(files)
if err != nil {
return nil, xerrors.Errorf("failed to analyze libraries: %w", err)
@@ -35,7 +34,7 @@ func (s Scanner) Scan(files extractor.FileMap) (map[string][]types.DetectedVulne
vulnerabilities := map[string][]types.DetectedVulnerability{}
for path, libs := range results {
vulns, err := s.detector.Detect(string(path), libs)
vulns, err := s.detector.Detect(imageName, string(path), created, libs)
if err != nil {
return nil, xerrors.Errorf("failed library scan: %w", err)
}
@@ -44,24 +43,3 @@ func (s Scanner) Scan(files extractor.FileMap) (map[string][]types.DetectedVulne
}
return vulnerabilities, nil
}
func (s Scanner) ScanFile(f *os.File) ([]types.DetectedVulnerability, error) {
content, err := ioutil.ReadAll(f)
if err != nil {
return nil, err
}
files := extractor.FileMap{
f.Name(): content,
}
results, err := s.Scan(files)
if err != nil {
return nil, err
}
// need only 1 result
for _, vulns := range results {
return vulns, nil
}
return nil, nil
}

View File

@@ -2,6 +2,7 @@ package library
import (
"testing"
"time"
library2 "github.com/aquasecurity/trivy/pkg/detector/library"
@@ -17,8 +18,10 @@ import (
func TestScanner_Scan(t *testing.T) {
type detectInput struct {
filePath string
libs []ptypes.Library
imageName string
filePath string
created time.Time
libs []ptypes.Library
}
type detectOutput struct {
vulns []types.DetectedVulnerability
@@ -29,7 +32,9 @@ func TestScanner_Scan(t *testing.T) {
output detectOutput
}
type args struct {
files extractor.FileMap
imageName string
created time.Time
files extractor.FileMap
}
tests := []struct {
name string
@@ -41,6 +46,8 @@ func TestScanner_Scan(t *testing.T) {
{
name: "happy",
args: args{
imageName: "alpine:3.10",
created: time.Date(2019, 5, 11, 0, 7, 3, 510395965, time.UTC),
files: extractor.FileMap{
"app/Pipfile.lock": []byte(`{
"_meta": {
@@ -94,7 +101,9 @@ func TestScanner_Scan(t *testing.T) {
detect: []detect{
{
input: detectInput{
filePath: "app/Pipfile.lock",
imageName: "alpine:3.10",
filePath: "app/Pipfile.lock",
created: time.Date(2019, 5, 11, 0, 7, 3, 510395965, time.UTC),
libs: []ptypes.Library{
{Name: "django", Version: "3.0.0"},
},
@@ -107,7 +116,9 @@ func TestScanner_Scan(t *testing.T) {
},
{
input: detectInput{
filePath: "app/package-lock.json",
imageName: "alpine:3.10",
filePath: "app/package-lock.json",
created: time.Date(2019, 5, 11, 0, 7, 3, 510395965, time.UTC),
libs: []ptypes.Library{
{Name: "react", Version: "16.8.6"},
},
@@ -131,6 +142,8 @@ func TestScanner_Scan(t *testing.T) {
{
name: "broken lock file",
args: args{
imageName: "alpine:3.10",
created: time.Date(2019, 5, 11, 0, 7, 3, 510395965, time.UTC),
files: extractor.FileMap{
"app/Pipfile.lock": []byte(`{broken}`),
},
@@ -179,14 +192,14 @@ func TestScanner_Scan(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
mockDetector := new(library2.MockDetector)
for _, d := range tt.detect {
mockDetector.On("Detect", d.input.filePath, d.input.libs).Return(
mockDetector.On("Detect", d.input.imageName, d.input.filePath, d.input.created, d.input.libs).Return(
d.output.vulns, d.output.err)
}
s := Scanner{
detector: mockDetector,
}
got, err := s.Scan(tt.args.files)
got, err := s.Scan(tt.args.imageName, tt.args.created, tt.args.files)
if tt.wantErr != "" {
require.NotNil(t, err, tt.name)
assert.Contains(t, err.Error(), tt.wantErr, tt.name)

View File

@@ -1,6 +1,8 @@
package ospkg
import (
"time"
"golang.org/x/xerrors"
"github.com/aquasecurity/fanal/analyzer"
@@ -28,7 +30,7 @@ func NewScanner(detector detector.Operation) Scanner {
return Scanner{detector: detector}
}
func (s Scanner) Scan(files extractor.FileMap) (string, string, []types.DetectedVulnerability, error) {
func (s Scanner) Scan(imageName string, created time.Time, files extractor.FileMap) (string, string, []types.DetectedVulnerability, error) {
os, err := analyzer.GetOS(files)
if err != nil {
return "", "", nil, xerrors.Errorf("failed to analyze OS: %w", err)
@@ -53,11 +55,12 @@ func (s Scanner) Scan(files extractor.FileMap) (string, string, []types.Detected
pkgs = mergePkgs(pkgs, pkgsFromCommands)
log.Logger.Debugf("the number of packages: %d", len(pkgs))
vulns, eosl, err := s.detector.Detect(os.Family, os.Name, pkgs)
vulns, eosl, err := s.detector.Detect(imageName, os.Family, os.Name, created, pkgs)
if err != nil {
return "", "", nil, xerrors.Errorf("failed to detect vulnerabilities: %w", err)
}
if eosl {
// TODO: test logger
log.Logger.Warnf("This OS version is no longer supported by the distribution: %s %s", os.Family, os.Name)
log.Logger.Warnf("The vulnerability detection may be insufficient because security updates are not provided")
}

View File

@@ -3,11 +3,12 @@ package ospkg
import (
"os"
"testing"
ospkg2 "github.com/aquasecurity/trivy/pkg/detector/ospkg"
"time"
"golang.org/x/xerrors"
ospkg2 "github.com/aquasecurity/trivy/pkg/detector/ospkg"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/assert"
@@ -26,9 +27,11 @@ func TestMain(m *testing.M) {
func TestScanner_Scan(t *testing.T) {
type detectInput struct {
osFamily string
osName string
pkgs []analyzer.Package
imageName string
osFamily string
osName string
buildTime time.Time
pkgs []analyzer.Package
}
type detectOutput struct {
vulns []types.DetectedVulnerability
@@ -41,7 +44,9 @@ func TestScanner_Scan(t *testing.T) {
}
type fields struct {
files extractor.FileMap
imageName string
created time.Time
files extractor.FileMap
}
type want struct {
osFamily string
@@ -58,7 +63,10 @@ func TestScanner_Scan(t *testing.T) {
{
name: "happy path",
fields: fields{
imageName: "alpine:3.10.2",
created: time.Date(2019, 5, 11, 0, 7, 3, 510395965, time.UTC),
files: extractor.FileMap{
"/config": []byte(`{"architecture":"amd64","config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh"],"ArgsEscaped":true,"Image":"sha256:09f2bbe58e774849d74dc1391c2e01731896c745c4aba1ecf69a283bdb4b537a","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"container":"c10d36fa368a7ea673683682666758adf35efe98e10989505f4f566b5b18538f","container_config":{"Hostname":"c10d36fa368a","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","#(nop) ","CMD [\"/bin/sh\"]"],"ArgsEscaped":true,"Image":"sha256:09f2bbe58e774849d74dc1391c2e01731896c745c4aba1ecf69a283bdb4b537a","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":{}},"created":"2019-05-11T00:07:03.510395965Z","docker_version":"18.06.1-ce","history":[{"created":"2019-05-11T00:07:03.358250803Z","created_by":"/bin/sh -c #(nop) ADD file:a86aea1f3a7d68f6ae03397b99ea77f2e9ee901c5c59e59f76f93adbb4035913 in / "},{"created":"2019-05-11T00:07:03.510395965Z","created_by":"/bin/sh -c #(nop) CMD [\"/bin/sh\"]","empty_layer":true}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:f1b5933fe4b5f49bbe8258745cf396afe07e625bdab3168e364daf7c956b6b81"]}}`),
"etc/alpine-release": []byte("3.10.2"),
"lib/apk/db/installed": []byte(`C:Q11Ing8/u1VIdY9czSxaDO9wJg72I=
P:musl
@@ -88,8 +96,10 @@ F:usr/lib
},
detect: detect{
input: detectInput{
osFamily: "alpine",
osName: "3.10.2",
imageName: "alpine:3.10.2",
osFamily: "alpine",
osName: "3.10.2",
buildTime: time.Date(2019, 5, 11, 0, 7, 3, 510395965, time.UTC),
pkgs: []analyzer.Package{
{Name: "musl", Version: "1.1.22-r3"},
},
@@ -122,7 +132,10 @@ F:usr/lib
{
name: "Detect returns an error",
fields: fields{
imageName: "alpine:3.10",
created: time.Date(2019, 5, 11, 0, 7, 3, 510395965, time.UTC),
files: extractor.FileMap{
"/config": []byte(`{"architecture":"amd64","config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh"],"ArgsEscaped":true,"Image":"sha256:09f2bbe58e774849d74dc1391c2e01731896c745c4aba1ecf69a283bdb4b537a","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"container":"c10d36fa368a7ea673683682666758adf35efe98e10989505f4f566b5b18538f","container_config":{"Hostname":"c10d36fa368a","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","#(nop) ","CMD [\"/bin/sh\"]"],"ArgsEscaped":true,"Image":"sha256:09f2bbe58e774849d74dc1391c2e01731896c745c4aba1ecf69a283bdb4b537a","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":{}},"created":"2019-05-11T00:07:03.510395965Z","docker_version":"18.06.1-ce","history":[{"created":"2019-05-11T00:07:03.358250803Z","created_by":"/bin/sh -c #(nop) ADD file:a86aea1f3a7d68f6ae03397b99ea77f2e9ee901c5c59e59f76f93adbb4035913 in / "},{"created":"2019-05-11T00:07:03.510395965Z","created_by":"/bin/sh -c #(nop) CMD [\"/bin/sh\"]","empty_layer":true}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:f1b5933fe4b5f49bbe8258745cf396afe07e625bdab3168e364daf7c956b6b81"]}}`),
"etc/alpine-release": []byte("3.10.2"),
"lib/apk/db/installed": []byte(`C:Q11Ing8/u1VIdY9czSxaDO9wJg72I=
P:musl
@@ -133,8 +146,10 @@ A:x86_64
},
detect: detect{
input: detectInput{
osFamily: "alpine",
osName: "3.10.2",
imageName: "alpine:3.10",
osFamily: "alpine",
osName: "3.10.2",
buildTime: time.Date(2019, 5, 11, 0, 7, 3, 510395965, time.UTC),
pkgs: []analyzer.Package{
{Name: "musl", Version: "1.1.22-r3"},
},
@@ -151,11 +166,11 @@ A:x86_64
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockDetector := new(ospkg2.MockDetector)
mockDetector.On("Detect", tt.detect.input.osFamily, tt.detect.input.osName,
tt.detect.input.pkgs).Return(tt.detect.output.vulns, tt.detect.output.eosl, tt.detect.output.err)
mockDetector.On("Detect", tt.detect.input.imageName, tt.detect.input.osFamily, tt.detect.input.osName,
tt.detect.input.buildTime, tt.detect.input.pkgs).Return(tt.detect.output.vulns, tt.detect.output.eosl, tt.detect.output.err)
s := NewScanner(mockDetector)
got, got1, got2, err := s.Scan(tt.fields.files)
got, got1, got2, err := s.Scan(tt.fields.imageName, tt.fields.created, tt.fields.files)
if tt.want.err != "" {
require.NotNil(t, err, tt.name)

View File

@@ -2,10 +2,12 @@ package scanner
import (
"context"
"encoding/json"
"flag"
"fmt"
"os"
"sort"
"time"
"github.com/google/wire"
"golang.org/x/crypto/ssh/terminal"
@@ -96,8 +98,13 @@ func (s Scanner) ScanImage(imageName, filePath string, scanOptions types.ScanOpt
return nil, xerrors.New("image name or image file must be specified")
}
created, err := getCreated(files["/config"])
if err != nil {
return nil, err
}
if utils.StringInSlice("os", scanOptions.VulnType) {
osFamily, osVersion, osVulns, err := s.ospkgScanner.Scan(files)
osFamily, osVersion, osVulns, err := s.ospkgScanner.Scan(target, created, files)
if err != nil && err != ospkgDetector.ErrUnsupportedOS {
return nil, xerrors.Errorf("failed to scan the image: %w", err)
}
@@ -111,7 +118,7 @@ func (s Scanner) ScanImage(imageName, filePath string, scanOptions types.ScanOpt
}
if utils.StringInSlice("library", scanOptions.VulnType) {
libVulns, err := s.libScanner.Scan(files)
libVulns, err := s.libScanner.Scan(target, created, files)
if err != nil {
return nil, xerrors.Errorf("failed to scan libraries: %w", err)
}
@@ -132,15 +139,16 @@ func (s Scanner) ScanImage(imageName, filePath string, scanOptions types.ScanOpt
return results, nil
}
func (s Scanner) ScanFile(f *os.File) (report.Results, error) {
vulns, err := s.libScanner.ScanFile(f)
if err != nil {
return nil, xerrors.Errorf("failed to scan libraries in file: %w", err)
type config struct {
Created time.Time
}
func getCreated(configBlob []byte) (time.Time, error) {
var config config
if err := json.Unmarshal(configBlob, &config); err != nil {
return time.Time{}, xerrors.Errorf("invalid config JSON: %w", err)
}
results := report.Results{
{Target: f.Name(), Vulnerabilities: vulns},
}
return results, nil
return config.Created, nil
}
func openStream(path string) (*os.File, error) {

View File

@@ -6,6 +6,7 @@ package detector
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
math "math"
)
@@ -55,12 +56,14 @@ func (Severity) EnumDescriptor() ([]byte, []int) {
}
type OSDetectRequest struct {
OsFamily string `protobuf:"bytes,1,opt,name=os_family,json=osFamily,proto3" json:"os_family,omitempty"`
OsName string `protobuf:"bytes,2,opt,name=os_name,json=osName,proto3" json:"os_name,omitempty"`
Packages []*Package `protobuf:"bytes,3,rep,name=packages,proto3" json:"packages,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
OsFamily string `protobuf:"bytes,1,opt,name=os_family,json=osFamily,proto3" json:"os_family,omitempty"`
OsName string `protobuf:"bytes,2,opt,name=os_name,json=osName,proto3" json:"os_name,omitempty"`
Packages []*Package `protobuf:"bytes,3,rep,name=packages,proto3" json:"packages,omitempty"`
ImageName string `protobuf:"bytes,4,opt,name=image_name,json=imageName,proto3" json:"image_name,omitempty"`
Created *timestamp.Timestamp `protobuf:"bytes,5,opt,name=created,proto3" json:"created,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *OSDetectRequest) Reset() { *m = OSDetectRequest{} }
@@ -109,6 +112,20 @@ func (m *OSDetectRequest) GetPackages() []*Package {
return nil
}
func (m *OSDetectRequest) GetImageName() string {
if m != nil {
return m.ImageName
}
return ""
}
func (m *OSDetectRequest) GetCreated() *timestamp.Timestamp {
if m != nil {
return m.Created
}
return nil
}
type DetectResponse struct {
Vulnerabilities []*Vulnerability `protobuf:"bytes,1,rep,name=vulnerabilities,proto3" json:"vulnerabilities,omitempty"`
Eosl bool `protobuf:"varint,2,opt,name=eosl,proto3" json:"eosl,omitempty"`
@@ -264,11 +281,13 @@ func (m *Package) GetSrcEpoch() int32 {
}
type LibDetectRequest struct {
FilePath string `protobuf:"bytes,1,opt,name=file_path,json=filePath,proto3" json:"file_path,omitempty"`
Libraries []*Library `protobuf:"bytes,2,rep,name=libraries,proto3" json:"libraries,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
FilePath string `protobuf:"bytes,1,opt,name=file_path,json=filePath,proto3" json:"file_path,omitempty"`
Libraries []*Library `protobuf:"bytes,2,rep,name=libraries,proto3" json:"libraries,omitempty"`
ImageName string `protobuf:"bytes,3,opt,name=image_name,json=imageName,proto3" json:"image_name,omitempty"`
Created *timestamp.Timestamp `protobuf:"bytes,4,opt,name=created,proto3" json:"created,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *LibDetectRequest) Reset() { *m = LibDetectRequest{} }
@@ -310,6 +329,20 @@ func (m *LibDetectRequest) GetLibraries() []*Library {
return nil
}
func (m *LibDetectRequest) GetImageName() string {
if m != nil {
return m.ImageName
}
return ""
}
func (m *LibDetectRequest) GetCreated() *timestamp.Timestamp {
if m != nil {
return m.Created
}
return nil
}
type Library struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
@@ -465,44 +498,49 @@ func init() {
func init() { proto.RegisterFile("rpc/detector/service.proto", fileDescriptor_93e16dbd737b8924) }
var fileDescriptor_93e16dbd737b8924 = []byte{
// 618 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x4d, 0x4f, 0xdb, 0x40,
0x10, 0x6d, 0x3e, 0xed, 0x4c, 0xf8, 0x70, 0x57, 0x48, 0xb8, 0xa0, 0x42, 0x94, 0x5e, 0x68, 0x2b,
0x05, 0x29, 0xb4, 0xea, 0xb9, 0x05, 0x0a, 0x69, 0x43, 0x40, 0xa6, 0x80, 0xda, 0x4b, 0xb4, 0x71,
0x26, 0x64, 0x85, 0x93, 0x75, 0x77, 0x97, 0xa8, 0x96, 0xfa, 0xb7, 0xfa, 0xd3, 0x7a, 0xaf, 0x76,
0xd7, 0x36, 0x49, 0xca, 0x85, 0xdb, 0xcc, 0xbc, 0xe7, 0x99, 0xd9, 0xf7, 0xd6, 0x0b, 0x5b, 0x22,
0x0e, 0xf7, 0x87, 0xa8, 0x30, 0x54, 0x5c, 0xec, 0x4b, 0x14, 0x33, 0x16, 0x62, 0x2b, 0x16, 0x5c,
0x71, 0xb2, 0xa6, 0x04, 0x9b, 0x25, 0xad, 0x0c, 0x6d, 0xfe, 0x86, 0xf5, 0xf3, 0xcb, 0x23, 0x93,
0x05, 0xf8, 0xf3, 0x1e, 0xa5, 0x22, 0xdb, 0x50, 0xe3, 0xb2, 0x3f, 0xa2, 0x13, 0x16, 0x25, 0x7e,
0xa1, 0x51, 0xd8, 0xab, 0x05, 0x2e, 0x97, 0x9f, 0x4d, 0x4e, 0x36, 0xc1, 0xe1, 0xb2, 0x3f, 0xa5,
0x13, 0xf4, 0x8b, 0x06, 0xaa, 0x72, 0xd9, 0xa3, 0x13, 0x24, 0x07, 0xe0, 0xc6, 0x34, 0xbc, 0xa3,
0xb7, 0x28, 0xfd, 0x52, 0xa3, 0xb4, 0x57, 0x6f, 0x6f, 0xb6, 0x16, 0x67, 0xb5, 0x2e, 0x2c, 0x1e,
0xe4, 0xc4, 0xe6, 0x04, 0xd6, 0xb2, 0xd9, 0x32, 0xe6, 0x53, 0x89, 0xe4, 0x04, 0xd6, 0x67, 0xf7,
0xd1, 0x14, 0x05, 0x1d, 0xb0, 0x88, 0x29, 0x86, 0xd2, 0x2f, 0x98, 0x6e, 0x2f, 0x97, 0xbb, 0x5d,
0xcf, 0xd1, 0x92, 0x60, 0xf9, 0x2b, 0x42, 0xa0, 0x8c, 0x5c, 0x46, 0x66, 0x4b, 0x37, 0x30, 0x71,
0xf3, 0x6f, 0x01, 0x9c, 0x74, 0x09, 0x8d, 0x9b, 0x53, 0xd8, 0x03, 0x9a, 0x98, 0xf8, 0xe0, 0xcc,
0x50, 0x48, 0xc6, 0xa7, 0xe9, 0xe1, 0xb2, 0x54, 0x23, 0x02, 0x23, 0xa4, 0x12, 0xfd, 0x92, 0x45,
0xd2, 0x94, 0x6c, 0x40, 0x05, 0x63, 0x1e, 0x8e, 0xfd, 0x72, 0xa3, 0xb0, 0x57, 0x09, 0x6c, 0xa2,
0xbb, 0x53, 0x11, 0x8e, 0xfd, 0x8a, 0xed, 0xae, 0x63, 0xf2, 0x02, 0x5c, 0x29, 0x42, 0xab, 0x5d,
0xd5, 0x36, 0x91, 0x22, 0x34, 0xe2, 0xed, 0x42, 0x5d, 0x43, 0xd9, 0x70, 0xc7, 0xa0, 0x20, 0x45,
0x78, 0x9d, 0xce, 0x4f, 0x09, 0xd9, 0x0e, 0x6e, 0x4e, 0x08, 0xd2, 0x35, 0xb6, 0xa1, 0xa6, 0x09,
0x76, 0x95, 0x9a, 0x59, 0x45, 0x4f, 0x3b, 0xd6, 0x79, 0x73, 0x04, 0x5e, 0x97, 0x0d, 0xfe, 0x73,
0x79, 0xc4, 0x22, 0xec, 0xc7, 0x54, 0x8d, 0x33, 0x97, 0x75, 0xe1, 0x82, 0xaa, 0x31, 0x79, 0x0f,
0xb5, 0x88, 0x0d, 0x04, 0x15, 0x5a, 0xff, 0xe2, 0xe3, 0x6e, 0x76, 0x0d, 0x21, 0x09, 0x1e, 0x98,
0xcd, 0x0f, 0xe0, 0xa4, 0xd5, 0xa7, 0xc9, 0xdb, 0xfc, 0x53, 0x84, 0xd5, 0x05, 0x3f, 0xc9, 0x6b,
0xf0, 0xe6, 0x1d, 0x4d, 0xfa, 0x6c, 0x98, 0xf6, 0x5a, 0x70, 0x3a, 0xe9, 0x0c, 0xb5, 0xae, 0xf1,
0xdd, 0xed, 0xfc, 0x9d, 0x74, 0xe2, 0xbb, 0x5b, 0xa3, 0xeb, 0x5b, 0x78, 0xce, 0xa6, 0x52, 0xd1,
0x28, 0xc2, 0x61, 0xae, 0xae, 0x35, 0xd0, 0xcb, 0x81, 0x4c, 0xe3, 0x57, 0xb0, 0x3a, 0x62, 0xbf,
0xe6, 0x88, 0x65, 0x43, 0x5c, 0x31, 0xc5, 0x8c, 0xb4, 0x01, 0x15, 0xc5, 0x54, 0x84, 0xa9, 0xb3,
0x36, 0x21, 0x0d, 0xa8, 0x0f, 0x51, 0x86, 0x82, 0xc5, 0x4a, 0x7f, 0x68, 0xdd, 0x9d, 0x2f, 0x91,
0x77, 0xe0, 0x4a, 0x9c, 0xa1, 0x60, 0x2a, 0x31, 0xf6, 0xae, 0xb5, 0xfd, 0x65, 0x41, 0x2f, 0x53,
0x3c, 0xc8, 0x99, 0x64, 0x07, 0x40, 0xe0, 0x08, 0x05, 0x4e, 0x43, 0x94, 0xbe, 0xdb, 0x28, 0x69,
0xd7, 0x1f, 0x2a, 0x6f, 0x8e, 0xc0, 0xcd, 0xbe, 0x22, 0x75, 0x70, 0xae, 0x7a, 0x5f, 0x7b, 0xe7,
0x37, 0x3d, 0xef, 0x19, 0x71, 0xa0, 0xd4, 0x3d, 0xbf, 0xf1, 0x0a, 0x04, 0xa0, 0x7a, 0x76, 0x7c,
0xd4, 0xb9, 0x3a, 0xf3, 0x8a, 0xc4, 0x85, 0xf2, 0x69, 0xe7, 0xe4, 0xd4, 0x2b, 0x91, 0x15, 0x70,
0x0f, 0x83, 0xce, 0xb7, 0xce, 0xe1, 0xc7, 0xae, 0x57, 0x6e, 0xdf, 0x00, 0x64, 0x6f, 0x00, 0x17,
0xa4, 0x03, 0x55, 0x1b, 0x93, 0xdd, 0xe5, 0x0d, 0x97, 0x5e, 0x8a, 0xad, 0x9d, 0x65, 0xc2, 0xe2,
0xcf, 0xdc, 0xfe, 0x0e, 0xf5, 0xfc, 0xde, 0x71, 0x41, 0xbe, 0xe4, 0x9d, 0x1b, 0x8f, 0x5c, 0xa6,
0x27, 0xb5, 0xfe, 0x04, 0x3f, 0xdc, 0x0c, 0x1a, 0x54, 0xcd, 0xd3, 0x76, 0xf0, 0x2f, 0x00, 0x00,
0xff, 0xff, 0xde, 0x1c, 0x85, 0x42, 0xf8, 0x04, 0x00, 0x00,
// 693 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x4d, 0x6f, 0xd3, 0x40,
0x10, 0xc5, 0xf9, 0xb2, 0x33, 0xe9, 0x87, 0x59, 0x55, 0xaa, 0x49, 0xd5, 0x36, 0x0a, 0x97, 0x02,
0x52, 0x22, 0xa5, 0x45, 0x9c, 0xa1, 0x2d, 0x6d, 0x20, 0x4d, 0x2b, 0xf7, 0x4b, 0x70, 0x89, 0x36,
0xce, 0x24, 0x59, 0xd5, 0xc9, 0x9a, 0xdd, 0x6d, 0x44, 0x7e, 0x18, 0x27, 0x7e, 0x05, 0x3f, 0x86,
0x3b, 0xf2, 0xae, 0x9d, 0x26, 0xa1, 0x42, 0xf4, 0xb6, 0x33, 0xef, 0xed, 0xec, 0xbc, 0x99, 0x67,
0x43, 0x59, 0x44, 0x41, 0xbd, 0x87, 0x0a, 0x03, 0xc5, 0x45, 0x5d, 0xa2, 0x98, 0xb0, 0x00, 0x6b,
0x91, 0xe0, 0x8a, 0x93, 0x35, 0x25, 0xd8, 0x64, 0x5a, 0x4b, 0xd1, 0xf2, 0xee, 0x80, 0xf3, 0x41,
0x88, 0x75, 0x8d, 0x76, 0xef, 0xfb, 0x75, 0xc5, 0x46, 0x28, 0x15, 0x1d, 0x45, 0xe6, 0x42, 0xf5,
0x97, 0x05, 0xeb, 0xe7, 0x97, 0x47, 0x9a, 0xef, 0xe3, 0xb7, 0x7b, 0x94, 0x8a, 0x6c, 0x41, 0x91,
0xcb, 0x4e, 0x9f, 0x8e, 0x58, 0x38, 0xf5, 0xac, 0x8a, 0xb5, 0x57, 0xf4, 0x1d, 0x2e, 0x3f, 0xea,
0x98, 0x6c, 0x82, 0xcd, 0x65, 0x67, 0x4c, 0x47, 0xe8, 0x65, 0x34, 0x54, 0xe0, 0xb2, 0x4d, 0x47,
0x48, 0xf6, 0xc1, 0x89, 0x68, 0x70, 0x47, 0x07, 0x28, 0xbd, 0x6c, 0x25, 0xbb, 0x57, 0x6a, 0x6c,
0xd6, 0x16, 0xbb, 0xa9, 0x5d, 0x18, 0xdc, 0x9f, 0x11, 0xc9, 0x36, 0x00, 0x1b, 0xd1, 0x01, 0x9a,
0x82, 0x39, 0x5d, 0xb0, 0xa8, 0x33, 0xba, 0xe6, 0x01, 0xd8, 0x81, 0x40, 0xaa, 0xb0, 0xe7, 0xe5,
0x2b, 0xd6, 0x5e, 0xa9, 0x51, 0xae, 0x19, 0x41, 0xb5, 0x54, 0x50, 0xed, 0x2a, 0x15, 0xe4, 0xa7,
0xd4, 0xea, 0x08, 0xd6, 0x52, 0x41, 0x32, 0xe2, 0x63, 0x89, 0xe4, 0x04, 0xd6, 0x27, 0xf7, 0xe1,
0x18, 0x05, 0xed, 0xb2, 0x90, 0x29, 0x86, 0xd2, 0xb3, 0x74, 0x8b, 0xdb, 0xcb, 0x2d, 0xde, 0xcc,
0xd1, 0xa6, 0xfe, 0xf2, 0x2d, 0x42, 0x20, 0x87, 0x5c, 0x86, 0x5a, 0xba, 0xe3, 0xeb, 0x73, 0xf5,
0xb7, 0x05, 0x76, 0xa2, 0x2c, 0xc6, 0xb5, 0x12, 0x33, 0x35, 0x7d, 0x26, 0x1e, 0xd8, 0x13, 0x14,
0x92, 0xf1, 0x71, 0x32, 0xb1, 0x34, 0x8c, 0x11, 0x81, 0x21, 0x52, 0x89, 0x5e, 0xd6, 0x20, 0x49,
0x48, 0x36, 0x20, 0x8f, 0x11, 0x0f, 0x86, 0x7a, 0x24, 0x79, 0xdf, 0x04, 0x71, 0x75, 0x2a, 0x82,
0xa1, 0x9e, 0x45, 0xd1, 0xd7, 0x67, 0xf2, 0x02, 0x1c, 0x29, 0x02, 0x33, 0xbf, 0x82, 0x29, 0x22,
0x45, 0xa0, 0xa7, 0xb7, 0x0b, 0xa5, 0x18, 0x4a, 0x1f, 0xb7, 0x35, 0x0a, 0x52, 0x04, 0x37, 0xc9,
0xfb, 0x09, 0x21, 0xed, 0xc1, 0x99, 0x11, 0xfc, 0xa4, 0x8d, 0x2d, 0x28, 0xc6, 0x04, 0xd3, 0x4a,
0x51, 0xb7, 0x12, 0xbf, 0x76, 0x1c, 0xc7, 0xd5, 0x9f, 0x16, 0xb8, 0x2d, 0xd6, 0xfd, 0xcb, 0x3b,
0x7d, 0x16, 0x62, 0x27, 0xa2, 0x6a, 0x98, 0x7a, 0x27, 0x4e, 0x5c, 0x50, 0x35, 0x24, 0x6f, 0xa1,
0x18, 0xb2, 0xae, 0xa0, 0x22, 0x5e, 0x40, 0xe6, 0x71, 0x8f, 0xb4, 0x34, 0x61, 0xea, 0x3f, 0x30,
0x97, 0x4c, 0x92, 0xfd, 0x87, 0x49, 0x72, 0xff, 0x6f, 0x92, 0x77, 0x60, 0x27, 0x4f, 0x3d, 0x6d,
0x69, 0xd5, 0x1f, 0x19, 0x58, 0x5d, 0x70, 0x09, 0x79, 0x05, 0xee, 0xbc, 0x4f, 0xa6, 0x1d, 0xd6,
0x4b, 0x6a, 0x2d, 0xf8, 0x67, 0xda, 0xec, 0xc5, 0xdb, 0x8a, 0xee, 0x06, 0xf3, 0x9f, 0x8f, 0x1d,
0xdd, 0x0d, 0xb4, 0x8c, 0x37, 0xf0, 0x9c, 0x8d, 0xa5, 0xa2, 0x61, 0x88, 0xbd, 0xd9, 0xce, 0x8c,
0x58, 0x77, 0x06, 0xa4, 0x9b, 0x7b, 0x09, 0xab, 0x7d, 0xf6, 0x7d, 0x8e, 0x68, 0x3e, 0x9d, 0x15,
0x9d, 0x4c, 0x49, 0x1b, 0x90, 0x57, 0x4c, 0x85, 0x98, 0xf8, 0xc5, 0x04, 0xa4, 0x02, 0xa5, 0x1e,
0xca, 0x40, 0xb0, 0x48, 0xc5, 0x17, 0x8d, 0x67, 0xe6, 0x53, 0xe4, 0x00, 0x1c, 0x89, 0x13, 0x14,
0x4c, 0x4d, 0xb5, 0x69, 0xd6, 0x1a, 0xde, 0xf2, 0x96, 0x2e, 0x13, 0xdc, 0x9f, 0x31, 0xc9, 0x0e,
0x80, 0xc0, 0x3e, 0x0a, 0x1c, 0x07, 0x28, 0x3d, 0xa7, 0x92, 0x8d, 0xbd, 0xf4, 0x90, 0x79, 0x7d,
0x04, 0x4e, 0x7a, 0x8b, 0x94, 0xc0, 0xbe, 0x6e, 0x7f, 0x6e, 0x9f, 0xdf, 0xb6, 0xdd, 0x67, 0xc4,
0x86, 0x6c, 0xeb, 0xfc, 0xd6, 0xb5, 0x08, 0x40, 0xe1, 0xec, 0xf8, 0xa8, 0x79, 0x7d, 0xe6, 0x66,
0x88, 0x03, 0xb9, 0xd3, 0xe6, 0xc9, 0xa9, 0x9b, 0x25, 0x2b, 0xe0, 0x1c, 0xfa, 0xcd, 0xab, 0xe6,
0xe1, 0xfb, 0x96, 0x9b, 0x6b, 0xdc, 0x02, 0xa4, 0xbf, 0x2b, 0x2e, 0x48, 0x13, 0x0a, 0xe6, 0x4c,
0x76, 0x97, 0x3b, 0x5c, 0xfa, 0xa9, 0x95, 0x77, 0x96, 0x09, 0x8b, 0xbf, 0x88, 0xc6, 0x17, 0x28,
0xcd, 0xcc, 0xcc, 0x05, 0xf9, 0x34, 0xab, 0x5c, 0x79, 0xc4, 0xa1, 0x4f, 0x2a, 0xfd, 0x01, 0xbe,
0x3a, 0x29, 0xd4, 0x2d, 0x68, 0x4f, 0xee, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0x65, 0x1f, 0xdb,
0x8d, 0xc5, 0x05, 0x00, 0x00,
}

View File

@@ -1,5 +1,7 @@
syntax = "proto3";
import "google/protobuf/timestamp.proto";
package trivy.detector;
option go_package = "detector";
@@ -8,9 +10,11 @@ service OSDetector {
}
message OSDetectRequest {
string os_family = 1;
string os_name = 2;
repeated Package packages = 3;
string os_family = 1;
string os_name = 2;
repeated Package packages = 3;
string image_name = 4;
google.protobuf.Timestamp created = 5;
}
message DetectResponse {
@@ -39,8 +43,10 @@ service LibDetector {
}
message LibDetectRequest {
string file_path = 1;
repeated Library libraries = 2;
string file_path = 1;
repeated Library libraries = 2;
string image_name = 3;
google.protobuf.Timestamp created = 4;
}
message Library {

View File

@@ -1084,44 +1084,49 @@ func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) conte
}
var twirpFileDescriptor0 = []byte{
// 618 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x4d, 0x4f, 0xdb, 0x40,
0x10, 0x6d, 0x3e, 0xed, 0x4c, 0xf8, 0x70, 0x57, 0x48, 0xb8, 0xa0, 0x42, 0x94, 0x5e, 0x68, 0x2b,
0x05, 0x29, 0xb4, 0xea, 0xb9, 0x05, 0x0a, 0x69, 0x43, 0x40, 0xa6, 0x80, 0xda, 0x4b, 0xb4, 0x71,
0x26, 0x64, 0x85, 0x93, 0x75, 0x77, 0x97, 0xa8, 0x96, 0xfa, 0xb7, 0xfa, 0xd3, 0x7a, 0xaf, 0x76,
0xd7, 0x36, 0x49, 0xca, 0x85, 0xdb, 0xcc, 0xbc, 0xe7, 0x99, 0xd9, 0xf7, 0xd6, 0x0b, 0x5b, 0x22,
0x0e, 0xf7, 0x87, 0xa8, 0x30, 0x54, 0x5c, 0xec, 0x4b, 0x14, 0x33, 0x16, 0x62, 0x2b, 0x16, 0x5c,
0x71, 0xb2, 0xa6, 0x04, 0x9b, 0x25, 0xad, 0x0c, 0x6d, 0xfe, 0x86, 0xf5, 0xf3, 0xcb, 0x23, 0x93,
0x05, 0xf8, 0xf3, 0x1e, 0xa5, 0x22, 0xdb, 0x50, 0xe3, 0xb2, 0x3f, 0xa2, 0x13, 0x16, 0x25, 0x7e,
0xa1, 0x51, 0xd8, 0xab, 0x05, 0x2e, 0x97, 0x9f, 0x4d, 0x4e, 0x36, 0xc1, 0xe1, 0xb2, 0x3f, 0xa5,
0x13, 0xf4, 0x8b, 0x06, 0xaa, 0x72, 0xd9, 0xa3, 0x13, 0x24, 0x07, 0xe0, 0xc6, 0x34, 0xbc, 0xa3,
0xb7, 0x28, 0xfd, 0x52, 0xa3, 0xb4, 0x57, 0x6f, 0x6f, 0xb6, 0x16, 0x67, 0xb5, 0x2e, 0x2c, 0x1e,
0xe4, 0xc4, 0xe6, 0x04, 0xd6, 0xb2, 0xd9, 0x32, 0xe6, 0x53, 0x89, 0xe4, 0x04, 0xd6, 0x67, 0xf7,
0xd1, 0x14, 0x05, 0x1d, 0xb0, 0x88, 0x29, 0x86, 0xd2, 0x2f, 0x98, 0x6e, 0x2f, 0x97, 0xbb, 0x5d,
0xcf, 0xd1, 0x92, 0x60, 0xf9, 0x2b, 0x42, 0xa0, 0x8c, 0x5c, 0x46, 0x66, 0x4b, 0x37, 0x30, 0x71,
0xf3, 0x6f, 0x01, 0x9c, 0x74, 0x09, 0x8d, 0x9b, 0x53, 0xd8, 0x03, 0x9a, 0x98, 0xf8, 0xe0, 0xcc,
0x50, 0x48, 0xc6, 0xa7, 0xe9, 0xe1, 0xb2, 0x54, 0x23, 0x02, 0x23, 0xa4, 0x12, 0xfd, 0x92, 0x45,
0xd2, 0x94, 0x6c, 0x40, 0x05, 0x63, 0x1e, 0x8e, 0xfd, 0x72, 0xa3, 0xb0, 0x57, 0x09, 0x6c, 0xa2,
0xbb, 0x53, 0x11, 0x8e, 0xfd, 0x8a, 0xed, 0xae, 0x63, 0xf2, 0x02, 0x5c, 0x29, 0x42, 0xab, 0x5d,
0xd5, 0x36, 0x91, 0x22, 0x34, 0xe2, 0xed, 0x42, 0x5d, 0x43, 0xd9, 0x70, 0xc7, 0xa0, 0x20, 0x45,
0x78, 0x9d, 0xce, 0x4f, 0x09, 0xd9, 0x0e, 0x6e, 0x4e, 0x08, 0xd2, 0x35, 0xb6, 0xa1, 0xa6, 0x09,
0x76, 0x95, 0x9a, 0x59, 0x45, 0x4f, 0x3b, 0xd6, 0x79, 0x73, 0x04, 0x5e, 0x97, 0x0d, 0xfe, 0x73,
0x79, 0xc4, 0x22, 0xec, 0xc7, 0x54, 0x8d, 0x33, 0x97, 0x75, 0xe1, 0x82, 0xaa, 0x31, 0x79, 0x0f,
0xb5, 0x88, 0x0d, 0x04, 0x15, 0x5a, 0xff, 0xe2, 0xe3, 0x6e, 0x76, 0x0d, 0x21, 0x09, 0x1e, 0x98,
0xcd, 0x0f, 0xe0, 0xa4, 0xd5, 0xa7, 0xc9, 0xdb, 0xfc, 0x53, 0x84, 0xd5, 0x05, 0x3f, 0xc9, 0x6b,
0xf0, 0xe6, 0x1d, 0x4d, 0xfa, 0x6c, 0x98, 0xf6, 0x5a, 0x70, 0x3a, 0xe9, 0x0c, 0xb5, 0xae, 0xf1,
0xdd, 0xed, 0xfc, 0x9d, 0x74, 0xe2, 0xbb, 0x5b, 0xa3, 0xeb, 0x5b, 0x78, 0xce, 0xa6, 0x52, 0xd1,
0x28, 0xc2, 0x61, 0xae, 0xae, 0x35, 0xd0, 0xcb, 0x81, 0x4c, 0xe3, 0x57, 0xb0, 0x3a, 0x62, 0xbf,
0xe6, 0x88, 0x65, 0x43, 0x5c, 0x31, 0xc5, 0x8c, 0xb4, 0x01, 0x15, 0xc5, 0x54, 0x84, 0xa9, 0xb3,
0x36, 0x21, 0x0d, 0xa8, 0x0f, 0x51, 0x86, 0x82, 0xc5, 0x4a, 0x7f, 0x68, 0xdd, 0x9d, 0x2f, 0x91,
0x77, 0xe0, 0x4a, 0x9c, 0xa1, 0x60, 0x2a, 0x31, 0xf6, 0xae, 0xb5, 0xfd, 0x65, 0x41, 0x2f, 0x53,
0x3c, 0xc8, 0x99, 0x64, 0x07, 0x40, 0xe0, 0x08, 0x05, 0x4e, 0x43, 0x94, 0xbe, 0xdb, 0x28, 0x69,
0xd7, 0x1f, 0x2a, 0x6f, 0x8e, 0xc0, 0xcd, 0xbe, 0x22, 0x75, 0x70, 0xae, 0x7a, 0x5f, 0x7b, 0xe7,
0x37, 0x3d, 0xef, 0x19, 0x71, 0xa0, 0xd4, 0x3d, 0xbf, 0xf1, 0x0a, 0x04, 0xa0, 0x7a, 0x76, 0x7c,
0xd4, 0xb9, 0x3a, 0xf3, 0x8a, 0xc4, 0x85, 0xf2, 0x69, 0xe7, 0xe4, 0xd4, 0x2b, 0x91, 0x15, 0x70,
0x0f, 0x83, 0xce, 0xb7, 0xce, 0xe1, 0xc7, 0xae, 0x57, 0x6e, 0xdf, 0x00, 0x64, 0x6f, 0x00, 0x17,
0xa4, 0x03, 0x55, 0x1b, 0x93, 0xdd, 0xe5, 0x0d, 0x97, 0x5e, 0x8a, 0xad, 0x9d, 0x65, 0xc2, 0xe2,
0xcf, 0xdc, 0xfe, 0x0e, 0xf5, 0xfc, 0xde, 0x71, 0x41, 0xbe, 0xe4, 0x9d, 0x1b, 0x8f, 0x5c, 0xa6,
0x27, 0xb5, 0xfe, 0x04, 0x3f, 0xdc, 0x0c, 0x1a, 0x54, 0xcd, 0xd3, 0x76, 0xf0, 0x2f, 0x00, 0x00,
0xff, 0xff, 0xde, 0x1c, 0x85, 0x42, 0xf8, 0x04, 0x00, 0x00,
// 693 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x4d, 0x6f, 0xd3, 0x40,
0x10, 0xc5, 0xf9, 0xb2, 0x33, 0xe9, 0x87, 0x59, 0x55, 0xaa, 0x49, 0xd5, 0x36, 0x0a, 0x97, 0x02,
0x52, 0x22, 0xa5, 0x45, 0x9c, 0xa1, 0x2d, 0x6d, 0x20, 0x4d, 0x2b, 0xf7, 0x4b, 0x70, 0x89, 0x36,
0xce, 0x24, 0x59, 0xd5, 0xc9, 0x9a, 0xdd, 0x6d, 0x44, 0x7e, 0x18, 0x27, 0x7e, 0x05, 0x3f, 0x86,
0x3b, 0xf2, 0xae, 0x9d, 0x26, 0xa1, 0x42, 0xf4, 0xb6, 0x33, 0xef, 0xed, 0xec, 0xbc, 0x99, 0x67,
0x43, 0x59, 0x44, 0x41, 0xbd, 0x87, 0x0a, 0x03, 0xc5, 0x45, 0x5d, 0xa2, 0x98, 0xb0, 0x00, 0x6b,
0x91, 0xe0, 0x8a, 0x93, 0x35, 0x25, 0xd8, 0x64, 0x5a, 0x4b, 0xd1, 0xf2, 0xee, 0x80, 0xf3, 0x41,
0x88, 0x75, 0x8d, 0x76, 0xef, 0xfb, 0x75, 0xc5, 0x46, 0x28, 0x15, 0x1d, 0x45, 0xe6, 0x42, 0xf5,
0x97, 0x05, 0xeb, 0xe7, 0x97, 0x47, 0x9a, 0xef, 0xe3, 0xb7, 0x7b, 0x94, 0x8a, 0x6c, 0x41, 0x91,
0xcb, 0x4e, 0x9f, 0x8e, 0x58, 0x38, 0xf5, 0xac, 0x8a, 0xb5, 0x57, 0xf4, 0x1d, 0x2e, 0x3f, 0xea,
0x98, 0x6c, 0x82, 0xcd, 0x65, 0x67, 0x4c, 0x47, 0xe8, 0x65, 0x34, 0x54, 0xe0, 0xb2, 0x4d, 0x47,
0x48, 0xf6, 0xc1, 0x89, 0x68, 0x70, 0x47, 0x07, 0x28, 0xbd, 0x6c, 0x25, 0xbb, 0x57, 0x6a, 0x6c,
0xd6, 0x16, 0xbb, 0xa9, 0x5d, 0x18, 0xdc, 0x9f, 0x11, 0xc9, 0x36, 0x00, 0x1b, 0xd1, 0x01, 0x9a,
0x82, 0x39, 0x5d, 0xb0, 0xa8, 0x33, 0xba, 0xe6, 0x01, 0xd8, 0x81, 0x40, 0xaa, 0xb0, 0xe7, 0xe5,
0x2b, 0xd6, 0x5e, 0xa9, 0x51, 0xae, 0x19, 0x41, 0xb5, 0x54, 0x50, 0xed, 0x2a, 0x15, 0xe4, 0xa7,
0xd4, 0xea, 0x08, 0xd6, 0x52, 0x41, 0x32, 0xe2, 0x63, 0x89, 0xe4, 0x04, 0xd6, 0x27, 0xf7, 0xe1,
0x18, 0x05, 0xed, 0xb2, 0x90, 0x29, 0x86, 0xd2, 0xb3, 0x74, 0x8b, 0xdb, 0xcb, 0x2d, 0xde, 0xcc,
0xd1, 0xa6, 0xfe, 0xf2, 0x2d, 0x42, 0x20, 0x87, 0x5c, 0x86, 0x5a, 0xba, 0xe3, 0xeb, 0x73, 0xf5,
0xb7, 0x05, 0x76, 0xa2, 0x2c, 0xc6, 0xb5, 0x12, 0x33, 0x35, 0x7d, 0x26, 0x1e, 0xd8, 0x13, 0x14,
0x92, 0xf1, 0x71, 0x32, 0xb1, 0x34, 0x8c, 0x11, 0x81, 0x21, 0x52, 0x89, 0x5e, 0xd6, 0x20, 0x49,
0x48, 0x36, 0x20, 0x8f, 0x11, 0x0f, 0x86, 0x7a, 0x24, 0x79, 0xdf, 0x04, 0x71, 0x75, 0x2a, 0x82,
0xa1, 0x9e, 0x45, 0xd1, 0xd7, 0x67, 0xf2, 0x02, 0x1c, 0x29, 0x02, 0x33, 0xbf, 0x82, 0x29, 0x22,
0x45, 0xa0, 0xa7, 0xb7, 0x0b, 0xa5, 0x18, 0x4a, 0x1f, 0xb7, 0x35, 0x0a, 0x52, 0x04, 0x37, 0xc9,
0xfb, 0x09, 0x21, 0xed, 0xc1, 0x99, 0x11, 0xfc, 0xa4, 0x8d, 0x2d, 0x28, 0xc6, 0x04, 0xd3, 0x4a,
0x51, 0xb7, 0x12, 0xbf, 0x76, 0x1c, 0xc7, 0xd5, 0x9f, 0x16, 0xb8, 0x2d, 0xd6, 0xfd, 0xcb, 0x3b,
0x7d, 0x16, 0x62, 0x27, 0xa2, 0x6a, 0x98, 0x7a, 0x27, 0x4e, 0x5c, 0x50, 0x35, 0x24, 0x6f, 0xa1,
0x18, 0xb2, 0xae, 0xa0, 0x22, 0x5e, 0x40, 0xe6, 0x71, 0x8f, 0xb4, 0x34, 0x61, 0xea, 0x3f, 0x30,
0x97, 0x4c, 0x92, 0xfd, 0x87, 0x49, 0x72, 0xff, 0x6f, 0x92, 0x77, 0x60, 0x27, 0x4f, 0x3d, 0x6d,
0x69, 0xd5, 0x1f, 0x19, 0x58, 0x5d, 0x70, 0x09, 0x79, 0x05, 0xee, 0xbc, 0x4f, 0xa6, 0x1d, 0xd6,
0x4b, 0x6a, 0x2d, 0xf8, 0x67, 0xda, 0xec, 0xc5, 0xdb, 0x8a, 0xee, 0x06, 0xf3, 0x9f, 0x8f, 0x1d,
0xdd, 0x0d, 0xb4, 0x8c, 0x37, 0xf0, 0x9c, 0x8d, 0xa5, 0xa2, 0x61, 0x88, 0xbd, 0xd9, 0xce, 0x8c,
0x58, 0x77, 0x06, 0xa4, 0x9b, 0x7b, 0x09, 0xab, 0x7d, 0xf6, 0x7d, 0x8e, 0x68, 0x3e, 0x9d, 0x15,
0x9d, 0x4c, 0x49, 0x1b, 0x90, 0x57, 0x4c, 0x85, 0x98, 0xf8, 0xc5, 0x04, 0xa4, 0x02, 0xa5, 0x1e,
0xca, 0x40, 0xb0, 0x48, 0xc5, 0x17, 0x8d, 0x67, 0xe6, 0x53, 0xe4, 0x00, 0x1c, 0x89, 0x13, 0x14,
0x4c, 0x4d, 0xb5, 0x69, 0xd6, 0x1a, 0xde, 0xf2, 0x96, 0x2e, 0x13, 0xdc, 0x9f, 0x31, 0xc9, 0x0e,
0x80, 0xc0, 0x3e, 0x0a, 0x1c, 0x07, 0x28, 0x3d, 0xa7, 0x92, 0x8d, 0xbd, 0xf4, 0x90, 0x79, 0x7d,
0x04, 0x4e, 0x7a, 0x8b, 0x94, 0xc0, 0xbe, 0x6e, 0x7f, 0x6e, 0x9f, 0xdf, 0xb6, 0xdd, 0x67, 0xc4,
0x86, 0x6c, 0xeb, 0xfc, 0xd6, 0xb5, 0x08, 0x40, 0xe1, 0xec, 0xf8, 0xa8, 0x79, 0x7d, 0xe6, 0x66,
0x88, 0x03, 0xb9, 0xd3, 0xe6, 0xc9, 0xa9, 0x9b, 0x25, 0x2b, 0xe0, 0x1c, 0xfa, 0xcd, 0xab, 0xe6,
0xe1, 0xfb, 0x96, 0x9b, 0x6b, 0xdc, 0x02, 0xa4, 0xbf, 0x2b, 0x2e, 0x48, 0x13, 0x0a, 0xe6, 0x4c,
0x76, 0x97, 0x3b, 0x5c, 0xfa, 0xa9, 0x95, 0x77, 0x96, 0x09, 0x8b, 0xbf, 0x88, 0xc6, 0x17, 0x28,
0xcd, 0xcc, 0xcc, 0x05, 0xf9, 0x34, 0xab, 0x5c, 0x79, 0xc4, 0xa1, 0x4f, 0x2a, 0xfd, 0x01, 0xbe,
0x3a, 0x29, 0xd4, 0x2d, 0x68, 0x4f, 0xee, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0x65, 0x1f, 0xdb,
0x8d, 0xc5, 0x05, 0x00, 0x00,
}