mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-08 13:50:49 -08:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42043a0888 | ||
|
|
246793e873 | ||
|
|
692b0f1410 | ||
|
|
0629e1d731 | ||
|
|
9707c7bcb1 | ||
|
|
194fbef73c | ||
|
|
f7db00c1eb | ||
|
|
2f4b31ecc6 | ||
|
|
9289624688 | ||
|
|
5a8749cd5b | ||
|
|
4a7fb525d7 | ||
|
|
8888fcafa7 | ||
|
|
63a8c6d26b | ||
|
|
fc222bed7c | ||
|
|
6132ff93a2 | ||
|
|
87556aa741 | ||
|
|
43362b2832 | ||
|
|
db2d0c2e9b | ||
|
|
922d493159 |
@@ -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"]
|
||||
|
||||
46
README.md
46
README.md
@@ -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
|
||||
|
||||
|
||||
@@ -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 \
|
||||
|
||||
29
contrib/Trivy.gitlab-ci.yml
Normal file
29
contrib/Trivy.gitlab-ci.yml
Normal 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
80
contrib/gitlab.tpl
Normal 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
409
contrib/install.sh
Executable 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
6
go.mod
@@ -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
31
go.sum
@@ -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=
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
26
integration/testdata/centos-6.json.golden
vendored
26
integration/testdata/centos-6.json.golden
vendored
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
26
integration/testdata/centos-7.json.golden
vendored
26
integration/testdata/centos-7.json.golden
vendored
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
var SuperSet = wire.NewSet(
|
||||
cache.New,
|
||||
cache.Initialize,
|
||||
NewCache,
|
||||
)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"},
|
||||
},
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user