Continue scanning even when some hosts have tech issues

see #264
This commit is contained in:
Kota Kanbe
2017-01-31 14:35:16 +09:00
parent 00660485b7
commit 386b97d2be
19 changed files with 447 additions and 311 deletions

View File

@@ -23,7 +23,6 @@ import (
"os"
"path/filepath"
"github.com/Sirupsen/logrus"
"github.com/google/subcommands"
c "github.com/future-architect/vuls/config"
@@ -88,26 +87,27 @@ func (p *ConfigtestCmd) SetFlags(f *flag.FlagSet) {
// Execute execute
func (p *ConfigtestCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
// Setup Logger
c.Conf.Debug = p.debug
c.Conf.LogDir = p.logDir
util.Log = util.NewCustomLogger(c.ServerInfo{})
var keyPass string
var err error
if p.askKeyPassword {
prompt := "SSH key password: "
if keyPass, err = getPasswd(prompt); err != nil {
logrus.Error(err)
util.Log.Error(err)
return subcommands.ExitFailure
}
}
c.Conf.Debug = p.debug
c.Conf.SSHExternal = p.sshExternal
c.Conf.LogDir = p.logDir
err = c.Load(p.configPath, keyPass)
if err != nil {
logrus.Errorf("Error loading %s, %s", p.configPath, err)
util.Log.Errorf("Error loading %s, %s", p.configPath, err)
return subcommands.ExitUsageError
}
c.Conf.SSHExternal = p.sshExternal
var servernames []string
if 0 < len(f.Args()) {
@@ -125,7 +125,7 @@ func (p *ConfigtestCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interfa
}
}
if !found {
logrus.Errorf("%s is not in config", arg)
util.Log.Errorf("%s is not in config", arg)
return subcommands.ExitUsageError
}
}
@@ -133,25 +133,20 @@ func (p *ConfigtestCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interfa
c.Conf.Servers = target
}
// logger
Log := util.NewCustomLogger(c.ServerInfo{})
Log.Info("Validating Config...")
util.Log.Info("Validating config...")
if !c.Conf.ValidateOnConfigtest() {
return subcommands.ExitUsageError
}
Log.Info("Detecting Server/Container OS... ")
if err := scan.InitServers(Log); err != nil {
Log.Errorf("Failed to init servers: %s", err)
util.Log.Info("Detecting Server/Container OS... ")
if err := scan.InitServers(); err != nil {
util.Log.Errorf("Failed to init servers: %s", err)
return subcommands.ExitFailure
}
Log.Info("Checking sudo configuration... ")
if err := scan.CheckIfSudoNoPasswd(Log); err != nil {
Log.Errorf("Failed to sudo with nopassword via SSH. Define NOPASSWD in /etc/sudoers on target servers. err: %s", err)
return subcommands.ExitFailure
}
util.Log.Info("Checking sudo configuration...")
scan.CheckIfSudoNoPasswd()
scan.PrintSSHableServerNames()
return subcommands.ExitSuccess
}

View File

@@ -23,7 +23,6 @@ import (
"os"
"path/filepath"
"github.com/Sirupsen/logrus"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/scan"
"github.com/future-architect/vuls/util"
@@ -116,27 +115,31 @@ func (p *PrepareCmd) SetFlags(f *flag.FlagSet) {
// Execute execute
func (p *PrepareCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
c.Conf.LogDir = p.logDir
c.Conf.Debug = p.debug
util.Log = util.NewCustomLogger(c.ServerInfo{})
var keyPass string
var err error
if p.askKeyPassword {
prompt := "SSH key password: "
if keyPass, err = getPasswd(prompt); err != nil {
logrus.Error(err)
util.Log.Error(err)
return subcommands.ExitFailure
}
}
if p.askSudoPassword {
logrus.Errorf("[Deprecated] -ask-sudo-password WAS REMOVED FOR SECURITY REASONS. Define NOPASSWD in /etc/sudoers on target servers and use SSH key-based authentication")
util.Log.Errorf("[Deprecated] -ask-sudo-password WAS REMOVED FOR SECURITY REASONS. Define NOPASSWD in /etc/sudoers on target servers and use SSH key-based authentication")
return subcommands.ExitFailure
}
err = c.Load(p.configPath, keyPass)
if err != nil {
logrus.Errorf("Error loading %s, %s", p.configPath, err)
util.Log.Errorf("Error loading %s, %s", p.configPath, err)
return subcommands.ExitUsageError
}
logrus.Infof("Start Preparing (config: %s)", p.configPath)
util.Log.Infof("Start Preparing (config: %s)", p.configPath)
target := make(map[string]c.ServerInfo)
for _, arg := range f.Args() {
found := false
@@ -148,7 +151,7 @@ func (p *PrepareCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{
}
}
if !found {
logrus.Errorf("%s is not in config", arg)
util.Log.Errorf("%s is not in config", arg)
return subcommands.ExitUsageError
}
}
@@ -156,34 +159,25 @@ func (p *PrepareCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{
c.Conf.Servers = target
}
c.Conf.Debug = p.debug
c.Conf.SSHExternal = p.sshExternal
c.Conf.AssumeYes = p.assumeYes
c.Conf.LogDir = p.logDir
logrus.Info("Validating Config...")
util.Log.Info("Validating config...")
if !c.Conf.ValidateOnPrepare() {
return subcommands.ExitUsageError
}
// Set up custom logger
logger := util.NewCustomLogger(c.ServerInfo{})
logger.Info("Detecting OS... ")
if err := scan.InitServers(logger); err != nil {
logger.Errorf("Failed to init servers: %s", err)
util.Log.Info("Detecting OS... ")
if err := scan.InitServers(); err != nil {
util.Log.Errorf("Failed to init servers: %s", err)
return subcommands.ExitFailure
}
logger.Info("Checking sudo configuration... ")
if err := scan.CheckIfSudoNoPasswd(logger); err != nil {
logger.Errorf("Failed to sudo with nopassword via SSH. Define NOPASSWD in /etc/sudoers on target servers")
return subcommands.ExitFailure
}
util.Log.Info("Checking sudo configuration... ")
scan.CheckIfSudoNoPasswd()
if errs := scan.Prepare(); 0 < len(errs) {
for _, e := range errs {
logger.Errorf("Failed to prepare: %s", e)
}
if err := scan.Prepare(); err != nil {
util.Log.Errorf("Failed to prepare: %s", err)
return subcommands.ExitFailure
}

View File

@@ -249,10 +249,10 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
c.Conf.Debug = p.debug
c.Conf.DebugSQL = p.debugSQL
c.Conf.LogDir = p.logDir
Log := util.NewCustomLogger(c.ServerInfo{})
util.Log = util.NewCustomLogger(c.ServerInfo{})
if err := c.Load(p.configPath, ""); err != nil {
Log.Errorf("Error loading %s, %s", p.configPath, err)
util.Log.Errorf("Error loading %s, %s", p.configPath, err)
return subcommands.ExitUsageError
}
@@ -268,7 +268,7 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
c.Conf.Pipe = p.pipe
jsonDir, err := jsonDir(f.Args())
if err != nil {
Log.Errorf("Failed to read from JSON: %s", err)
util.Log.Errorf("Failed to read from JSON: %s", err)
return subcommands.ExitFailure
}
@@ -304,7 +304,7 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
c.Conf.AwsProfile = p.awsProfile
c.Conf.S3Bucket = p.awsS3Bucket
if err := report.CheckIfBucketExists(); err != nil {
Log.Errorf("Check if there is a bucket beforehand: %s, err: %s", c.Conf.S3Bucket, err)
util.Log.Errorf("Check if there is a bucket beforehand: %s, err: %s", c.Conf.S3Bucket, err)
return subcommands.ExitUsageError
}
reports = append(reports, report.S3Writer{})
@@ -323,11 +323,11 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
c.Conf.AzureContainer = p.azureContainer
if len(c.Conf.AzureContainer) == 0 {
Log.Error("Azure storage container name is requied with --azure-container option")
util.Log.Error("Azure storage container name is requied with --azure-container option")
return subcommands.ExitUsageError
}
if err := report.CheckIfAzureContainerExists(); err != nil {
Log.Errorf("Check if there is a container beforehand: %s, err: %s", c.Conf.AzureContainer, err)
util.Log.Errorf("Check if there is a container beforehand: %s, err: %s", c.Conf.AzureContainer, err)
return subcommands.ExitUsageError
}
reports = append(reports, report.AzureBlobWriter{})
@@ -338,20 +338,20 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
c.Conf.FormatShortText = true
}
Log.Info("Validating Config...")
util.Log.Info("Validating config...")
if !c.Conf.ValidateOnReport() {
return subcommands.ExitUsageError
}
if ok, err := cveapi.CveClient.CheckHealth(); !ok {
Log.Errorf("CVE HTTP server is not running. err: %s", err)
Log.Errorf("Run go-cve-dictionary as server mode before reporting or run with --cvedb-path option")
util.Log.Errorf("CVE HTTP server is not running. err: %s", err)
util.Log.Errorf("Run go-cve-dictionary as server mode before reporting or run with --cvedb-path option")
return subcommands.ExitFailure
}
if c.Conf.CveDictionaryURL != "" {
Log.Infof("cve-dictionary: %s", c.Conf.CveDictionaryURL)
util.Log.Infof("cve-dictionary: %s", c.Conf.CveDictionaryURL)
} else {
if c.Conf.CveDBType == "sqlite3" {
Log.Infof("cve-dictionary: %s", c.Conf.CveDBPath)
util.Log.Infof("cve-dictionary: %s", c.Conf.CveDBPath)
}
}
@@ -360,10 +360,10 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
var results []models.ScanResult
for _, r := range history.ScanResults {
if p.refreshCve || needToRefreshCve(r) {
Log.Debugf("need to refresh")
util.Log.Debugf("need to refresh")
if c.Conf.CveDBType == "sqlite3" && c.Conf.CveDictionaryURL == "" {
if _, err := os.Stat(c.Conf.CveDBPath); os.IsNotExist(err) {
Log.Errorf("SQLite3 DB(CVE-Dictionary) is not exist: %s",
util.Log.Errorf("SQLite3 DB(CVE-Dictionary) is not exist: %s",
c.Conf.CveDBPath)
return subcommands.ExitFailure
}
@@ -371,18 +371,18 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
filled, err := fillCveInfoFromCveDB(r)
if err != nil {
Log.Errorf("Failed to fill CVE information: %s", err)
util.Log.Errorf("Failed to fill CVE information: %s", err)
return subcommands.ExitFailure
}
filled.Lang = c.Conf.Lang
if err := overwriteJSONFile(jsonDir, filled); err != nil {
Log.Errorf("Failed to write JSON: %s", err)
util.Log.Errorf("Failed to write JSON: %s", err)
return subcommands.ExitFailure
}
results = append(results, filled)
} else {
Log.Debugf("no need to refresh")
util.Log.Debugf("no need to refresh")
results = append(results, r)
}
}
@@ -393,7 +393,7 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
}
for _, w := range reports {
if err := w.Write(res...); err != nil {
Log.Errorf("Failed to report: %s", err)
util.Log.Errorf("Failed to report: %s", err)
return subcommands.ExitFailure
}
}

View File

@@ -26,7 +26,6 @@ import (
"path/filepath"
"strings"
"github.com/Sirupsen/logrus"
c "github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/scan"
"github.com/future-architect/vuls/util"
@@ -138,25 +137,30 @@ func (p *ScanCmd) SetFlags(f *flag.FlagSet) {
// Execute execute
func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
// Setup Logger
c.Conf.Debug = p.debug
c.Conf.LogDir = p.logDir
util.Log = util.NewCustomLogger(c.ServerInfo{})
var keyPass string
var err error
if p.askKeyPassword {
prompt := "SSH key password: "
if keyPass, err = getPasswd(prompt); err != nil {
logrus.Error(err)
util.Log.Error(err)
return subcommands.ExitFailure
}
}
c.Conf.Debug = p.debug
err = c.Load(p.configPath, keyPass)
if err != nil {
logrus.Errorf("Error loading %s, %s", p.configPath, err)
util.Log.Errorf("Error loading %s, %s", p.configPath, err)
return subcommands.ExitUsageError
}
logrus.Info("Start scanning")
logrus.Infof("config: %s", p.configPath)
util.Log.Info("Start scanning")
util.Log.Infof("config: %s", p.configPath)
c.Conf.Pipe = p.pipe
var servernames []string
@@ -165,7 +169,7 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
} else if c.Conf.Pipe {
bytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
logrus.Errorf("Failed to read stdin: %s", err)
util.Log.Errorf("Failed to read stdin: %s", err)
return subcommands.ExitFailure
}
fields := strings.Fields(string(bytes))
@@ -185,18 +189,14 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
}
}
if !found {
logrus.Errorf("%s is not in config", arg)
util.Log.Errorf("%s is not in config", arg)
return subcommands.ExitUsageError
}
}
if 0 < len(servernames) {
c.Conf.Servers = target
}
logrus.Debugf("%s", pp.Sprintf("%v", target))
// logger
c.Conf.LogDir = p.logDir
Log := util.NewCustomLogger(c.ServerInfo{})
util.Log.Debugf("%s", pp.Sprintf("%v", target))
c.Conf.ResultsDir = p.resultsDir
c.Conf.CacheDBPath = p.cacheDBPath
@@ -205,31 +205,26 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
c.Conf.ContainersOnly = p.containersOnly
c.Conf.SkipBroken = p.skipBroken
Log.Info("Validating Config...")
util.Log.Info("Validating config...")
if !c.Conf.ValidateOnScan() {
return subcommands.ExitUsageError
}
Log.Info("Detecting Server/Container OS... ")
if err := scan.InitServers(Log); err != nil {
Log.Errorf("Failed to init servers: %s", err)
util.Log.Info("Detecting Server/Container OS... ")
if err := scan.InitServers(); err != nil {
util.Log.Errorf("Failed to init servers: %s", err)
return subcommands.ExitFailure
}
Log.Info("Checking sudo configuration... ")
if err := scan.CheckIfSudoNoPasswd(Log); err != nil {
Log.Errorf("Failed to sudo with nopassword via SSH. Define NOPASSWD in /etc/sudoers on target servers")
return subcommands.ExitFailure
}
util.Log.Info("Checking sudo configuration... ")
scan.CheckIfSudoNoPasswd()
Log.Info("Detecting Platforms... ")
scan.DetectPlatforms(Log)
util.Log.Info("Detecting Platforms... ")
scan.DetectPlatforms()
Log.Info("Scanning vulnerabilities... ")
if errs := scan.Scan(); 0 < len(errs) {
for _, e := range errs {
Log.Errorf("Failed to scan. err: %s", e)
}
util.Log.Info("Scanning vulnerabilities... ")
if err := scan.Scan(); err != nil {
util.Log.Errorf("Failed to scan. err: %s", err)
return subcommands.ExitFailure
}
fmt.Printf("\n\n\n")

View File

@@ -115,7 +115,7 @@ func (p *TuiCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) s
c.Conf.CveDBPath = p.cvedbpath
c.Conf.CveDictionaryURL = p.cveDictionaryURL
log.Info("Validating Config...")
log.Info("Validating config...")
if !c.Conf.ValidateOnTui() {
return subcommands.ExitUsageError
}