Add -pipe flag #294

Solved the problem of trying to read from STDIN and stopping on the way when running from CRON or AWS Lambda.
This commit is contained in:
Kota Kanbe
2017-01-24 00:21:56 +09:00
parent 49b4b8be22
commit 2d854cd64d
9 changed files with 71 additions and 41 deletions

View File

@@ -667,6 +667,7 @@ scan:
[-http-proxy=http://192.168.0.1:8080]
[-ask-key-password]
[-debug]
[-pipe]
[SERVER]...
-ask-key-password
@@ -681,6 +682,8 @@ scan:
debug mode
-http-proxy string
http://proxy-url:port (default: empty)
-pipe
Use stdin via PIPE
-results-dir string
/path/to/results
-skip-broken
@@ -831,6 +834,7 @@ report:
[-http-proxy=http://192.168.0.1:8080]
[-debug]
[-debug-sql]
[-pipe]
[SERVER]...
-aws-profile string
@@ -877,6 +881,8 @@ report:
Don't report the unscored CVEs
-lang string
[en|ja] (default "en")
-pipe
Use stdin via PIPE
-refresh-cve
Refresh CVE information in JSON file under results dir
-results-dir string
@@ -904,6 +910,7 @@ With this sample command, it will ..
- Slack通知
- CVSS score が 7.0以上のもののみ通知
## Example: Put results in S3 bucket
事前にAWS関連の設定を行う
@@ -1108,6 +1115,7 @@ tui:
[-results-dir=/path/to/results]
[-refresh-cve]
[-debug-sql]
[-pipe]
-cvedb-path string
/path/to/sqlite3 (For get cve detail from cve.sqlite3)
@@ -1117,6 +1125,8 @@ tui:
http://cve-dictionary.com:8080 or mysql connection string
-debug-sql
debug SQL
-pipe
Use stdin via PIPE
-refresh-cve
Refresh CVE information in JSON file under results dir
-results-dir string
@@ -1156,7 +1166,7 @@ $ vuls tui 20160524_1940
# Display the previous scan results using peco
```
$ vuls history | peco | vuls tui
$ vuls history | peco | vuls tui -pipe
```
[![asciicast](https://asciinema.org/a/emi7y7docxr60bq080z10t7v8.png)](https://asciinema.org/a/emi7y7docxr60bq080z10t7v8)

View File

@@ -676,6 +676,7 @@ scan:
[-http-proxy=http://192.168.0.1:8080]
[-ask-key-password]
[-debug]
[-pipe]
[SERVER]...
-ask-key-password
@@ -690,6 +691,8 @@ scan:
debug mode
-http-proxy string
http://proxy-url:port (default: empty)
-pipe
Use stdin via PIPE
-results-dir string
/path/to/results
-skip-broken
@@ -840,6 +843,7 @@ report:
[-http-proxy=http://192.168.0.1:8080]
[-debug]
[-debug-sql]
[-pipe]
[SERVER]...
-aws-profile string
@@ -886,6 +890,8 @@ report:
Don't report the unscored CVEs
-lang string
[en|ja] (default "en")
-pipe
Use stdin via PIPE
-refresh-cve
Refresh CVE information in JSON file under results dir
-results-dir string
@@ -913,6 +919,7 @@ With this sample command, it will ..
- Send scan results to slack
- Only Report CVEs that CVSS score is over 7
## Example: Put results in S3 bucket
To put results in S3 bucket, configure following settings in AWS before reporting.
- Create S3 bucket. see [Creating a Bucket](http://docs.aws.amazon.com/AmazonS3/latest/UG/CreatingaBucket.html)
@@ -1108,6 +1115,7 @@ tui:
[-results-dir=/path/to/results]
[-refresh-cve]
[-debug-sql]
[-pipe]
-cvedb-path string
/path/to/sqlite3 (For get cve detail from cve.sqlite3) (default "/Users/kotakanbe/go/src/github.com/future-architect/vuls/cve.sqlite3")
@@ -1117,6 +1125,8 @@ tui:
http://cve-dictionary.com:8080 or mysql connection string
-debug-sql
debug SQL
-pipe
Use stdin via PIPE
-refresh-cve
Refresh CVE information in JSON file under results dir
-results-dir string
@@ -1152,7 +1162,7 @@ $ vuls tui 2016-12-30T10:34:38+09:00
# Display the previous scan results using peco
```
$ vuls history | peco | vuls tui
$ vuls history | peco | vuls tui -pipe
```
[![asciicast](https://asciinema.org/a/emi7y7docxr60bq080z10t7v8.png)](https://asciinema.org/a/emi7y7docxr60bq080z10t7v8)

View File

@@ -20,10 +20,8 @@ package commands
import (
"context"
"flag"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/Sirupsen/logrus"
"github.com/google/subcommands"
@@ -108,19 +106,6 @@ func (p *ConfigtestCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interfa
var servernames []string
if 0 < len(f.Args()) {
servernames = f.Args()
} else {
stat, _ := os.Stdin.Stat()
if (stat.Mode() & os.ModeCharDevice) == 0 {
bytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
logrus.Errorf("Failed to read stdin: %s", err)
return subcommands.ExitFailure
}
fields := strings.Fields(string(bytes))
if 0 < len(fields) {
servernames = fields
}
}
}
target := make(map[string]c.ServerInfo)

View File

@@ -30,7 +30,6 @@ import (
"github.com/future-architect/vuls/report"
"github.com/future-architect/vuls/util"
"github.com/google/subcommands"
"github.com/kotakanbe/go-cve-dictionary/log"
)
// ReportCmd is subcommand for reporting
@@ -71,6 +70,8 @@ type ReportCmd struct {
azureAccount string
azureKey string
azureContainer string
pipe bool
}
// Name return subcommand name
@@ -112,6 +113,7 @@ func (*ReportCmd) Usage() string {
[-http-proxy=http://192.168.0.1:8080]
[-debug]
[-debug-sql]
[-pipe]
[SERVER]...
`
@@ -229,6 +231,12 @@ func (p *ReportCmd) SetFlags(f *flag.FlagSet) {
"",
"Azure account key to use. AZURE_STORAGE_ACCESS_KEY environment variable is used if not specified")
f.StringVar(&p.azureContainer, "azure-container", "", "Azure storage container name")
f.BoolVar(
&p.pipe,
"pipe",
false,
"Use args passed via PIPE")
}
// Execute execute
@@ -251,9 +259,10 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
c.Conf.IgnoreUnscoredCves = p.ignoreUnscoredCves
c.Conf.HTTPProxy = p.httpProxy
c.Conf.Pipe = p.pipe
jsonDir, err := jsonDir(f.Args())
if err != nil {
log.Errorf("Failed to read from JSON: %s", err)
Log.Errorf("Failed to read from JSON: %s", err)
return subcommands.ExitFailure
}
@@ -348,7 +357,7 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
Log.Debugf("need to refresh")
if c.Conf.CveDBType == "sqlite3" {
if _, err := os.Stat(c.Conf.CveDBPath); os.IsNotExist(err) {
log.Errorf("SQLite3 DB(CVE-Dictionary) is not exist: %s",
Log.Errorf("SQLite3 DB(CVE-Dictionary) is not exist: %s",
c.Conf.CveDBPath)
return subcommands.ExitFailure
}

View File

@@ -45,6 +45,7 @@ type ScanCmd struct {
containersOnly bool
skipBroken bool
sshExternal bool
pipe bool
}
// Name return subcommand name
@@ -66,6 +67,7 @@ func (*ScanCmd) Usage() string {
[-http-proxy=http://192.168.0.1:8080]
[-ask-key-password]
[-debug]
[-pipe]
[SERVER]...
`
@@ -121,6 +123,12 @@ func (p *ScanCmd) SetFlags(f *flag.FlagSet) {
false,
"Ask ssh privatekey password before scanning",
)
f.BoolVar(
&p.pipe,
"pipe",
false,
"Use stdin via PIPE")
}
// Execute execute
@@ -145,21 +153,19 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
logrus.Info("Start scanning")
logrus.Infof("config: %s", p.configPath)
c.Conf.Pipe = p.pipe
var servernames []string
if 0 < len(f.Args()) {
servernames = f.Args()
} else {
stat, _ := os.Stdin.Stat()
if (stat.Mode() & os.ModeCharDevice) == 0 {
bytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
logrus.Errorf("Failed to read stdin: %s", err)
return subcommands.ExitFailure
}
fields := strings.Fields(string(bytes))
if 0 < len(fields) {
servernames = fields
}
} else if c.Conf.Pipe {
bytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
logrus.Errorf("Failed to read stdin: %s", err)
return subcommands.ExitFailure
}
fields := strings.Fields(string(bytes))
if 0 < len(fields) {
servernames = fields
}
}

View File

@@ -40,6 +40,8 @@ type TuiCmd struct {
cvedbtype string
cvedbpath string
cveDictionaryURL string
pipe bool
}
// Name return subcommand name
@@ -58,6 +60,7 @@ func (*TuiCmd) Usage() string {
[-results-dir=/path/to/results]
[-refresh-cve]
[-debug-sql]
[-pipe]
`
}
@@ -95,6 +98,12 @@ func (p *TuiCmd) SetFlags(f *flag.FlagSet) {
"cvedb-url",
"",
"http://cve-dictionary.com:8080 or mysql connection string")
f.BoolVar(
&p.pipe,
"pipe",
false,
"Use stdin via PIPE")
}
// Execute execute
@@ -111,6 +120,7 @@ func (p *TuiCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) s
return subcommands.ExitUsageError
}
c.Conf.Pipe = p.pipe
jsonDir, err := jsonDir(f.Args())
if err != nil {
log.Errorf("Failed to read json dir under results: %s", err)

View File

@@ -74,7 +74,7 @@ func lsValidJSONDirs() (dirs jsonDirs, err error) {
// jsonDir returns
// If there is an arg, check if it is a valid format and return the corresponding path under results.
// If passed via PIPE (such as history subcommand), return that path.
// 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
@@ -98,8 +98,7 @@ func jsonDir(args []string) (string, error) {
}
// PIPE
stat, _ := os.Stdin.Stat()
if (stat.Mode() & os.ModeCharDevice) == 0 {
if c.Conf.Pipe {
bytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
return "", fmt.Errorf("Failed to read stdin: %s", err)

View File

@@ -72,6 +72,8 @@ type Config struct {
AzureAccount string
AzureKey string
AzureContainer string
Pipe bool
}
// ValidateOnConfigtest validates

View File

@@ -97,11 +97,11 @@ func detectRedhat(c config.ServerInfo) (itsMe bool, red osTypeInterface) {
}
func (o *redhat) checkIfSudoNoPasswd() error {
cmd := "yum --version"
if o.Distro.Family == "centos" {
cmd = "echo N | " + cmd
}
r := o.exec(cmd, o.sudo())
cmd := "yum --version"
if o.Distro.Family == "centos" {
cmd = "echo N | " + cmd
}
r := o.exec(cmd, o.sudo())
if !r.isSuccess() {
o.log.Errorf("sudo error on %s", r)
return fmt.Errorf("Failed to sudo: %s", r)
@@ -644,7 +644,6 @@ func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos,
// All information collected.
// Convert to VulnInfos.
o.log.Info("Fetching CVE details...")
vinfos := models.VulnInfos{}
for _, advIDCveIDs := range advisoryCveIDsList {
for _, cveID := range advIDCveIDs.CveIDs {