Skip to content

Commit

Permalink
Confirm before installing dependencies on prepare
Browse files Browse the repository at this point in the history
  • Loading branch information
kotakanbe committed Oct 13, 2016
1 parent cb5a6f3 commit 21beb39
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 28 deletions.
3 changes: 1 addition & 2 deletions commands/prepare.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,9 @@ func (p *PrepareCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{
return subcommands.ExitFailure
}

logger.Info("Installing...")
if errs := scan.Prepare(); 0 < len(errs) {
for _, e := range errs {
logger.Errorf("Failed: %s", e)
logger.Errorf("Failed to prepare: %s", e)
}
return subcommands.ExitFailure
}
Expand Down
7 changes: 6 additions & 1 deletion scan/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ import (
type base struct {
ServerInfo config.ServerInfo
Distro config.Distro
Platform models.Platform

Platform models.Platform
lackDependencies []string
osPackages

log *logrus.Entry
Expand Down Expand Up @@ -77,6 +78,10 @@ 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":
Expand Down
31 changes: 27 additions & 4 deletions scan/debian.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,31 @@ func (o *debian) checkIfSudoNoPasswd() error {
return nil
}

func (o *debian) checkDependencies() error {
switch o.Distro.Family {
case "ubuntu":
return nil

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.ssh(cmd, noSudo); !r.isSuccess() {
o.lackDependencies = []string{name}
}
return nil

default:
return fmt.Errorf("Not implemented yet: %s", o.Distro)
}
}

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")
Expand All @@ -134,15 +158,14 @@ func (o *debian) install() error {
return fmt.Errorf(msg)
}

if o.Distro.Family == "debian" {
// install aptitude
cmd = util.PrependProxyEnv("apt-get install --force-yes -y aptitude")
for _, name := range o.lackDependencies {
cmd = util.PrependProxyEnv("apt-get install " + name)
if r := o.ssh(cmd, sudo); !r.isSuccess() {
msg := fmt.Sprintf("Failed to SSH: %s", r)
o.log.Errorf(msg)
return fmt.Errorf(msg)
}
o.log.Infof("Installed: aptitude")
o.log.Infof("Installed: " + name)
}
return nil
}
Expand Down
4 changes: 4 additions & 0 deletions scan/freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ func (o *bsd) checkIfSudoNoPasswd() error {
return nil
}

func (o *bsd) checkDependencies() error {
return nil
}

func (o *bsd) install() error {
return nil
}
Expand Down
37 changes: 19 additions & 18 deletions scan/redhat.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,45 +112,46 @@ func (o *redhat) checkIfSudoNoPasswd() error {
// CentOS 6 ... yum-plugin-changelog
// CentOS 7 ... yum-plugin-changelog
// RHEL, Amazon ... no additinal packages needed
func (o *redhat) install() error {
func (o *redhat) checkDependencies() error {
switch o.Distro.Family {
case "rhel", "amazon":
o.log.Infof("Nothing to do")
// o.log.Infof("Nothing to do")
return nil
}
// CentOS
return o.installYumChangelog()
}

func (o *redhat) installYumChangelog() error {
if o.Distro.Family == "centos" {
case "centos":
var majorVersion int
if 0 < len(o.Distro.Release) {
majorVersion, _ = strconv.Atoi(strings.Split(o.Distro.Release, ".")[0])
} else {
return fmt.Errorf(
"Not implemented yet: %s", o.Distro)
return fmt.Errorf("Not implemented yet: %s", o.Distro)
}

var packName = ""
var name = ""
if majorVersion < 6 {
packName = "yum-changelog"
name = "yum-changelog"
} else {
packName = "yum-plugin-changelog"
name = "yum-plugin-changelog"
}

cmd := "rpm -q " + packName
cmd := "rpm -q " + name
if r := o.ssh(cmd, noSudo); r.isSuccess() {
o.log.Infof("Ignored: %s already installed", packName)
return nil
}
o.lackDependencies = []string{name}
return nil

o.log.Infof("Installing %s...", packName)
cmd = util.PrependProxyEnv("yum install -y " + packName)
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.ssh(cmd, sudo); !r.isSuccess() {
return fmt.Errorf("Failed to SSH: %s", r)
}
o.log.Infof("Installed: %s", packName)
o.log.Infof("Installed: %s", name)
}
return nil
}
Expand Down
65 changes: 62 additions & 3 deletions scan/serverapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package scan

import (
"bufio"
"fmt"
"os"
"strings"
"time"

"github.com/Sirupsen/logrus"
Expand All @@ -40,7 +43,10 @@ type osTypeInterface interface {

setDistro(string, string)
getDistro() config.Distro
// getFamily() string

// checkDependencies checks if dependencies are installed on the target server.
checkDependencies() error
getLackDependencies() []string

checkIfSudoNoPasswd() error
detectPlatform() error
Expand All @@ -60,7 +66,7 @@ type osTypeInterface interface {
setErrs([]error)
}

// osPackages included by linux struct
// osPackages is included by base struct
type osPackages struct {
// installed packages
Packages models.PackageInfoList
Expand Down Expand Up @@ -425,12 +431,65 @@ func detectPlatforms() []error {

// Prepare installs requred packages to scan vulnerabilities.
func Prepare() []error {
return parallelSSHExec(func(o osTypeInterface) error {
errs := parallelSSHExec(func(o osTypeInterface) error {
if err := o.checkDependencies(); err != nil {
return err
}
return nil
})
if len(errs) != 0 {
return errs
}

var targets []osTypeInterface
for _, s := range servers {
deps := s.getLackDependencies()
if len(deps) != 0 {
targets = append(targets, s)
}
}
if len(targets) == 0 {
Log.Info("No need to install dependencies")
return nil
}

Log.Info("Below servers are needed to install dependencies")
for _, s := range targets {
for _, d := range s.getLackDependencies() {
Log.Infof(" - %s on %s", d, s.getServerInfo().GetServerName())
}
}
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 []error{err}
}
switch strings.TrimSpace(text) {
case "", "N", "n":
return nil
case "y", "Y":
goto yes
default:
Log.Info("Please enter y or N")
}
}

yes:
servers = targets
errs = parallelSSHExec(func(o osTypeInterface) error {
if err := o.install(); err != nil {
return err
}
return nil
})
if len(errs) != 0 {
return errs
}
Log.Info("All dependencies were installed correctly")
return nil
}

// Scan scan
Expand Down

0 comments on commit 21beb39

Please sign in to comment.