refactor: don't use global Config in private func (#1197)

* refactor: cve_client.go

* refactor: don't use global Config in private func

* remove import alias for config

* refactor: dbclient

* refactor: resultDir

* refactor: resultsDir

* refactor

* refactor: gost

* refactor: db client

* refactor: cveDB

* refactor: cvedb

* refactor: exploitDB

* refactor: remove detector/dbclient.go

* refactor: writer

* refactor: syslog writer

* refactor: ips

* refactor: ensureResultDir

* refactor: proxy

* fix(db): call CloseDB

* add integration test

* feat(report): sort array in json

* sort func for json diff

* add build-int to makefile

* add int-rds-redis to makefile

* fix: test case, makefile

* fix makefile

* show cve count after diff

* make diff

* diff -c

* sort exploits in json for diff

* sort metasploit, exploit
This commit is contained in:
Kota Kanbe
2021-04-01 13:36:24 +09:00
committed by GitHub
parent 0179f4299a
commit 9bfe0627ae
70 changed files with 48982 additions and 1274 deletions

3
.gitignore vendored
View File

@@ -1,6 +1,5 @@
.vscode
*.txt
*.json
*.sqlite3*
*.db
tags
@@ -10,7 +9,7 @@ issues/
vendor/
log/
results/
*config.toml
config.toml
!setup/docker/*
.DS_Store
dist/

View File

@@ -80,3 +80,114 @@ build-trivy-to-vuls: pretest fmt
# future-vuls
build-future-vuls: pretest fmt
$(GO) build -o future-vuls contrib/future-vuls/cmd/*.go
# integration-test
BASE_DIR := '${PWD}/integration/results'
NOW=$(shell date --iso-8601=seconds)
NOW_JSON_DIR := '${BASE_DIR}/$(NOW)'
ONE_SEC_AFTER=$(shell date -d '+1 second' --iso-8601=seconds)
ONE_SEC_AFTER_JSON_DIR := '${BASE_DIR}/$(ONE_SEC_AFTER)'
diff:
# git clone git@github.com:vulsio/vulsctl.git
# cd vulsctl/docker
# ./update-all.sh
# cd /path/to/vuls
# vim integration/int-config.toml
# ln -s vuls vuls.new
# ln -s oldvuls vuls.old
# make int
# (ex. test 10 times: for i in `seq 10`; do make int ARGS=-quiet ; done)
mv ${BASE_DIR}/* /tmp
mkdir -p ${NOW_JSON_DIR}
cp integration/data/*.json ${NOW_JSON_DIR}
./vuls.old report --format-json --refresh-cve --results-dir=${BASE_DIR} -config=./integration/int-config.toml $(ARGS)
mkdir -p ${ONE_SEC_AFTER_JSON_DIR}
cp integration/data/*.json ${ONE_SEC_AFTER_JSON_DIR}
./vuls.new report --format-json --refresh-cve --results-dir=${BASE_DIR} -config=./integration/int-config.toml $(ARGS)
find ${NOW_JSON_DIR} -type f -exec sed -i -e '/reportedAt/d' {} \;
find ${ONE_SEC_AFTER_JSON_DIR} -type f -exec sed -i -e '/reportedAt/d' {} \;
diff -c ${NOW_JSON_DIR} ${ONE_SEC_AFTER_JSON_DIR}
echo "old: ${NOW_JSON_DIR} , new: ${ONE_SEC_AFTER_JSON_DIR}"
diff-redis:
# docker network create redis-nw
# docker run --name redis -d --network redis-nw -p 127.0.0.1:6379:6379 redis
# git clone git@github.com:vulsio/vulsctl.git
# cd vulsctl/docker
# ./update-all-redis.sh
# (or export DOCKER_NETWORK=redis-nw; cd /home/ubuntu/vulsctl/docker; ./update-all.sh --dbtype redis --dbpath "redis://redis/0")
# vim integration/int-redis-config.toml
# ln -s vuls vuls.new
# ln -s oldvuls vuls.old
# make int-redis
mv ${BASE_DIR}/* /tmp
mkdir -p ${NOW_JSON_DIR}
cp integration/data/*.json ${NOW_JSON_DIR}
./vuls.old report --format-json --refresh-cve --results-dir=${BASE_DIR} -config=./integration/int-redis-config.toml
mkdir -p ${ONE_SEC_AFTER_JSON_DIR}
cp integration/data/*.json ${ONE_SEC_AFTER_JSON_DIR}
./vuls.new report --format-json --refresh-cve --results-dir=${BASE_DIR} -config=./integration/int-redis-config.toml
find ${NOW_JSON_DIR} -type f -exec sed -i -e '/reportedAt/d' {} \;
find ${ONE_SEC_AFTER_JSON_DIR} -type f -exec sed -i -e '/reportedAt/d' {} \;
diff -c ${NOW_JSON_DIR} ${ONE_SEC_AFTER_JSON_DIR}
echo "old: ${NOW_JSON_DIR} , new: ${ONE_SEC_AFTER_JSON_DIR}"
diff-rdb-redis:
mv ${BASE_DIR}/* /tmp
mkdir -p ${NOW_JSON_DIR}
cp integration/data/*.json ${NOW_JSON_DIR}
./vuls.new report --format-json --refresh-cve --results-dir=${BASE_DIR} -config=./integration/int-config.toml
mkdir -p ${ONE_SEC_AFTER_JSON_DIR}
cp integration/data/*.json ${ONE_SEC_AFTER_JSON_DIR}
./vuls.new report --format-json --refresh-cve --results-dir=${BASE_DIR} -config=./integration/int-redis-config.toml
# remove reportedAt line
find ${NOW_JSON_DIR} -type f -exec sed -i -e '/reportedAt/d' {} \;
find ${ONE_SEC_AFTER_JSON_DIR} -type f -exec sed -i -e '/reportedAt/d' {} \;
# remove "Type": line
find ${NOW_JSON_DIR} -type f -exec sed -i -e '/"Type":/d' {} \;
find ${ONE_SEC_AFTER_JSON_DIR} -type f -exec sed -i -e '/"Type":/d' {} \;
# remove "SQLite3Path": line
find ${NOW_JSON_DIR} -type f -exec sed -i -e '/"SQLite3Path":/d' {} \;
find ${ONE_SEC_AFTER_JSON_DIR} -type f -exec sed -i -e '/"SQLite3Path":/d' {} \;
diff -c ${NOW_JSON_DIR} ${ONE_SEC_AFTER_JSON_DIR}
echo "old: ${NOW_JSON_DIR} , new: ${ONE_SEC_AFTER_JSON_DIR}"
for jsonfile in ${NOW_JSON_DIR}/*.json ; do \
echo $$jsonfile; cat $$jsonfile | jq ".scannedCves | length" ; \
done
for jsonfile in ${ONE_SEC_AFTER_JSON_DIR}/*.json ; do \
echo $$jsonfile; cat $$jsonfile | jq ".scannedCves | length" ; \
done
head= $(shell git rev-parse HEAD)
prev= $(shell git rev-parse HEAD^)
branch=$(shell git rev-parse --abbrev-ref HEAD)
build-integration:
git stash
# buld HEAD
git checkout ${head}
make build
mv -f ./vuls ./vuls.${head}
# HEAD^
git checkout ${prev}
make build
mv -f ./vuls ./vuls.${prev}
git checkout ${branch}
git stash apply stash@\{0\}
# working tree
make build
# for integration testing, vuls.new and vuls.old needed.
# ex)
# $ ln -s ./vuls ./vuls.new
# $ ln -s ./vuls.${head} ./vuls.old
# or
# $ ln -s ./vuls.${prev} ./vuls.old
# $ make int
# $ make int-redis

View File

@@ -23,11 +23,9 @@ var Conf Config
//Config is struct of Configuration
type Config struct {
logging.LogOpts
// scan, report
Debug bool `json:"debug,omitempty"`
DebugSQL bool `json:"debugSQL,omitempty"`
LogDir string `json:"logDir,omitempty"`
Quiet bool `json:"quiet,omitempty"`
HTTPProxy string `valid:"url" json:"httpProxy,omitempty"`
ResultsDir string `json:"resultsDir,omitempty"`
Pipe bool `json:"pipe,omitempty"`
@@ -65,8 +63,7 @@ type ReportConf interface {
// ScanOpts is options for scan
type ScanOpts struct {
Vvv bool `json:"vvv,omitempty"`
DetectIPS bool `json:"detectIps,omitempty"`
Vvv bool `json:"vvv,omitempty"`
}
// ReportOpts is options for report
@@ -164,25 +161,25 @@ func (c *Config) ValidateOnReport() bool {
}
}
for _, err := range errs {
logging.Log.Error(err)
}
return len(errs) == 0
}
// ValidateOnTui validates configuration
func (c Config) ValidateOnTui() bool {
errs := []error{}
if len(c.ResultsDir) != 0 {
if ok, _ := govalidator.IsFilePath(c.ResultsDir); !ok {
errs = append(errs, xerrors.Errorf(
"JSON base directory must be a *Absolute* file path. -results-dir: %s", c.ResultsDir))
for _, cnf := range []VulnDictInterface{
&Conf.CveDict,
&Conf.OvalDict,
&Conf.Gost,
&Conf.Exploit,
&Conf.Metasploit,
} {
if err := cnf.Validate(); err != nil {
errs = append(errs, xerrors.Errorf("Failed to validate %s: %+v", cnf.GetName(), err))
}
if err := cnf.CheckHTTPHealth(); err != nil {
errs = append(errs, xerrors.Errorf("Run %s as server mode before reporting: %+v", cnf.GetName(), err))
}
}
for _, err := range errs {
logging.Log.Error(err)
}
return len(errs) == 0
}

View File

@@ -1,6 +0,0 @@
package config
const (
// DeepSecurity is
DeepSecurity string = "deepsecurity"
)

View File

@@ -22,6 +22,7 @@ type VulnDictInterface interface {
GetType() string
GetURL() string
GetSQLite3Path() string
GetDebugSQL() bool
}
// VulnDict is a base struct of vuln dicts
@@ -35,31 +36,38 @@ type VulnDict struct {
URL string `json:"-"`
// /path/to/cve.sqlite3
SQLite3Path string `json:"-"`
SQLite3Path string
DebugSQL bool
}
// GetType returns type
func (cnf *VulnDict) GetType() string {
func (cnf VulnDict) GetType() string {
return cnf.Type
}
// GetName returns name
func (cnf *VulnDict) GetName() string {
func (cnf VulnDict) GetName() string {
return cnf.Name
}
// GetURL returns url
func (cnf *VulnDict) GetURL() string {
func (cnf VulnDict) GetURL() string {
return cnf.URL
}
// GetSQLite3Path return the path of SQLite3
func (cnf *VulnDict) GetSQLite3Path() string {
func (cnf VulnDict) GetSQLite3Path() string {
return cnf.SQLite3Path
}
// GetDebugSQL return debugSQL flag
func (cnf VulnDict) GetDebugSQL() bool {
return cnf.DebugSQL
}
// Validate settings
func (cnf *VulnDict) Validate() error {
func (cnf VulnDict) Validate() error {
logging.Log.Infof("%s.type=%s, %s.url=%s, %s.SQLite3Path=%s",
cnf.Name, cnf.Type, cnf.Name, cnf.URL, cnf.Name, cnf.SQLite3Path)
@@ -99,7 +107,7 @@ func (cnf *VulnDict) Validate() error {
}
// Init the struct
func (cnf *VulnDict) Init() {}
func (cnf VulnDict) Init() {}
func (cnf *VulnDict) setDefault(sqlite3Name string) {
if cnf.Type == "" {
@@ -112,12 +120,12 @@ func (cnf *VulnDict) setDefault(sqlite3Name string) {
}
// IsFetchViaHTTP returns if fetch via HTTP
func (cnf *VulnDict) IsFetchViaHTTP() bool {
func (cnf VulnDict) IsFetchViaHTTP() bool {
return cnf.Type == "http"
}
// CheckHTTPHealth checks http server status
func (cnf *VulnDict) CheckHTTPHealth() error {
func (cnf VulnDict) CheckHTTPHealth() error {
if !cnf.IsFetchViaHTTP() {
return nil
}
@@ -156,6 +164,7 @@ func (cnf *GovalDictConf) Init() {
cnf.SQLite3Path = os.Getenv(govalPATH)
}
cnf.setDefault("oval.sqlite3")
cnf.DebugSQL = Conf.DebugSQL
}
// ExploitConf is exploit config
@@ -182,6 +191,7 @@ func (cnf *ExploitConf) Init() {
cnf.SQLite3Path = os.Getenv(exploitDBPATH)
}
cnf.setDefault("go-exploitdb.sqlite3")
cnf.DebugSQL = Conf.DebugSQL
}
// GoCveDictConf is GoCveDict config
@@ -208,6 +218,7 @@ func (cnf *GoCveDictConf) Init() {
cnf.SQLite3Path = os.Getenv(cveDBPATH)
}
cnf.setDefault("cve.sqlite3")
cnf.DebugSQL = Conf.DebugSQL
}
// GostConf is gost config
@@ -234,6 +245,7 @@ func (cnf *GostConf) Init() {
cnf.SQLite3Path = os.Getenv(gostDBPATH)
}
cnf.setDefault("gost.sqlite3")
cnf.DebugSQL = Conf.DebugSQL
}
// MetasploitConf is gost go-metasploitdb
@@ -260,4 +272,5 @@ func (cnf *MetasploitConf) Init() {
cnf.SQLite3Path = os.Getenv(metasploitDBPATH)
}
cnf.setDefault("go-msfdb.sqlite3")
cnf.DebugSQL = Conf.DebugSQL
}

View File

@@ -16,15 +16,50 @@ import (
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/util"
cvedb "github.com/kotakanbe/go-cve-dictionary/db"
cvelog "github.com/kotakanbe/go-cve-dictionary/log"
cvemodels "github.com/kotakanbe/go-cve-dictionary/models"
)
// CveClient is api client of CVE dictionary service.
var CveClient cvedictClient
type goCveDictClient struct {
cnf config.VulnDictInterface
driver cvedb.DB
}
type cvedictClient struct {
// httpProxy string
baseURL string
func newGoCveDictClient(cnf config.VulnDictInterface, o logging.LogOpts) (*goCveDictClient, error) {
cvelog.SetLogger(o.LogDir, o.Quiet, o.Debug, false)
driver, locked, err := newCveDB(cnf)
if locked {
return nil, xerrors.Errorf("SQLite3 is locked: %s", cnf.GetSQLite3Path())
} else if err != nil {
return nil, err
}
return &goCveDictClient{cnf: cnf, driver: driver}, nil
}
func (api goCveDictClient) closeDB() error {
if api.driver == nil {
return nil
}
if err := api.driver.CloseDB(); err != nil {
return xerrors.Errorf("Failed to close DB: %+v", err)
}
return nil
}
func (api goCveDictClient) fetchCveDetails(cveIDs []string) (cveDetails []cvemodels.CveDetail, err error) {
for _, cveID := range cveIDs {
cveDetail, err := api.driver.Get(cveID)
if err != nil {
return nil, xerrors.Errorf("Failed to fetch CVE. err: %w", err)
}
if len(cveDetail.CveID) == 0 {
cveDetails = append(cveDetails, cvemodels.CveDetail{CveID: cveID})
} else {
cveDetails = append(cveDetails, *cveDetail)
}
}
return
}
type response struct {
@@ -32,28 +67,7 @@ type response struct {
CveDetail cvemodels.CveDetail
}
func (api cvedictClient) FetchCveDetails(driver cvedb.DB, cveIDs []string) (cveDetails []cvemodels.CveDetail, err error) {
if !config.Conf.CveDict.IsFetchViaHTTP() {
if driver == nil {
return
}
for _, cveID := range cveIDs {
cveDetail, err := driver.Get(cveID)
if err != nil {
return nil, xerrors.Errorf("Failed to fetch CVE. err: %w", err)
}
if len(cveDetail.CveID) == 0 {
cveDetails = append(cveDetails, cvemodels.CveDetail{
CveID: cveID,
})
} else {
cveDetails = append(cveDetails, *cveDetail)
}
}
return
}
api.baseURL = config.Conf.CveDict.URL
func (api goCveDictClient) fetchCveDetailsViaHTTP(cveIDs []string) (cveDetails []cvemodels.CveDetail, err error) {
reqChan := make(chan string, len(cveIDs))
resChan := make(chan response, len(cveIDs))
errChan := make(chan error, len(cveIDs))
@@ -73,7 +87,7 @@ func (api cvedictClient) FetchCveDetails(driver cvedb.DB, cveIDs []string) (cveD
tasks <- func() {
select {
case cveID := <-reqChan:
url, err := util.URLPathJoin(api.baseURL, "cves", cveID)
url, err := util.URLPathJoin(api.cnf.GetURL(), "cves", cveID)
if err != nil {
errChan <- err
} else {
@@ -109,12 +123,11 @@ func (api cvedictClient) FetchCveDetails(driver cvedb.DB, cveIDs []string) (cveD
return
}
func (api cvedictClient) httpGet(key, url string, resChan chan<- response, errChan chan<- error) {
func (api goCveDictClient) httpGet(key, url string, resChan chan<- response, errChan chan<- error) {
var body string
var errs []error
var resp *http.Response
f := func() (err error) {
// resp, body, errs = gorequest.New().SetDebug(config.Conf.Debug).Get(url).End()
resp, body, errs = gorequest.New().Timeout(10 * time.Second).Get(url).End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
return xerrors.Errorf("HTTP GET Error, url: %s, resp: %v, err: %+v",
@@ -123,8 +136,7 @@ func (api cvedictClient) httpGet(key, url string, resChan chan<- response, errCh
return nil
}
notify := func(err error, t time.Duration) {
logging.Log.Warnf("Failed to HTTP GET. retrying in %s seconds. err: %+v",
t, err)
logging.Log.Warnf("Failed to HTTP GET. retrying in %s seconds. err: %+v", t, err)
}
err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify)
if err != nil {
@@ -142,10 +154,9 @@ func (api cvedictClient) httpGet(key, url string, resChan chan<- response, errCh
}
}
func (api cvedictClient) FetchCveDetailsByCpeName(driver cvedb.DB, cpeName string) ([]cvemodels.CveDetail, error) {
if config.Conf.CveDict.IsFetchViaHTTP() {
api.baseURL = config.Conf.CveDict.URL
url, err := util.URLPathJoin(api.baseURL, "cpes")
func (api goCveDictClient) fetchCveDetailsByCpeName(cpeName string) ([]cvemodels.CveDetail, error) {
if api.cnf.IsFetchViaHTTP() {
url, err := util.URLPathJoin(api.cnf.GetURL(), "cpes")
if err != nil {
return nil, err
}
@@ -154,15 +165,14 @@ func (api cvedictClient) FetchCveDetailsByCpeName(driver cvedb.DB, cpeName strin
logging.Log.Debugf("HTTP Request to %s, query: %#v", url, query)
return api.httpPost(cpeName, url, query)
}
return driver.GetByCpeURI(cpeName)
return api.driver.GetByCpeURI(cpeName)
}
func (api cvedictClient) httpPost(key, url string, query map[string]string) ([]cvemodels.CveDetail, error) {
func (api goCveDictClient) httpPost(key, url string, query map[string]string) ([]cvemodels.CveDetail, error) {
var body string
var errs []error
var resp *http.Response
f := func() (err error) {
// req := gorequest.New().SetDebug(config.Conf.Debug).Post(url)
req := gorequest.New().Timeout(10 * time.Second).Post(url)
for key := range query {
req = req.Send(fmt.Sprintf("%s=%s", key, query[key])).Type("json")
@@ -188,3 +198,19 @@ func (api cvedictClient) httpPost(key, url string, query map[string]string) ([]c
}
return cveDetails, nil
}
func newCveDB(cnf config.VulnDictInterface) (driver cvedb.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
driver, locked, err = cvedb.NewDB(cnf.GetType(), path, cnf.GetDebugSQL())
if err != nil {
err = xerrors.Errorf("Failed to init CVE DB. err: %w, path: %s", err, path)
return nil, locked, err
}
return driver, false, nil
}

View File

@@ -1,184 +0,0 @@
// +build !scanner
package detector
import (
"github.com/future-architect/vuls/config"
gostdb "github.com/knqyf263/gost/db"
cvedb "github.com/kotakanbe/go-cve-dictionary/db"
ovaldb "github.com/kotakanbe/goval-dictionary/db"
metasploitdb "github.com/takuzoo3868/go-msfdb/db"
exploitdb "github.com/vulsio/go-exploitdb/db"
"golang.org/x/xerrors"
)
// DBClient is DB client for reporting
type DBClient struct {
CveDB cvedb.DB
OvalDB ovaldb.DB
GostDB gostdb.DB
ExploitDB exploitdb.DB
MetasploitDB metasploitdb.DB
}
// NewDBClient returns db clients
func NewDBClient(cveDict, ovalDict, gost, exploit, metasploit config.VulnDictInterface, debugSQL bool) (dbclient *DBClient, err error) {
for _, cnf := range []config.VulnDictInterface{cveDict, ovalDict, gost, exploit, metasploit} {
if err := cnf.Validate(); err != nil {
return nil, xerrors.Errorf("Failed to validate %s: %+v", cnf.GetName(), err)
}
if err := cnf.CheckHTTPHealth(); err != nil {
return nil, xerrors.Errorf("Run %s as server mode before reporting: %+v", cnf.GetName(), err)
}
}
cveDriver, locked, err := NewCveDB(cveDict, debugSQL)
if locked {
return nil, xerrors.Errorf("SQLite3 is locked: %s", cveDict.GetSQLite3Path())
} else if err != nil {
return nil, err
}
ovaldb, locked, err := NewOvalDB(ovalDict, debugSQL)
if locked {
return nil, xerrors.Errorf("SQLite3 is locked: %s", ovalDict.GetSQLite3Path())
} else if err != nil {
return nil, err
}
gostdb, locked, err := NewGostDB(gost, debugSQL)
if locked {
return nil, xerrors.Errorf("SQLite3 is locked: %s", gost.GetSQLite3Path())
} else if err != nil {
return nil, err
}
exploitdb, locked, err := NewExploitDB(exploit, debugSQL)
if locked {
return nil, xerrors.Errorf("SQLite3 is locked: %s", exploit.GetSQLite3Path())
} else if err != nil {
return nil, err
}
metasploitdb, locked, err := NewMetasploitDB(metasploit, debugSQL)
if locked {
return nil, xerrors.Errorf("SQLite3 is locked: %s", metasploit.GetSQLite3Path())
} else if err != nil {
return nil, err
}
return &DBClient{
CveDB: cveDriver,
OvalDB: ovaldb,
GostDB: gostdb,
ExploitDB: exploitdb,
MetasploitDB: metasploitdb,
}, nil
}
// NewCveDB returns cve db client
func NewCveDB(cnf config.VulnDictInterface, debugSQL bool) (driver cvedb.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
driver, locked, err = cvedb.NewDB(cnf.GetType(), path, debugSQL)
if err != nil {
err = xerrors.Errorf("Failed to init CVE DB. err: %w, path: %s", err, path)
return nil, locked, err
}
return driver, false, nil
}
// NewOvalDB returns oval db client
func NewOvalDB(cnf config.VulnDictInterface, debugSQL bool) (driver ovaldb.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
driver, locked, err = ovaldb.NewDB("", cnf.GetType(), path, debugSQL)
if err != nil {
err = xerrors.Errorf("Failed to new OVAL DB. err: %w", err)
if locked {
return nil, true, err
}
return nil, false, err
}
return driver, false, nil
}
// NewGostDB returns db client for Gost
func NewGostDB(cnf config.VulnDictInterface, debugSQL bool) (driver gostdb.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
if driver, locked, err = gostdb.NewDB(cnf.GetType(), path, debugSQL); err != nil {
if locked {
return nil, true, xerrors.Errorf("gostDB is locked. err: %w", err)
}
return nil, false, err
}
return driver, false, nil
}
// NewExploitDB returns db client for Exploit
func NewExploitDB(cnf config.VulnDictInterface, debugSQL bool) (driver exploitdb.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
if driver, locked, err = exploitdb.NewDB(cnf.GetType(), path, debugSQL); err != nil {
if locked {
return nil, true, xerrors.Errorf("exploitDB is locked. err: %w", err)
}
return nil, false, err
}
return driver, false, nil
}
// NewMetasploitDB returns db client for Metasploit
func NewMetasploitDB(cnf config.VulnDictInterface, debugSQL bool) (driver metasploitdb.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
if driver, locked, err = metasploitdb.NewDB(cnf.GetType(), path, debugSQL, false); err != nil {
if locked {
return nil, true, xerrors.Errorf("metasploitDB is locked. err: %w", err)
}
return nil, false, err
}
return driver, false, nil
}
// CloseDB close dbs
func (d DBClient) CloseDB() (errs []error) {
if d.CveDB != nil {
if err := d.CveDB.CloseDB(); err != nil {
errs = append(errs, xerrors.Errorf("Failed to close cveDB. err: %+v", err))
}
}
if d.OvalDB != nil {
if err := d.OvalDB.CloseDB(); err != nil {
errs = append(errs, xerrors.Errorf("Failed to close ovalDB. err: %+v", err))
}
}
//TODO CloseDB gost, exploitdb, metasploit
return errs
}

View File

@@ -7,38 +7,27 @@ import (
"strings"
"time"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/constant"
"github.com/future-architect/vuls/contrib/owasp-dependency-check/parser"
"github.com/future-architect/vuls/cwe"
"github.com/future-architect/vuls/exploit"
"github.com/future-architect/vuls/gost"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/msf"
"github.com/future-architect/vuls/oval"
"github.com/future-architect/vuls/reporter"
"github.com/future-architect/vuls/util"
gostdb "github.com/knqyf263/gost/db"
cvedb "github.com/kotakanbe/go-cve-dictionary/db"
cvemodels "github.com/kotakanbe/go-cve-dictionary/models"
ovaldb "github.com/kotakanbe/goval-dictionary/db"
metasploitdb "github.com/takuzoo3868/go-msfdb/db"
exploitdb "github.com/vulsio/go-exploitdb/db"
"golang.org/x/xerrors"
)
// type Detector struct {
// Targets map[string]c.ServerInfo
// }
// Detect vulns and fill CVE detailed information
func Detect(dbclient DBClient, rs []models.ScanResult, dir string) ([]models.ScanResult, error) {
func Detect(rs []models.ScanResult, dir string) ([]models.ScanResult, error) {
// Use the same reportedAt for all rs
reportedAt := time.Now()
for i, r := range rs {
if !c.Conf.RefreshCve && !needToRefreshCve(r) {
if !config.Conf.RefreshCve && !needToRefreshCve(r) {
logging.Log.Info("No need to refresh")
continue
}
@@ -49,10 +38,10 @@ func Detect(dbclient DBClient, rs []models.ScanResult, dir string) ([]models.Sca
cpeURIs, owaspDCXMLPath := []string{}, ""
if len(r.Container.ContainerID) == 0 {
cpeURIs = c.Conf.Servers[r.ServerName].CpeNames
owaspDCXMLPath = c.Conf.Servers[r.ServerName].OwaspDCXMLPath
cpeURIs = config.Conf.Servers[r.ServerName].CpeNames
owaspDCXMLPath = config.Conf.Servers[r.ServerName].OwaspDCXMLPath
} else {
if s, ok := c.Conf.Servers[r.ServerName]; ok {
if s, ok := config.Conf.Servers[r.ServerName]; ok {
if con, ok := s.Containers[r.Container.Name]; ok {
cpeURIs = con.Cpes
owaspDCXMLPath = con.OwaspDCXMLPath
@@ -68,46 +57,66 @@ func Detect(dbclient DBClient, rs []models.ScanResult, dir string) ([]models.Sca
cpeURIs = append(cpeURIs, cpes...)
}
if err := DetectLibsCves(&r, c.Conf.TrivyCacheDBDir, c.Conf.NoProgress); err != nil {
if err := DetectLibsCves(&r, config.Conf.TrivyCacheDBDir, config.Conf.NoProgress); err != nil {
return nil, xerrors.Errorf("Failed to fill with Library dependency: %w", err)
}
if err := DetectPkgCves(dbclient, &r); err != nil {
if err := DetectPkgCves(&r, config.Conf.OvalDict, config.Conf.Gost); err != nil {
return nil, xerrors.Errorf("Failed to detect Pkg CVE: %w", err)
}
if err := DetectCpeURIsCves(dbclient.CveDB, &r, cpeURIs); err != nil {
if err := DetectCpeURIsCves(&r, cpeURIs, config.Conf.CveDict, config.Conf.LogOpts); err != nil {
return nil, xerrors.Errorf("Failed to detect CVE of `%s`: %w", cpeURIs, err)
}
repos := c.Conf.Servers[r.ServerName].GitHubRepos
if err := DetectGitHubCves(&r, repos, c.Conf.IgnoreGitHubDismissed); err != nil {
repos := config.Conf.Servers[r.ServerName].GitHubRepos
if err := DetectGitHubCves(&r, repos, config.Conf.IgnoreGitHubDismissed); err != nil {
return nil, xerrors.Errorf("Failed to detect GitHub Cves: %w", err)
}
if err := DetectWordPressCves(&r, &c.Conf.WpScan); err != nil {
if err := DetectWordPressCves(&r, config.Conf.WpScan); err != nil {
return nil, xerrors.Errorf("Failed to detect WordPress Cves: %w", err)
}
if err := FillCveInfo(dbclient, &r); err != nil {
return nil, err
logging.Log.Infof("Fill CVE detailed with gost")
if err := gost.FillCVEsWithRedHat(&r, config.Conf.Gost); err != nil {
return nil, xerrors.Errorf("Failed to fill with gost: %w", err)
}
logging.Log.Infof("Fill CVE detailed with go-cve-dictionary")
if err := FillCvesWithNvdJvn(&r, config.Conf.CveDict, config.Conf.LogOpts); err != nil {
return nil, xerrors.Errorf("Failed to fill with CVE: %w", err)
}
nExploitCve, err := FillWithExploit(&r, config.Conf.Exploit)
if err != nil {
return nil, xerrors.Errorf("Failed to fill with exploit: %w", err)
}
logging.Log.Infof("%s: %d exploits are detected", r.FormatServerName(), nExploitCve)
nMetasploitCve, err := FillWithMetasploit(&r, config.Conf.Metasploit)
if err != nil {
return nil, xerrors.Errorf("Failed to fill with metasploit: %w", err)
}
logging.Log.Infof("%s: %d modules are detected", r.FormatServerName(), nMetasploitCve)
FillCweDict(&r)
r.ReportedBy, _ = os.Hostname()
r.Lang = c.Conf.Lang
r.Lang = config.Conf.Lang
r.ReportedAt = reportedAt
r.ReportedVersion = c.Version
r.ReportedRevision = c.Revision
r.Config.Report = c.Conf
r.Config.Report.Servers = map[string]c.ServerInfo{
r.ServerName: c.Conf.Servers[r.ServerName],
r.ReportedVersion = config.Version
r.ReportedRevision = config.Revision
r.Config.Report = config.Conf
r.Config.Report.Servers = map[string]config.ServerInfo{
r.ServerName: config.Conf.Servers[r.ServerName],
}
rs[i] = r
}
// Overwrite the json file every time to clear the fields specified in config.IgnoredJSONKeys
for _, r := range rs {
if s, ok := c.Conf.Servers[r.ServerName]; ok {
if s, ok := config.Conf.Servers[r.ServerName]; ok {
r = r.ClearFields(s.IgnoredJSONKeys)
}
//TODO don't call here
@@ -116,23 +125,23 @@ func Detect(dbclient DBClient, rs []models.ScanResult, dir string) ([]models.Sca
}
}
if c.Conf.DiffPlus || c.Conf.DiffMinus {
prevs, err := loadPrevious(rs)
if config.Conf.DiffPlus || config.Conf.DiffMinus {
prevs, err := loadPrevious(rs, config.Conf.ResultsDir)
if err != nil {
return nil, err
}
rs = diff(rs, prevs, c.Conf.DiffPlus, c.Conf.DiffMinus)
rs = diff(rs, prevs, config.Conf.DiffPlus, config.Conf.DiffMinus)
}
for i, r := range rs {
r.ScannedCves = r.ScannedCves.FilterByCvssOver(c.Conf.CvssScoreOver)
r.ScannedCves = r.ScannedCves.FilterUnfixed(c.Conf.IgnoreUnfixed)
r.ScannedCves = r.ScannedCves.FilterByCvssOver(config.Conf.CvssScoreOver)
r.ScannedCves = r.ScannedCves.FilterUnfixed(config.Conf.IgnoreUnfixed)
// IgnoreCves
ignoreCves := []string{}
if r.Container.Name == "" {
ignoreCves = c.Conf.Servers[r.ServerName].IgnoreCves
} else if con, ok := c.Conf.Servers[r.ServerName].Containers[r.Container.Name]; ok {
ignoreCves = config.Conf.Servers[r.ServerName].IgnoreCves
} else if con, ok := config.Conf.Servers[r.ServerName].Containers[r.Container.Name]; ok {
ignoreCves = con.IgnoreCves
}
r.ScannedCves = r.ScannedCves.FilterIgnoreCves(ignoreCves)
@@ -140,34 +149,35 @@ func Detect(dbclient DBClient, rs []models.ScanResult, dir string) ([]models.Sca
// ignorePkgs
ignorePkgsRegexps := []string{}
if r.Container.Name == "" {
ignorePkgsRegexps = c.Conf.Servers[r.ServerName].IgnorePkgsRegexp
} else if s, ok := c.Conf.Servers[r.ServerName].Containers[r.Container.Name]; ok {
ignorePkgsRegexps = config.Conf.Servers[r.ServerName].IgnorePkgsRegexp
} else if s, ok := config.Conf.Servers[r.ServerName].Containers[r.Container.Name]; ok {
ignorePkgsRegexps = s.IgnorePkgsRegexp
}
r.ScannedCves = r.ScannedCves.FilterIgnorePkgs(ignorePkgsRegexps)
// IgnoreUnscored
if c.Conf.IgnoreUnscoredCves {
if config.Conf.IgnoreUnscoredCves {
r.ScannedCves = r.ScannedCves.FindScoredVulns()
}
r.FilterInactiveWordPressLibs(c.Conf.WpScan.DetectInactive)
r.FilterInactiveWordPressLibs(config.Conf.WpScan.DetectInactive)
rs[i] = r
}
return rs, nil
}
// DetectPkgCves detects OS pkg cves
func DetectPkgCves(dbclient DBClient, r *models.ScanResult) error {
// pass 2 configs
func DetectPkgCves(r *models.ScanResult, ovalCnf config.GovalDictConf, gostCnf config.GostConf) error {
// Pkg Scan
if r.Release != "" {
// OVAL
if err := detectPkgsCvesWithOval(dbclient.OvalDB, r); err != nil {
if err := detectPkgsCvesWithOval(ovalCnf, r); err != nil {
return xerrors.Errorf("Failed to detect CVE with OVAL: %w", err)
}
// gost
if err := detectPkgsCvesWithGost(dbclient.GostDB, r); err != nil {
if err := detectPkgsCvesWithGost(gostCnf, r); err != nil {
return xerrors.Errorf("Failed to detect CVE with gost: %w", err)
}
} else if reuseScannedCves(r) {
@@ -209,7 +219,7 @@ func DetectPkgCves(dbclient DBClient, r *models.ScanResult) error {
}
// DetectGitHubCves fetches CVEs from GitHub Security Alerts
func DetectGitHubCves(r *models.ScanResult, githubConfs map[string]c.GitHubConf, ignoreDismissed bool) error {
func DetectGitHubCves(r *models.ScanResult, githubConfs map[string]config.GitHubConf, ignoreDismissed bool) error {
if len(githubConfs) == 0 {
return nil
}
@@ -230,7 +240,7 @@ func DetectGitHubCves(r *models.ScanResult, githubConfs map[string]c.GitHubConf,
}
// DetectWordPressCves detects CVEs of WordPress
func DetectWordPressCves(r *models.ScanResult, wpCnf *c.WpScanConf) error {
func DetectWordPressCves(r *models.ScanResult, wpCnf config.WpScanConf) error {
if len(r.WordPressPackages) == 0 {
return nil
}
@@ -243,51 +253,33 @@ func DetectWordPressCves(r *models.ScanResult, wpCnf *c.WpScanConf) error {
return nil
}
// FillCveInfo fill scanResult with cve info.
func FillCveInfo(dbclient DBClient, r *models.ScanResult) error {
logging.Log.Infof("Fill CVE detailed with gost")
if err := gost.NewClient(r.Family).FillCVEsWithRedHat(dbclient.GostDB, r); err != nil {
return xerrors.Errorf("Failed to fill with gost: %w", err)
}
logging.Log.Infof("Fill CVE detailed with CVE-DB")
if err := fillCvesWithNvdJvn(dbclient.CveDB, r); err != nil {
return xerrors.Errorf("Failed to fill with CVE: %w", err)
}
logging.Log.Infof("Fill exploit with Exploit-DB")
nExploitCve, err := fillWithExploitDB(dbclient.ExploitDB, r)
if err != nil {
return xerrors.Errorf("Failed to fill with exploit: %w", err)
}
logging.Log.Infof("%s: %d exploits are detected",
r.FormatServerName(), nExploitCve)
logging.Log.Infof("Fill metasploit module with Metasploit-DB")
nMetasploitCve, err := fillWithMetasploit(dbclient.MetasploitDB, r)
if err != nil {
return xerrors.Errorf("Failed to fill with metasploit: %w", err)
}
logging.Log.Infof("%s: %d modules are detected",
r.FormatServerName(), nMetasploitCve)
logging.Log.Infof("Fill CWE with NVD")
fillCweDict(r)
return nil
}
// fillCvesWithNvdJvn fills CVE detail with NVD, JVN
func fillCvesWithNvdJvn(driver cvedb.DB, r *models.ScanResult) error {
// FillCvesWithNvdJvn fills CVE detail with NVD, JVN
func FillCvesWithNvdJvn(r *models.ScanResult, cnf config.GoCveDictConf, logOpts logging.LogOpts) (err error) {
cveIDs := []string{}
for _, v := range r.ScannedCves {
cveIDs = append(cveIDs, v.CveID)
}
ds, err := CveClient.FetchCveDetails(driver, cveIDs)
client, err := newGoCveDictClient(&cnf, logOpts)
if err != nil {
return err
}
defer func() {
if err := client.closeDB(); err != nil {
logging.Log.Errorf("Failed to close DB. err: %+v")
}
}()
var ds []cvemodels.CveDetail
if cnf.IsFetchViaHTTP() {
ds, err = client.fetchCveDetailsViaHTTP(cveIDs)
} else {
ds, err = client.fetchCveDetails(cveIDs)
}
if err != nil {
return err
}
for _, d := range ds {
nvd, exploits, mitigations := models.ConvertNvdJSONToModel(d.CveID, d.NvdJSON)
jvn := models.ConvertJvnToModel(d.CveID, d.Jvn)
@@ -337,72 +329,29 @@ func fillCertAlerts(cvedetail *cvemodels.CveDetail) (dict models.AlertDict) {
}
// detectPkgsCvesWithOval fetches OVAL database
func detectPkgsCvesWithOval(driver ovaldb.DB, r *models.ScanResult) error {
var ovalClient oval.Client
var ovalFamily string
switch r.Family {
case constant.Debian, constant.Raspbian:
ovalClient = oval.NewDebian()
ovalFamily = constant.Debian
case constant.Ubuntu:
ovalClient = oval.NewUbuntu()
ovalFamily = constant.Ubuntu
case constant.RedHat:
ovalClient = oval.NewRedhat()
ovalFamily = constant.RedHat
case constant.CentOS:
ovalClient = oval.NewCentOS()
//use RedHat's OVAL
ovalFamily = constant.RedHat
case constant.Oracle:
ovalClient = oval.NewOracle()
ovalFamily = constant.Oracle
case constant.SUSEEnterpriseServer:
// TODO other suse family
ovalClient = oval.NewSUSE()
ovalFamily = constant.SUSEEnterpriseServer
case constant.Alpine:
ovalClient = oval.NewAlpine()
ovalFamily = constant.Alpine
case constant.Amazon:
ovalClient = oval.NewAmazon()
ovalFamily = constant.Amazon
case constant.FreeBSD, constant.Windows:
return nil
case constant.ServerTypePseudo:
return nil
default:
if r.Family == "" {
return xerrors.New("Probably an error occurred during scanning. Check the error message")
}
return xerrors.Errorf("OVAL for %s is not implemented yet", r.Family)
func detectPkgsCvesWithOval(cnf config.GovalDictConf, r *models.ScanResult) error {
ovalClient, err := oval.NewOVALClient(r.Family, cnf)
if err != nil {
return err
}
if !c.Conf.OvalDict.IsFetchViaHTTP() {
if driver == nil {
return xerrors.Errorf("You have to fetch OVAL data for %s before reporting. For details, see `https://github.com/kotakanbe/goval-dictionary#usage`", r.Family)
}
if err := driver.NewOvalDB(ovalFamily); err != nil {
return xerrors.Errorf("Failed to New Oval DB. err: %w", err)
}
}
logging.Log.Debugf("Check whether oval fetched: %s %s", ovalFamily, r.Release)
ok, err := ovalClient.CheckIfOvalFetched(driver, ovalFamily, r.Release)
logging.Log.Debugf("Check if oval fetched: %s %s", r.Family, r.Release)
ok, err := ovalClient.CheckIfOvalFetched(r.Family, r.Release)
if err != nil {
return err
}
if !ok {
return xerrors.Errorf("OVAL entries of %s %s are not found. Fetch OVAL before reporting. For details, see `https://github.com/kotakanbe/goval-dictionary#usage`", ovalFamily, r.Release)
return xerrors.Errorf("OVAL entries of %s %s are not found. Fetch OVAL before reporting. For details, see `https://github.com/kotakanbe/goval-dictionary#usage`", r.Family, r.Release)
}
_, err = ovalClient.CheckIfOvalFresh(driver, ovalFamily, r.Release)
logging.Log.Debugf("Check if oval fresh: %s %s", r.Family, r.Release)
_, err = ovalClient.CheckIfOvalFresh(r.Family, r.Release)
if err != nil {
return err
}
nCVEs, err := ovalClient.FillWithOval(driver, r)
logging.Log.Debugf("Fill with oval: %s %s", r.Family, r.Release)
nCVEs, err := ovalClient.FillWithOval(r)
if err != nil {
return err
}
@@ -411,36 +360,36 @@ func detectPkgsCvesWithOval(driver ovaldb.DB, r *models.ScanResult) error {
return nil
}
func detectPkgsCvesWithGost(driver gostdb.DB, r *models.ScanResult) error {
nCVEs, err := gost.NewClient(r.Family).DetectUnfixed(driver, r, true)
func detectPkgsCvesWithGost(cnf config.GostConf, r *models.ScanResult) error {
client, err := gost.NewClient(cnf, r.Family)
if err != nil {
return xerrors.Errorf("Failed to new a gost client: %w", err)
}
logging.Log.Infof("%s: %d unfixed CVEs are detected with gost",
r.FormatServerName(), nCVEs)
return err
}
nCVEs, err := client.DetectUnfixed(r, true)
if err != nil {
return xerrors.Errorf("Failed to detect unfixed CVEs with gost: %w", err)
}
// fillWithExploitDB fills Exploits with exploit dataabase
// https://github.com/vulsio/go-exploitdb
func fillWithExploitDB(driver exploitdb.DB, r *models.ScanResult) (nExploitCve int, err error) {
return exploit.FillWithExploit(driver, r, &c.Conf.Exploit)
}
// fillWithMetasploit fills metasploit modules with metasploit database
// https://github.com/takuzoo3868/go-msfdb
func fillWithMetasploit(driver metasploitdb.DB, r *models.ScanResult) (nMetasploitCve int, err error) {
return msf.FillWithMetasploit(driver, r)
logging.Log.Infof("%s: %d unfixed CVEs are detected with gost", r.FormatServerName(), nCVEs)
return nil
}
// DetectCpeURIsCves detects CVEs of given CPE-URIs
func DetectCpeURIsCves(driver cvedb.DB, r *models.ScanResult, cpeURIs []string) error {
nCVEs := 0
if len(cpeURIs) != 0 && driver == nil && !c.Conf.CveDict.IsFetchViaHTTP() {
return xerrors.Errorf("cpeURIs %s specified, but cve-dictionary DB not found. Fetch cve-dictionary before reporting. For details, see `https://github.com/kotakanbe/go-cve-dictionary#deploy-go-cve-dictionary`",
cpeURIs)
func DetectCpeURIsCves(r *models.ScanResult, cpeURIs []string, cnf config.GoCveDictConf, logOpts logging.LogOpts) error {
client, err := newGoCveDictClient(&cnf, logOpts)
if err != nil {
return err
}
defer func() {
if err := client.closeDB(); err != nil {
logging.Log.Errorf("Failed to close DB. err: %+v")
}
}()
nCVEs := 0
for _, name := range cpeURIs {
details, err := CveClient.FetchCveDetailsByCpeName(driver, name)
details, err := client.fetchCveDetailsByCpeName(name)
if err != nil {
return err
}
@@ -466,7 +415,8 @@ func DetectCpeURIsCves(driver cvedb.DB, r *models.ScanResult, cpeURIs []string)
return nil
}
func fillCweDict(r *models.ScanResult) {
// FillCweDict fills CWE
func FillCweDict(r *models.ScanResult) {
uniqCweIDMap := map[string]bool{}
for _, vinfo := range r.ScannedCves {
for _, cont := range vinfo.CveContents {

223
detector/exploitdb.go Normal file
View File

@@ -0,0 +1,223 @@
// +build !scanner
package detector
import (
"encoding/json"
"net/http"
"time"
"github.com/cenkalti/backoff"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/util"
"github.com/parnurzeal/gorequest"
exploitdb "github.com/vulsio/go-exploitdb/db"
exploitmodels "github.com/vulsio/go-exploitdb/models"
"golang.org/x/xerrors"
)
// FillWithExploit fills exploit information that has in Exploit
func FillWithExploit(r *models.ScanResult, cnf config.ExploitConf) (nExploitCve int, err error) {
if cnf.IsFetchViaHTTP() {
var cveIDs []string
for cveID := range r.ScannedCves {
cveIDs = append(cveIDs, cveID)
}
prefix, _ := util.URLPathJoin(cnf.GetURL(), "cves")
responses, err := getCvesViaHTTP(cveIDs, prefix)
if err != nil {
return 0, err
}
for _, res := range responses {
exps := []*exploitmodels.Exploit{}
if err := json.Unmarshal([]byte(res.json), &exps); err != nil {
return 0, err
}
exploits := ConvertToModels(exps)
v, ok := r.ScannedCves[res.request.cveID]
if ok {
v.Exploits = exploits
}
r.ScannedCves[res.request.cveID] = v
nExploitCve++
}
} else {
driver, locked, err := newExploitDB(&cnf)
if locked {
return 0, xerrors.Errorf("SQLite3 is locked: %s", cnf.GetSQLite3Path())
} else if err != nil {
return 0, err
}
defer func() {
if err := driver.CloseDB(); err != nil {
logging.Log.Errorf("Failed to close DB. err: %+v")
}
}()
for cveID, vuln := range r.ScannedCves {
if cveID == "" {
continue
}
es := driver.GetExploitByCveID(cveID)
if len(es) == 0 {
continue
}
exploits := ConvertToModels(es)
vuln.Exploits = exploits
r.ScannedCves[cveID] = vuln
nExploitCve++
}
}
return nExploitCve, nil
}
// ConvertToModels converts gost model to vuls model
func ConvertToModels(es []*exploitmodels.Exploit) (exploits []models.Exploit) {
for _, e := range es {
var documentURL, shellURL *string
if e.OffensiveSecurity != nil {
os := e.OffensiveSecurity
if os.Document != nil {
documentURL = &os.Document.DocumentURL
}
if os.ShellCode != nil {
shellURL = &os.ShellCode.ShellCodeURL
}
}
exploit := models.Exploit{
ExploitType: e.ExploitType,
ID: e.ExploitUniqueID,
URL: e.URL,
Description: e.Description,
DocumentURL: documentURL,
ShellCodeURL: shellURL,
}
exploits = append(exploits, exploit)
}
return exploits
}
type exploitResponse struct {
request request
json string
}
func getCvesViaHTTP(cveIDs []string, urlPrefix string) (
responses []exploitResponse, err error) {
nReq := len(cveIDs)
reqChan := make(chan request, nReq)
resChan := make(chan exploitResponse, nReq)
errChan := make(chan error, nReq)
defer close(reqChan)
defer close(resChan)
defer close(errChan)
go func() {
for _, cveID := range cveIDs {
reqChan <- request{
cveID: cveID,
}
}
}()
concurrency := 10
tasks := util.GenWorkers(concurrency)
for i := 0; i < nReq; i++ {
tasks <- func() {
select {
case req := <-reqChan:
url, err := util.URLPathJoin(
urlPrefix,
req.cveID,
)
if err != nil {
errChan <- err
} else {
logging.Log.Debugf("HTTP Request to %s", url)
httpGet(url, req, resChan, errChan)
}
}
}
}
timeout := time.After(2 * 60 * time.Second)
var errs []error
for i := 0; i < nReq; i++ {
select {
case res := <-resChan:
responses = append(responses, res)
case err := <-errChan:
errs = append(errs, err)
case <-timeout:
return nil, xerrors.New("Timeout Fetching OVAL")
}
}
if len(errs) != 0 {
return nil, xerrors.Errorf("Failed to fetch OVAL. err: %w", errs)
}
return
}
type request struct {
osMajorVersion string
packName string
isSrcPack bool
cveID string
}
func httpGet(url string, req request, resChan chan<- exploitResponse, errChan chan<- error) {
var body string
var errs []error
var resp *http.Response
count, retryMax := 0, 3
f := func() (err error) {
// resp, body, errs = gorequest.New().SetDebug(config.Conf.Debug).Get(url).End()
resp, body, errs = gorequest.New().Timeout(10 * time.Second).Get(url).End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
count++
if count == retryMax {
return nil
}
return xerrors.Errorf("HTTP GET error, url: %s, resp: %v, err: %+v", url, resp, errs)
}
return nil
}
notify := func(err error, t time.Duration) {
logging.Log.Warnf("Failed to HTTP GET. retrying in %s seconds. err: %+v", t, err)
}
err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify)
if err != nil {
errChan <- xerrors.Errorf("HTTP Error %w", err)
return
}
if count == retryMax {
errChan <- xerrors.New("Retry count exceeded")
return
}
resChan <- exploitResponse{
request: req,
json: body,
}
}
func newExploitDB(cnf config.VulnDictInterface) (driver exploitdb.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
if driver, locked, err = exploitdb.NewDB(cnf.GetType(), path, cnf.GetDebugSQL()); err != nil {
if locked {
return nil, true, xerrors.Errorf("exploitDB is locked. err: %w", err)
}
return nil, false, err
}
return driver, false, nil
}

81
detector/msf.go Normal file
View File

@@ -0,0 +1,81 @@
// +build !scanner
package detector
import (
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
metasploitdb "github.com/takuzoo3868/go-msfdb/db"
metasploitmodels "github.com/takuzoo3868/go-msfdb/models"
"golang.org/x/xerrors"
)
// FillWithMetasploit fills metasploit module information that has in module
func FillWithMetasploit(r *models.ScanResult, cnf config.MetasploitConf) (nMetasploitCve int, err error) {
driver, locked, err := newMetasploitDB(&cnf)
if locked {
return 0, xerrors.Errorf("SQLite3 is locked: %s", cnf.GetSQLite3Path())
} else if err != nil {
return 0, err
}
defer func() {
if err := driver.CloseDB(); err != nil {
logging.Log.Errorf("Failed to close DB. err: %+v")
}
}()
for cveID, vuln := range r.ScannedCves {
if cveID == "" {
continue
}
ms := driver.GetModuleByCveID(cveID)
if len(ms) == 0 {
continue
}
modules := ConvertToModelsMsf(ms)
vuln.Metasploits = modules
r.ScannedCves[cveID] = vuln
nMetasploitCve++
}
return nMetasploitCve, nil
}
// ConvertToModelsMsf converts gost model to vuls model
func ConvertToModelsMsf(ms []*metasploitmodels.Metasploit) (modules []models.Metasploit) {
for _, m := range ms {
var links []string
if 0 < len(m.References) {
for _, u := range m.References {
links = append(links, u.Link)
}
}
module := models.Metasploit{
Name: m.Name,
Title: m.Title,
Description: m.Description,
URLs: links,
}
modules = append(modules, module)
}
return modules
}
func newMetasploitDB(cnf config.VulnDictInterface) (driver metasploitdb.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
if driver, locked, err = metasploitdb.NewDB(cnf.GetType(), path, cnf.GetDebugSQL(), false); err != nil {
if locked {
return nil, true, xerrors.Errorf("metasploitDB is locked. err: %w", err)
}
return nil, false, err
}
return driver, false, nil
}

View File

@@ -42,8 +42,8 @@ func needToRefreshCve(r models.ScanResult) bool {
return true
}
func loadPrevious(currs models.ScanResults) (prevs models.ScanResults, err error) {
dirs, err := ListValidJSONDirs()
func loadPrevious(currs models.ScanResults, resultsDir string) (prevs models.ScanResults, err error) {
dirs, err := ListValidJSONDirs(resultsDir)
if err != nil {
return
}
@@ -234,16 +234,16 @@ var jsonDirPattern = regexp.MustCompile(
// ListValidJSONDirs returns valid json directory as array
// Returned array is sorted so that recent directories are at the head
func ListValidJSONDirs() (dirs []string, err error) {
func ListValidJSONDirs(resultsDir string) (dirs []string, err error) {
var dirInfo []os.FileInfo
if dirInfo, err = ioutil.ReadDir(config.Conf.ResultsDir); err != nil {
if dirInfo, err = ioutil.ReadDir(resultsDir); err != nil {
err = xerrors.Errorf("Failed to read %s: %w",
config.Conf.ResultsDir, err)
return
}
for _, d := range dirInfo {
if d.IsDir() && jsonDirPattern.MatchString(d.Name()) {
jsonDir := filepath.Join(config.Conf.ResultsDir, d.Name())
jsonDir := filepath.Join(resultsDir, d.Name())
dirs = append(dirs, jsonDir)
}
}

View File

@@ -9,7 +9,7 @@ import (
"strings"
"time"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/errof"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
@@ -50,7 +50,7 @@ type References struct {
// DetectWordPressCves access to wpscan and fetch scurity alerts and then set to the given ScanResult.
// https://wpscan.com/
func detectWordPressCves(r *models.ScanResult, cnf *c.WpScanConf) (int, error) {
func detectWordPressCves(r *models.ScanResult, cnf config.WpScanConf) (int, error) {
if len(r.WordPressPackages) == 0 {
return 0, nil
}
@@ -230,7 +230,7 @@ func httpRequest(url, token string) (string, error) {
fmt.Sprintf("Failed to access to wpscan.com. err: %s", err))
}
req.Header.Set("Authorization", fmt.Sprintf("Token token=%s", token))
client, err := util.GetHTTPClient(c.Conf.HTTPProxy)
client, err := util.GetHTTPClient(config.Conf.HTTPProxy)
if err != nil {
return "", err
}

View File

@@ -1,85 +0,0 @@
// +build !scanner
package exploit
import (
"encoding/json"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/util"
"github.com/vulsio/go-exploitdb/db"
exploitmodels "github.com/vulsio/go-exploitdb/models"
)
// FillWithExploit fills exploit information that has in Exploit
func FillWithExploit(driver db.DB, r *models.ScanResult, cnf *config.ExploitConf) (nExploitCve int, err error) {
if cnf.IsFetchViaHTTP() {
var cveIDs []string
for cveID := range r.ScannedCves {
cveIDs = append(cveIDs, cveID)
}
prefix, _ := util.URLPathJoin(cnf.URL, "cves")
responses, err := getCvesViaHTTP(cveIDs, prefix)
if err != nil {
return 0, err
}
for _, res := range responses {
exps := []*exploitmodels.Exploit{}
if err := json.Unmarshal([]byte(res.json), &exps); err != nil {
return 0, err
}
exploits := ConvertToModels(exps)
v, ok := r.ScannedCves[res.request.cveID]
if ok {
v.Exploits = exploits
}
r.ScannedCves[res.request.cveID] = v
nExploitCve++
}
} else {
if driver == nil {
return 0, nil
}
for cveID, vuln := range r.ScannedCves {
if cveID == "" {
continue
}
es := driver.GetExploitByCveID(cveID)
if len(es) == 0 {
continue
}
exploits := ConvertToModels(es)
vuln.Exploits = exploits
r.ScannedCves[cveID] = vuln
nExploitCve++
}
}
return nExploitCve, nil
}
// ConvertToModels converts gost model to vuls model
func ConvertToModels(es []*exploitmodels.Exploit) (exploits []models.Exploit) {
for _, e := range es {
var documentURL, shellURL *string
if e.OffensiveSecurity != nil {
os := e.OffensiveSecurity
if os.Document != nil {
documentURL = &os.Document.DocumentURL
}
if os.ShellCode != nil {
shellURL = &os.ShellCode.ShellCodeURL
}
}
exploit := models.Exploit{
ExploitType: e.ExploitType,
ID: e.ExploitUniqueID,
URL: e.URL,
Description: e.Description,
DocumentURL: documentURL,
ShellCodeURL: shellURL,
}
exploits = append(exploits, exploit)
}
return exploits
}

View File

@@ -1,116 +0,0 @@
package exploit
import (
"net/http"
"time"
"github.com/cenkalti/backoff"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/util"
"github.com/parnurzeal/gorequest"
"golang.org/x/xerrors"
)
type response struct {
request request
json string
}
func getCvesViaHTTP(cveIDs []string, urlPrefix string) (
responses []response, err error) {
nReq := len(cveIDs)
reqChan := make(chan request, nReq)
resChan := make(chan response, nReq)
errChan := make(chan error, nReq)
defer close(reqChan)
defer close(resChan)
defer close(errChan)
go func() {
for _, cveID := range cveIDs {
reqChan <- request{
cveID: cveID,
}
}
}()
concurrency := 10
tasks := util.GenWorkers(concurrency)
for i := 0; i < nReq; i++ {
tasks <- func() {
select {
case req := <-reqChan:
url, err := util.URLPathJoin(
urlPrefix,
req.cveID,
)
if err != nil {
errChan <- err
} else {
logging.Log.Debugf("HTTP Request to %s", url)
httpGet(url, req, resChan, errChan)
}
}
}
}
timeout := time.After(2 * 60 * time.Second)
var errs []error
for i := 0; i < nReq; i++ {
select {
case res := <-resChan:
responses = append(responses, res)
case err := <-errChan:
errs = append(errs, err)
case <-timeout:
return nil, xerrors.New("Timeout Fetching OVAL")
}
}
if len(errs) != 0 {
return nil, xerrors.Errorf("Failed to fetch OVAL. err: %w", errs)
}
return
}
type request struct {
osMajorVersion string
packName string
isSrcPack bool
cveID string
}
func httpGet(url string, req request, resChan chan<- response, errChan chan<- error) {
var body string
var errs []error
var resp *http.Response
count, retryMax := 0, 3
f := func() (err error) {
// resp, body, errs = gorequest.New().SetDebug(config.Conf.Debug).Get(url).End()
resp, body, errs = gorequest.New().Timeout(10 * time.Second).Get(url).End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
count++
if count == retryMax {
return nil
}
return xerrors.Errorf("HTTP GET error, url: %s, resp: %v, err: %+v", url, resp, errs)
}
return nil
}
notify := func(err error, t time.Duration) {
logging.Log.Warnf("Failed to HTTP GET. retrying in %s seconds. err: %+v", t, err)
}
err := backoff.RetryNotify(f, backoff.NewExponentialBackOff(), notify)
if err != nil {
errChan <- xerrors.Errorf("HTTP Error %w", err)
return
}
if count == retryMax {
errChan <- xerrors.New("Retry count exceeded")
return
}
resChan <- response{
request: req,
json: body,
}
}

32
go.mod
View File

@@ -8,7 +8,7 @@ require (
github.com/aquasecurity/fanal v0.0.0-20210119051230-28c249da7cfd
github.com/aquasecurity/trivy v0.16.0
github.com/aquasecurity/trivy-db v0.0.0-20210121143430-2a5c54036a86
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
github.com/aws/aws-sdk-go v1.36.31
github.com/boltdb/bolt v1.3.1
github.com/cenkalti/backoff v2.2.1+incompatible
@@ -26,27 +26,35 @@ require (
github.com/knqyf263/go-cpe v0.0.0-20201213041631-54f6ab28673f
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d
github.com/knqyf263/go-rpm-version v0.0.0-20170716094938-74609b86c936
github.com/knqyf263/gost v0.1.8
github.com/kotakanbe/go-cve-dictionary v0.5.9
github.com/knqyf263/gost v0.1.10
github.com/kotakanbe/go-cve-dictionary v0.5.10
github.com/kotakanbe/go-pingscanner v0.1.0
github.com/kotakanbe/goval-dictionary v0.3.2
github.com/kotakanbe/goval-dictionary v0.3.3
github.com/kotakanbe/logrus-prefixed-formatter v0.0.0-20180123152602-928f7356cb96
github.com/lib/pq v1.10.0 // indirect
github.com/magiconair/properties v1.8.4 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/nlopes/slack v0.6.0
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 // indirect
github.com/olekukonko/tablewriter v0.0.4
github.com/olekukonko/tablewriter v0.0.5
github.com/parnurzeal/gorequest v0.2.16
github.com/pelletier/go-toml v1.8.1 // indirect
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
github.com/sirupsen/logrus v1.7.0
github.com/spf13/afero v1.5.1
github.com/spf13/cobra v1.1.1
github.com/takuzoo3868/go-msfdb v0.1.4
github.com/vulsio/go-exploitdb v0.1.6
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect
github.com/spf13/afero v1.6.0
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/cobra v1.1.3
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/takuzoo3868/go-msfdb v0.1.5
github.com/vulsio/go-exploitdb v0.1.7
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect
golang.org/x/net v0.0.0-20210323141857-08027d57d8cf // indirect
golang.org/x/oauth2 v0.0.0-20210125201302-af13f521f196
golang.org/x/sys v0.0.0-20210301091718-77cc2087c03b // indirect
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
gopkg.in/ini.v1 v1.62.0 // indirect
k8s.io/utils v0.0.0-20210111153108-fddb29f9d009
)

198
go.sum
View File

@@ -1,6 +1,5 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
@@ -70,7 +69,6 @@ github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jB
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.7/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
@@ -79,8 +77,6 @@ github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM=
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
@@ -91,13 +87,10 @@ github.com/alicebob/miniredis/v2 v2.14.1/go.mod h1:uS970Sw5Gs9/iK3yBg0l9Uj9s25wX
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxBp0T0eFw1RUQY=
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/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 h1:2a30xLN2sUZcMXl50hg+PJCIDdJgIvIbVcKqLJ/ZrtM=
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986/go.mod h1:NT+jyeCzXk6vXR5MTkdn4z64TgGfE5HMLC8qfj5unl8=
github.com/aquasecurity/fanal v0.0.0-20190819081512-f04452b627c6/go.mod h1:enEz4FFetw4XAbkffaYgyCVq1556R9Ry+noqT4rq9BE=
github.com/aquasecurity/fanal v0.0.0-20210119051230-28c249da7cfd h1:meqa2AA+7K1r/nfNB19K2AP/v8+nemuWeQoTSqZ2R9s=
github.com/aquasecurity/fanal v0.0.0-20210119051230-28c249da7cfd/go.mod h1:kur6SaohYhsjQLzijAdtn+X8rkTtwxawE51WyVCXLKk=
github.com/aquasecurity/go-dep-parser v0.0.0-20190819075924-ea223f0ef24b/go.mod h1:BpNTD9vHfrejKsED9rx04ldM1WIbeyXGYxUrqTVwxVQ=
github.com/aquasecurity/go-dep-parser v0.0.0-20201028043324-889d4a92b8e0 h1:cLH3SebzhbJ+jU1GIad8A1N8p7m7OjHhtY6JePISiVc=
github.com/aquasecurity/go-dep-parser v0.0.0-20201028043324-889d4a92b8e0/go.mod h1:X42mTIRhgPalSm81Om2kD+3ydeunbC8TZtZj1bvgRo8=
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce h1:QgBRgJvtEOBtUXilDb1MLi1p1MWoyFDXAu5DEUl5nwM=
@@ -110,7 +103,6 @@ github.com/aquasecurity/go-version v0.0.0-20201107203531-5e48ac5d022a/go.mod h1:
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 h1:rcEG5HI490FF0a7zuvxOxen52ddygCfNVjP0XOCMl+M=
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492/go.mod h1:9Beu8XsUNNfzml7WBf3QmyPToP1wm1Gj/Vc5UJKqTzU=
github.com/aquasecurity/testdocker v0.0.0-20210106133225-0b17fe083674/go.mod h1:psfu0MVaiTDLpNxCoNsTeILSKY2EICBwv345f3M+Ffs=
github.com/aquasecurity/trivy v0.1.6/go.mod h1:5hobyhxLzDtxruHzPxpND2PUKOssvGUdE9BocpJUwo4=
github.com/aquasecurity/trivy v0.16.0 h1:lyzqYGQ2TYxcjFwKBw6aU3PwHLvc0+6VTech+0/LnqQ=
github.com/aquasecurity/trivy v0.16.0/go.mod h1:SLXDW/zKJWE7XhMEGGfkFGABNvz6b8BAbNjuXztJlj0=
github.com/aquasecurity/trivy-db v0.0.0-20210105160501-c5bf4e153277/go.mod h1:N7CWA/vjVw78GWAdCJGhFQVqNGEA4e47a6eIWm+C/Bc=
@@ -124,10 +116,10 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg=
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.19.11/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.36.31 h1:BMVngapDGAfLBVEVzaSIw3fmJdWx7jOvhLCXgRXbXQI=
github.com/aws/aws-sdk-go v1.36.31/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
@@ -138,7 +130,6 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/briandowns/spinner v0.0.0-20190319032542-ac46072a5a91/go.mod h1:hw/JEQBIE+c/BLI4aKM8UU8v+ZqrD3h7HC27kKt8JQU=
github.com/briandowns/spinner v1.12.0 h1:72O0PzqGJb6G3KgrcIOtL/JAGGZ5ptOMCn9cUHmqsmw=
github.com/briandowns/spinner v1.12.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ=
github.com/caarlos0/env/v6 v6.0.0 h1:NZt6FAoB8ieKO5lEwRdwCzYxWFx7ZYF2R7UcoyaWtyc=
@@ -151,8 +142,9 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheggaaa/pb/v3 v3.0.3/go.mod h1:Pp35CDuiEpHa/ZLGCtBbM6CBwMstv1bJlG884V+73Yc=
github.com/cheggaaa/pb/v3 v3.0.5 h1:lmZOti7CraK9RSjzExsY53+WWfub9Qv13B5m4ptEoPE=
github.com/cheggaaa/pb/v3 v3.0.5/go.mod h1:X1L61/+36nz9bjIsrDU52qHKOQukUQe2Ge+YvGuquCw=
github.com/cheggaaa/pb/v3 v3.0.7 h1:58wduqwoqpsklsCZ7NZ5dsrCqPWv2t0+p85FcBds6XY=
github.com/cheggaaa/pb/v3 v3.0.7/go.mod h1:X1L61/+36nz9bjIsrDU52qHKOQukUQe2Ge+YvGuquCw=
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=
@@ -161,10 +153,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/continuity v0.0.0-20180921161001-7f53d412b9eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/clair v0.0.0-20180919182544-44ae4bc9590a/go.mod h1:uXhHPWAoRqw0jJc2f8RrPCwRhIo9otQ8OEWUFtpCiwA=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
@@ -188,7 +178,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
@@ -198,33 +187,21 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/cli v0.0.0-20180920165730-54c19e67f69c/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v0.0.0-20180920194744-16128bbac47f/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v0.0.0-20180924202107-a9c061deec0f/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v0.7.3-0.20190506211059-b20a14b54661/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-ce v0.0.0-20180924210327-f53bd8bb8e43/go.mod h1:l1FUGRYBvbjnZ8MS6A2xOji4aZFlY/Qmgz7p4oXH7ac=
github.com/docker/docker-credential-helpers v0.6.1/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/go-connections v0.0.0-20180821093606-97c2040d34df/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
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=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/elazarl/goproxy v0.0.0-20200809112317-0581fc3aee2d/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy v0.0.0-20210110162100-a92cc753f88e h1:/cwV7t2xezilMljIftb7WlFtzGANRCnoOhPjtl2ifcs=
github.com/elazarl/goproxy v0.0.0-20210110162100-a92cc753f88e/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
@@ -237,7 +214,6 @@ github.com/emersion/go-smtp v0.14.0 h1:RYW203p+EcPjL8Z/ZpT9lZ6iOc8MG1MQzEx1UKEkX
github.com/emersion/go-smtp v0.14.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emirpasic/gods v1.9.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -245,26 +221,20 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/etcd-io/bbolt v1.3.2/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fernet/fernet-go v0.0.0-20180830025343-9eac43b88a5e/go.mod h1:2H9hjfbpSMHwY503FclkV/lZTBh2YlOmLLSda12uL8c=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/genuinetools/pkg v0.0.0-20180910213200-1c141f661797/go.mod h1:XTcrCYlXPxnxL2UpnwuRn7tcaTn9HAhxFoFJucootk8=
github.com/genuinetools/reg v0.16.0/go.mod h1:12Fe9EIvK3dG/qWhNk5e9O96I8SGmCKLsJ8GsXUbk+Y=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/gliderlabs/ssh v0.1.3/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
@@ -299,8 +269,9 @@ github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGK
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis/v8 v8.4.0/go.mod h1:A1tbYoHSa1fXwN+//ljcCYYJeLmVrwL9hbQN45Jdy0M=
github.com/go-redis/redis/v8 v8.4.10/go.mod h1:d5yY/TlkQyYBSBHnXUmnf1OrHbyQere5JV4dLKwvXmo=
github.com/go-redis/redis/v8 v8.4.11 h1:t2lToev01VTrqYQcv+QFbxtGgcf64K+VUMgf9Ap6A/E=
github.com/go-redis/redis/v8 v8.4.11/go.mod h1:d5yY/TlkQyYBSBHnXUmnf1OrHbyQere5JV4dLKwvXmo=
github.com/go-redis/redis/v8 v8.8.0 h1:fDZP58UN/1RD3DjtTXP/fFZ04TFohSYhjZDkcDe2dnw=
github.com/go-redis/redis/v8 v8.8.0/go.mod h1:F7resOH5Kdug49Otu24RjHWwgK7u9AmtqWMnCV1iP5Y=
github.com/go-restruct/restruct v0.0.0-20191227155143-5734170a48a1/go.mod h1:KqrpKpn4M8OLznErihXTGLlsXFGeLxHUrLRRI/1YjGk=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
@@ -326,7 +297,6 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
@@ -350,7 +320,6 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -361,8 +330,9 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-containerregistry v0.0.0-20200331213917-3d03ed9b1ca2/go.mod h1:pD1UFYs7MCAx+ZLShBdttcaOSbyc8F9Na/9IZLNwJeA=
github.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo=
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
@@ -408,12 +378,11 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY=
github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grokify/html-strip-tags-go v0.0.0-20190424092004-025bd760b278 h1:DZo48DQFIDo/YWjUeFip1dfJztBhRuaxfUnPd+gAfcs=
github.com/grokify/html-strip-tags-go v0.0.0-20190424092004-025bd760b278/go.mod h1:Xk7G0nwBiIloTMbLddk4WWJOqi4i/JLhadLd0HUXO30=
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
@@ -451,7 +420,6 @@ github.com/htcat/htcat v1.0.2 h1:zro95dGwkKDeZOgq9ei+9szd5qurGxBGfHY8hRehA7k=
github.com/htcat/htcat v1.0.2/go.mod h1:i8ViQbjSi2+lJzM6Lx20FIxHENCz6mzJglK3HH06W3s=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/log15 v0.0.0-20180818164646-67afb5ed74ec/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
github.com/inconshreveable/log15 v0.0.0-20201112154412-8562bdadbbac h1:n1DqxAo4oWPMvH1+v+DLYlMCecgumhhgnxAPdqDIFHI=
github.com/inconshreveable/log15 v0.0.0-20201112154412-8562bdadbbac/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
@@ -461,7 +429,6 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i
github.com/jesseduffield/gocui v0.3.0 h1:l7wH8MKR2p+ozuZdtdhQiX7szILbv50vkMk1tg2+xow=
github.com/jesseduffield/gocui v0.3.0/go.mod h1:2RtZznzYKt8RLRwvFiSkXjU0Ei8WwHdubgnlaYH47dw=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/gorm v1.9.10/go.mod h1:Kh6hTsSGffh4ui079FHrR5Gg+5D0hgihqDcsDN2BBJY=
github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs=
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
@@ -489,12 +456,10 @@ github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQ
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
github.com/k0kubun/pp v3.0.1+incompatible h1:3tqvf7QgUnZ5tXO6pNAZlrvHgl6DvifjDrd9g2S9Z40=
github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/knqyf263/berkeleydb v0.0.0-20190501065933-fafe01fb9662/go.mod h1:bu1CcN4tUtoRcI/B/RFHhxMNKFHVq/c3SV+UTyduoXg=
github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f h1:GvCU5GXhHq+7LeOzx/haG7HSIZokl3/0GkoUFzsRJjg=
github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f/go.mod h1:q59u9px8b7UTj0nIjEjvmTWekazka6xIt6Uogz5Dm+8=
github.com/knqyf263/go-cpe v0.0.0-20201213041631-54f6ab28673f h1:vZP1dTKPOR7zSAbgqNbnTnYX77+gj3eu0QK+UmANZqE=
@@ -503,20 +468,18 @@ github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d h1:X4cedH4
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d/go.mod h1:o8sgWoz3JADecfc/cTYD92/Et1yMqMy0utV1z+VaZao=
github.com/knqyf263/go-rpm-version v0.0.0-20170716094938-74609b86c936 h1:HDjRqotkViMNcGMGicb7cgxklx8OwnjtCBmyWEqrRvM=
github.com/knqyf263/go-rpm-version v0.0.0-20170716094938-74609b86c936/go.mod h1:i4sF0l1fFnY1aiw08QQSwVAFxHEm311Me3WsU/X7nL0=
github.com/knqyf263/go-rpmdb v0.0.0-20190501070121-10a1c42a10dc/go.mod h1:MrSSvdMpTSymaQWk1yFr9sxFSyQmKMj6jkbvGrchBV8=
github.com/knqyf263/go-rpmdb v0.0.0-20201215100354-a9e3110d8ee1/go.mod h1:RDPNeIkU5NWXtt0OMEoILyxwUC/DyXeRtK295wpqSi0=
github.com/knqyf263/go-version v1.1.1/go.mod h1:0tBvHvOBSf5TqGNcY+/ih9o8qo3R16iZCpB9rP0D3VM=
github.com/knqyf263/gost v0.1.8 h1:8tHClkE3sMMl+qmPU3v7TyUpucs2goGzMAnD+1V6dow=
github.com/knqyf263/gost v0.1.8/go.mod h1:rlf9JZR6qMyXtnz0bqyMIexDoYhFt+on0FK+OL7MhmU=
github.com/knqyf263/gost v0.1.10 h1:9SWMPRsZh+0kKqQb/o20f5PNMESpJi3/8CdzrikaA4o=
github.com/knqyf263/gost v0.1.10/go.mod h1:Vs6YmVm5GdkVUc9uu8VEGaOdhMKk+0lf7rZALLJlUSA=
github.com/knqyf263/nested v0.0.1/go.mod h1:zwhsIhMkBg90DTOJQvxPkKIypEHPYkgWHs4gybdlUmk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kotakanbe/go-cve-dictionary v0.5.9 h1:T5bhMjC4V3c5ansidn/08q9yL15Buu/N7xG3Bx4ZfjQ=
github.com/kotakanbe/go-cve-dictionary v0.5.9/go.mod h1:Yp8EUO4zMTuM9lvwm1NwTUQtlhsTSJQDIpfNlk3meFc=
github.com/kotakanbe/go-cve-dictionary v0.5.10 h1:20d+JF9pgbURTL8G9pRinqYarLO/Cf0cBvZYzCbFHic=
github.com/kotakanbe/go-cve-dictionary v0.5.10/go.mod h1:E/CipfNDV31W39MH9QtgkA12JFBMe/3CELxXVvPRphQ=
github.com/kotakanbe/go-pingscanner v0.1.0 h1:VG4/9l0i8WeToXclj7bIGoAZAu7a07Z3qmQiIfU0gT0=
github.com/kotakanbe/go-pingscanner v0.1.0/go.mod h1:/761QZzuZFcfN8h/1QuawUA+pKukp3qcNj5mxJCOiAk=
github.com/kotakanbe/goval-dictionary v0.3.2 h1:n3ZBiw3XqIvwm8bDtgNKgKawfNznuaWoysl8HwunTlU=
github.com/kotakanbe/goval-dictionary v0.3.2/go.mod h1:1FcXF2+KKTN+IwLbU+iUsufgUrlpurk8nFJUThksEiQ=
github.com/kotakanbe/goval-dictionary v0.3.3 h1:b9o1ZPFGmk0WZV0nnk4mWl5vTKINequ+QVW6w9m+8RI=
github.com/kotakanbe/goval-dictionary v0.3.3/go.mod h1:69e5kFTZEAcT5Lqq8NRlKUjXm0ZNxvT8d3yS/iqFJjs=
github.com/kotakanbe/logrus-prefixed-formatter v0.0.0-20180123152602-928f7356cb96 h1:xNVK0mQJdQjw+QYeaMM4G6fvucWr8rTGGIhlPakx1wU=
github.com/kotakanbe/logrus-prefixed-formatter v0.0.0-20180123152602-928f7356cb96/go.mod h1:ljq48H1V+0Vh0u7ucA3LjR4AfkAeCpxrf7LaaCk8Vmo=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
@@ -524,6 +487,7 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
@@ -538,11 +502,13 @@ github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdA
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E=
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY=
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -572,8 +538,6 @@ github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
@@ -589,12 +553,12 @@ github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
@@ -618,43 +582,40 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.2-0.20190607075207-195002e6e56a/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ=
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4=
github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.10.4 h1:NiTx7EEvBzu9sFOD1zORteLSt3o8gnlvZZwSE9TnY9U=
github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ=
github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ=
github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
github.com/open-policy-agent/opa v0.21.1/go.mod h1:cZaTfhxsj7QdIiUI0U9aBtOLLTqVNe+XE60+9kZKLHw=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/parnurzeal/gorequest v0.2.16 h1:T/5x+/4BT+nj+3eSknXmCTnEVGSzFzPGdpqmUVVZXHQ=
github.com/parnurzeal/gorequest v0.2.16/go.mod h1:3Kh2QUMJoqw3icWAecsyzkpY7UzRfDhbRdTjtNwNiUE=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/peterh/liner v0.0.0-20170211195444-bf27d3ba8e1d/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/peterhellberg/link v1.0.0/go.mod h1:gtSlOT4jmkY8P47hbTc8PTgiDDWpdPbFYl75keYyBB8=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.0.0-20181023235946-059132a15dd0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -666,25 +627,18 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prometheus/client_golang v0.0.0-20180924113449-f69c853d21c1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.0.0-20181025174421-f30f42803563/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20180920065004-418d78d0b9a7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
@@ -710,10 +664,8 @@ github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/simplereach/timeutils v1.2.0/go.mod h1:VVbQDfN/FHRZa1LSqcwo4kNZ62OOyqLLGQKYB3pB0Q8=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -724,7 +676,6 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@@ -732,18 +683,21 @@ github.com/sosedoff/gitkit v0.2.0/go.mod h1:A+o6ZazfVJwetlcHz3ah6th66XcBdsyzLo+a
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.5.1 h1:VHu76Lk0LSP1x254maIu2bplkWpfBWI+B+6fdoZprcg=
github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.0-20181021141114-fe5e611709b0/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v0.0.0-20181024212040-082b515c9490/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -766,13 +720,14 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/takuzoo3868/go-msfdb v0.1.4 h1:NjnK1dzUEA4Nwm2Z6jmld2K7Snn6oAmW68KAT/qOH6I=
github.com/takuzoo3868/go-msfdb v0.1.4/go.mod h1:VdYWAq8ikjJGOx0+srShozXsd1x0aHZ+yqAB59tJQsI=
github.com/tealeg/xlsx v1.0.3/go.mod h1:uxu5UY2ovkuRPWKQ8Q7JG0JbSivrISjdPzZQKeo74mA=
github.com/takuzoo3868/go-msfdb v0.1.5 h1:qYTWYM/JVFFR30Y5JsONfhrlXn9//ZcA93aknatPI5Q=
github.com/takuzoo3868/go-msfdb v0.1.5/go.mod h1:ThpfHn0SeVo8hVKwhQ2jXoPFq4+auinU5BHcDVKZBpk=
github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM=
github.com/testcontainers/testcontainers-go v0.3.1/go.mod h1:br7bkzIukhPSIjy07Ma3OuXjjFvl2jm7CDU0LQNsqLw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@@ -793,9 +748,8 @@ github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/vdemeester/k8s-pkg-credentialprovider v1.17.4/go.mod h1:inCTmtUdr5KJbreVojo06krnTgaeAz/Z7lynpPk/Q2c=
github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
github.com/vulsio/go-exploitdb v0.1.6 h1:RbjF6pakpuUqR1XLDaN/vsFeM+oKZC8nJrPbt8+v5hE=
github.com/vulsio/go-exploitdb v0.1.6/go.mod h1:CMNvEqjsVa2IMGsoyDV4QKXlOSWIaB6b6+29F6YmJWU=
github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8=
github.com/vulsio/go-exploitdb v0.1.7 h1:wdq+6H/PvGGnUiyAaLQ3DtczsLy3rrBQgmNOiXH62z0=
github.com/vulsio/go-exploitdb v0.1.7/go.mod h1:4strSWuNtCTz76QB8RuxpMQmYifArGKiHKBFCMOTxY4=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
@@ -805,21 +759,28 @@ github.com/ymomoi/goval-parser v0.0.0-20170813122243-0a0be1dd9d08/go.mod h1:ox1N
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/otel v0.14.0/go.mod h1:vH5xEuwy7Rts0GNtsCW3HYQoZDY+OmBJ6t1bFGGlxgw=
go.opentelemetry.io/otel v0.16.0 h1:uIWEbdeb4vpKPGITLsRVUS44L5oDbDUCZxn8lkxhmgw=
go.opentelemetry.io/otel v0.16.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA=
go.opentelemetry.io/otel v0.19.0 h1:Lenfy7QHRXPZVsw/12CWpxX6d/JkrX8wrx2vO8G80Ng=
go.opentelemetry.io/otel v0.19.0/go.mod h1:j9bF567N9EfomkSidSfmMwIwIBuP37AMAIzVW85OxSg=
go.opentelemetry.io/otel/metric v0.19.0 h1:dtZ1Ju44gkJkYvo+3qGqVXmf88tc+a42edOywypengg=
go.opentelemetry.io/otel/metric v0.19.0/go.mod h1:8f9fglJPRnXuskQmKpnad31lcLJ2VmNNqIsx/uIwBSc=
go.opentelemetry.io/otel/oteltest v0.19.0 h1:YVfA0ByROYqTwOxqHVZYZExzEpfZor+MU1rU+ip2v9Q=
go.opentelemetry.io/otel/oteltest v0.19.0/go.mod h1:tI4yxwh8U21v7JD6R3BcA/2+RBoTKFexE/PJ/nSO7IA=
go.opentelemetry.io/otel/trace v0.19.0 h1:1ucYlenXIDA1OlHVLDZKX0ObXV5RLaq06DtUKz5e5zc=
go.opentelemetry.io/otel/trace v0.19.0/go.mod h1:4IXiNextNOpPnRlI4ryK69mn5iC84bjBWZQA5DXz/qg=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
@@ -831,22 +792,20 @@ go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E=
go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -857,8 +816,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -873,7 +832,6 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181023182221-1baf3a9d7d67/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -901,13 +859,11 @@ golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180925072008-f04abc6bdfa7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -938,12 +894,14 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210323141857-08027d57d8cf h1:sewfyKLWuY3ko6EI4hbFziQ8bHkfammpzCDfLT92I1c=
golang.org/x/net v0.0.0-20210323141857-08027d57d8cf/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -960,17 +918,15 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180925112736-b09afc3d579e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/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-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -978,7 +934,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
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=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1022,10 +977,12 @@ golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210301091718-77cc2087c03b h1:kHlr0tATeLRMEiZJu5CknOw/E8V6h69sXXQFGoPtjcc=
golang.org/x/sys v0.0.0-20210301091718-77cc2087c03b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 h1:EZ2mChiOa8udjfp6rRmswTbtZN/QzUQp4ptM4rnjHvc=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -1063,6 +1020,7 @@ golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -1096,9 +1054,9 @@ golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d h1:W07d4xkoAUSNOkOzdzXCdFGxT7o2rW4q8M34tB2i//k=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1107,7 +1065,6 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
@@ -1134,9 +1091,7 @@ google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuh
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180924164928-221a8d4f7494/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -1164,7 +1119,6 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.15.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
@@ -1192,7 +1146,6 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -1206,24 +1159,22 @@ gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M=
gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/src-d/go-billy.v4 v4.2.1/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk=
gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk=
gopkg.in/src-d/go-git-fixtures.v3 v3.1.1/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git-fixtures.v3 v3.4.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git.v4 v4.10.0/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk=
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
@@ -1241,7 +1192,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v0.0.0-20181223230014-1083505acf35/go.mod h1:R//lfYlUuTOTfblYI3lGoAAAebUdzjvbmQsuB7Ykd90=
gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -1,17 +0,0 @@
// +build !scanner
package gost
import (
"github.com/future-architect/vuls/models"
"github.com/knqyf263/gost/db"
)
// Base is a base struct
type Base struct {
}
// FillCVEsWithRedHat fills cve information that has in Gost
func (b Base) FillCVEsWithRedHat(driver db.DB, r *models.ScanResult) error {
return RedHat{}.fillCvesWithRedHatAPI(driver, r)
}

View File

@@ -5,12 +5,10 @@ package gost
import (
"encoding/json"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/constant"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/util"
"github.com/knqyf263/gost/db"
gostmodels "github.com/knqyf263/gost/models"
)
@@ -35,7 +33,7 @@ func (deb Debian) supported(major string) bool {
}
// DetectUnfixed fills cve information that has in Gost
func (deb Debian) DetectUnfixed(driver db.DB, r *models.ScanResult, _ bool) (nCVEs int, err error) {
func (deb Debian) DetectUnfixed(r *models.ScanResult, _ bool) (nCVEs int, err error) {
if !deb.supported(major(r.Release)) {
// only logging
logging.Log.Warnf("Debian %s is not supported yet", r.Release)
@@ -65,8 +63,8 @@ func (deb Debian) DetectUnfixed(driver db.DB, r *models.ScanResult, _ bool) (nCV
}
packCvesList := []packCves{}
if config.Conf.Gost.IsFetchViaHTTP() {
url, _ := util.URLPathJoin(config.Conf.Gost.URL, "debian", major(scanResult.Release), "pkgs")
if deb.DBDriver.Cnf.IsFetchViaHTTP() {
url, _ := util.URLPathJoin(deb.DBDriver.Cnf.GetURL(), "debian", major(scanResult.Release), "pkgs")
responses, err := getAllUnfixedCvesViaHTTP(r, url)
if err != nil {
return 0, err
@@ -88,11 +86,11 @@ func (deb Debian) DetectUnfixed(driver db.DB, r *models.ScanResult, _ bool) (nCV
})
}
} else {
if driver == nil {
if deb.DBDriver.DB == nil {
return 0, nil
}
for _, pack := range scanResult.Packages {
cveDebs := driver.GetUnfixedCvesDebian(major(scanResult.Release), pack.Name)
cveDebs := deb.DBDriver.DB.GetUnfixedCvesDebian(major(scanResult.Release), pack.Name)
cves := []models.CveContent{}
for _, cveDeb := range cveDebs {
cves = append(cves, *deb.ConvertToModel(&cveDeb))
@@ -106,7 +104,7 @@ func (deb Debian) DetectUnfixed(driver db.DB, r *models.ScanResult, _ bool) (nCV
// SrcPack
for _, pack := range scanResult.SrcPackages {
cveDebs := driver.GetUnfixedCvesDebian(major(scanResult.Release), pack.Name)
cveDebs := deb.DBDriver.DB.GetUnfixedCvesDebian(major(scanResult.Release), pack.Name)
cves := []models.CveContent{}
for _, cveDeb := range cveDebs {
cves = append(cves, *deb.ConvertToModel(&cveDeb))

View File

@@ -3,28 +3,84 @@
package gost
import (
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/knqyf263/gost/db"
"golang.org/x/xerrors"
"github.com/future-architect/vuls/constant"
)
// DBDriver is a DB Driver
type DBDriver struct {
DB db.DB
Cnf config.VulnDictInterface
}
// Client is the interface of OVAL client.
type Client interface {
DetectUnfixed(db.DB, *models.ScanResult, bool) (int, error)
FillCVEsWithRedHat(db.DB, *models.ScanResult) error
DetectUnfixed(*models.ScanResult, bool) (int, error)
}
// Base is a base struct
type Base struct {
DBDriver DBDriver
}
// FillCVEsWithRedHat fills CVE detailed with Red Hat Security
func FillCVEsWithRedHat(r *models.ScanResult, cnf config.GostConf) error {
db, locked, err := newGostDB(cnf)
if locked {
return xerrors.Errorf("SQLite3 is locked: %s", cnf.GetSQLite3Path())
} else if err != nil {
return err
}
defer func() {
if err := db.CloseDB(); err != nil {
logging.Log.Errorf("Failed to close DB. err: %+v")
}
}()
return RedHat{Base{DBDriver{DB: db, Cnf: &cnf}}}.fillCvesWithRedHatAPI(r)
}
// NewClient make Client by family
func NewClient(family string) Client {
func NewClient(cnf config.GostConf, family string) (Client, error) {
db, locked, err := newGostDB(cnf)
if locked {
return nil, xerrors.Errorf("SQLite3 is locked: %s", cnf.GetSQLite3Path())
} else if err != nil {
return nil, err
}
driver := DBDriver{DB: db, Cnf: &cnf}
switch family {
case constant.RedHat, constant.CentOS:
return RedHat{}
return RedHat{Base{DBDriver: driver}}, nil
case constant.Debian, constant.Raspbian:
return Debian{}
return Debian{Base{DBDriver: driver}}, nil
case constant.Windows:
return Microsoft{}
return Microsoft{Base{DBDriver: driver}}, nil
default:
return Pseudo{}
return Pseudo{}, nil
}
}
// NewGostDB returns db client for Gost
func newGostDB(cnf config.GostConf) (driver db.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
if driver, locked, err = db.NewDB(cnf.GetType(), path, cnf.GetDebugSQL()); err != nil {
if locked {
return nil, true, xerrors.Errorf("gostDB is locked. err: %w", err)
}
return nil, false, err
}
return driver, false, nil
}

View File

@@ -6,7 +6,6 @@ import (
"strings"
"github.com/future-architect/vuls/models"
"github.com/knqyf263/gost/db"
gostmodels "github.com/knqyf263/gost/models"
)
@@ -16,15 +15,15 @@ type Microsoft struct {
}
// DetectUnfixed fills cve information that has in Gost
func (ms Microsoft) DetectUnfixed(driver db.DB, r *models.ScanResult, _ bool) (nCVEs int, err error) {
if driver == nil {
func (ms Microsoft) DetectUnfixed(r *models.ScanResult, _ bool) (nCVEs int, err error) {
if ms.DBDriver.DB == nil {
return 0, nil
}
cveIDs := []string{}
for cveID := range r.ScannedCves {
cveIDs = append(cveIDs, cveID)
}
for cveID, msCve := range driver.GetMicrosoftMulti(cveIDs) {
for cveID, msCve := range ms.DBDriver.DB.GetMicrosoftMulti(cveIDs) {
if _, ok := r.ScannedCves[cveID]; !ok {
continue
}

View File

@@ -4,7 +4,6 @@ package gost
import (
"github.com/future-architect/vuls/models"
"github.com/knqyf263/gost/db"
)
// Pseudo is Gost client except for RedHat family and Debian
@@ -13,6 +12,6 @@ type Pseudo struct {
}
// DetectUnfixed fills cve information that has in Gost
func (pse Pseudo) DetectUnfixed(driver db.DB, r *models.ScanResult, _ bool) (int, error) {
func (pse Pseudo) DetectUnfixed(r *models.ScanResult, _ bool) (int, error) {
return 0, nil
}

View File

@@ -10,7 +10,6 @@ import (
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/util"
"github.com/knqyf263/gost/db"
gostmodels "github.com/knqyf263/gost/models"
)
@@ -20,14 +19,9 @@ type RedHat struct {
}
// DetectUnfixed fills cve information that has in Gost
func (red RedHat) DetectUnfixed(driver db.DB, r *models.ScanResult, ignoreWillNotFix bool) (nCVEs int, err error) {
return red.detectUnfixed(driver, r, ignoreWillNotFix)
}
func (red RedHat) detectUnfixed(driver db.DB, r *models.ScanResult, ignoreWillNotFix bool) (nCVEs int, err error) {
if config.Conf.Gost.IsFetchViaHTTP() {
prefix, _ := util.URLPathJoin(config.Conf.Gost.URL,
"redhat", major(r.Release), "pkgs")
func (red RedHat) DetectUnfixed(r *models.ScanResult, ignoreWillNotFix bool) (nCVEs int, err error) {
if red.DBDriver.Cnf.IsFetchViaHTTP() {
prefix, _ := util.URLPathJoin(red.DBDriver.Cnf.GetURL(), "redhat", major(r.Release), "pkgs")
responses, err := getAllUnfixedCvesViaHTTP(r, prefix)
if err != nil {
return 0, err
@@ -45,12 +39,12 @@ func (red RedHat) detectUnfixed(driver db.DB, r *models.ScanResult, ignoreWillNo
}
}
} else {
if driver == nil {
if red.DBDriver.DB == nil {
return 0, nil
}
for _, pack := range r.Packages {
// CVE-ID: RedhatCVE
cves := driver.GetUnfixedCvesRedhat(major(r.Release), pack.Name, ignoreWillNotFix)
cves := red.DBDriver.DB.GetUnfixedCvesRedhat(major(r.Release), pack.Name, ignoreWillNotFix)
for _, cve := range cves {
if newly := red.setUnfixedCveToScanResult(&cve, r); newly {
nCVEs++
@@ -61,7 +55,7 @@ func (red RedHat) detectUnfixed(driver db.DB, r *models.ScanResult, ignoreWillNo
return nCVEs, nil
}
func (red RedHat) fillCvesWithRedHatAPI(driver db.DB, r *models.ScanResult) error {
func (red RedHat) fillCvesWithRedHatAPI(r *models.ScanResult) error {
cveIDs := []string{}
for cveID, vuln := range r.ScannedCves {
if _, ok := vuln.CveContents[models.RedHatAPI]; ok {
@@ -70,9 +64,8 @@ func (red RedHat) fillCvesWithRedHatAPI(driver db.DB, r *models.ScanResult) erro
cveIDs = append(cveIDs, cveID)
}
if config.Conf.Gost.IsFetchViaHTTP() {
prefix, _ := util.URLPathJoin(config.Conf.Gost.URL,
"redhat", "cves")
if red.DBDriver.Cnf.IsFetchViaHTTP() {
prefix, _ := util.URLPathJoin(config.Conf.Gost.URL, "redhat", "cves")
responses, err := getCvesViaHTTP(cveIDs, prefix)
if err != nil {
return err
@@ -88,10 +81,10 @@ func (red RedHat) fillCvesWithRedHatAPI(driver db.DB, r *models.ScanResult) erro
red.setFixedCveToScanResult(&redCve, r)
}
} else {
if driver == nil {
if red.DBDriver.DB == nil {
return nil
}
for _, redCve := range driver.GetRedhatMulti(cveIDs) {
for _, redCve := range red.DBDriver.DB.GetRedhatMulti(cveIDs) {
if len(redCve.Name) == 0 {
continue
}

6534
integration/data/amazon_2.json Executable file

File diff suppressed because it is too large Load Diff

5634
integration/data/centos_7.json Executable file

File diff suppressed because it is too large Load Diff

5631
integration/data/debian_10.json Executable file

File diff suppressed because it is too large Load Diff

131
integration/data/rails.json Normal file
View File

@@ -0,0 +1,131 @@
{
"jsonVersion": 4,
"lang": "",
"serverUUID": "",
"serverName": "rails",
"family": "pseudo",
"release": "",
"container": {
"containerID": "",
"name": "",
"image": "",
"type": "",
"uuid": ""
},
"platform": {
"name": "other",
"instanceID": ""
},
"scannedAt": "2021-03-31T12:22:26.428630183+09:00",
"scanMode": "fast mode",
"scannedVersion": "v0.15.9",
"scannedRevision": "build-20210331_121257_1a58c94",
"scannedBy": "dev",
"scannedVia": "pseudo",
"scannedIpv4Addrs": [
"172.19.0.1",
"172.17.0.1",
"172.27.0.1"
],
"reportedAt": "0001-01-01T00:00:00Z",
"reportedVersion": "",
"reportedRevision": "",
"reportedBy": "",
"errors": [],
"warnings": [],
"scannedCves": {},
"runningKernel": {
"release": "",
"version": "",
"rebootRequired": false
},
"packages": {},
"config": {
"scan": {
"logDir": "/var/log/vuls",
"resultsDir": "/home/ubuntu/go/src/github.com/future-architect/vuls/results",
"default": {
"port": "22",
"scanMode": [
"fast"
]
},
"servers": {
"rails": {
"serverName": "rails",
"cpeNames": [
"cpe:/a:rubyonrails:ruby_on_rails:3.0.1"
],
"scanMode": [
"fast"
],
"type": "pseudo",
"wordpress": {}
}
},
"cveDict": {
"Name": "cveDict",
"Type": "sqlite3",
"SQLite3Path": "/home/ubuntu/go/src/github.com/kotakanbe/go-cve-dictionary/cve.sqlite3",
"DebugSQL": false
},
"ovalDict": {
"Name": "ovalDict",
"Type": "sqlite3",
"SQLite3Path": "/home/ubuntu/go/src/github.com/kotakanbe/goval-dictionary/oval.sqlite3",
"DebugSQL": false
},
"gost": {
"Name": "gost",
"Type": "sqlite3",
"SQLite3Path": "/home/ubuntu/go/src/github.com/future-architect/vuls/gost.sqlite3",
"DebugSQL": false
},
"exploit": {
"Name": "exploit",
"Type": "sqlite3",
"SQLite3Path": "/home/ubuntu/go/src/github.com/vulsio/go-exploitdb/go-exploitdb.sqlite3",
"DebugSQL": false
},
"metasploit": {
"Name": "metasploit",
"Type": "sqlite3",
"SQLite3Path": "/home/ubuntu/go/src/github.com/takuzoo3868/go-msfdb/go-msfdb.sqlite3",
"DebugSQL": false
}
},
"report": {
"default": {},
"cveDict": {
"Name": "",
"Type": "",
"SQLite3Path": "",
"DebugSQL": false
},
"ovalDict": {
"Name": "",
"Type": "",
"SQLite3Path": "",
"DebugSQL": false
},
"gost": {
"Name": "",
"Type": "",
"SQLite3Path": "",
"DebugSQL": false
},
"exploit": {
"Name": "",
"Type": "",
"SQLite3Path": "",
"DebugSQL": false
},
"metasploit": {
"Name": "",
"Type": "",
"SQLite3Path": "",
"DebugSQL": false
}
}
}
}

5158
integration/data/rhel_71.json Executable file

File diff suppressed because it is too large Load Diff

6926
integration/data/rhel_8.json Executable file

File diff suppressed because it is too large Load Diff

8609
integration/data/ubuntu_1804.json Executable file

File diff suppressed because it is too large Load Diff

8559
integration/data/ubuntu_2004.json Executable file

File diff suppressed because it is too large Load Diff

27
integration/int-config.toml Executable file
View File

@@ -0,0 +1,27 @@
[cveDict]
Type = "sqlite3"
SQLite3Path = "/home/ubuntu/vulsctl/docker/cve.sqlite3"
[ovalDict]
Type = "sqlite3"
SQLite3Path = "/home/ubuntu/vulsctl/docker/oval.sqlite3"
[gost]
Type = "sqlite3"
SQLite3Path = "/home/ubuntu/vulsctl/docker/gost.sqlite3"
[exploit]
Type = "sqlite3"
SQLite3Path = "/home/ubuntu/vulsctl/docker/go-exploitdb.sqlite3"
[metasploit]
type = "sqlite3"
SQLite3Path = "/home/ubuntu/vulsctl/docker/go-msfdb.sqlite3"
[default]
[servers]
[servers.rails]
type = "pseudo"
cpeNames = [ "cpe:/a:rubyonrails:ruby_on_rails:3.0.1" ]

View File

@@ -0,0 +1,27 @@
[cveDict]
Type = "redis"
Url = "redis://127.0.0.1/3"
[ovalDict]
Type = "redis"
Url = "redis://127.0.0.1/1"
[gost]
Type = "redis"
Url = "redis://127.0.0.1/2"
[exploit]
Type = "redis"
Url = "redis://127.0.0.1/4"
[metasploit]
Type = "redis"
Url = "redis://127.0.0.1/5"
[default]
[servers]
[servers.rails]
type = "pseudo"
cpeNames = [ "cpe:/a:rubyonrails:ruby_on_rails:3.0.1" ]

View File

@@ -15,6 +15,14 @@ import (
formatter "github.com/kotakanbe/logrus-prefixed-formatter"
)
//LogOpts has options for logging
type LogOpts struct {
Debug bool `json:"debug,omitempty"`
DebugSQL bool `json:"debugSQL,omitempty"`
LogDir string `json:"logDir,omitempty"`
Quiet bool `json:"quiet,omitempty"`
}
// Log for localhost
var Log Logger

View File

@@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"reflect"
"sort"
"strings"
"time"
@@ -56,7 +57,7 @@ type ScanResult struct {
Config struct {
Scan config.Config `json:"scan"`
Report config.Config `json:"report"`
} `json:"constant"`
} `json:"config"`
}
// Container has Container information
@@ -374,6 +375,48 @@ func (r *ScanResult) CheckEOL() {
}
}
func (r *ScanResult) SortForJSONOutput() {
for k, v := range r.Packages {
sort.SliceStable(v.AffectedProcs, func(i, j int) bool {
return v.AffectedProcs[i].PID < v.AffectedProcs[j].PID
})
sort.SliceStable(v.NeedRestartProcs, func(i, j int) bool {
return v.NeedRestartProcs[i].PID < v.NeedRestartProcs[j].PID
})
r.Packages[k] = v
}
for k, v := range r.ScannedCves {
sort.SliceStable(v.AffectedPackages, func(i, j int) bool {
return v.AffectedPackages[i].Name < v.AffectedPackages[j].Name
})
sort.SliceStable(v.DistroAdvisories, func(i, j int) bool {
return v.DistroAdvisories[i].AdvisoryID < v.DistroAdvisories[j].AdvisoryID
})
sort.SliceStable(v.Exploits, func(i, j int) bool {
return v.Exploits[i].ID < v.Exploits[j].ID
})
sort.SliceStable(v.Metasploits, func(i, j int) bool {
return v.Metasploits[i].Name < v.Metasploits[j].Name
})
for kk, vv := range v.CveContents {
sort.SliceStable(vv.References, func(i, j int) bool {
return vv.References[i].Link < vv.References[j].Link
})
v.CveContents[kk] = vv
}
sort.SliceStable(v.AlertDict.En, func(i, j int) bool {
return v.AlertDict.En[i].Title < v.AlertDict.En[j].Title
})
sort.SliceStable(v.AlertDict.Ja, func(i, j int) bool {
return v.AlertDict.Ja[i].Title < v.AlertDict.Ja[j].Title
})
r.ScannedCves[k] = v
}
}
// CweDict is a dictionary for CWE
type CweDict map[string]CweDictEntry

View File

@@ -1,6 +1,7 @@
package models
import (
"reflect"
"testing"
"github.com/future-architect/vuls/config"
@@ -92,3 +93,274 @@ func TestIsDisplayUpdatableNum(t *testing.T) {
}
}
}
func TestScanResult_Sort(t *testing.T) {
type fields struct {
Packages Packages
ScannedCves VulnInfos
}
tests := []struct {
name string
fields fields
expected fields
}{
{
name: "already asc",
fields: fields{
Packages: map[string]Package{
"pkgA": {
Name: "pkgA",
AffectedProcs: []AffectedProcess{
{PID: "1", Name: "procB"},
{PID: "2", Name: "procA"},
},
NeedRestartProcs: []NeedRestartProcess{
{PID: "1"},
{PID: "2"},
},
},
},
ScannedCves: VulnInfos{
"CVE-2014-3591": VulnInfo{
AffectedPackages: PackageFixStatuses{
PackageFixStatus{Name: "pkgA"},
PackageFixStatus{Name: "pkgB"},
},
DistroAdvisories: []DistroAdvisory{
{AdvisoryID: "adv-1"},
{AdvisoryID: "adv-2"},
},
Exploits: []Exploit{
{ID: "a"},
{ID: "b"},
},
Metasploits: []Metasploit{
{Name: "a"},
{Name: "b"},
},
CveContents: CveContents{
"nvd": CveContent{
References: References{
Reference{Link: "a"},
Reference{Link: "b"},
},
},
"jvn": CveContent{
References: References{
Reference{Link: "a"},
Reference{Link: "b"},
},
},
},
AlertDict: AlertDict{
En: []Alert{
{Title: "a"},
{Title: "b"},
},
Ja: []Alert{
{Title: "a"},
{Title: "b"},
},
},
},
},
},
expected: fields{
Packages: map[string]Package{
"pkgA": {
Name: "pkgA",
AffectedProcs: []AffectedProcess{
{PID: "1", Name: "procB"},
{PID: "2", Name: "procA"},
},
NeedRestartProcs: []NeedRestartProcess{
{PID: "1"},
{PID: "2"},
},
},
},
ScannedCves: VulnInfos{
"CVE-2014-3591": VulnInfo{
AffectedPackages: PackageFixStatuses{
PackageFixStatus{Name: "pkgA"},
PackageFixStatus{Name: "pkgB"},
},
DistroAdvisories: []DistroAdvisory{
{AdvisoryID: "adv-1"},
{AdvisoryID: "adv-2"},
},
Exploits: []Exploit{
{ID: "a"},
{ID: "b"},
},
Metasploits: []Metasploit{
{Name: "a"},
{Name: "b"},
},
CveContents: CveContents{
"nvd": CveContent{
References: References{
Reference{Link: "a"},
Reference{Link: "b"},
},
},
"jvn": CveContent{
References: References{
Reference{Link: "a"},
Reference{Link: "b"},
},
},
},
AlertDict: AlertDict{
En: []Alert{
{Title: "a"},
{Title: "b"},
},
Ja: []Alert{
{Title: "a"},
{Title: "b"},
},
},
},
},
},
},
{
name: "sort",
fields: fields{
Packages: map[string]Package{
"pkgA": {
Name: "pkgA",
AffectedProcs: []AffectedProcess{
{PID: "2", Name: "procA"},
{PID: "1", Name: "procB"},
},
NeedRestartProcs: []NeedRestartProcess{
{PID: "91"},
{PID: "90"},
},
},
},
ScannedCves: VulnInfos{
"CVE-2014-3591": VulnInfo{
AffectedPackages: PackageFixStatuses{
PackageFixStatus{Name: "pkgB"},
PackageFixStatus{Name: "pkgA"},
},
DistroAdvisories: []DistroAdvisory{
{AdvisoryID: "adv-2"},
{AdvisoryID: "adv-1"},
},
Exploits: []Exploit{
{ID: "b"},
{ID: "a"},
},
Metasploits: []Metasploit{
{Name: "b"},
{Name: "a"},
},
CveContents: CveContents{
"nvd": CveContent{
References: References{
Reference{Link: "b"},
Reference{Link: "a"},
},
},
"jvn": CveContent{
References: References{
Reference{Link: "b"},
Reference{Link: "a"},
},
},
},
AlertDict: AlertDict{
En: []Alert{
{Title: "b"},
{Title: "a"},
},
Ja: []Alert{
{Title: "b"},
{Title: "a"},
},
},
},
},
},
expected: fields{
Packages: map[string]Package{
"pkgA": {
Name: "pkgA",
AffectedProcs: []AffectedProcess{
{PID: "1", Name: "procB"},
{PID: "2", Name: "procA"},
},
NeedRestartProcs: []NeedRestartProcess{
{PID: "90"},
{PID: "91"},
},
},
},
ScannedCves: VulnInfos{
"CVE-2014-3591": VulnInfo{
AffectedPackages: PackageFixStatuses{
PackageFixStatus{Name: "pkgA"},
PackageFixStatus{Name: "pkgB"},
},
DistroAdvisories: []DistroAdvisory{
{AdvisoryID: "adv-1"},
{AdvisoryID: "adv-2"},
},
Exploits: []Exploit{
{ID: "a"},
{ID: "b"},
},
Metasploits: []Metasploit{
{Name: "a"},
{Name: "b"},
},
CveContents: CveContents{
"nvd": CveContent{
References: References{
Reference{Link: "a"},
Reference{Link: "b"},
},
},
"jvn": CveContent{
References: References{
Reference{Link: "a"},
Reference{Link: "b"},
},
},
},
AlertDict: AlertDict{
En: []Alert{
{Title: "a"},
{Title: "b"},
},
Ja: []Alert{
{Title: "a"},
{Title: "b"},
},
},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := &ScanResult{
Packages: tt.fields.Packages,
ScannedCves: tt.fields.ScannedCves,
}
r.SortForJSONOutput()
if !reflect.DeepEqual(r.Packages, tt.expected.Packages) {
t.Errorf("act %+v, want %+v", r.Packages, tt.expected.Packages)
}
if !reflect.DeepEqual(r.ScannedCves, tt.expected.ScannedCves) {
t.Errorf("act %+v, want %+v", r.ScannedCves, tt.expected.ScannedCves)
}
})
}
}

View File

@@ -763,14 +763,10 @@ type AlertDict struct {
// FormatSource returns which source has this alert
func (a AlertDict) FormatSource() string {
s := []string{}
if len(a.En) != 0 {
s = append(s, "USCERT")
if len(a.En) != 0 || len(a.Ja) != 0 {
return "CERT"
}
if len(a.Ja) != 0 {
s = append(s, "JPCERT")
}
return strings.Join(s, "/")
return ""
}
// Confidences is a list of Confidence

View File

@@ -1 +0,0 @@
package msf

View File

@@ -1,51 +0,0 @@
// +build !scanner
package msf
import (
"github.com/future-architect/vuls/models"
"github.com/takuzoo3868/go-msfdb/db"
metasploitmodels "github.com/takuzoo3868/go-msfdb/models"
)
// FillWithMetasploit fills metasploit module information that has in module
func FillWithMetasploit(driver db.DB, r *models.ScanResult) (nMetasploitCve int, err error) {
if driver == nil {
return 0, nil
}
for cveID, vuln := range r.ScannedCves {
if cveID == "" {
continue
}
ms := driver.GetModuleByCveID(cveID)
if len(ms) == 0 {
continue
}
modules := ConvertToModels(ms)
vuln.Metasploits = modules
r.ScannedCves[cveID] = vuln
nMetasploitCve++
}
return nMetasploitCve, nil
}
// ConvertToModels converts gost model to vuls model
func ConvertToModels(ms []*metasploitmodels.Metasploit) (modules []models.Metasploit) {
for _, m := range ms {
var links []string
if 0 < len(m.References) {
for _, u := range m.References {
links = append(links, u.Link)
}
}
module := models.Metasploit{
Name: m.Name,
Title: m.Title,
Description: m.Description,
URLs: links,
}
modules = append(modules, module)
}
return modules
}

View File

@@ -7,7 +7,6 @@ import (
"github.com/future-architect/vuls/constant"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/kotakanbe/goval-dictionary/db"
)
// Alpine is the struct of Alpine Linux
@@ -16,22 +15,33 @@ type Alpine struct {
}
// NewAlpine creates OVAL client for SUSE
func NewAlpine() Alpine {
func NewAlpine(cnf config.VulnDictInterface) Alpine {
return Alpine{
Base{
family: constant.Alpine,
Cnf: cnf,
},
}
}
// FillWithOval returns scan result after updating CVE info by OVAL
func (o Alpine) FillWithOval(driver db.DB, r *models.ScanResult) (nCVEs int, err error) {
func (o Alpine) FillWithOval(r *models.ScanResult) (nCVEs int, err error) {
var relatedDefs ovalResult
if config.Conf.OvalDict.IsFetchViaHTTP() {
if relatedDefs, err = getDefsByPackNameViaHTTP(r); err != nil {
if o.Cnf.IsFetchViaHTTP() {
if relatedDefs, err = getDefsByPackNameViaHTTP(r, o.Cnf.GetURL()); err != nil {
return 0, err
}
} else {
driver, err := newOvalDB(o.Cnf, r.Family)
if err != nil {
return 0, err
}
defer func() {
if err := driver.CloseDB(); err != nil {
logging.Log.Errorf("Failed to close DB. err: %+v")
}
}()
if relatedDefs, err = getDefsByPackNameFromOvalDB(driver, r); err != nil {
return 0, err
}

View File

@@ -11,7 +11,6 @@ import (
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/util"
"github.com/kotakanbe/goval-dictionary/db"
ovalmodels "github.com/kotakanbe/goval-dictionary/models"
)
@@ -111,18 +110,19 @@ type Debian struct {
}
// NewDebian creates OVAL client for Debian
func NewDebian() Debian {
func NewDebian(cnf config.VulnDictInterface) Debian {
return Debian{
DebianBase{
Base{
family: constant.Debian,
Cnf: cnf,
},
},
}
}
// FillWithOval returns scan result after updating CVE info by OVAL
func (o Debian) FillWithOval(driver db.DB, r *models.ScanResult) (nCVEs int, err error) {
func (o Debian) FillWithOval(r *models.ScanResult) (nCVEs int, err error) {
//Debian's uname gives both of kernel release(uname -r), version(kernel-image version)
linuxImage := "linux-image-" + r.RunningKernel.Release
@@ -141,19 +141,29 @@ func (o Debian) FillWithOval(driver db.DB, r *models.ScanResult) (nCVEs int, err
}
var relatedDefs ovalResult
if config.Conf.OvalDict.IsFetchViaHTTP() {
if o.Cnf.IsFetchViaHTTP() {
if r.Family != constant.Raspbian {
if relatedDefs, err = getDefsByPackNameViaHTTP(r); err != nil {
if relatedDefs, err = getDefsByPackNameViaHTTP(r, o.Cnf.GetURL()); err != nil {
return 0, err
}
} else {
// OVAL does not support Package for Raspbian, so skip it.
result := r.RemoveRaspbianPackFromResult()
if relatedDefs, err = getDefsByPackNameViaHTTP(&result); err != nil {
if relatedDefs, err = getDefsByPackNameViaHTTP(&result, o.Cnf.GetURL()); err != nil {
return 0, err
}
}
} else {
driver, err := newOvalDB(o.Cnf, r.Family)
if err != nil {
return 0, err
}
defer func() {
if err := driver.CloseDB(); err != nil {
logging.Log.Errorf("Failed to close DB. err: %+v")
}
}()
if r.Family != constant.Raspbian {
if relatedDefs, err = getDefsByPackNameFromOvalDB(driver, r); err != nil {
return 0, err
@@ -201,18 +211,19 @@ type Ubuntu struct {
}
// NewUbuntu creates OVAL client for Debian
func NewUbuntu() Ubuntu {
func NewUbuntu(cnf config.VulnDictInterface) Ubuntu {
return Ubuntu{
DebianBase{
Base{
family: constant.Ubuntu,
Cnf: cnf,
},
},
}
}
// FillWithOval returns scan result after updating CVE info by OVAL
func (o Ubuntu) FillWithOval(driver db.DB, r *models.ScanResult) (nCVEs int, err error) {
func (o Ubuntu) FillWithOval(r *models.ScanResult) (nCVEs int, err error) {
switch util.Major(r.Release) {
case "14":
kernelNamesInOval := []string{
@@ -228,7 +239,7 @@ func (o Ubuntu) FillWithOval(driver db.DB, r *models.ScanResult) (nCVEs int, err
"linux-signed-lts-xenial",
"linux",
}
return o.fillWithOval(driver, r, kernelNamesInOval)
return o.fillWithOval(r, kernelNamesInOval)
case "16":
kernelNamesInOval := []string{
"linux-aws",
@@ -263,7 +274,7 @@ func (o Ubuntu) FillWithOval(driver db.DB, r *models.ScanResult) (nCVEs int, err
"linux-snapdragon",
"linux",
}
return o.fillWithOval(driver, r, kernelNamesInOval)
return o.fillWithOval(r, kernelNamesInOval)
case "18":
kernelNamesInOval := []string{
"linux-aws",
@@ -318,7 +329,7 @@ func (o Ubuntu) FillWithOval(driver db.DB, r *models.ScanResult) (nCVEs int, err
"linux-snapdragon",
"linux",
}
return o.fillWithOval(driver, r, kernelNamesInOval)
return o.fillWithOval(r, kernelNamesInOval)
case "20":
kernelNamesInOval := []string{
"linux-aws",
@@ -346,12 +357,12 @@ func (o Ubuntu) FillWithOval(driver db.DB, r *models.ScanResult) (nCVEs int, err
"linux-signed-oracle",
"linux",
}
return o.fillWithOval(driver, r, kernelNamesInOval)
return o.fillWithOval(r, kernelNamesInOval)
}
return 0, fmt.Errorf("Ubuntu %s is not support for now", r.Release)
}
func (o Ubuntu) fillWithOval(driver db.DB, r *models.ScanResult, kernelNamesInOval []string) (nCVEs int, err error) {
func (o Ubuntu) fillWithOval(r *models.ScanResult, kernelNamesInOval []string) (nCVEs int, err error) {
linuxImage := "linux-image-" + r.RunningKernel.Release
runningKernelVersion := ""
kernelPkgInOVAL := ""
@@ -417,11 +428,21 @@ func (o Ubuntu) fillWithOval(driver db.DB, r *models.ScanResult, kernelNamesInOv
}
var relatedDefs ovalResult
if config.Conf.OvalDict.IsFetchViaHTTP() {
if relatedDefs, err = getDefsByPackNameViaHTTP(r); err != nil {
if o.Cnf.IsFetchViaHTTP() {
if relatedDefs, err = getDefsByPackNameViaHTTP(r, o.Cnf.GetURL()); err != nil {
return 0, err
}
} else {
driver, err := newOvalDB(o.Cnf, r.Family)
if err != nil {
return 0, err
}
defer func() {
if err := driver.CloseDB(); err != nil {
logging.Log.Errorf("Failed to close DB. err: %+v")
}
}()
if relatedDefs, err = getDefsByPackNameFromOvalDB(driver, r); err != nil {
return 0, err
}

View File

@@ -6,7 +6,7 @@ import (
"encoding/json"
"time"
cnf "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/util"
@@ -17,29 +17,43 @@ import (
// Client is the interface of OVAL client.
type Client interface {
FillWithOval(db.DB, *models.ScanResult) (int, error)
// CheckIfOvalFetched checks if oval entries are in DB by family, release.
CheckIfOvalFetched(db.DB, string, string) (bool, error)
CheckIfOvalFresh(db.DB, string, string) (bool, error)
FillWithOval(*models.ScanResult) (int, error)
CheckIfOvalFetched(string, string) (bool, error)
CheckIfOvalFresh(string, string) (bool, error)
}
// Base is a base struct
type Base struct {
family string
Cnf config.VulnDictInterface
}
// CheckIfOvalFetched checks if oval entries are in DB by family, release.
func (b Base) CheckIfOvalFetched(driver db.DB, osFamily, release string) (fetched bool, err error) {
if !cnf.Conf.OvalDict.IsFetchViaHTTP() {
count, err := driver.CountDefs(osFamily, release)
func (b Base) CheckIfOvalFetched(osFamily, release string) (fetched bool, err error) {
ovalFamily, err := GetFamilyInOval(osFamily)
if err != nil {
return false, err
}
if !b.Cnf.IsFetchViaHTTP() {
driver, err := newOvalDB(b.Cnf, ovalFamily)
if err != nil {
return false, xerrors.Errorf("Failed to count OVAL defs: %s, %s, %w", osFamily, release, err)
return false, err
}
defer func() {
if err := driver.CloseDB(); err != nil {
logging.Log.Errorf("Failed to close DB. err: %+v")
}
}()
count, err := driver.CountDefs(ovalFamily, release)
if err != nil {
return false, xerrors.Errorf("Failed to count OVAL defs: %s, %s, %w", ovalFamily, release, err)
}
logging.Log.Infof("OVAL %s %s found. defs: %d", osFamily, release, count)
return 0 < count, nil
}
url, _ := util.URLPathJoin(cnf.Conf.OvalDict.URL, "count", osFamily, release)
url, _ := util.URLPathJoin(config.Conf.OvalDict.URL, "count", ovalFamily, release)
resp, body, errs := gorequest.New().Timeout(10 * time.Second).Get(url).End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
return false, xerrors.Errorf("HTTP GET error, url: %s, resp: %v, err: %+v", url, resp, errs)
@@ -48,16 +62,30 @@ func (b Base) CheckIfOvalFetched(driver db.DB, osFamily, release string) (fetche
if err := json.Unmarshal([]byte(body), &count); err != nil {
return false, xerrors.Errorf("Failed to Unmarshal. body: %s, err: %w", body, err)
}
logging.Log.Infof("OVAL %s %s is fresh. defs: %d", osFamily, release, count)
return 0 < count, nil
}
// CheckIfOvalFresh checks if oval entries are fresh enough
func (b Base) CheckIfOvalFresh(driver db.DB, osFamily, release string) (ok bool, err error) {
func (b Base) CheckIfOvalFresh(osFamily, release string) (ok bool, err error) {
ovalFamily, err := GetFamilyInOval(osFamily)
if err != nil {
return false, err
}
var lastModified time.Time
if !cnf.Conf.OvalDict.IsFetchViaHTTP() {
lastModified = driver.GetLastModified(osFamily, release)
if !b.Cnf.IsFetchViaHTTP() {
driver, err := newOvalDB(b.Cnf, ovalFamily)
if err != nil {
return false, err
}
defer func() {
if err := driver.CloseDB(); err != nil {
logging.Log.Errorf("Failed to close DB. err: %+v")
}
}()
lastModified = driver.GetLastModified(ovalFamily, release)
} else {
url, _ := util.URLPathJoin(cnf.Conf.OvalDict.URL, "lastmodified", osFamily, release)
url, _ := util.URLPathJoin(config.Conf.OvalDict.URL, "lastmodified", ovalFamily, release)
resp, body, errs := gorequest.New().Timeout(10 * time.Second).Get(url).End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
return false, xerrors.Errorf("HTTP GET error, url: %s, resp: %v, err: %+v", url, resp, errs)
@@ -75,6 +103,33 @@ func (b Base) CheckIfOvalFresh(driver db.DB, osFamily, release string) (ok bool,
osFamily, release, lastModified)
return false, nil
}
logging.Log.Infof("OVAL is fresh: %s %s ", osFamily, release)
logging.Log.Infof("OVAL %s %s is fresh. lastModified: %s", osFamily, release, lastModified.Format(time.RFC3339))
return true, nil
}
// NewOvalDB returns oval db client
func newOvalDB(cnf config.VulnDictInterface, familyInScanResult string) (driver db.DB, err error) {
if cnf.IsFetchViaHTTP() {
return nil, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
ovalFamily, err := GetFamilyInOval(familyInScanResult)
if err != nil {
return nil, err
}
driver, locked, err := db.NewDB(ovalFamily, cnf.GetType(), path, cnf.GetDebugSQL())
if err != nil {
if locked {
err = xerrors.Errorf("SQLite3: %s is locked. err: %w", cnf.GetSQLite3Path(), err)
}
err = xerrors.Errorf("Failed to new OVAL DB. err: %w", err)
return nil, err
}
return driver, nil
}

View File

@@ -11,7 +11,6 @@ import (
"github.com/future-architect/vuls/constant"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/kotakanbe/goval-dictionary/db"
ovalmodels "github.com/kotakanbe/goval-dictionary/models"
)
@@ -21,18 +20,29 @@ type RedHatBase struct {
}
// FillWithOval returns scan result after updating CVE info by OVAL
func (o RedHatBase) FillWithOval(driver db.DB, r *models.ScanResult) (nCVEs int, err error) {
func (o RedHatBase) FillWithOval(r *models.ScanResult) (nCVEs int, err error) {
var relatedDefs ovalResult
if config.Conf.OvalDict.IsFetchViaHTTP() {
if relatedDefs, err = getDefsByPackNameViaHTTP(r); err != nil {
if o.Cnf.IsFetchViaHTTP() {
if relatedDefs, err = getDefsByPackNameViaHTTP(r, o.Cnf.GetURL()); err != nil {
return 0, err
}
} else {
driver, err := newOvalDB(o.Cnf, r.Family)
if err != nil {
return 0, err
}
defer func() {
if err := driver.CloseDB(); err != nil {
logging.Log.Errorf("Failed to close DB. err: %+v")
}
}()
if relatedDefs, err = getDefsByPackNameFromOvalDB(driver, r); err != nil {
return 0, err
}
}
relatedDefs.Sort()
for _, defPacks := range relatedDefs.entries {
nCVEs += o.update(r, defPacks)
}
@@ -92,7 +102,7 @@ func (o RedHatBase) update(r *models.ScanResult, defPacks defPacks) (nCVEs int)
ovalContent := *o.convertToModel(cve.CveID, &defPacks.def)
vinfo, ok := r.ScannedCves[cve.CveID]
if !ok {
logging.Log.Debugf("%s is newly detected by OVAL", cve.CveID)
logging.Log.Debugf("%s is newly detected by OVAL: DefID: %s", cve.CveID, defPacks.def.DefinitionID)
vinfo = models.VulnInfo{
CveID: cve.CveID,
Confidences: models.Confidences{models.OvalMatch},
@@ -103,13 +113,12 @@ func (o RedHatBase) update(r *models.ScanResult, defPacks defPacks) (nCVEs int)
cveContents := vinfo.CveContents
if v, ok := vinfo.CveContents[ctype]; ok {
if v.LastModified.After(ovalContent.LastModified) {
logging.Log.Debugf("%s, OvalID: %d ignored: ",
cve.CveID, defPacks.def.ID)
logging.Log.Debugf("%s ignored. DefID: %s ", cve.CveID, defPacks.def.DefinitionID)
} else {
logging.Log.Debugf("%s OVAL will be overwritten", cve.CveID)
logging.Log.Debugf("%s OVAL will be overwritten. DefID: %s", cve.CveID, defPacks.def.DefinitionID)
}
} else {
logging.Log.Debugf("%s also detected by OVAL", cve.CveID)
logging.Log.Debugf("%s also detected by OVAL. DefID: %s", cve.CveID, defPacks.def.DefinitionID)
cveContents = models.CveContents{}
}
@@ -247,11 +256,12 @@ type RedHat struct {
}
// NewRedhat creates OVAL client for Redhat
func NewRedhat() RedHat {
func NewRedhat(cnf config.VulnDictInterface) RedHat {
return RedHat{
RedHatBase{
Base{
family: constant.RedHat,
Cnf: cnf,
},
},
}
@@ -263,11 +273,12 @@ type CentOS struct {
}
// NewCentOS creates OVAL client for CentOS
func NewCentOS() CentOS {
func NewCentOS(cnf config.VulnDictInterface) CentOS {
return CentOS{
RedHatBase{
Base{
family: constant.CentOS,
Cnf: cnf,
},
},
}
@@ -279,11 +290,12 @@ type Oracle struct {
}
// NewOracle creates OVAL client for Oracle
func NewOracle() Oracle {
func NewOracle(cnf config.VulnDictInterface) Oracle {
return Oracle{
RedHatBase{
Base{
family: constant.Oracle,
Cnf: cnf,
},
},
}
@@ -296,11 +308,12 @@ type Amazon struct {
}
// NewAmazon creates OVAL client for Amazon Linux
func NewAmazon() Amazon {
func NewAmazon(cnf config.VulnDictInterface) Amazon {
return Amazon{
RedHatBase{
Base{
family: constant.Amazon,
Cnf: cnf,
},
},
}

View File

@@ -7,7 +7,6 @@ import (
"github.com/future-architect/vuls/constant"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/kotakanbe/goval-dictionary/db"
ovalmodels "github.com/kotakanbe/goval-dictionary/models"
)
@@ -17,23 +16,34 @@ type SUSE struct {
}
// NewSUSE creates OVAL client for SUSE
func NewSUSE() SUSE {
func NewSUSE(cnf config.VulnDictInterface) SUSE {
// TODO implement other family
return SUSE{
Base{
family: constant.SUSEEnterpriseServer,
Cnf: cnf,
},
}
}
// FillWithOval returns scan result after updating CVE info by OVAL
func (o SUSE) FillWithOval(driver db.DB, r *models.ScanResult) (nCVEs int, err error) {
func (o SUSE) FillWithOval(r *models.ScanResult) (nCVEs int, err error) {
var relatedDefs ovalResult
if config.Conf.OvalDict.IsFetchViaHTTP() {
if relatedDefs, err = getDefsByPackNameViaHTTP(r); err != nil {
if o.Cnf.IsFetchViaHTTP() {
if relatedDefs, err = getDefsByPackNameViaHTTP(r, o.Cnf.GetURL()); err != nil {
return 0, err
}
} else {
driver, err := newOvalDB(o.Cnf, r.Family)
if err != nil {
return 0, err
}
defer func() {
if err := driver.CloseDB(); err != nil {
logging.Log.Errorf("Failed to close DB. err: %+v")
}
}()
if relatedDefs, err = getDefsByPackNameFromOvalDB(driver, r); err != nil {
return 0, err
}

View File

@@ -6,6 +6,7 @@ import (
"encoding/json"
"net/http"
"regexp"
"sort"
"time"
"github.com/cenkalti/backoff"
@@ -72,6 +73,12 @@ func (e *ovalResult) upsert(def ovalmodels.Definition, packName string, fstat fi
return false
}
func (e *ovalResult) Sort() {
sort.SliceStable(e.entries, func(i, j int) bool {
return e.entries[i].def.DefinitionID < e.entries[j].def.DefinitionID
})
}
type request struct {
packName string
versionRelease string
@@ -88,8 +95,7 @@ type response struct {
}
// getDefsByPackNameViaHTTP fetches OVAL information via HTTP
func getDefsByPackNameViaHTTP(r *models.ScanResult) (
relatedDefs ovalResult, err error) {
func getDefsByPackNameViaHTTP(r *models.ScanResult, url string) (relatedDefs ovalResult, err error) {
nReq := len(r.Packages) + len(r.SrcPackages)
reqChan := make(chan request, nReq)
@@ -127,7 +133,7 @@ func getDefsByPackNameViaHTTP(r *models.ScanResult) (
select {
case req := <-reqChan:
url, err := util.URLPathJoin(
config.Conf.OvalDict.URL,
url,
"packs",
r.Family,
r.Release,
@@ -190,7 +196,6 @@ func httpGet(url string, req request, resChan chan<- response, errChan chan<- er
var resp *http.Response
count, retryMax := 0, 3
f := func() (err error) {
// resp, body, errs = gorequest.New().SetDebug(config.Conf.Debug).Get(url).End()
resp, body, errs = gorequest.New().Timeout(10 * time.Second).Get(url).End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
count++
@@ -246,13 +251,18 @@ func getDefsByPackNameFromOvalDB(driver db.DB, r *models.ScanResult) (relatedDef
})
}
ovalFamily, err := GetFamilyInOval(r.Family)
if err != nil {
return relatedDefs, err
}
for _, req := range requests {
definitions, err := driver.GetByPackName(r.Family, r.Release, req.packName, req.arch)
definitions, err := driver.GetByPackName(ovalFamily, r.Release, req.packName, req.arch)
if err != nil {
return relatedDefs, xerrors.Errorf("Failed to get %s OVAL info by package: %#v, err: %w", r.Family, req, err)
}
for _, def := range definitions {
affected, notFixedYet, fixedIn := isOvalDefAffected(def, req, r.Family, r.RunningKernel, r.EnabledDnfModules)
affected, notFixedYet, fixedIn := isOvalDefAffected(def, req, ovalFamily, r.RunningKernel, r.EnabledDnfModules)
if !affected {
continue
}
@@ -414,3 +424,71 @@ var centosVerPattern = regexp.MustCompile(`\.[es]l(\d+)(?:_\d+)?(?:\.centos)?`)
func centOSVersionToRHEL(ver string) string {
return centosVerPattern.ReplaceAllString(ver, ".el$1")
}
// NewOVALClient returns a client for OVAL database
func NewOVALClient(family string, cnf config.GovalDictConf) (Client, error) {
switch family {
case constant.Debian, constant.Raspbian:
return NewDebian(&cnf), nil
case constant.Ubuntu:
return NewUbuntu(&cnf), nil
case constant.RedHat:
return NewRedhat(&cnf), nil
case constant.CentOS:
//use RedHat's OVAL
return NewCentOS(&cnf), nil
case constant.Oracle:
return NewOracle(&cnf), nil
case constant.SUSEEnterpriseServer:
// TODO other suse family
return NewSUSE(&cnf), nil
case constant.Alpine:
return NewAlpine(&cnf), nil
case constant.Amazon:
return NewAmazon(&cnf), nil
case constant.FreeBSD, constant.Windows:
return nil, nil
case constant.ServerTypePseudo:
return nil, nil
default:
if family == "" {
return nil, xerrors.New("Probably an error occurred during scanning. Check the error message")
}
return nil, xerrors.Errorf("OVAL for %s is not implemented yet", family)
}
}
// GetFamilyInOval returns the OS family name in OVAL
// For example, CentOS uses Red Hat's OVAL, so return 'redhat'
func GetFamilyInOval(familyInScanResult string) (string, error) {
switch familyInScanResult {
case constant.Debian, constant.Raspbian:
return constant.Debian, nil
case constant.Ubuntu:
return constant.Ubuntu, nil
case constant.RedHat:
return constant.RedHat, nil
case constant.CentOS:
//use RedHat's OVAL
return constant.RedHat, nil
case constant.Oracle:
return constant.Oracle, nil
case constant.SUSEEnterpriseServer:
// TODO other suse family
return constant.SUSEEnterpriseServer, nil
case constant.Alpine:
return constant.Alpine, nil
case constant.Amazon:
return constant.Amazon, nil
case constant.FreeBSD, constant.Windows:
return "", nil
case constant.ServerTypePseudo:
return "", nil
default:
if familyInScanResult == "" {
return "", xerrors.New("Probably an error occurred during scanning. Check the error message")
}
return "", xerrors.Errorf("OVAL for %s is not implemented yet", familyInScanResult)
}
}

View File

@@ -1281,3 +1281,57 @@ func Test_lessThan(t *testing.T) {
})
}
}
func Test_ovalResult_Sort(t *testing.T) {
type fields struct {
entries []defPacks
}
tests := []struct {
name string
fields fields
want fields
}{
{
name: "already sorted",
fields: fields{
entries: []defPacks{
{def: ovalmodels.Definition{DefinitionID: "0"}},
{def: ovalmodels.Definition{DefinitionID: "1"}},
},
},
want: fields{
entries: []defPacks{
{def: ovalmodels.Definition{DefinitionID: "0"}},
{def: ovalmodels.Definition{DefinitionID: "1"}},
},
},
},
{
name: "sort",
fields: fields{
entries: []defPacks{
{def: ovalmodels.Definition{DefinitionID: "1"}},
{def: ovalmodels.Definition{DefinitionID: "0"}},
},
},
want: fields{
entries: []defPacks{
{def: ovalmodels.Definition{DefinitionID: "0"}},
{def: ovalmodels.Definition{DefinitionID: "1"}},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
o := &ovalResult{
entries: tt.fields.entries,
}
o.Sort()
if !reflect.DeepEqual(o.entries, tt.want.entries) {
t.Errorf("act %#v, want %#v", o.entries, tt.want.entries)
}
})
}
}

View File

@@ -9,7 +9,7 @@ import (
storage "github.com/Azure/azure-sdk-for-go/storage"
"golang.org/x/xerrors"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
)
@@ -21,7 +21,7 @@ type AzureBlobWriter struct {
FormatList bool
Gzip bool
c.AzureConf
config.AzureConf
}
// Write results to Azure Blob storage

View File

@@ -15,14 +15,16 @@ import (
)
// ChatWorkWriter send report to ChatWork
type ChatWorkWriter struct{}
type ChatWorkWriter struct {
Cnf config.ChatWorkConf
Proxy string
}
func (w ChatWorkWriter) Write(rs ...models.ScanResult) (err error) {
conf := config.Conf.ChatWork
for _, r := range rs {
serverInfo := fmt.Sprintf("%s", r.ServerInfo())
if err = chatWorkpostMessage(conf.Room, conf.APIToken, serverInfo); err != nil {
if err = w.chatWorkpostMessage(serverInfo); err != nil {
return err
}
@@ -40,7 +42,7 @@ func (w ChatWorkWriter) Write(rs ...models.ScanResult) (err error) {
severity,
vinfo.Summaries(r.Lang, r.Family)[0].Value)
if err = chatWorkpostMessage(conf.Room, conf.APIToken, message); err != nil {
if err = w.chatWorkpostMessage(message); err != nil {
return err
}
}
@@ -49,8 +51,8 @@ func (w ChatWorkWriter) Write(rs ...models.ScanResult) (err error) {
return nil
}
func chatWorkpostMessage(room, token, message string) error {
uri := fmt.Sprintf("https://api.chatwork.com/v2/rooms/%s/messages=%s", room, token)
func (w ChatWorkWriter) chatWorkpostMessage(message string) error {
uri := fmt.Sprintf("https://api.chatwork.com/v2/rooms/%s/messages=%s", w.Cnf.Room, w.Cnf.APIToken)
payload := url.Values{"body": {message}}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
@@ -59,10 +61,9 @@ func chatWorkpostMessage(room, token, message string) error {
if err != nil {
return err
}
req.Header.Add("X-ChatWorkToken", token)
req.Header.Add("X-ChatWorkToken", w.Cnf.APIToken)
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
client, err := util.GetHTTPClient(config.Conf.HTTPProxy)
client, err := util.GetHTTPClient(w.Proxy)
if err != nil {
return err
}

View File

@@ -20,12 +20,12 @@ type EMailWriter struct {
FormatOneEMail bool
FormatOneLineText bool
FormatList bool
Cnf config.SMTPConf
}
func (w EMailWriter) Write(rs ...models.ScanResult) (err error) {
conf := config.Conf
var message string
sender := NewEMailSender()
sender := NewEMailSender(w.Cnf)
m := map[string]int{}
for _, r := range rs {
if w.FormatOneEMail {
@@ -39,10 +39,10 @@ func (w EMailWriter) Write(rs ...models.ScanResult) (err error) {
var subject string
if len(r.Errors) != 0 {
subject = fmt.Sprintf("%s%s An error occurred while scanning",
conf.EMail.SubjectPrefix, r.ServerInfo())
w.Cnf.SubjectPrefix, r.ServerInfo())
} else {
subject = fmt.Sprintf("%s%s %s",
conf.EMail.SubjectPrefix,
w.Cnf.SubjectPrefix,
r.ServerInfo(),
r.ScannedCves.FormatCveSummary())
}
@@ -72,7 +72,7 @@ func (w EMailWriter) Write(rs ...models.ScanResult) (err error) {
}
subject := fmt.Sprintf("%s %s",
conf.EMail.SubjectPrefix, summary)
w.Cnf.SubjectPrefix, summary)
return sender.Send(subject, message)
}
return nil
@@ -196,8 +196,8 @@ func (e *emailSender) Send(subject, body string) (err error) {
}
// NewEMailSender creates emailSender
func NewEMailSender() EMailSender {
return &emailSender{config.Conf.EMail}
func NewEMailSender(cnf config.SMTPConf) EMailSender {
return &emailSender{cnf}
}
func (e *emailSender) newSaslClient(authList []string) sasl.Client {

View File

@@ -5,13 +5,14 @@ import (
"encoding/json"
"net/http"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
"golang.org/x/xerrors"
)
// HTTPRequestWriter writes results to HTTP request
type HTTPRequestWriter struct{}
type HTTPRequestWriter struct {
Proxy string
}
// Write sends results as HTTP response
func (w HTTPRequestWriter) Write(rs ...models.ScanResult) (err error) {
@@ -20,7 +21,7 @@ func (w HTTPRequestWriter) Write(rs ...models.ScanResult) (err error) {
if err := json.NewEncoder(b).Encode(r); err != nil {
return err
}
_, err = http.Post(config.Conf.HTTP.URL, "application/json; charset=utf-8", b)
_, err = http.Post(w.Proxy, "application/json; charset=utf-8", b)
if err != nil {
return err
}

View File

@@ -35,8 +35,9 @@ func (w LocalFileWriter) Write(rs ...models.ScanResult) (err error) {
}
for _, r := range rs {
path := filepath.Join(w.CurrentDir, r.ReportFileName())
r.SortForJSONOutput()
path := filepath.Join(w.CurrentDir, r.ReportFileName())
if w.FormatJSON {
p := path + ".json"
if w.DiffPlus || w.DiffMinus {

View File

@@ -15,7 +15,7 @@ import (
"github.com/aws/aws-sdk-go/service/s3"
"golang.org/x/xerrors"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/models"
)
@@ -27,7 +27,7 @@ type S3Writer struct {
FormatList bool
Gzip bool
c.AWSConf
config.AWSConf
}
func (w S3Writer) getS3() (*s3.S3, error) {

View File

@@ -21,6 +21,8 @@ type SlackWriter struct {
FormatOneLineText bool
lang string
osFamily string
Cnf config.SlackConf
Proxy string
}
type message struct {
@@ -32,10 +34,8 @@ type message struct {
}
func (w SlackWriter) Write(rs ...models.ScanResult) (err error) {
conf := config.Conf.Slack
channel := conf.Channel
token := conf.LegacyToken
channel := w.Cnf.Channel
for _, r := range rs {
w.lang, w.osFamily = r.Lang, r.Family
if channel == "${servername}" {
@@ -57,15 +57,15 @@ func (w SlackWriter) Write(rs ...models.ScanResult) (err error) {
sort.Ints(chunkKeys)
summary := fmt.Sprintf("%s\n%s",
w.getNotifyUsers(config.Conf.Slack.NotifyUsers),
w.getNotifyUsers(w.Cnf.NotifyUsers),
formatOneLineSummary(r))
// Send slack by API
if 0 < len(token) {
api := slack.New(token)
if 0 < len(w.Cnf.LegacyToken) {
api := slack.New(w.Cnf.LegacyToken)
msgPrms := slack.PostMessageParameters{
Username: conf.AuthUser,
IconEmoji: conf.IconEmoji,
Username: w.Cnf.AuthUser,
IconEmoji: w.Cnf.IconEmoji,
}
var ts string
@@ -83,8 +83,8 @@ func (w SlackWriter) Write(rs ...models.ScanResult) (err error) {
for _, k := range chunkKeys {
params := slack.PostMessageParameters{
Username: conf.AuthUser,
IconEmoji: conf.IconEmoji,
Username: w.Cnf.AuthUser,
IconEmoji: w.Cnf.IconEmoji,
ThreadTimestamp: ts,
}
if _, _, err = api.PostMessage(
@@ -99,8 +99,8 @@ func (w SlackWriter) Write(rs ...models.ScanResult) (err error) {
} else {
msg := message{
Text: summary,
Username: conf.AuthUser,
IconEmoji: conf.IconEmoji,
Username: w.Cnf.AuthUser,
IconEmoji: w.Cnf.IconEmoji,
Channel: channel,
}
if err := w.send(msg); err != nil {
@@ -119,8 +119,8 @@ func (w SlackWriter) Write(rs ...models.ScanResult) (err error) {
msg := message{
Text: txt,
Username: conf.AuthUser,
IconEmoji: conf.IconEmoji,
Username: w.Cnf.AuthUser,
IconEmoji: w.Cnf.IconEmoji,
Channel: channel,
Attachments: m[k],
}
@@ -134,14 +134,13 @@ func (w SlackWriter) Write(rs ...models.ScanResult) (err error) {
}
func (w SlackWriter) send(msg message) error {
conf := config.Conf.Slack
count, retryMax := 0, 10
count, retryMax := 0, 10
bytes, _ := json.Marshal(msg)
jsonBody := string(bytes)
f := func() (err error) {
resp, body, errs := gorequest.New().Timeout(10 * time.Second).Proxy(config.Conf.HTTPProxy).Post(conf.HookURL).Send(string(jsonBody)).End()
resp, body, errs := gorequest.New().Timeout(10 * time.Second).Proxy(w.Proxy).Post(w.Cnf.HookURL).Send(string(jsonBody)).End()
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
count++
if count == retryMax {
@@ -149,7 +148,7 @@ func (w SlackWriter) send(msg message) error {
}
return xerrors.Errorf(
"HTTP POST error. url: %s, resp: %v, body: %s, err: %+v",
conf.HookURL, resp, body, errs)
w.Cnf.HookURL, resp, body, errs)
}
return nil
}

View File

@@ -12,15 +12,16 @@ import (
)
// SyslogWriter send report to syslog
type SyslogWriter struct{}
type SyslogWriter struct {
Cnf config.SyslogConf
}
func (w SyslogWriter) Write(rs ...models.ScanResult) (err error) {
conf := config.Conf.Syslog
facility, _ := conf.GetFacility()
severity, _ := conf.GetSeverity()
raddr := fmt.Sprintf("%s:%s", conf.Host, conf.Port)
facility, _ := w.Cnf.GetFacility()
severity, _ := w.Cnf.GetSeverity()
raddr := fmt.Sprintf("%s:%s", w.Cnf.Host, w.Cnf.Port)
sysLog, err := syslog.Dial(conf.Protocol, raddr, severity|facility, conf.Tag)
sysLog, err := syslog.Dial(w.Cnf.Protocol, raddr, severity|facility, w.Cnf.Tag)
if err != nil {
return xerrors.Errorf("Failed to initialize syslog client: %w", err)
}
@@ -72,7 +73,7 @@ func (w SyslogWriter) encodeSyslog(result models.ScanResult) (messages []string)
if content, ok := vinfo.CveContents[models.Nvd]; ok {
cwes := strings.Join(content.CweIDs, ",")
kvPairs = append(kvPairs, fmt.Sprintf(`cwe_ids="%s"`, cwes))
if config.Conf.Syslog.Verbose {
if w.Cnf.Verbose {
kvPairs = append(kvPairs, fmt.Sprintf(`source_link="%s"`, content.SourceLink))
kvPairs = append(kvPairs, fmt.Sprintf(`summary="%s"`, content.Summary))
}

View File

@@ -16,10 +16,12 @@ import (
)
// TelegramWriter sends report to Telegram
type TelegramWriter struct{}
type TelegramWriter struct {
Cnf config.TelegramConf
Proxy string
}
func (w TelegramWriter) Write(rs ...models.ScanResult) (err error) {
conf := config.Conf.Telegram
for _, r := range rs {
msgs := []string{fmt.Sprintf("*%s*\n%s\n%s\n%s",
r.ServerInfo(),
@@ -40,14 +42,14 @@ func (w TelegramWriter) Write(rs ...models.ScanResult) (err error) {
maxCvss.Value.Vector,
vinfo.Summaries(r.Lang, r.Family)[0].Value))
if len(msgs) == 5 {
if err = sendMessage(conf.ChatID, conf.Token, strings.Join(msgs, "\n\n")); err != nil {
if err = w.sendMessage(w.Cnf.ChatID, w.Cnf.Token, strings.Join(msgs, "\n\n")); err != nil {
return err
}
msgs = []string{}
}
}
if len(msgs) != 0 {
if err = sendMessage(conf.ChatID, conf.Token, strings.Join(msgs, "\n\n")); err != nil {
if err = w.sendMessage(w.Cnf.ChatID, w.Cnf.Token, strings.Join(msgs, "\n\n")); err != nil {
return err
}
}
@@ -55,7 +57,7 @@ func (w TelegramWriter) Write(rs ...models.ScanResult) (err error) {
return nil
}
func sendMessage(chatID, token, message string) error {
func (w TelegramWriter) sendMessage(chatID, token, message string) error {
uri := fmt.Sprintf("https://api.telegram.org/bot%s/sendMessage", token)
payload := `{"text": "` + strings.Replace(message, `"`, `\"`, -1) + `", "chat_id": "` + chatID + `", "parse_mode": "Markdown" }`
@@ -67,7 +69,7 @@ func sendMessage(chatID, token, message string) error {
}
req.Header.Add("Content-Type", "application/json")
client, err := util.GetHTTPClient(config.Conf.HTTPProxy)
client, err := util.GetHTTPClient(w.Proxy)
if err != nil {
return err
}

View File

@@ -85,16 +85,15 @@ var jsonDirPattern = regexp.MustCompile(
// ListValidJSONDirs returns valid json directory as array
// Returned array is sorted so that recent directories are at the head
func ListValidJSONDirs() (dirs []string, err error) {
func ListValidJSONDirs(resultsDir string) (dirs []string, err error) {
var dirInfo []os.FileInfo
if dirInfo, err = ioutil.ReadDir(config.Conf.ResultsDir); err != nil {
err = xerrors.Errorf("Failed to read %s: %w",
config.Conf.ResultsDir, err)
if dirInfo, err = ioutil.ReadDir(resultsDir); err != nil {
err = xerrors.Errorf("Failed to read %s: %w", resultsDir, err)
return
}
for _, d := range dirInfo {
if d.IsDir() && jsonDirPattern.MatchString(d.Name()) {
jsonDir := filepath.Join(config.Conf.ResultsDir, d.Name())
jsonDir := filepath.Join(resultsDir, d.Name())
dirs = append(dirs, jsonDir)
}
}
@@ -105,19 +104,17 @@ func ListValidJSONDirs() (dirs []string, err error) {
}
// JSONDir returns
// If there is an arg, check if it is a valid format and return the corresponding path under results.
// If there is args, check if it is a valid format and return the corresponding path under results.
// If arg passed via PIPE (such as history subcommand), return that path.
// Otherwise, returns the path of the latest directory
func JSONDir(args []string) (string, error) {
var err error
func JSONDir(resultsDir string, args []string) (path string, err error) {
var dirs []string
if 0 < len(args) {
if dirs, err = ListValidJSONDirs(); err != nil {
if dirs, err = ListValidJSONDirs(resultsDir); err != nil {
return "", err
}
path := filepath.Join(config.Conf.ResultsDir, args[0])
path = filepath.Join(resultsDir, args[0])
for _, d := range dirs {
ss := strings.Split(d, string(os.PathSeparator))
timedir := ss[len(ss)-1]
@@ -125,11 +122,10 @@ func JSONDir(args []string) (string, error) {
return path, nil
}
}
return "", xerrors.Errorf("Invalid path: %s", path)
}
// PIPE
// TODO remove Pipe flag
if config.Conf.Pipe {
bytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
@@ -137,18 +133,17 @@ func JSONDir(args []string) (string, error) {
}
fields := strings.Fields(string(bytes))
if 0 < len(fields) {
return filepath.Join(config.Conf.ResultsDir, fields[0]), nil
return filepath.Join(resultsDir, fields[0]), nil
}
return "", xerrors.Errorf("Stdin is invalid: %s", string(bytes))
}
// returns latest dir when no args or no PIPE
if dirs, err = ListValidJSONDirs(); err != nil {
if dirs, err = ListValidJSONDirs(resultsDir); err != nil {
return "", err
}
if len(dirs) == 0 {
return "", xerrors.Errorf("No results under %s",
config.Conf.ResultsDir)
return "", xerrors.Errorf("No results under %s", resultsDir)
}
return dirs[0], nil
}
@@ -224,6 +219,7 @@ func formatOneLineSummary(rs ...models.ScanResult) string {
}
}
// We don't want warning message to the summary file
// TODO Don't use global variable
if config.Conf.Quiet {
return fmt.Sprintf("%s\n", table)
}
@@ -483,7 +479,7 @@ No CVE-IDs are found in updatable packages.
}
for _, alert := range vuln.AlertDict.En {
data = append(data, []string{"USCERT Alert", alert.URL})
data = append(data, []string{"US-CERT Alert", alert.URL})
}
// for _, rr := range vuln.CveContents.References(r.Family) {

View File

@@ -18,7 +18,6 @@ import (
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/future-architect/vuls/config"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/util"
@@ -56,8 +55,8 @@ func (w Writer) Write(rs ...models.ScanResult) error {
hostname, _ := os.Hostname()
payload := payload{
GroupID: c.Conf.Saas.GroupID,
Token: c.Conf.Saas.Token,
GroupID: config.Conf.Saas.GroupID,
Token: config.Conf.Saas.Token,
ScannedBy: hostname,
ScannedIPv4s: strings.Join(ipv4s, ", "),
ScannedIPv6s: strings.Join(ipv6s, ", "),
@@ -68,13 +67,14 @@ func (w Writer) Write(rs ...models.ScanResult) error {
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.Conf.Saas.URL, bytes.NewBuffer(body))
req, err := http.NewRequestWithContext(ctx, http.MethodPost, config.Conf.Saas.URL, bytes.NewBuffer(body))
defer cancel()
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
// TODO Don't use global variable
client, err := util.GetHTTPClient(config.Conf.HTTPProxy)
if err != nil {
return err

View File

@@ -9,7 +9,7 @@ import (
"strings"
"github.com/BurntSushi/toml"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/hashicorp/go-uuid"
@@ -18,7 +18,7 @@ import (
// EnsureUUIDs generate a new UUID of the scan target server if UUID is not assigned yet.
// And then set the generated UUID to config.toml and scan results.
func EnsureUUIDs(servers map[string]c.ServerInfo, path string, scanResults models.ScanResults) (err error) {
func EnsureUUIDs(servers map[string]config.ServerInfo, path string, scanResults models.ScanResults) (err error) {
needsOverwrite, err := ensure(servers, path, scanResults, uuid.GenerateUUID)
if err != nil {
return xerrors.Errorf("Failed to ensure UUIDs. err: %w", err)
@@ -27,10 +27,10 @@ func EnsureUUIDs(servers map[string]c.ServerInfo, path string, scanResults model
if !needsOverwrite {
return
}
return writeToFile(c.Conf, path)
return writeToFile(config.Conf, path)
}
func ensure(servers map[string]c.ServerInfo, path string, scanResults models.ScanResults, generateFunc func() (string, error)) (needsOverwrite bool, err error) {
func ensure(servers map[string]config.ServerInfo, path string, scanResults models.ScanResults, generateFunc func() (string, error)) (needsOverwrite bool, err error) {
for i, r := range scanResults {
serverInfo := servers[r.ServerName]
if serverInfo.UUIDs == nil {
@@ -96,7 +96,7 @@ func ensure(servers map[string]c.ServerInfo, path string, scanResults models.Sca
return needsOverwrite, nil
}
func writeToFile(cnf c.Config, path string) error {
func writeToFile(cnf config.Config, path string) error {
for name, server := range cnf.Servers {
server = cleanForTOMLEncoding(server, cnf.Default)
cnf.Servers[name] = server
@@ -106,9 +106,9 @@ func writeToFile(cnf c.Config, path string) error {
}
c := struct {
Saas *c.SaasConf `toml:"saas"`
Default c.ServerInfo `toml:"default"`
Servers map[string]c.ServerInfo `toml:"servers"`
Saas *config.SaasConf `toml:"saas"`
Default config.ServerInfo `toml:"default"`
Servers map[string]config.ServerInfo `toml:"servers"`
}{
Saas: &cnf.Saas,
Default: cnf.Default,
@@ -142,7 +142,7 @@ func writeToFile(cnf c.Config, path string) error {
return ioutil.WriteFile(realPath, []byte(str), 0600)
}
func cleanForTOMLEncoding(server c.ServerInfo, def c.ServerInfo) c.ServerInfo {
func cleanForTOMLEncoding(server config.ServerInfo, def config.ServerInfo) config.ServerInfo {
if reflect.DeepEqual(server.Optional, def.Optional) {
server.Optional = nil
}

View File

@@ -357,17 +357,15 @@ func (l *base) detectDeepSecurity() (string, error) {
return "", xerrors.Errorf("Failed to detect deepsecurity %s", l.ServerInfo.ServerName)
}
func (l *base) detectIPS() {
if !config.Conf.DetectIPS {
return
}
const deepSecurity string = "deepsecurity"
func (l *base) detectIPS() {
ips := map[string]string{}
fingerprint, err := l.detectDeepSecurity()
if err != nil {
return
}
ips[config.DeepSecurity] = fingerprint
ips[deepSecurity] = fingerprint
l.ServerInfo.IPSIdentifiers = ips
}

View File

@@ -11,14 +11,14 @@ import (
"golang.org/x/xerrors"
conf "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
homedir "github.com/mitchellh/go-homedir"
)
type execResult struct {
Servername string
Container conf.Container
Container config.Container
Host string
Port string
Cmd string
@@ -131,7 +131,7 @@ func parallelExec(fn func(osTypeInterface) error, timeoutSec ...int) {
return
}
func exec(c conf.ServerInfo, cmd string, sudo bool, log ...logging.Logger) (result execResult) {
func exec(c config.ServerInfo, cmd string, sudo bool, log ...logging.Logger) (result execResult) {
logger := getSSHLogger(log...)
logger.Debugf("Executing... %s", strings.Replace(cmd, "\n", "", -1))
@@ -149,7 +149,7 @@ func isLocalExec(port, host string) bool {
return port == "local" && (host == "127.0.0.1" || host == "localhost")
}
func localExec(c conf.ServerInfo, cmdstr string, sudo bool) (result execResult) {
func localExec(c config.ServerInfo, cmdstr string, sudo bool) (result execResult) {
cmdstr = decorateCmd(c, cmdstr, sudo)
var cmd *ex.Cmd
switch c.Distro.Family {
@@ -180,7 +180,7 @@ func localExec(c conf.ServerInfo, cmdstr string, sudo bool) (result execResult)
return
}
func sshExecExternal(c conf.ServerInfo, cmd string, sudo bool) (result execResult) {
func sshExecExternal(c config.ServerInfo, cmd string, sudo bool) (result execResult) {
sshBinaryPath, err := ex.LookPath("ssh")
if err != nil {
return execResult{Error: err}
@@ -211,7 +211,7 @@ func sshExecExternal(c conf.ServerInfo, cmd string, sudo bool) (result execResul
)
}
if conf.Conf.Vvv {
if config.Conf.Vvv {
defaultSSHArgs = append(defaultSSHArgs, "-vvv")
}
@@ -276,7 +276,7 @@ func dockerShell(family string) string {
}
}
func decorateCmd(c conf.ServerInfo, cmd string, sudo bool) string {
func decorateCmd(c config.ServerInfo, cmd string, sudo bool) string {
if sudo && c.User != "root" && !c.IsContainer() {
cmd = fmt.Sprintf("sudo -S %s", cmd)
}

View File

@@ -66,12 +66,14 @@ type osTypeInterface interface {
// Scanner has functions for scan
type Scanner struct {
ResultsDir string
TimeoutSec int
ScanTimeoutSec int
CacheDBPath string
Debug bool
LogDir string
Quiet bool
DetectIPS bool
Targets map[string]config.ServerInfo
}
@@ -91,8 +93,10 @@ func (s Scanner) Scan() error {
logging.Log.Info("Detecting Platforms... ")
s.detectPlatform()
logging.Log.Info("Detecting IPS identifiers... ")
s.detectIPS()
if s.DetectIPS {
logging.Log.Info("Detecting IPS identifiers... ")
s.detectIPS()
}
if err := s.execScan(); err != nil {
return xerrors.Errorf("Failed to scan. err: %w", err)
@@ -593,7 +597,7 @@ func (s Scanner) execScan() error {
}()
scannedAt := time.Now()
dir, err := EnsureResultDir(scannedAt)
dir, err := EnsureResultDir(s.ResultsDir, scannedAt)
if err != nil {
return err
}

View File

@@ -7,7 +7,6 @@ import (
"strings"
"time"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/constant"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
@@ -42,11 +41,9 @@ func isRunningKernel(pack models.Package, family string, kernel models.Kernel) (
}
// EnsureResultDir ensures the directory for scan results
func EnsureResultDir(scannedAt time.Time) (currentDir string, err error) {
func EnsureResultDir(resultsDir string, scannedAt time.Time) (currentDir string, err error) {
jsonDirName := scannedAt.Format(time.RFC3339)
resultsDir := config.Conf.ResultsDir
if len(resultsDir) == 0 {
if resultsDir == "" {
wd, _ := os.Getwd()
resultsDir = filepath.Join(wd, "results")
}

View File

@@ -11,7 +11,9 @@ import (
"net/http"
"time"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/detector"
"github.com/future-architect/vuls/gost"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/reporter"
@@ -20,14 +22,13 @@ import (
// VulsHandler is used for vuls server mode
type VulsHandler struct {
DBclient detector.DBClient
ToLocalFile bool
}
// ServeHTTP is http handler
func (h VulsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
var err error
result := models.ScanResult{ScannedCves: models.VulnInfos{}}
r := models.ScanResult{ScannedCves: models.VulnInfos{}}
contentType := req.Header.Get("Content-Type")
mediatype, _, err := mime.ParseMediaType(contentType)
@@ -38,7 +39,7 @@ func (h VulsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
if mediatype == "application/json" {
if err = json.NewDecoder(req.Body).Decode(&result); err != nil {
if err = json.NewDecoder(req.Body).Decode(&r); err != nil {
logging.Log.Error(err)
http.Error(w, "Invalid JSON", http.StatusBadRequest)
return
@@ -49,7 +50,7 @@ func (h VulsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if result, err = scanner.ViaHTTP(req.Header, buf.String(), h.ToLocalFile); err != nil {
if r, err = scanner.ViaHTTP(req.Header, buf.String(), h.ToLocalFile); err != nil {
logging.Log.Error(err)
http.Error(w, err.Error(), http.StatusBadRequest)
return
@@ -60,22 +61,44 @@ func (h VulsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return
}
if err := detector.DetectPkgCves(h.DBclient, &result); err != nil {
if err := detector.DetectPkgCves(&r, config.Conf.OvalDict, config.Conf.Gost); err != nil {
logging.Log.Errorf("Failed to detect Pkg CVE: %+v", err)
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
}
if err := detector.FillCveInfo(h.DBclient, &result); err != nil {
logging.Log.Errorf("Failed to fill CVE detailed info: %+v", err)
logging.Log.Infof("Fill CVE detailed with gost")
if err := gost.FillCVEsWithRedHat(&r, config.Conf.Gost); err != nil {
logging.Log.Errorf("Failed to fill with gost: %+v", err)
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return
}
logging.Log.Infof("Fill CVE detailed with CVE-DB")
if err := detector.FillCvesWithNvdJvn(&r, config.Conf.CveDict, config.Conf.LogOpts); err != nil {
logging.Log.Errorf("Failed to fill with CVE: %+v", err)
http.Error(w, err.Error(), http.StatusServiceUnavailable)
}
nExploitCve, err := detector.FillWithExploit(&r, config.Conf.Exploit)
if err != nil {
logging.Log.Errorf("Failed to fill with exploit: %+v", err)
http.Error(w, err.Error(), http.StatusServiceUnavailable)
}
logging.Log.Infof("%s: %d exploits are detected", r.FormatServerName(), nExploitCve)
nMetasploitCve, err := detector.FillWithMetasploit(&r, config.Conf.Metasploit)
if err != nil {
logging.Log.Errorf("Failed to fill with metasploit: %+v", err)
http.Error(w, err.Error(), http.StatusServiceUnavailable)
}
logging.Log.Infof("%s: %d modules are detected", r.FormatServerName(), nMetasploitCve)
detector.FillCweDict(&r)
// set ReportedAt to current time when it's set to the epoch, ensures that ReportedAt will be set
// properly for scans sent to vuls when running in server mode
if result.ReportedAt.IsZero() {
result.ReportedAt = time.Now()
if r.ReportedAt.IsZero() {
r.ReportedAt = time.Now()
}
// report
@@ -83,12 +106,12 @@ func (h VulsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
reporter.HTTPResponseWriter{Writer: w},
}
if h.ToLocalFile {
scannedAt := result.ScannedAt
scannedAt := r.ScannedAt
if scannedAt.IsZero() {
scannedAt = time.Now().Truncate(1 * time.Hour)
result.ScannedAt = scannedAt
r.ScannedAt = scannedAt
}
dir, err := scanner.EnsureResultDir(scannedAt)
dir, err := scanner.EnsureResultDir(config.Conf.ResultsDir, scannedAt)
if err != nil {
logging.Log.Errorf("Failed to ensure the result directory: %+v", err)
http.Error(w, err.Error(), http.StatusServiceUnavailable)
@@ -103,7 +126,7 @@ func (h VulsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
for _, w := range reports {
if err := w.Write(result); err != nil {
if err := w.Write(r); err != nil {
logging.Log.Errorf("Failed to report. err: %+v", err)
return
}

View File

@@ -10,7 +10,7 @@ import (
"github.com/google/subcommands"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/scanner"
)
@@ -52,8 +52,8 @@ func (p *ConfigtestCmd) SetFlags(f *flag.FlagSet) {
f.StringVar(&p.configPath, "config", defaultConfPath, "/path/to/toml")
defaultLogDir := logging.GetDefaultLogDir()
f.StringVar(&c.Conf.LogDir, "log-dir", defaultLogDir, "/path/to/log")
f.BoolVar(&c.Conf.Debug, "debug", false, "debug mode")
f.StringVar(&config.Conf.LogDir, "log-dir", defaultLogDir, "/path/to/log")
f.BoolVar(&config.Conf.Debug, "debug", false, "debug mode")
f.IntVar(&p.timeoutSec, "timeout", 5*60, "Timeout(Sec)")
@@ -61,16 +61,16 @@ func (p *ConfigtestCmd) SetFlags(f *flag.FlagSet) {
"Ask ssh privatekey password before scanning",
)
f.StringVar(&c.Conf.HTTPProxy, "http-proxy", "",
f.StringVar(&config.Conf.HTTPProxy, "http-proxy", "",
"http://proxy-url:port (default: empty)")
f.BoolVar(&c.Conf.Vvv, "vvv", false, "ssh -vvv")
f.BoolVar(&config.Conf.Vvv, "vvv", false, "ssh -vvv")
}
// Execute execute
func (p *ConfigtestCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
logging.Log = logging.NewCustomLogger(c.Conf.Debug, c.Conf.Quiet, c.Conf.LogDir, "", "")
logging.Log.Infof("vuls-%s-%s", c.Version, c.Revision)
logging.Log = logging.NewCustomLogger(config.Conf.Debug, config.Conf.Quiet, config.Conf.LogDir, "", "")
logging.Log.Infof("vuls-%s-%s", config.Version, config.Revision)
if err := mkdirDotVuls(); err != nil {
logging.Log.Errorf("Failed to create $HOME/.vuls: %+v", err)
@@ -87,7 +87,7 @@ func (p *ConfigtestCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interfa
}
}
err = c.Load(p.configPath, keyPass)
err = config.Load(p.configPath, keyPass)
if err != nil {
msg := []string{
fmt.Sprintf("Error loading %s", p.configPath),
@@ -103,10 +103,10 @@ func (p *ConfigtestCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interfa
servernames = f.Args()
}
targets := make(map[string]c.ServerInfo)
targets := make(map[string]config.ServerInfo)
for _, arg := range servernames {
found := false
for servername, info := range c.Conf.Servers {
for servername, info := range config.Conf.Servers {
if servername == arg {
targets[servername] = info
found = true
@@ -120,14 +120,14 @@ func (p *ConfigtestCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interfa
}
if 0 < len(servernames) {
// if scan target servers are specified by args, set to the config
c.Conf.Servers = targets
config.Conf.Servers = targets
} else {
// if not specified by args, scan all servers in the config
targets = c.Conf.Servers
targets = config.Conf.Servers
}
logging.Log.Info("Validating config...")
if !c.Conf.ValidateOnConfigtest() {
if !config.Conf.ValidateOnConfigtest() {
return subcommands.ExitUsageError
}

View File

@@ -9,7 +9,7 @@ import (
"path/filepath"
"strings"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/reporter"
"github.com/google/subcommands"
)
@@ -35,17 +35,16 @@ func (*HistoryCmd) Usage() string {
// SetFlags set flag
func (p *HistoryCmd) SetFlags(f *flag.FlagSet) {
f.BoolVar(&c.Conf.DebugSQL, "debug-sql", false, "SQL debug mode")
f.BoolVar(&config.Conf.DebugSQL, "debug-sql", false, "SQL debug mode")
wd, _ := os.Getwd()
defaultResultsDir := filepath.Join(wd, "results")
f.StringVar(&c.Conf.ResultsDir, "results-dir", defaultResultsDir, "/path/to/results")
f.StringVar(&config.Conf.ResultsDir, "results-dir", defaultResultsDir, "/path/to/results")
}
// Execute execute
func (p *HistoryCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
dirs, err := reporter.ListValidJSONDirs()
dirs, err := reporter.ListValidJSONDirs(config.Conf.ResultsDir)
if err != nil {
return subcommands.ExitFailure
}

View File

@@ -9,7 +9,7 @@ import (
"path/filepath"
"github.com/aquasecurity/trivy/pkg/utils"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/detector"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
@@ -92,48 +92,48 @@ func (*ReportCmd) Usage() string {
// SetFlags set flag
func (p *ReportCmd) SetFlags(f *flag.FlagSet) {
f.StringVar(&c.Conf.Lang, "lang", "en", "[en|ja]")
f.BoolVar(&c.Conf.Debug, "debug", false, "debug mode")
f.BoolVar(&c.Conf.DebugSQL, "debug-sql", false, "SQL debug mode")
f.BoolVar(&c.Conf.Quiet, "quiet", false, "Quiet mode. No output on stdout")
f.BoolVar(&c.Conf.NoProgress, "no-progress", false, "Suppress progress bar")
f.StringVar(&config.Conf.Lang, "lang", "en", "[en|ja]")
f.BoolVar(&config.Conf.Debug, "debug", false, "debug mode")
f.BoolVar(&config.Conf.DebugSQL, "debug-sql", false, "SQL debug mode")
f.BoolVar(&config.Conf.Quiet, "quiet", false, "Quiet mode. No output on stdout")
f.BoolVar(&config.Conf.NoProgress, "no-progress", false, "Suppress progress bar")
wd, _ := os.Getwd()
defaultConfPath := filepath.Join(wd, "config.toml")
f.StringVar(&p.configPath, "config", defaultConfPath, "/path/to/toml")
defaultResultsDir := filepath.Join(wd, "results")
f.StringVar(&c.Conf.ResultsDir, "results-dir", defaultResultsDir, "/path/to/results")
f.StringVar(&config.Conf.ResultsDir, "results-dir", defaultResultsDir, "/path/to/results")
defaultLogDir := logging.GetDefaultLogDir()
f.StringVar(&c.Conf.LogDir, "log-dir", defaultLogDir, "/path/to/log")
f.StringVar(&config.Conf.LogDir, "log-dir", defaultLogDir, "/path/to/log")
f.BoolVar(&c.Conf.RefreshCve, "refresh-cve", false,
f.BoolVar(&config.Conf.RefreshCve, "refresh-cve", false,
"Refresh CVE information in JSON file under results dir")
f.Float64Var(&c.Conf.CvssScoreOver, "cvss-over", 0,
f.Float64Var(&config.Conf.CvssScoreOver, "cvss-over", 0,
"-cvss-over=6.5 means reporting CVSS Score 6.5 and over (default: 0 (means report all))")
f.BoolVar(&c.Conf.DiffMinus, "diff-minus", false,
f.BoolVar(&config.Conf.DiffMinus, "diff-minus", false,
"Minus Difference between previous result and current result")
f.BoolVar(&c.Conf.DiffPlus, "diff-plus", false,
f.BoolVar(&config.Conf.DiffPlus, "diff-plus", false,
"Plus Difference between previous result and current result")
f.BoolVar(&c.Conf.Diff, "diff", false,
f.BoolVar(&config.Conf.Diff, "diff", false,
"Plus & Minus Difference between previous result and current result")
f.BoolVar(&c.Conf.IgnoreUnscoredCves, "ignore-unscored-cves", false,
f.BoolVar(&config.Conf.IgnoreUnscoredCves, "ignore-unscored-cves", false,
"Don't report the unscored CVEs")
f.BoolVar(&c.Conf.IgnoreUnfixed, "ignore-unfixed", false,
f.BoolVar(&config.Conf.IgnoreUnfixed, "ignore-unfixed", false,
"Don't report the unfixed CVEs")
f.BoolVar(&c.Conf.IgnoreGitHubDismissed, "ignore-github-dismissed", false,
f.BoolVar(&config.Conf.IgnoreGitHubDismissed, "ignore-github-dismissed", false,
"Don't report the dismissed CVEs on GitHub Security Alerts")
f.StringVar(
&c.Conf.HTTPProxy, "http-proxy", "",
&config.Conf.HTTPProxy, "http-proxy", "",
"http://proxy-url:port (default: empty)")
f.BoolVar(&p.formatJSON, "format-json", false, "JSON format")
@@ -158,40 +158,40 @@ func (p *ReportCmd) SetFlags(f *flag.FlagSet) {
"Write report to Azure Storage blob (container/yyyyMMdd_HHmm/servername.json/txt)")
f.BoolVar(&p.gzip, "gzip", false, "gzip compression")
f.BoolVar(&c.Conf.Pipe, "pipe", false, "Use args passed via PIPE")
f.BoolVar(&config.Conf.Pipe, "pipe", false, "Use args passed via PIPE")
f.StringVar(&c.Conf.TrivyCacheDBDir, "trivy-cachedb-dir",
f.StringVar(&config.Conf.TrivyCacheDBDir, "trivy-cachedb-dir",
utils.DefaultCacheDir(), "/path/to/dir")
}
// Execute execute
func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
logging.Log = logging.NewCustomLogger(c.Conf.Debug, c.Conf.Quiet, c.Conf.LogDir, "", "")
logging.Log.Infof("vuls-%s-%s", c.Version, c.Revision)
logging.Log = logging.NewCustomLogger(config.Conf.Debug, config.Conf.Quiet, config.Conf.LogDir, "", "")
logging.Log.Infof("vuls-%s-%s", config.Version, config.Revision)
if err := c.Load(p.configPath, ""); err != nil {
if err := config.Load(p.configPath, ""); err != nil {
logging.Log.Errorf("Error loading %s, %+v", p.configPath, err)
return subcommands.ExitUsageError
}
c.Conf.Slack.Enabled = p.toSlack
c.Conf.ChatWork.Enabled = p.toChatWork
c.Conf.Telegram.Enabled = p.toTelegram
c.Conf.EMail.Enabled = p.toEmail
c.Conf.Syslog.Enabled = p.toSyslog
c.Conf.AWS.Enabled = p.toS3
c.Conf.Azure.Enabled = p.toAzureBlob
c.Conf.HTTP.Enabled = p.toHTTP
config.Conf.Slack.Enabled = p.toSlack
config.Conf.ChatWork.Enabled = p.toChatWork
config.Conf.Telegram.Enabled = p.toTelegram
config.Conf.EMail.Enabled = p.toEmail
config.Conf.Syslog.Enabled = p.toSyslog
config.Conf.AWS.Enabled = p.toS3
config.Conf.Azure.Enabled = p.toAzureBlob
config.Conf.HTTP.Enabled = p.toHTTP
if c.Conf.Diff {
c.Conf.DiffPlus, c.Conf.DiffMinus = true, true
if config.Conf.Diff {
config.Conf.DiffPlus, config.Conf.DiffMinus = true, true
}
var dir string
var err error
if c.Conf.DiffPlus || c.Conf.DiffMinus {
dir, err = reporter.JSONDir([]string{})
if config.Conf.DiffPlus || config.Conf.DiffMinus {
dir, err = reporter.JSONDir(config.Conf.ResultsDir, []string{})
} else {
dir, err = reporter.JSONDir(f.Args())
dir, err = reporter.JSONDir(config.Conf.ResultsDir, f.Args())
}
if err != nil {
logging.Log.Errorf("Failed to read from JSON: %+v", err)
@@ -199,7 +199,7 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
}
logging.Log.Info("Validating config...")
if !c.Conf.ValidateOnReport() {
if !config.Conf.ValidateOnReport() {
return subcommands.ExitUsageError
}
@@ -233,28 +233,10 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
for _, r := range res {
logging.Log.Debugf("%s: %s",
r.ServerInfo(), pp.Sprintf("%s", c.Conf.Servers[r.ServerName]))
r.ServerInfo(), pp.Sprintf("%s", config.Conf.Servers[r.ServerName]))
}
dbclient, err := detector.NewDBClient(
&c.Conf.CveDict,
&c.Conf.OvalDict,
&c.Conf.Gost,
&c.Conf.Exploit,
&c.Conf.Metasploit,
c.Conf.DebugSQL,
)
if err != nil {
logging.Log.Errorf("Failed to init DB Clients. err: %+v", err)
return subcommands.ExitFailure
}
defer func() {
for _, err := range dbclient.CloseDB() {
logging.Log.Errorf("Failed to CloseDB. err: %+v", err)
}
}()
if res, err = detector.Detect(*dbclient, res, dir); err != nil {
if res, err = detector.Detect(res, dir); err != nil {
logging.Log.Errorf("%+v", err)
return subcommands.ExitFailure
}
@@ -272,15 +254,17 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
if p.toSlack {
reports = append(reports, reporter.SlackWriter{
FormatOneLineText: p.formatOneLineText,
Cnf: config.Conf.Slack,
Proxy: config.Conf.HTTPProxy,
})
}
if p.toChatWork {
reports = append(reports, reporter.ChatWorkWriter{})
reports = append(reports, reporter.ChatWorkWriter{Cnf: config.Conf.ChatWork, Proxy: config.Conf.HTTPProxy})
}
if p.toTelegram {
reports = append(reports, reporter.TelegramWriter{})
reports = append(reports, reporter.TelegramWriter{Cnf: config.Conf.Telegram})
}
if p.toEmail {
@@ -288,22 +272,23 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
FormatOneEMail: p.formatOneEMail,
FormatOneLineText: p.formatOneLineText,
FormatList: p.formatList,
Cnf: config.Conf.EMail,
})
}
if p.toSyslog {
reports = append(reports, reporter.SyslogWriter{})
reports = append(reports, reporter.SyslogWriter{Cnf: config.Conf.Syslog})
}
if p.toHTTP {
reports = append(reports, reporter.HTTPRequestWriter{})
reports = append(reports, reporter.HTTPRequestWriter{Proxy: config.Conf.HTTPProxy})
}
if p.toLocalFile {
reports = append(reports, reporter.LocalFileWriter{
CurrentDir: dir,
DiffPlus: c.Conf.DiffPlus,
DiffMinus: c.Conf.DiffMinus,
DiffPlus: config.Conf.DiffPlus,
DiffMinus: config.Conf.DiffMinus,
FormatJSON: p.formatJSON,
FormatCsv: p.formatCsv,
FormatFullText: p.formatFullText,
@@ -320,10 +305,10 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
FormatOneLineText: p.formatOneLineText,
FormatList: p.formatList,
Gzip: p.gzip,
AWSConf: c.Conf.AWS,
AWSConf: config.Conf.AWS,
}
if err := w.Validate(); err != nil {
logging.Log.Errorf("Check if there is a bucket beforehand: %s, err: %+v", c.Conf.AWS.S3Bucket, err)
logging.Log.Errorf("Check if there is a bucket beforehand: %s, err: %+v", config.Conf.AWS.S3Bucket, err)
return subcommands.ExitUsageError
}
reports = append(reports, w)
@@ -336,10 +321,10 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
FormatOneLineText: p.formatOneLineText,
FormatList: p.formatList,
Gzip: p.gzip,
AzureConf: c.Conf.Azure,
AzureConf: config.Conf.Azure,
}
if err := w.Validate(); err != nil {
logging.Log.Errorf("Check if there is a container beforehand: %s, err: %+v", c.Conf.Azure.ContainerName, err)
logging.Log.Errorf("Check if there is a container beforehand: %s, err: %+v", config.Conf.Azure.ContainerName, err)
return subcommands.ExitUsageError
}
reports = append(reports, w)

View File

@@ -6,7 +6,7 @@ import (
"os"
"path/filepath"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/future-architect/vuls/reporter"
@@ -41,41 +41,41 @@ func (*SaaSCmd) Usage() string {
// SetFlags set flag
func (p *SaaSCmd) SetFlags(f *flag.FlagSet) {
f.BoolVar(&c.Conf.Debug, "debug", false, "debug mode")
f.BoolVar(&c.Conf.Quiet, "quiet", false, "Quiet mode. No output on stdout")
f.BoolVar(&config.Conf.Debug, "debug", false, "debug mode")
f.BoolVar(&config.Conf.Quiet, "quiet", false, "Quiet mode. No output on stdout")
wd, _ := os.Getwd()
defaultConfPath := filepath.Join(wd, "config.toml")
f.StringVar(&p.configPath, "config", defaultConfPath, "/path/to/toml")
defaultResultsDir := filepath.Join(wd, "results")
f.StringVar(&c.Conf.ResultsDir, "results-dir", defaultResultsDir, "/path/to/results")
f.StringVar(&config.Conf.ResultsDir, "results-dir", defaultResultsDir, "/path/to/results")
defaultLogDir := logging.GetDefaultLogDir()
f.StringVar(&c.Conf.LogDir, "log-dir", defaultLogDir, "/path/to/log")
f.StringVar(&config.Conf.LogDir, "log-dir", defaultLogDir, "/path/to/log")
f.StringVar(
&c.Conf.HTTPProxy, "http-proxy", "",
&config.Conf.HTTPProxy, "http-proxy", "",
"http://proxy-url:port (default: empty)")
}
// Execute execute
func (p *SaaSCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
logging.Log = logging.NewCustomLogger(c.Conf.Debug, c.Conf.Quiet, c.Conf.LogDir, "", "")
logging.Log.Infof("vuls-%s-%s", c.Version, c.Revision)
if err := c.Load(p.configPath, ""); err != nil {
logging.Log = logging.NewCustomLogger(config.Conf.Debug, config.Conf.Quiet, config.Conf.LogDir, "", "")
logging.Log.Infof("vuls-%s-%s", config.Version, config.Revision)
if err := config.Load(p.configPath, ""); err != nil {
logging.Log.Errorf("Error loading %s, %+v", p.configPath, err)
return subcommands.ExitUsageError
}
dir, err := reporter.JSONDir(f.Args())
dir, err := reporter.JSONDir(config.Conf.ResultsDir, f.Args())
if err != nil {
logging.Log.Errorf("Failed to read from JSON: %+v", err)
return subcommands.ExitFailure
}
logging.Log.Info("Validating config...")
if !c.Conf.ValidateOnSaaS() {
if !config.Conf.ValidateOnSaaS() {
return subcommands.ExitUsageError
}
@@ -104,11 +104,11 @@ func (p *SaaSCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
for _, r := range res {
logging.Log.Debugf("%s: %s",
r.ServerInfo(), pp.Sprintf("%s", c.Conf.Servers[r.ServerName]))
r.ServerInfo(), pp.Sprintf("%s", config.Conf.Servers[r.ServerName]))
}
// Ensure UUIDs of scan target servers in config.toml
if err := saas.EnsureUUIDs(c.Conf.Servers, p.configPath, res); err != nil {
if err := saas.EnsureUUIDs(config.Conf.Servers, p.configPath, res); err != nil {
logging.Log.Errorf("Failed to ensure UUIDs. err: %+v", err)
return subcommands.ExitFailure
}

View File

@@ -10,7 +10,7 @@ import (
"strings"
"github.com/asaskevich/govalidator"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/scanner"
"github.com/google/subcommands"
@@ -24,6 +24,7 @@ type ScanCmd struct {
timeoutSec int
scanTimeoutSec int
cacheDBPath string
detectIPS bool
}
// Name return subcommand name
@@ -57,34 +58,34 @@ func (*ScanCmd) Usage() string {
// SetFlags set flag
func (p *ScanCmd) SetFlags(f *flag.FlagSet) {
f.BoolVar(&c.Conf.Debug, "debug", false, "debug mode")
f.BoolVar(&c.Conf.Quiet, "quiet", false, "Quiet mode. No output on stdout")
f.BoolVar(&config.Conf.Debug, "debug", false, "debug mode")
f.BoolVar(&config.Conf.Quiet, "quiet", false, "Quiet mode. No output on stdout")
wd, _ := os.Getwd()
defaultConfPath := filepath.Join(wd, "config.toml")
f.StringVar(&p.configPath, "config", defaultConfPath, "/path/to/toml")
defaultResultsDir := filepath.Join(wd, "results")
f.StringVar(&c.Conf.ResultsDir, "results-dir", defaultResultsDir, "/path/to/results")
f.StringVar(&config.Conf.ResultsDir, "results-dir", defaultResultsDir, "/path/to/results")
defaultLogDir := logging.GetDefaultLogDir()
f.StringVar(&c.Conf.LogDir, "log-dir", defaultLogDir, "/path/to/log")
f.StringVar(&config.Conf.LogDir, "log-dir", defaultLogDir, "/path/to/log")
defaultCacheDBPath := filepath.Join(wd, "cache.db")
f.StringVar(&p.cacheDBPath, "cachedb-path", defaultCacheDBPath,
"/path/to/cache.db (local cache of changelog for Ubuntu/Debian)")
f.StringVar(&c.Conf.HTTPProxy, "http-proxy", "",
f.StringVar(&config.Conf.HTTPProxy, "http-proxy", "",
"http://proxy-url:port (default: empty)")
f.BoolVar(&p.askKeyPassword, "ask-key-password", false,
"Ask ssh privatekey password before scanning",
)
f.BoolVar(&c.Conf.Pipe, "pipe", false, "Use stdin via PIPE")
f.BoolVar(&config.Conf.Pipe, "pipe", false, "Use stdin via PIPE")
f.BoolVar(&c.Conf.DetectIPS, "ips", false, "retrieve IPS information")
f.BoolVar(&c.Conf.Vvv, "vvv", false, "ssh -vvv")
f.BoolVar(&p.detectIPS, "ips", false, "retrieve IPS information")
f.BoolVar(&config.Conf.Vvv, "vvv", false, "ssh -vvv")
f.IntVar(&p.timeoutSec, "timeout", 5*60,
"Number of seconds for processing other than scan",
@@ -97,8 +98,8 @@ func (p *ScanCmd) SetFlags(f *flag.FlagSet) {
// Execute execute
func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
logging.Log = logging.NewCustomLogger(c.Conf.Debug, c.Conf.Quiet, c.Conf.LogDir, "", "")
logging.Log.Infof("vuls-%s-%s", c.Version, c.Revision)
logging.Log = logging.NewCustomLogger(config.Conf.Debug, config.Conf.Quiet, config.Conf.LogDir, "", "")
logging.Log.Infof("vuls-%s-%s", config.Version, config.Revision)
if err := mkdirDotVuls(); err != nil {
logging.Log.Errorf("Failed to create $HOME/.vuls err: %+v", err)
@@ -123,7 +124,7 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
}
}
err = c.Load(p.configPath, keyPass)
err = config.Load(p.configPath, keyPass)
if err != nil {
msg := []string{
fmt.Sprintf("Error loading %s", p.configPath),
@@ -140,7 +141,7 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
var servernames []string
if 0 < len(f.Args()) {
servernames = f.Args()
} else if c.Conf.Pipe {
} else if config.Conf.Pipe {
bytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
logging.Log.Errorf("Failed to read stdin. err: %+v", err)
@@ -152,10 +153,10 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
}
}
targets := make(map[string]c.ServerInfo)
targets := make(map[string]config.ServerInfo)
for _, arg := range servernames {
found := false
for servername, info := range c.Conf.Servers {
for servername, info := range config.Conf.Servers {
if servername == arg {
targets[servername] = info
found = true
@@ -169,26 +170,28 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
}
if 0 < len(servernames) {
// if scan target servers are specified by args, set to the config
c.Conf.Servers = targets
config.Conf.Servers = targets
} else {
// if not specified by args, scan all servers in the config
targets = c.Conf.Servers
targets = config.Conf.Servers
}
logging.Log.Debugf("%s", pp.Sprintf("%v", targets))
logging.Log.Info("Validating config...")
if !c.Conf.ValidateOnScan() {
if !config.Conf.ValidateOnScan() {
return subcommands.ExitUsageError
}
s := scanner.Scanner{
ResultsDir: config.Conf.ResultsDir,
TimeoutSec: p.timeoutSec,
ScanTimeoutSec: p.scanTimeoutSec,
CacheDBPath: p.cacheDBPath,
Targets: targets,
Debug: c.Conf.Debug,
Quiet: c.Conf.Quiet,
LogDir: c.Conf.LogDir,
Debug: config.Conf.Debug,
Quiet: config.Conf.Quiet,
LogDir: config.Conf.LogDir,
DetectIPS: p.detectIPS,
}
if err := s.Scan(); err != nil {

View File

@@ -10,10 +10,7 @@ import (
"os"
"path/filepath"
// "github.com/future-architect/vuls/Server"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/detector"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/server"
"github.com/google/subcommands"
@@ -54,30 +51,30 @@ func (*ServerCmd) Usage() string {
// SetFlags set flag
func (p *ServerCmd) SetFlags(f *flag.FlagSet) {
f.StringVar(&c.Conf.Lang, "lang", "en", "[en|ja]")
f.BoolVar(&c.Conf.Debug, "debug", false, "debug mode")
f.BoolVar(&c.Conf.DebugSQL, "debug-sql", false, "SQL debug mode")
f.StringVar(&config.Conf.Lang, "lang", "en", "[en|ja]")
f.BoolVar(&config.Conf.Debug, "debug", false, "debug mode")
f.BoolVar(&config.Conf.DebugSQL, "debug-sql", false, "SQL debug mode")
wd, _ := os.Getwd()
defaultConfPath := filepath.Join(wd, "config.toml")
f.StringVar(&p.configPath, "config", defaultConfPath, "/path/to/toml")
defaultResultsDir := filepath.Join(wd, "results")
f.StringVar(&c.Conf.ResultsDir, "results-dir", defaultResultsDir, "/path/to/results")
f.StringVar(&config.Conf.ResultsDir, "results-dir", defaultResultsDir, "/path/to/results")
defaultLogDir := logging.GetDefaultLogDir()
f.StringVar(&c.Conf.LogDir, "log-dir", defaultLogDir, "/path/to/log")
f.StringVar(&config.Conf.LogDir, "log-dir", defaultLogDir, "/path/to/log")
f.Float64Var(&c.Conf.CvssScoreOver, "cvss-over", 0,
f.Float64Var(&config.Conf.CvssScoreOver, "cvss-over", 0,
"-cvss-over=6.5 means Servering CVSS Score 6.5 and over (default: 0 (means Server all))")
f.BoolVar(&c.Conf.IgnoreUnscoredCves, "ignore-unscored-cves", false,
f.BoolVar(&config.Conf.IgnoreUnscoredCves, "ignore-unscored-cves", false,
"Don't Server the unscored CVEs")
f.BoolVar(&c.Conf.IgnoreUnfixed, "ignore-unfixed", false,
f.BoolVar(&config.Conf.IgnoreUnfixed, "ignore-unfixed", false,
"Don't show the unfixed CVEs")
f.StringVar(&c.Conf.HTTPProxy, "http-proxy", "",
f.StringVar(&config.Conf.HTTPProxy, "http-proxy", "",
"http://proxy-url:port (default: empty)")
f.BoolVar(&p.toLocalFile, "to-localfile", false, "Write report to localfile")
@@ -87,38 +84,19 @@ func (p *ServerCmd) SetFlags(f *flag.FlagSet) {
// Execute execute
func (p *ServerCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
logging.Log = logging.NewCustomLogger(c.Conf.Debug, c.Conf.Quiet, c.Conf.LogDir, "", "")
logging.Log.Infof("vuls-%s-%s", c.Version, c.Revision)
if err := c.Load(p.configPath, ""); err != nil {
logging.Log = logging.NewCustomLogger(config.Conf.Debug, config.Conf.Quiet, config.Conf.LogDir, "", "")
logging.Log.Infof("vuls-%s-%s", config.Version, config.Revision)
if err := config.Load(p.configPath, ""); err != nil {
logging.Log.Errorf("Error loading %s. err: %+v", p.configPath, err)
return subcommands.ExitUsageError
}
logging.Log.Info("Validating config...")
if !c.Conf.ValidateOnReport() {
if !config.Conf.ValidateOnReport() {
return subcommands.ExitUsageError
}
dbclient, err := detector.NewDBClient(
&c.Conf.CveDict,
&c.Conf.OvalDict,
&c.Conf.Gost,
&c.Conf.Exploit,
&c.Conf.Metasploit,
c.Conf.DebugSQL,
)
if err != nil {
logging.Log.Errorf("Failed to init DB Clients. err: %+v", err)
return subcommands.ExitFailure
}
defer func() {
for _, err := range dbclient.CloseDB() {
logging.Log.Errorf("Failed to CloseDB. err: %+v", err)
}
}()
http.Handle("/vuls", server.VulsHandler{
DBclient: *dbclient,
ToLocalFile: p.toLocalFile,
})
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {

View File

@@ -9,7 +9,7 @@ import (
"path/filepath"
"github.com/aquasecurity/trivy/pkg/utils"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/detector"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
@@ -56,70 +56,70 @@ func (*TuiCmd) Usage() string {
// SetFlags set flag
func (p *TuiCmd) SetFlags(f *flag.FlagSet) {
// f.StringVar(&p.lang, "lang", "en", "[en|ja]")
f.BoolVar(&c.Conf.DebugSQL, "debug-sql", false, "debug SQL")
f.BoolVar(&c.Conf.Debug, "debug", false, "debug mode")
f.BoolVar(&c.Conf.Quiet, "quiet", false, "Quiet mode. No output on stdout")
f.BoolVar(&c.Conf.NoProgress, "no-progress", false, "Suppress progress bar")
f.BoolVar(&config.Conf.DebugSQL, "debug-sql", false, "debug SQL")
f.BoolVar(&config.Conf.Debug, "debug", false, "debug mode")
f.BoolVar(&config.Conf.Quiet, "quiet", false, "Quiet mode. No output on stdout")
f.BoolVar(&config.Conf.NoProgress, "no-progress", false, "Suppress progress bar")
defaultLogDir := logging.GetDefaultLogDir()
f.StringVar(&c.Conf.LogDir, "log-dir", defaultLogDir, "/path/to/log")
f.StringVar(&config.Conf.LogDir, "log-dir", defaultLogDir, "/path/to/log")
wd, _ := os.Getwd()
defaultResultsDir := filepath.Join(wd, "results")
f.StringVar(&c.Conf.ResultsDir, "results-dir", defaultResultsDir, "/path/to/results")
f.StringVar(&config.Conf.ResultsDir, "results-dir", defaultResultsDir, "/path/to/results")
defaultConfPath := filepath.Join(wd, "config.toml")
f.StringVar(&p.configPath, "config", defaultConfPath, "/path/to/toml")
f.BoolVar(&c.Conf.RefreshCve, "refresh-cve", false,
f.BoolVar(&config.Conf.RefreshCve, "refresh-cve", false,
"Refresh CVE information in JSON file under results dir")
f.Float64Var(&c.Conf.CvssScoreOver, "cvss-over", 0,
f.Float64Var(&config.Conf.CvssScoreOver, "cvss-over", 0,
"-cvss-over=6.5 means reporting CVSS Score 6.5 and over (default: 0 (means report all))")
f.BoolVar(&c.Conf.Diff, "diff", false,
f.BoolVar(&config.Conf.Diff, "diff", false,
"Plus Difference between previous result and current result")
f.BoolVar(&c.Conf.DiffPlus, "diff-plus", false,
f.BoolVar(&config.Conf.DiffPlus, "diff-plus", false,
"Plus Difference between previous result and current result")
f.BoolVar(&c.Conf.DiffMinus, "diff-minus", false,
f.BoolVar(&config.Conf.DiffMinus, "diff-minus", false,
"Minus Difference between previous result and current result")
f.BoolVar(
&c.Conf.IgnoreUnscoredCves, "ignore-unscored-cves", false,
&config.Conf.IgnoreUnscoredCves, "ignore-unscored-cves", false,
"Don't report the unscored CVEs")
f.BoolVar(&c.Conf.IgnoreUnfixed, "ignore-unfixed", false,
f.BoolVar(&config.Conf.IgnoreUnfixed, "ignore-unfixed", false,
"Don't report the unfixed CVEs")
f.BoolVar(&c.Conf.Pipe, "pipe", false, "Use stdin via PIPE")
f.BoolVar(&config.Conf.Pipe, "pipe", false, "Use stdin via PIPE")
f.StringVar(&c.Conf.TrivyCacheDBDir, "trivy-cachedb-dir",
f.StringVar(&config.Conf.TrivyCacheDBDir, "trivy-cachedb-dir",
utils.DefaultCacheDir(), "/path/to/dir")
}
// Execute execute
func (p *TuiCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
logging.Log = logging.NewCustomLogger(c.Conf.Debug, c.Conf.Quiet, c.Conf.LogDir, "", "")
logging.Log.Infof("vuls-%s-%s", c.Version, c.Revision)
if err := c.Load(p.configPath, ""); err != nil {
logging.Log = logging.NewCustomLogger(config.Conf.Debug, config.Conf.Quiet, config.Conf.LogDir, "", "")
logging.Log.Infof("vuls-%s-%s", config.Version, config.Revision)
if err := config.Load(p.configPath, ""); err != nil {
logging.Log.Errorf("Error loading %s, err: %+v", p.configPath, err)
return subcommands.ExitUsageError
}
c.Conf.Lang = "en"
config.Conf.Lang = "en"
if c.Conf.Diff {
c.Conf.DiffPlus = true
c.Conf.DiffMinus = true
if config.Conf.Diff {
config.Conf.DiffPlus = true
config.Conf.DiffMinus = true
}
var dir string
var err error
if c.Conf.DiffPlus || c.Conf.DiffMinus {
dir, err = reporter.JSONDir([]string{})
if config.Conf.DiffPlus || config.Conf.DiffMinus {
dir, err = reporter.JSONDir(config.Conf.ResultsDir, []string{})
} else {
dir, err = reporter.JSONDir(f.Args())
dir, err = reporter.JSONDir(config.Conf.ResultsDir, f.Args())
}
if err != nil {
logging.Log.Errorf("Failed to read from JSON. err: %+v", err)
@@ -127,7 +127,7 @@ func (p *TuiCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) s
}
logging.Log.Info("Validating config...")
if !c.Conf.ValidateOnTui() {
if !config.Conf.ValidateOnReport() {
return subcommands.ExitUsageError
}
@@ -138,25 +138,7 @@ func (p *TuiCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) s
}
logging.Log.Infof("Loaded: %s", dir)
dbclient, err := detector.NewDBClient(
&c.Conf.CveDict,
&c.Conf.OvalDict,
&c.Conf.Gost,
&c.Conf.Exploit,
&c.Conf.Metasploit,
c.Conf.DebugSQL,
)
if err != nil {
logging.Log.Errorf("Failed to init DB Clients. err: %+v", err)
return subcommands.ExitFailure
}
defer func() {
for _, err := range dbclient.CloseDB() {
logging.Log.Errorf("Failed to CloseDB. err: %+v", err)
}
}()
if res, err = detector.Detect(*dbclient, res, dir); err != nil {
if res, err = detector.Detect(res, dir); err != nil {
logging.Log.Error(err)
return subcommands.ExitFailure
}

View File

@@ -110,8 +110,16 @@ func IP() (ipv4Addrs []string, ipv6Addrs []string, err error) {
return ipv4Addrs, ipv6Addrs, nil
}
// ProxyEnv returns shell environment variables to set proxy
func ProxyEnv() string {
// PrependProxyEnv prepends proxy environment variable
func PrependProxyEnv(cmd string) string {
if config.Conf.HTTPProxy == "" {
return cmd
}
return fmt.Sprintf("%s %s", proxyEnv(), cmd)
}
// proxyEnv returns shell environment variables to set proxy
func proxyEnv() string {
httpProxyEnv := ""
keys := []string{
"http_proxy",
@@ -120,20 +128,11 @@ func ProxyEnv() string {
"HTTPS_PROXY",
}
for _, key := range keys {
httpProxyEnv += fmt.Sprintf(
` %s="%s"`, key, config.Conf.HTTPProxy)
httpProxyEnv += fmt.Sprintf(` %s="%s"`, key, config.Conf.HTTPProxy)
}
return httpProxyEnv
}
// PrependProxyEnv prepends proxy environment variable
func PrependProxyEnv(cmd string) string {
if config.Conf.HTTPProxy == "" {
return cmd
}
return fmt.Sprintf("%s %s", ProxyEnv(), cmd)
}
// func unixtime(s string) (time.Time, error) {
// i, err := strconv.ParseInt(s, 10, 64)
// if err != nil {