Disable -ask-sudo-password for security reasons

This commit is contained in:
kota kanbe
2016-08-09 10:23:57 +09:00
parent e5b1a0bef8
commit f939041606
13 changed files with 149 additions and 133 deletions

View File

@@ -45,11 +45,7 @@ func newDebian(c config.ServerInfo) *debian {
// Ubuntu, Debian
// https://github.com/serverspec/specinfra/blob/master/lib/specinfra/helper/detect_os/debian.rb
func detectDebian(c config.ServerInfo) (itsMe bool, deb osTypeInterface, err error) {
deb = newDebian(c)
// set sudo option flag
c.SudoOpt = config.SudoOption{ExecBySudo: true}
deb.setServerInfo(c)
if r := sshExec(c, "ls /etc/debian_version", noSudo); !r.isSuccess() {
@@ -119,6 +115,16 @@ func trim(str string) string {
return strings.TrimSpace(str)
}
func (o *debian) checkIfSudoNoPasswd() error {
r := o.ssh("apt-get -v", 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
}
func (o *debian) install() error {
// apt-get update

View File

@@ -39,6 +39,12 @@ func detectFreebsd(c config.ServerInfo) (itsMe bool, bsd osTypeInterface) {
return false, bsd
}
func (o *bsd) checkIfSudoNoPasswd() error {
// FreeBSD doesn't need root privilege
o.log.Infof("sudo ... OK")
return nil
}
func (o *bsd) install() error {
return nil
}

View File

@@ -47,11 +47,7 @@ func newRedhat(c config.ServerInfo) *redhat {
// https://github.com/serverspec/specinfra/blob/master/lib/specinfra/helper/detect_os/redhat.rb
func detectRedhat(c config.ServerInfo) (itsMe bool, red osTypeInterface) {
red = newRedhat(c)
// set sudo option flag
c.SudoOpt = config.SudoOption{ExecBySudo: true}
red.setServerInfo(c)
if r := sshExec(c, "ls /etc/fedora-release", noSudo); r.isSuccess() {
@@ -102,6 +98,16 @@ func detectRedhat(c config.ServerInfo) (itsMe bool, red osTypeInterface) {
return false, red
}
func (o *redhat) checkIfSudoNoPasswd() error {
r := o.ssh("yum --version", 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
}
// CentOS 5 ... yum-plugin-security, yum-changelog
// CentOS 6 ... yum-plugin-security, yum-plugin-changelog
// CentOS 7 ... yum-plugin-security, yum-plugin-changelog

View File

@@ -23,6 +23,7 @@ type osTypeInterface interface {
setDistributionInfo(string, string)
getDistributionInfo() string
checkIfSudoNoPasswd() error
detectPlatform() error
getPlatform() models.Platform
@@ -133,14 +134,8 @@ func detectOS(c config.ServerInfo) (osType osTypeInterface) {
return
}
// InitServers detect the kind of OS distribution of target servers
func InitServers(localLogger *logrus.Entry) {
Log = localLogger
servers = detectServerOSes()
containers := detectContainerOSes()
servers = append(servers, containers...)
// PrintSSHableServerNames print SSH-able servernames
func PrintSSHableServerNames() {
Log.Info("SSH-able servers are below...")
for _, s := range servers {
if s.getServerInfo().IsContainer() {
@@ -155,6 +150,14 @@ func InitServers(localLogger *logrus.Entry) {
fmt.Printf("\n")
}
// InitServers detect the kind of OS distribution of target servers
func InitServers(localLogger *logrus.Entry) {
Log = localLogger
servers = detectServerOSes()
containers := detectContainerOSes()
servers = append(servers, containers...)
}
func detectServerOSes() (sshAbleOses []osTypeInterface) {
Log.Info("Detecting OS of servers... ")
osTypeChan := make(chan osTypeInterface, len(config.Conf.Servers))
@@ -345,6 +348,19 @@ func detectContainerOSesOnServer(containerHost osTypeInterface) (oses []osTypeIn
return oses
}
// CheckIfSudoNoPasswd checks whether vuls can sudo with nopassword via SSH
func CheckIfSudoNoPasswd(localLogger *logrus.Entry) error {
timeoutSec := 1 * 15
errs := parallelSSHExec(func(o osTypeInterface) error {
return o.checkIfSudoNoPasswd()
}, timeoutSec)
if 0 < len(errs) {
return fmt.Errorf(fmt.Sprintf("%s", errs))
}
return nil
}
// DetectPlatforms detects the platform of each servers.
func DetectPlatforms(localLogger *logrus.Entry) {
errs := detectPlatforms()

View File

@@ -79,8 +79,11 @@ const sudo = true
const noSudo = false
func parallelSSHExec(fn func(osTypeInterface) error, timeoutSec ...int) (errs []error) {
resChan := make(chan string, len(servers))
errChan := make(chan error, len(servers))
defer close(errChan)
defer close(resChan)
for _, s := range servers {
go func(s osTypeInterface) {
defer func() {
@@ -97,7 +100,7 @@ func parallelSSHExec(fn func(osTypeInterface) error, timeoutSec ...int) (errs []
err,
)
} else {
errChan <- nil
resChan <- s.getServerInfo().ServerName
}
}(s)
}
@@ -109,19 +112,40 @@ func parallelSSHExec(fn func(osTypeInterface) error, timeoutSec ...int) (errs []
timeout = timeoutSec[0]
}
var snames []string
isTimedout := false
for i := 0; i < len(servers); i++ {
select {
case s := <-resChan:
snames = append(snames, s)
case err := <-errChan:
if err != nil {
errs = append(errs, err)
} else {
logrus.Debug("Parallel SSH Success")
}
errs = append(errs, err)
case <-time.After(time.Duration(timeout) * time.Second):
logrus.Errorf("Parallel SSH Timeout")
errs = append(errs, fmt.Errorf("Timed out"))
isTimedout = true
}
}
// collect timed out servernames
var timedoutSnames []string
if isTimedout {
for _, s := range servers {
name := s.getServerInfo().ServerName
found := false
for _, t := range snames {
if name == t {
found = true
break
}
}
if !found {
timedoutSnames = append(timedoutSnames, name)
}
}
}
if isTimedout {
errs = append(errs, fmt.Errorf(
"Timed out: %s", timedoutSnames))
}
return
}
@@ -196,7 +220,7 @@ func sshExecNative(c conf.ServerInfo, cmd string, sudo bool) (result sshResult)
result.Stdout = stdoutBuf.String()
result.Stderr = stderrBuf.String()
result.Cmd = strings.Replace(maskPassword(cmd, c.Password), "\n", "", -1)
result.Cmd = strings.Replace(cmd, "\n", "", -1)
return
}
@@ -234,6 +258,8 @@ func sshExecExternal(c conf.ServerInfo, cmd string, sudo bool) (result sshResult
}
cmd = decolateCmd(c, cmd, sudo)
// cmd = fmt.Sprintf("stty cols 256; set -o pipefail; %s", cmd)
args = append(args, cmd)
execCmd := exec.Command(sshBinaryPath, args...)
@@ -259,8 +285,7 @@ func sshExecExternal(c conf.ServerInfo, cmd string, sudo bool) (result sshResult
result.Servername = c.ServerName
result.Host = c.Host
result.Port = c.Port
result.Cmd = fmt.Sprintf("%s %s",
sshBinaryPath, maskPassword(strings.Join(args, " "), c.Password))
result.Cmd = fmt.Sprintf("%s %s", sshBinaryPath, strings.Join(args, " "))
return
}
@@ -272,14 +297,8 @@ func getSSHLogger(log ...*logrus.Entry) *logrus.Entry {
}
func decolateCmd(c conf.ServerInfo, cmd string, sudo bool) string {
c.SudoOpt.ExecBySudo = true
if sudo && c.User != "root" && !c.IsContainer() {
switch {
case c.SudoOpt.ExecBySudo:
cmd = fmt.Sprintf("echo %s | sudo -S %s", c.Password, cmd)
case c.SudoOpt.ExecBySudoSh:
cmd = fmt.Sprintf("echo %s | sudo sh -c '%s'", c.Password, cmd)
}
cmd = fmt.Sprintf("sudo -S %s", cmd)
}
if c.Family != "FreeBSD" {
@@ -331,10 +350,6 @@ func sshConnect(c conf.ServerInfo) (client *ssh.Client, err error) {
return nil, err
}
if c.Password != "" {
auths = append(auths, ssh.Password(c.Password))
}
// http://blog.ralch.com/tutorial/golang-ssh-connection/
config := &ssh.ClientConfig{
User: c.User,
@@ -411,8 +426,3 @@ func parsePemBlock(block *pem.Block) (interface{}, error) {
return nil, fmt.Errorf("Unsupported key type %q", block.Type)
}
}
// ref golang.org/x/crypto/ssh/keys.go#ParseRawPrivateKey.
func maskPassword(cmd, sudoPass string) string {
return strings.Replace(cmd, fmt.Sprintf("echo %s", sudoPass), "echo *****", -1)
}