diff --git a/README.ja.md b/README.ja.md
index c04f713f..8236052b 100644
--- a/README.ja.md
+++ b/README.ja.md
@@ -87,7 +87,7 @@ Hello Vulsチュートリアルでは手動でのセットアップ方法で説
1. go-cve-dictionaryをデプロイ
1. Vulsをデプロイ
1. 設定
-1. Prepare
+1. 設定ファイルと、スキャン対象サーバの設定のチェック
1. Scan
1. Reporting
1. TUI(Terminal-Based User Interface)で結果を参照する
@@ -216,15 +216,14 @@ port = "22"
user = "ec2-user"
keyPath = "/home/ec2-user/.ssh/id_rsa"
+```
+
+## Step7. Check config.toml and settings on the server before scanning
+
+```
$ vuls configtest
```
-
-## Step7. Setting up target servers for Vuls
-
-```
-$ vuls prepare
-```
-詳細は [Usage: Prepare](https://github.com/future-architect/vuls#usage-prepare) を参照
+詳細は [Usage: configtest](#usage-configtest) を参照
## Step8. Start Scanning
@@ -327,7 +326,7 @@ $ vuls tui
# Architecture
-## A. Scan via SSH Mode
+## A. Scan via SSH Mode (Remote Scan Mode)

@@ -585,8 +584,6 @@ host = "172.31.4.82"
# Usage: Configtest
-configtestサブコマンドは、config.tomlで定義されたサーバ/コンテナに対してSSH可能かどうかをチェックする。
-
```
$ vuls configtest --help
configtest:
@@ -595,6 +592,7 @@ configtest:
[-log-dir=/path/to/log]
[-ask-key-password]
[-ssh-external]
+ [-http-proxy=http://192.168.0.1:8080]
[-debug]
[SERVER]...
@@ -604,66 +602,70 @@ configtest:
/path/to/toml (default "/Users/kotakanbe/go/src/github.com/future-architect/vuls/config.toml")
-debug
debug mode
+ -http-proxy string
+ http://proxy-url:port (default: empty)
-log-dir string
/path/to/log (default "/var/log/vuls")
-ssh-external
Use external ssh command. Default: Use the Go native implementation
```
-また、スキャン対象サーバに対してパスワードなしでSUDO可能な状態かもチェックする。
+configtestサブコマンドは以下をチェックする
+- config.tomlで定義されたサーバ/コンテナに対してSSH可能かどうか
+- スキャン対象のサーバ上に依存パッケーがインストールされているか
+- /etc/sudoers
-スキャン対象サーバ上の`/etc/sudoers`のサンプル
+## Dependencies on Target Servers
-- CentOS, RHEL, Amazon Linux
-```
-vuls ALL=(root) NOPASSWD: /usr/bin/yum
-```
-- Ubuntu, Debian, Raspbian
-```
-vuls ALL=(root) NOPASSWD: /usr/bin/apt-get
-```
-- Amazon Linux, FreeBSDはRoot権限なしでスキャン可能
-
-----
-
-# Usage: Prepare
-
-Prepareサブコマンドは、Vuls内部で利用する以下のパッケージをスキャン対象サーバにインストールする。
+スキャンするためには、下記のパッケージが必要なので、手動かまたはAnsibleなどのツールで事前にインストールする必要がある。
| Distribution| Release | Requirements |
|:------------|-------------------:|:-------------|
| Ubuntu | 12, 14, 16| - |
| Debian | 7, 8| aptitude |
-| CentOS | 5| yum-changelog |
| CentOS | 6, 7| yum-plugin-changelog |
-| Amazon | All | - |
-| RHEL | 5, 6, 7 | - |
+| Amazon | All | - |
+| RHEL | 5 | yum-security |
+| RHEL | 6, 7 | - |
| FreeBSD | 10 | - |
| Raspbian | Wheezy, Jessie | - |
+## Check /etc/sudoers
-```
-$ vuls prepare -help
-prepare:
- prepare
- [-config=/path/to/config.toml]
- [-log-dir=/path/to/log]
- [-ask-key-password]
- [-debug]
- [-ssh-external]
+スキャン対象サーバに対してパスワードなしでSUDO可能な状態かもチェックする。
+スキャン対象サーバ上の`/etc/sudoers`のサンプル
- [SERVER]...
- -ask-key-password
- Ask ssh privatekey password before scanning
- -config string
- /path/to/toml (default "$PWD/config.toml")
- -debug
- debug mode
- -log-dir string
- /path/to/log (default "/var/log/vuls")
- -ssh-external
- Use external ssh command. Default: Use the Go native implementation
+- CentOS
```
+vuls ALL=(ALL) NOPASSWD:/usr/bin/yum --changelog --assumeno update *
+Defaults:vuls env_keep="http_proxy https_proxy HTTP_PROXY HTTPS_PROXY"
+```
+
+- RHEL 5
+```
+vuls ALL=(ALL) NOPASSWD:/usr/bin/yum --color=never repolist, /usr/bin/yum --color=never list-security --security, /usr/bin/yum --color=never check-update, /usr/bin/yum --color=never info-security
+Defaults:vuls env_keep="http_proxy https_proxy HTTP_PROXY HTTPS_PROXY"
+```
+
+- RHEL 6, 7
+```
+vuls ALL=(ALL) NOPASSWD:/usr/bin/yum --color=never repolist, /usr/bin/yum --color=never --security updateinfo list updates, /usr/bin/yum --color=never check-update, /usr/bin/yum --color=never --security updateinfo updates
+Defaults:vuls env_keep="http_proxy https_proxy HTTP_PROXY HTTPS_PROXY"
+```
+
+- Debian
+```
+vuls ALL=(ALL) NOPASSWD: /usr/bin/apt-get update
+Defaults:vuls env_keep="http_proxy https_proxy HTTP_PROXY HTTPS_PROXY"
+```
+
+- Ubuntu/Raspbian
+```
+vuls ALL=(ALL) NOPASSWD: /usr/bin/apt-get update
+Defaults:vuls env_keep="http_proxy https_proxy HTTP_PROXY HTTPS_PROXY"
+```
+
+- Amazon Linux, FreeBSDは今のところRoot権限なしでスキャン可能
----
diff --git a/README.md b/README.md
index 6135ae00..2bbd2662 100644
--- a/README.md
+++ b/README.md
@@ -93,7 +93,7 @@ This can be done in the following steps.
1. Deploy go-cve-dictionary
1. Deploy Vuls
1. Configuration
-1. Prepare
+1. Check config.toml and settings on the server before scanning
1. Scan
1. Reporting
1. TUI(Terminal-Based User Interface)
@@ -211,15 +211,15 @@ port = "22"
user = "ec2-user"
keyPath = "/home/ec2-user/.ssh/id_rsa"
+```
+
+## Step7. Check config.toml and settings on the server before scanning
+
+```
$ vuls configtest
```
-## Step7. Setting up target servers for Vuls
-
-```
-$ vuls prepare
-```
-see [Usage: Prepare](https://github.com/future-architect/vuls#usage-prepare)
+see [Usage: configtest](#usage-configtest)
## Step8. Start Scanning
@@ -325,7 +325,7 @@ see https://github.com/future-architect/vuls/tree/master/setup/docker
# Architecture
-## A. Scan via SSH Mode
+## A. Scan via SSH Mode (Remote Scan Mode)

@@ -589,7 +589,6 @@ You can customize your configuration using this template.
# Usage: Configtest
-Configtest subcommand check if vuls is able to connect via ssh to servers/containers defined in the config.toml.
```
$ vuls configtest --help
configtest:
@@ -607,72 +606,72 @@ configtest:
/path/to/toml (default "/Users/kotakanbe/go/src/github.com/future-architect/vuls/config.toml")
-debug
debug mode
+ -http-proxy string
+ http://proxy-url:port (default: empty)
-log-dir string
/path/to/log (default "/var/log/vuls")
-ssh-external
Use external ssh command. Default: Use the Go native implementation
```
-And also, configtest subcommand checks sudo settings on target servers whether Vuls is able to SUDO with nopassword via SSH.
+The configtest subcommand checks the following
+- Whether vuls is able to connect via ssh to servers/containers defined in the config.toml
+- Whether Dependent package is installed on the scan target server
+- Check /etc/sudoers
-Example of /etc/sudoers on target servers
-- CentOS and RHEL
-```
-vuls ALL=(root) NOPASSWD: /usr/bin/yum
-```
-- Ubuntu, Debian and Raspbian
-```
-vuls ALL=(root) NOPASSWD: /usr/bin/apt-get
-```
-- It is possible to scan without root privilege for Amazon Linux, FreeBSD.
+## Dependencies on Target Servers
-
-
-----
-
-# Usage: Prepare
-
-Prepare subcommand installs required packages on each server.
+In order to scan, the following dependencies are required, so you need to install them manually or with tools such as Ansible.
| Distribution| Release | Requirements |
|:------------|-------------------:|:-------------|
| Ubuntu | 12, 14, 16| - |
| Debian | 7, 8| aptitude |
-| CentOS | 5| yum-changelog |
| CentOS | 6, 7| yum-plugin-changelog |
-| Amazon | All | - |
-| RHEL | 5, 6, 7 | - |
+| Amazon | All | - |
+| RHEL | 5 | yum-security |
+| RHEL | 6, 7 | - |
| FreeBSD | 10 | - |
| Raspbian | Wheezy, Jessie | - |
+## Check /etc/sudoers
-```
-$ vuls prepare -help
-prepare:
- prepare
- [-config=/path/to/config.toml]
- [-log-dir=/path/to/log]
- [-ask-key-password]
- [-assume-yes]
- [-debug]
- [-ssh-external]
+The configtest subcommand checks sudo settings on target servers whether Vuls is able to SUDO with nopassword via SSH.
- [SERVER]...
- -ask-key-password
- Ask ssh privatekey password before scanning
- -ask-sudo-password
- [Deprecated] THIS OPTION WAS REMOVED FOR SECURITY REASONS. Define NOPASSWD in /etc/sudoers on target servers and use SSH key-based authentication
- -assume-yes
- Assume any dependencies should be installed
- -config string
- /path/to/toml (default "$PWD/config.toml")
- -debug
- debug mode
- -log-dir string
- /path/to/log (default "/var/log/vuls")
- -ssh-external
- Use external ssh command. Default: Use the Go native implementation
+Example of /etc/sudoers on target servers
+
+- CentOS
```
+vuls ALL=(ALL) NOPASSWD:/usr/bin/yum --changelog --assumeno update *
+Defaults:vuls env_keep="http_proxy https_proxy HTTP_PROXY HTTPS_PROXY"
+```
+
+- RHEL 5
+```
+vuls ALL=(ALL) NOPASSWD:/usr/bin/yum --color=never repolist, /usr/bin/yum --color=never list-security --security, /usr/bin/yum --color=never check-update, /usr/bin/yum --color=never info-security
+Defaults:vuls env_keep="http_proxy https_proxy HTTP_PROXY HTTPS_PROXY"
+```
+
+- RHEL 6, 7
+```
+vuls ALL=(ALL) NOPASSWD:/usr/bin/yum --color=never repolist, /usr/bin/yum --color=never --security updateinfo list updates, /usr/bin/yum --color=never check-update, /usr/bin/yum --color=never --security updateinfo updates
+Defaults:vuls env_keep="http_proxy https_proxy HTTP_PROXY HTTPS_PROXY"
+```
+
+- Debian
+```
+vuls ALL=(ALL) NOPASSWD: /usr/bin/apt-get update
+Defaults:vuls env_keep="http_proxy https_proxy HTTP_PROXY HTTPS_PROXY"
+```
+
+- Ubuntu/Raspbian
+```
+vuls ALL=(ALL) NOPASSWD: /usr/bin/apt-get update
+Defaults:vuls env_keep="http_proxy https_proxy HTTP_PROXY HTTPS_PROXY"
+```
+
+- On Amazon Linux, FreeBSD, it is possible to scan without root privilege for now.
+
----
# Usage: Scan
diff --git a/commands/configtest.go b/commands/configtest.go
index 4a4f5da2..049e9cf8 100644
--- a/commands/configtest.go
+++ b/commands/configtest.go
@@ -36,6 +36,7 @@ type ConfigtestCmd struct {
logDir string
askKeyPassword bool
sshExternal bool
+ httpProxy string
debug bool
}
@@ -54,6 +55,7 @@ func (*ConfigtestCmd) Usage() string {
[-log-dir=/path/to/log]
[-ask-key-password]
[-ssh-external]
+ [-http-proxy=http://192.168.0.1:8080]
[-debug]
[SERVER]...
@@ -78,6 +80,13 @@ func (p *ConfigtestCmd) SetFlags(f *flag.FlagSet) {
"Ask ssh privatekey password before scanning",
)
+ f.StringVar(
+ &p.httpProxy,
+ "http-proxy",
+ "",
+ "http://proxy-url:port (default: empty)",
+ )
+
f.BoolVar(
&p.sshExternal,
"ssh-external",
@@ -108,6 +117,7 @@ func (p *ConfigtestCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interfa
return subcommands.ExitUsageError
}
c.Conf.SSHExternal = p.sshExternal
+ c.Conf.HTTPProxy = p.httpProxy
var servernames []string
if 0 < len(f.Args()) {
@@ -144,7 +154,10 @@ func (p *ConfigtestCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interfa
return subcommands.ExitFailure
}
- util.Log.Info("Checking sudo configuration...")
+ util.Log.Info("Checking dependendies...")
+ scan.CheckDependencies()
+
+ util.Log.Info("Checking sudo settings...")
scan.CheckIfSudoNoPasswd()
scan.PrintSSHableServerNames()
diff --git a/commands/prepare.go b/commands/prepare.go
deleted file mode 100644
index b582fba9..00000000
--- a/commands/prepare.go
+++ /dev/null
@@ -1,185 +0,0 @@
-/* Vuls - Vulnerability Scanner
-Copyright (C) 2016 Future Architect, Inc. Japan.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-package commands
-
-import (
- "context"
- "flag"
- "os"
- "path/filepath"
-
- c "github.com/future-architect/vuls/config"
- "github.com/future-architect/vuls/scan"
- "github.com/future-architect/vuls/util"
- "github.com/google/subcommands"
-)
-
-// PrepareCmd is Subcommand of host discovery mode
-type PrepareCmd struct {
- debug bool
- configPath string
- logDir string
-
- askSudoPassword bool
- askKeyPassword bool
-
- sshExternal bool
- assumeYes bool
-}
-
-// Name return subcommand name
-func (*PrepareCmd) Name() string { return "prepare" }
-
-// Synopsis return synopsis
-func (*PrepareCmd) Synopsis() string {
- return `Install required packages to scan.
- CentOS: yum-plugin-security, yum-plugin-changelog
- Amazon: None
- RHEL: None
- Ubuntu: None
- Debian: aptitude
-
- `
-}
-
-// Usage return usage
-func (*PrepareCmd) Usage() string {
- return `prepare:
- prepare
- [-config=/path/to/config.toml]
- [-log-dir=/path/to/log]
- [-ask-key-password]
- [-assume-yes]
- [-debug]
- [-ssh-external]
-
- [SERVER]...
-`
-}
-
-// SetFlags set flag
-func (p *PrepareCmd) SetFlags(f *flag.FlagSet) {
-
- f.BoolVar(&p.debug, "debug", false, "debug mode")
-
- wd, _ := os.Getwd()
-
- defaultConfPath := filepath.Join(wd, "config.toml")
- f.StringVar(&p.configPath, "config", defaultConfPath, "/path/to/toml")
-
- defaultLogDir := util.GetDefaultLogDir()
- f.StringVar(&p.logDir, "log-dir", defaultLogDir, "/path/to/log")
-
- f.BoolVar(
- &p.askKeyPassword,
- "ask-key-password",
- false,
- "Ask ssh privatekey password before scanning",
- )
-
- f.BoolVar(
- &p.askSudoPassword,
- "ask-sudo-password",
- false,
- "[Deprecated] THIS OPTION WAS REMOVED FOR SECURITY REASONS. Define NOPASSWD in /etc/sudoers on target servers and use SSH key-based authentication",
- )
-
- f.BoolVar(
- &p.sshExternal,
- "ssh-external",
- false,
- "Use external ssh command. Default: Use the Go native implementation")
-
- f.BoolVar(
- &p.assumeYes,
- "assume-yes",
- false,
- "Assume any dependencies should be installed")
-
-}
-
-// 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 {
- util.Log.Error(err)
- return subcommands.ExitFailure
- }
- }
- if p.askSudoPassword {
- 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 {
- util.Log.Errorf("Error loading %s, %s", p.configPath, err)
- return subcommands.ExitUsageError
- }
-
- util.Log.Infof("Start Preparing (config: %s)", p.configPath)
- target := make(map[string]c.ServerInfo)
- for _, arg := range f.Args() {
- found := false
- for servername, info := range c.Conf.Servers {
- if servername == arg {
- target[servername] = info
- found = true
- break
- }
- }
- if !found {
- util.Log.Errorf("%s is not in config", arg)
- return subcommands.ExitUsageError
- }
- }
- if 0 < len(f.Args()) {
- c.Conf.Servers = target
- }
-
- c.Conf.SSHExternal = p.sshExternal
- c.Conf.AssumeYes = p.assumeYes
-
- util.Log.Info("Validating config...")
- if !c.Conf.ValidateOnPrepare() {
- return subcommands.ExitUsageError
- }
-
- util.Log.Info("Detecting OS... ")
- if err := scan.InitServers(); err != nil {
- util.Log.Errorf("Failed to init servers: %s", err)
- return subcommands.ExitFailure
- }
-
- util.Log.Info("Checking sudo configuration... ")
- scan.CheckIfSudoNoPasswd()
-
- if err := scan.Prepare(); err != nil {
- util.Log.Errorf("Failed to prepare: %s", err)
- return subcommands.ExitFailure
- }
-
- return subcommands.ExitSuccess
-}
diff --git a/commands/scan.go b/commands/scan.go
index c65affdd..ebdef500 100644
--- a/commands/scan.go
+++ b/commands/scan.go
@@ -216,9 +216,6 @@ func (p *ScanCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
return subcommands.ExitFailure
}
- util.Log.Info("Checking sudo configuration... ")
- scan.CheckIfSudoNoPasswd()
-
util.Log.Info("Detecting Platforms... ")
scan.DetectPlatforms()
diff --git a/main.go b/main.go
index d690ff8a..39520b39 100644
--- a/main.go
+++ b/main.go
@@ -41,7 +41,6 @@ func main() {
subcommands.Register(&commands.DiscoverCmd{}, "discover")
subcommands.Register(&commands.TuiCmd{}, "tui")
subcommands.Register(&commands.ScanCmd{}, "scan")
- subcommands.Register(&commands.PrepareCmd{}, "prepare")
subcommands.Register(&commands.HistoryCmd{}, "history")
subcommands.Register(&commands.ReportCmd{}, "report")
subcommands.Register(&commands.ConfigtestCmd{}, "configtest")
diff --git a/scan/base.go b/scan/base.go
index 0fd3fe15..bd847331 100644
--- a/scan/base.go
+++ b/scan/base.go
@@ -34,7 +34,6 @@ type base struct {
Distro config.Distro
Platform models.Platform
- lackDependencies []string
osPackages
log *logrus.Entry
@@ -77,10 +76,6 @@ func (l base) getPlatform() models.Platform {
return l.Platform
}
-func (l base) getLackDependencies() []string {
- return l.lackDependencies
-}
-
func (l base) allContainers() (containers []config.Container, err error) {
switch l.ServerInfo.Container.Type {
case "", "docker":
diff --git a/scan/debian.go b/scan/debian.go
index 70658e5c..80b33b23 100644
--- a/scan/debian.go
+++ b/scan/debian.go
@@ -128,12 +128,14 @@ func trim(str string) string {
}
func (o *debian) checkIfSudoNoPasswd() error {
- r := o.exec("apt-get -v", noSudo)
+ cmd := util.PrependProxyEnv("apt-get update")
+ o.log.Infof("Checking... sudo %s", cmd)
+ r := o.exec(cmd, sudo)
if !r.isSuccess() {
o.log.Errorf("sudo error on %s", r)
return fmt.Errorf("Failed to sudo: %s", r)
}
- o.log.Infof("sudo ... OK")
+ o.log.Infof("Sudo... Pass")
return nil
}
@@ -145,11 +147,12 @@ func (o *debian) checkDependencies() error {
case "debian":
// Debian needs aptitude to get changelogs.
// Because unable to get changelogs via apt-get changelog on Debian.
- name := "aptitude"
- cmd := name + " -h"
- if r := o.exec(cmd, noSudo); !r.isSuccess() {
- o.lackDependencies = []string{name}
+ if r := o.exec("test -f /usr/bin/aptitude", noSudo); !r.isSuccess() {
+ msg := fmt.Sprintf("aptitude is not installed: %s", r)
+ o.log.Errorf(msg)
+ return fmt.Errorf(msg)
}
+ o.log.Infof("Dependencies... Pass")
return nil
default:
@@ -157,32 +160,6 @@ func (o *debian) checkDependencies() error {
}
}
-func (o *debian) install() error {
- if len(o.lackDependencies) == 0 {
- return nil
- }
-
- // apt-get update
- o.log.Infof("apt-get update...")
- cmd := util.PrependProxyEnv("apt-get update")
- if r := o.exec(cmd, sudo); !r.isSuccess() {
- msg := fmt.Sprintf("Failed to SSH: %s", r)
- o.log.Errorf(msg)
- return fmt.Errorf(msg)
- }
-
- for _, name := range o.lackDependencies {
- cmd = util.PrependProxyEnv("apt-get install -y " + name)
- if r := o.exec(cmd, sudo); !r.isSuccess() {
- msg := fmt.Sprintf("Failed to SSH: %s", r)
- o.log.Errorf(msg)
- return fmt.Errorf(msg)
- }
- o.log.Infof("Installed: " + name)
- }
- return nil
-}
-
func (o *debian) scanPackages() error {
var err error
var packs []models.PackageInfo
@@ -244,17 +221,6 @@ func (o *debian) parseScannedPackagesLine(line string) (name, version string, er
return "", "", fmt.Errorf("Unknown format: %s", line)
}
-func (o *debian) checkRequiredPackagesInstalled() error {
- if o.Distro.Family == "debian" {
- if r := o.exec("test -f /usr/bin/aptitude", noSudo); !r.isSuccess() {
- msg := fmt.Sprintf("aptitude is not installed: %s", r)
- o.log.Errorf(msg)
- return fmt.Errorf(msg)
- }
- }
- return nil
-}
-
func (o *debian) scanUnsecurePackages(installed []models.PackageInfo) ([]models.VulnInfo, error) {
o.log.Infof("apt-get update...")
cmd := util.PrependProxyEnv("apt-get update")
diff --git a/scan/executil.go b/scan/executil.go
index 7d9cd40b..07ee5729 100644
--- a/scan/executil.go
+++ b/scan/executil.go
@@ -327,9 +327,6 @@ func decorateCmd(c conf.ServerInfo, cmd string, sudo bool) string {
if sudo && c.User != "root" && !c.IsContainer() {
cmd = fmt.Sprintf("sudo -S %s", cmd)
cmd = strings.Replace(cmd, "|", "| sudo ", -1)
-
- // echo command does not need sudo (for CentOS)
- cmd = strings.Replace(cmd, "sudo -S echo", "echo", -1)
}
// If you are using pipe and you want to detect preprocessing errors, remove comment out
diff --git a/scan/freebsd.go b/scan/freebsd.go
index 7aaf1790..f8712ef6 100644
--- a/scan/freebsd.go
+++ b/scan/freebsd.go
@@ -69,14 +69,6 @@ func (o *bsd) checkDependencies() error {
return nil
}
-func (o *bsd) install() error {
- return nil
-}
-
-func (o *bsd) checkRequiredPackagesInstalled() error {
- return nil
-}
-
func (o *bsd) scanPackages() error {
var err error
var packs []models.PackageInfo
diff --git a/scan/redhat.go b/scan/redhat.go
index 06e74a56..c7bb44e7 100644
--- a/scan/redhat.go
+++ b/scan/redhat.go
@@ -102,83 +102,97 @@ func (o *redhat) checkIfSudoNoPasswd() error {
return nil
}
- cmd := "yum --version"
- if o.Distro.Family == "centos" {
- cmd = "echo N | " + cmd
+ type cmd struct {
+ cmd string
+ expectedStatusCodes []int
}
- 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)
- }
- o.log.Infof("sudo ... OK")
- return nil
-}
+ var cmds []cmd
+ var zero = []int{0}
-// CentOS 5 ... yum-changelog
-// CentOS 6 ... yum-plugin-changelog
-// CentOS 7 ... yum-plugin-changelog
-// RHEL, Amazon ... no additinal packages needed
-func (o *redhat) checkDependencies() error {
switch o.Distro.Family {
- case "rhel", "amazon":
- return nil
-
case "centos":
+ cmds = []cmd{
+ {"yum --changelog --assumeno update yum", []int{0, 1}},
+ }
+
+ case "rhel":
majorVersion, err := o.Distro.MajorVersion()
if err != nil {
return fmt.Errorf("Not implemented yet: %s, err: %s", o.Distro, err)
}
- var name = "yum-plugin-changelog"
if majorVersion < 6 {
- name = "yum-changelog"
+ cmds = []cmd{
+ {"yum --color=never repolist", zero},
+ {"yum --color=never check-update", []int{0, 100}},
+ {"yum --color=never list-security --security", zero},
+ {"yum --color=never info-security", zero},
+ }
+ } else {
+ cmds = []cmd{
+ {"yum --color=never repolist", zero},
+ {"yum --color=never check-update", []int{0, 100}},
+ {"yum --color=never --security updateinfo list updates", zero},
+ {"yum --color=never --security updateinfo updates", zero},
+ }
}
-
- cmd := "rpm -q " + name
- if r := o.exec(cmd, noSudo); r.isSuccess() {
- return nil
- }
- o.lackDependencies = []string{name}
- return nil
-
- default:
- return fmt.Errorf("Not implemented yet: %s", o.Distro)
}
-}
-func (o *redhat) install() error {
- for _, name := range o.lackDependencies {
- cmd := util.PrependProxyEnv("yum install -y " + name)
- if r := o.exec(cmd, sudo); !r.isSuccess() {
- return fmt.Errorf("Failed to SSH: %s", r)
+ for _, c := range cmds {
+ cmd := util.PrependProxyEnv(c.cmd)
+ o.log.Infof("Checking... sudo %s", cmd)
+ r := o.exec(util.PrependProxyEnv(cmd), o.sudo())
+ if !r.isSuccess(c.expectedStatusCodes...) {
+ o.log.Errorf("Check sudo or proxy settings: %s", r)
+ return fmt.Errorf("Failed to sudo: %s", r)
}
- o.log.Infof("Installed: %s", name)
}
+ o.log.Infof("Sudo... Pass")
return nil
}
-func (o *redhat) checkRequiredPackagesInstalled() error {
- if o.Distro.Family == "centos" {
- majorVersion, err := o.Distro.MajorVersion()
- if err != nil {
- msg := fmt.Sprintf("Not implemented yet: %s, err: %s", o.Distro, err)
- o.log.Errorf(msg)
- return fmt.Errorf(msg)
- }
+// CentOS 5 ... yum-changelog
+// CentOS 6, 7 ... yum-plugin-changelog
+// RHEL 5 ... yum-security
+// RHEL 6, 7 ... -
+// Amazon ... -
+func (o *redhat) checkDependencies() error {
+ var packName string
+ if o.Distro.Family == "amazon" {
+ return nil
+ }
- var packName = "yum-plugin-changelog"
+ majorVersion, err := o.Distro.MajorVersion()
+ if err != nil {
+ msg := fmt.Sprintf("Not implemented yet: %s, err: %s", o.Distro, err)
+ o.log.Errorf(msg)
+ return fmt.Errorf(msg)
+ }
+
+ switch o.Distro.Family {
+ case "centos":
+ packName = "yum-plugin-changelog"
if majorVersion < 6 {
packName = "yum-changelog"
}
-
- cmd := "rpm -q " + packName
- if r := o.exec(cmd, noSudo); !r.isSuccess() {
- msg := fmt.Sprintf("%s is not installed", packName)
- o.log.Errorf(msg)
- return fmt.Errorf(msg)
+ case "rhel":
+ if majorVersion < 6 {
+ packName = "yum-security"
+ } else {
+ // yum-plugin-security is installed by default on RHEL6, 7
+ return nil
}
+ default:
+ return fmt.Errorf("Not implemented yet: %s", o.Distro)
}
+
+ cmd := "rpm -q " + packName
+ if r := o.exec(cmd, noSudo); !r.isSuccess() {
+ msg := fmt.Sprintf("%s is not installed", packName)
+ o.log.Errorf(msg)
+ return fmt.Errorf(msg)
+ }
+ o.log.Infof("Dependencies... Pass")
return nil
}
@@ -551,7 +565,7 @@ func (o *redhat) getAllChangelog(packInfoList models.PackageInfoList) (stdout st
packageNames += fmt.Sprintf("%s ", packInfo.Name)
}
- command := "echo N | "
+ command := ""
if 0 < len(config.Conf.HTTPProxy) {
command += util.ProxyEnv()
}
@@ -565,7 +579,7 @@ func (o *redhat) getAllChangelog(packInfoList models.PackageInfoList) (stdout st
}
// yum update --changelog doesn't have --color option.
- command += fmt.Sprintf(" LANGUAGE=en_US.UTF-8 yum %s --changelog update ", yumopts) + packageNames
+ command += fmt.Sprintf(" LANGUAGE=en_US.UTF-8 yum --changelog --assumeno update %s ", yumopts) + packageNames
r := o.exec(command, sudo)
if !r.isSuccess(0, 1) {
@@ -647,7 +661,7 @@ func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos,
// get advisoryID(RHSA, ALAS) - CVE IDs
if o.Distro.Family == "rhel" && major == 5 {
- cmd = "yum --color=never info-sec"
+ cmd = "yum --color=never info-security"
} else {
cmd = "yum --color=never --security updateinfo updates"
}
diff --git a/scan/serverapi.go b/scan/serverapi.go
index c35e76e9..c0198267 100644
--- a/scan/serverapi.go
+++ b/scan/serverapi.go
@@ -18,11 +18,9 @@ along with this program. If not, see .
package scan
import (
- "bufio"
"fmt"
"os"
"path/filepath"
- "strings"
"time"
"github.com/future-architect/vuls/cache"
@@ -38,21 +36,16 @@ var servers, errServers []osTypeInterface
type osTypeInterface interface {
setServerInfo(config.ServerInfo)
getServerInfo() config.ServerInfo
-
setDistro(string, string)
getDistro() config.Distro
-
- // checkDependencies checks if dependencies are installed on the target server.
- checkDependencies() error
- getLackDependencies() []string
-
- checkIfSudoNoPasswd() error
detectPlatform()
getPlatform() models.Platform
- checkRequiredPackagesInstalled() error
+ // checkDependencies checks if dependencies are installed on the target server.
+ checkDependencies() error
+ checkIfSudoNoPasswd() error
+
scanPackages() error
- install() error
convertToModel() models.ScanResult
runningContainers() ([]config.Container, error)
@@ -113,7 +106,7 @@ func detectOS(c config.ServerInfo) (osType osTypeInterface) {
// PrintSSHableServerNames print SSH-able servernames
func PrintSSHableServerNames() {
- util.Log.Info("SSH-able servers are below...")
+ util.Log.Info("Scannable servers are below...")
for _, s := range servers {
if s.getServerInfo().IsContainer() {
fmt.Printf("%s@%s ",
@@ -338,9 +331,18 @@ func detectContainerOSesOnServer(containerHost osTypeInterface) (oses []osTypeIn
return oses
}
+// CheckDependencies checks dependencies are installed on target servers.
+func CheckDependencies() {
+ timeoutSec := 5 * 60
+ parallelExec(func(o osTypeInterface) error {
+ return o.checkDependencies()
+ }, timeoutSec)
+ return
+}
+
// CheckIfSudoNoPasswd checks whether vuls can sudo with nopassword via SSH
func CheckIfSudoNoPasswd() {
- timeoutSec := 15
+ timeoutSec := 5 * 60
parallelExec(func(o osTypeInterface) error {
return o.checkIfSudoNoPasswd()
}, timeoutSec)
@@ -380,117 +382,12 @@ func detectPlatforms() {
return
}
-// Prepare installs requred packages to scan vulnerabilities.
-func Prepare() error {
- parallelExec(func(o osTypeInterface) error {
- if err := o.checkDependencies(); err != nil {
- return err
- }
- return nil
- })
-
- var targets, nonTargets []osTypeInterface
- for _, s := range servers {
- deps := s.getLackDependencies()
- if len(deps) != 0 {
- targets = append(targets, s)
- } else {
- nonTargets = append(nonTargets, s)
- }
- }
- if len(targets) == 0 {
- if 0 < len(nonTargets) {
- util.Log.Info("The following servers were already installed dependencies")
- for _, s := range nonTargets {
- util.Log.Infof(" - %s", s.getServerInfo().GetServerName())
- }
- }
-
- if 0 < len(errServers) {
- util.Log.Error("Some errors occurred in the following servers")
- for _, s := range errServers {
- util.Log.Errorf(" - %s", s.getServerInfo().GetServerName())
- }
- } else {
- util.Log.Info("Success")
- }
- return nil
- }
-
- util.Log.Info("The following servers need to install dependencies")
- for _, s := range targets {
- for _, d := range s.getLackDependencies() {
- util.Log.Infof(" - %s on %s", d, s.getServerInfo().GetServerName())
- }
- }
-
- if !config.Conf.AssumeYes {
- util.Log.Info("Is this ok to install dependencies on the servers? [y/N]")
-
- reader := bufio.NewReader(os.Stdin)
- for {
- text, err := reader.ReadString('\n')
- if err != nil {
- return err
- }
- switch strings.TrimSpace(text) {
- case "", "N", "n":
- return nil
- case "y", "Y":
- goto yes
- default:
- util.Log.Info("Please enter y or N")
- }
- }
- }
-
-yes:
- servers = targets
- parallelExec(func(o osTypeInterface) error {
- if err := o.install(); err != nil {
- return err
- }
- return nil
- })
-
- if 0 < len(servers) {
- util.Log.Info("Successfully installed in the followring servers")
- for _, s := range servers {
- util.Log.Infof(" - %s", s.getServerInfo().GetServerName())
- }
- }
-
- if 0 < len(nonTargets) {
- util.Log.Info("The following servers were already installed dependencies")
- for _, s := range nonTargets {
- util.Log.Infof(" - %s", s.getServerInfo().GetServerName())
- }
- }
-
- if 0 < len(errServers) {
- util.Log.Error("Some errors occurred in the following servers")
- for _, s := range errServers {
- util.Log.Errorf(" - %s", s.getServerInfo().GetServerName())
- }
- }
-
- if len(errServers) == 0 {
- util.Log.Info("Success")
- } else {
- util.Log.Error("Failure")
- }
- return nil
-}
-
// Scan scan
func Scan() error {
if len(servers) == 0 {
return fmt.Errorf("No server defined. Check the configuration")
}
- util.Log.Info("Check required packages for scanning...")
- checkRequiredPackagesInstalled()
-
if err := setupChangelogCache(); err != nil {
return err
}
@@ -530,14 +427,6 @@ func setupChangelogCache() error {
return nil
}
-func checkRequiredPackagesInstalled() []error {
- timeoutSec := 30 * 60
- parallelExec(func(o osTypeInterface) error {
- return o.checkRequiredPackagesInstalled()
- }, timeoutSec)
- return nil
-}
-
func scanVulns(jsonDir string, scannedAt time.Time) error {
var results models.ScanResults
timeoutSec := 120 * 60
diff --git a/scan/unknownDistro.go b/scan/unknownDistro.go
index b7221ba8..30b0ab76 100644
--- a/scan/unknownDistro.go
+++ b/scan/unknownDistro.go
@@ -30,14 +30,6 @@ func (o unknown) checkDependencies() error {
return nil
}
-func (o *unknown) install() error {
- return nil
-}
-
-func (o *unknown) checkRequiredPackagesInstalled() error {
- return nil
-}
-
func (o *unknown) scanPackages() error {
return nil
}
diff --git a/util/util.go b/util/util.go
index 6942fb7c..3b94e8a6 100644
--- a/util/util.go
+++ b/util/util.go
@@ -95,7 +95,7 @@ func URLPathParamJoin(baseURL string, paths []string, params map[string]string)
// ProxyEnv returns shell environment variables to set proxy
func ProxyEnv() string {
- httpProxyEnv := "env"
+ httpProxyEnv := ""
keys := []string{
"http_proxy",
"https_proxy",
diff --git a/util/util_test.go b/util/util_test.go
index 2ec538d4..49340a3d 100644
--- a/util/util_test.go
+++ b/util/util_test.go
@@ -105,14 +105,14 @@ func TestPrependHTTPProxyEnv(t *testing.T) {
"http://proxy.co.jp:8080",
"yum check-update",
},
- `env http_proxy="http://proxy.co.jp:8080" https_proxy="http://proxy.co.jp:8080" HTTP_PROXY="http://proxy.co.jp:8080" HTTPS_PROXY="http://proxy.co.jp:8080" yum check-update`,
+ ` http_proxy="http://proxy.co.jp:8080" https_proxy="http://proxy.co.jp:8080" HTTP_PROXY="http://proxy.co.jp:8080" HTTPS_PROXY="http://proxy.co.jp:8080" yum check-update`,
},
{
[]string{
"http://proxy.co.jp:8080",
"",
},
- `env http_proxy="http://proxy.co.jp:8080" https_proxy="http://proxy.co.jp:8080" HTTP_PROXY="http://proxy.co.jp:8080" HTTPS_PROXY="http://proxy.co.jp:8080" `,
+ ` http_proxy="http://proxy.co.jp:8080" https_proxy="http://proxy.co.jp:8080" HTTP_PROXY="http://proxy.co.jp:8080" HTTPS_PROXY="http://proxy.co.jp:8080" `,
},
{
[]string{