Support SUSE Enterprise Linux (#487)
* Support SUSE Enterprise Linux * Implement Reboot Required detection on SLES * Fix query OVAL because SUSE provides OVAL data each major.minor version * Update README * Support SUSE Enterprise 11
This commit is contained in:
		@@ -280,14 +280,7 @@ func (o *redhat) scanInstalledPackages() (models.Packages, error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	installed := models.Packages{}
 | 
			
		||||
	var cmd string
 | 
			
		||||
	majorVersion, _ := o.Distro.MajorVersion()
 | 
			
		||||
	if majorVersion < 6 {
 | 
			
		||||
		cmd = "rpm -qa --queryformat '%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH}\n'"
 | 
			
		||||
	} else {
 | 
			
		||||
		cmd = "rpm -qa --queryformat '%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH}\n'"
 | 
			
		||||
	}
 | 
			
		||||
	r := o.exec(cmd, noSudo)
 | 
			
		||||
	r := o.exec(rpmQa(o.Distro), noSudo)
 | 
			
		||||
	if !r.isSuccess() {
 | 
			
		||||
		return nil, fmt.Errorf("Scan packages failed: %s", r)
 | 
			
		||||
	}
 | 
			
		||||
@@ -304,14 +297,13 @@ func (o *redhat) scanInstalledPackages() (models.Packages, error) {
 | 
			
		||||
			// Kernel package may be isntalled multiple versions.
 | 
			
		||||
			// From the viewpoint of vulnerability detection,
 | 
			
		||||
			// pay attention only to the running kernel
 | 
			
		||||
			if pack.Name == "kernel" {
 | 
			
		||||
				ver := fmt.Sprintf("%s-%s.%s", pack.Version, pack.Release, pack.Arch)
 | 
			
		||||
				if o.Kernel.Release != ver {
 | 
			
		||||
					o.log.Debugf("Not a running kernel: %s, uname: %s", ver, release)
 | 
			
		||||
			isKernel, running := isRunningKernel(pack, o.Distro.Family, o.Kernel)
 | 
			
		||||
			if isKernel {
 | 
			
		||||
				if !running {
 | 
			
		||||
					o.log.Debugf("Not a running kernel. pack: %#v, kernel: %#v", pack, o.Kernel)
 | 
			
		||||
					continue
 | 
			
		||||
				} else {
 | 
			
		||||
					o.log.Debugf("Running kernel: %s, uname: %s", ver, release)
 | 
			
		||||
				}
 | 
			
		||||
				o.log.Debugf("Found a running kernel. pack: %#v, kernel: %#v", pack, o.Kernel)
 | 
			
		||||
			}
 | 
			
		||||
			installed[pack.Name] = pack
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -89,6 +89,11 @@ func detectOS(c config.ServerInfo) (osType osTypeInterface) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if itsMe, osType = detectSUSE(c); itsMe {
 | 
			
		||||
		util.Log.Debugf("SUSE Linux. Host: %s:%s", c.Host, c.Port)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if itsMe, osType = detectFreebsd(c); itsMe {
 | 
			
		||||
		util.Log.Debugf("FreeBSD. Host: %s:%s", c.Host, c.Port)
 | 
			
		||||
		return
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										185
									
								
								scan/suse.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								scan/suse.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,185 @@
 | 
			
		||||
package scan
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/future-architect/vuls/config"
 | 
			
		||||
	"github.com/future-architect/vuls/models"
 | 
			
		||||
	"github.com/future-architect/vuls/util"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// inherit OsTypeInterface
 | 
			
		||||
type suse struct {
 | 
			
		||||
	redhat
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewRedhat is constructor
 | 
			
		||||
func newSUSE(c config.ServerInfo) *suse {
 | 
			
		||||
	r := &suse{
 | 
			
		||||
		redhat: redhat{
 | 
			
		||||
			base: base{
 | 
			
		||||
				osPackages: osPackages{
 | 
			
		||||
					Packages:  models.Packages{},
 | 
			
		||||
					VulnInfos: models.VulnInfos{},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	r.log = util.NewCustomLogger(c)
 | 
			
		||||
	r.setServerInfo(c)
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// https://github.com/mizzy/specinfra/blob/master/lib/specinfra/helper/detect_os/suse.rb
 | 
			
		||||
func detectSUSE(c config.ServerInfo) (itsMe bool, suse osTypeInterface) {
 | 
			
		||||
	suse = newSUSE(c)
 | 
			
		||||
 | 
			
		||||
	if r := exec(c, "ls /etc/os-release", noSudo); r.isSuccess() {
 | 
			
		||||
		if r := exec(c, "zypper -V", noSudo); r.isSuccess() {
 | 
			
		||||
			if r := exec(c, "cat /etc/os-release", noSudo); r.isSuccess() {
 | 
			
		||||
				name := ""
 | 
			
		||||
				if strings.Contains(r.Stdout, "ID=opensuse") {
 | 
			
		||||
					//TODO check opensuse or opensuse.leap
 | 
			
		||||
					name = config.OpenSUSE
 | 
			
		||||
				} else if strings.Contains(r.Stdout, `NAME="SLES"`) {
 | 
			
		||||
					name = config.SUSEEnterpriseServer
 | 
			
		||||
				} else {
 | 
			
		||||
					util.Log.Warn("Failed to parse SUSE edition: %s", r)
 | 
			
		||||
					return true, suse
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				re := regexp.MustCompile(`VERSION_ID=\"(\d+\.\d+|\d+)\"`)
 | 
			
		||||
				result := re.FindStringSubmatch(strings.TrimSpace(r.Stdout))
 | 
			
		||||
				if len(result) != 2 {
 | 
			
		||||
					util.Log.Warn("Failed to parse SUSE Linux version: %s", r)
 | 
			
		||||
					return true, suse
 | 
			
		||||
				}
 | 
			
		||||
				suse.setDistro(name, result[1])
 | 
			
		||||
				return true, suse
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else if r := exec(c, "ls /etc/SuSE-release", noSudo); r.isSuccess() {
 | 
			
		||||
		if r := exec(c, "zypper -V", noSudo); r.isSuccess() {
 | 
			
		||||
			if r := exec(c, "cat /etc/SuSE-release", noSudo); r.isSuccess() {
 | 
			
		||||
				re := regexp.MustCompile(`openSUSE (\d+\.\d+|\d+)`)
 | 
			
		||||
				result := re.FindStringSubmatch(strings.TrimSpace(r.Stdout))
 | 
			
		||||
				if len(result) == 2 {
 | 
			
		||||
					//TODO check opensuse or opensuse.leap
 | 
			
		||||
					suse.setDistro(config.OpenSUSE, result[1])
 | 
			
		||||
					return true, suse
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				re = regexp.MustCompile(`VERSION = (\d+)`)
 | 
			
		||||
				result = re.FindStringSubmatch(strings.TrimSpace(r.Stdout))
 | 
			
		||||
				if len(result) == 2 {
 | 
			
		||||
					version := result[1]
 | 
			
		||||
					re = regexp.MustCompile(`PATCHLEVEL = (\d+)`)
 | 
			
		||||
					result = re.FindStringSubmatch(strings.TrimSpace(r.Stdout))
 | 
			
		||||
					if len(result) == 2 {
 | 
			
		||||
						suse.setDistro(config.SUSEEnterpriseServer,
 | 
			
		||||
							fmt.Sprintf("%s.%s", version, result[1]))
 | 
			
		||||
						return true, suse
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				util.Log.Warn("Failed to parse SUSE Linux version: %s", r)
 | 
			
		||||
				return true, suse
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	util.Log.Debugf("Not SUSE Linux. servername: %s", c.ServerName)
 | 
			
		||||
	return false, suse
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *suse) checkDependencies() error {
 | 
			
		||||
	o.log.Infof("Dependencies... No need")
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *suse) checkIfSudoNoPasswd() error {
 | 
			
		||||
	// SUSE doesn't need root privilege
 | 
			
		||||
	o.log.Infof("sudo ... No need")
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *suse) scanPackages() error {
 | 
			
		||||
	installed, err := o.scanInstalledPackages()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		o.log.Errorf("Failed to scan installed packages: %s", err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rebootRequired, err := o.rebootRequired()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		o.log.Errorf("Failed to detect the kernel reboot required: %s", err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	o.Kernel.RebootRequired = rebootRequired
 | 
			
		||||
 | 
			
		||||
	updatable, err := o.scanUpdatablePackages()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		o.log.Errorf("Failed to scan updatable packages: %s", err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	installed.MergeNewVersion(updatable)
 | 
			
		||||
	o.Packages = installed
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *suse) rebootRequired() (bool, error) {
 | 
			
		||||
	r := o.exec("rpm -q --last kernel-default | head -n1", noSudo)
 | 
			
		||||
	if !r.isSuccess() {
 | 
			
		||||
		return false, fmt.Errorf("Failed to detect the last installed kernel : %v", r)
 | 
			
		||||
	}
 | 
			
		||||
	stdout := strings.Fields(r.Stdout)[0]
 | 
			
		||||
	return !strings.Contains(stdout, strings.TrimSuffix(o.Kernel.Release, "-default")), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *suse) scanUpdatablePackages() (models.Packages, error) {
 | 
			
		||||
	cmd := ""
 | 
			
		||||
	if v, _ := o.Distro.MajorVersion(); v < 12 {
 | 
			
		||||
		cmd = "zypper -q lu"
 | 
			
		||||
	} else {
 | 
			
		||||
		cmd = "zypper --no-color -q lu"
 | 
			
		||||
	}
 | 
			
		||||
	r := o.exec(cmd, noSudo)
 | 
			
		||||
	if !r.isSuccess() {
 | 
			
		||||
		return nil, fmt.Errorf("Failed to scan updatable packages: %v", r)
 | 
			
		||||
	}
 | 
			
		||||
	return o.parseZypperLULines(r.Stdout)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *suse) parseZypperLULines(stdout string) (models.Packages, error) {
 | 
			
		||||
	updatables := models.Packages{}
 | 
			
		||||
	scanner := bufio.NewScanner(strings.NewReader(stdout))
 | 
			
		||||
	for scanner.Scan() {
 | 
			
		||||
		line := scanner.Text()
 | 
			
		||||
		if strings.HasPrefix(line, "S | Repository") ||
 | 
			
		||||
			strings.HasPrefix(line, "--+----------------") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		pack, err := o.parseZypperLUOneLine(line)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		updatables[pack.Name] = *pack
 | 
			
		||||
	}
 | 
			
		||||
	return updatables, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *suse) parseZypperLUOneLine(line string) (*models.Package, error) {
 | 
			
		||||
	fs := strings.Fields(line)
 | 
			
		||||
	if len(fs) != 11 {
 | 
			
		||||
		return nil, fmt.Errorf("zypper -q lu Unknown format: %s", line)
 | 
			
		||||
	}
 | 
			
		||||
	available := strings.Split(fs[8], "-")
 | 
			
		||||
	return &models.Package{
 | 
			
		||||
		Name:       fs[4],
 | 
			
		||||
		NewVersion: available[0],
 | 
			
		||||
		NewRelease: available[1],
 | 
			
		||||
		Arch:       fs[10],
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										106
									
								
								scan/suse_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								scan/suse_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
			
		||||
/* 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 <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package scan
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/future-architect/vuls/config"
 | 
			
		||||
	"github.com/future-architect/vuls/models"
 | 
			
		||||
	"github.com/k0kubun/pp"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestScanUpdatablePackages(t *testing.T) {
 | 
			
		||||
	r := newSUSE(config.ServerInfo{})
 | 
			
		||||
	r.Distro = config.Distro{Family: "sles"}
 | 
			
		||||
	stdout := `S | Repository                                  | Name                          | Current Version             | Available Version           | Arch
 | 
			
		||||
--+---------------------------------------------+-------------------------------+-----------------------------+-----------------------------+-------
 | 
			
		||||
v | SLES12-SP2-Updates                          | SUSEConnect                   | 0.3.0-19.8.1                | 0.3.1-19.11.2               | x86_64
 | 
			
		||||
v | SLES12-SP2-Updates                          | SuSEfirewall2                 | 3.6.312-2.3.1               | 3.6.312-2.10.1              | noarch`
 | 
			
		||||
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		in  string
 | 
			
		||||
		out models.Packages
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			stdout,
 | 
			
		||||
			models.NewPackages(
 | 
			
		||||
				models.Package{
 | 
			
		||||
					Name:       "SUSEConnect",
 | 
			
		||||
					NewVersion: "0.3.1",
 | 
			
		||||
					NewRelease: "19.11.2",
 | 
			
		||||
					Arch:       "x86_64",
 | 
			
		||||
				},
 | 
			
		||||
				models.Package{
 | 
			
		||||
					Name:       "SuSEfirewall2",
 | 
			
		||||
					NewVersion: "3.6.312",
 | 
			
		||||
					NewRelease: "2.10.1",
 | 
			
		||||
					Arch:       "noarch",
 | 
			
		||||
				},
 | 
			
		||||
			),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		packages, err := r.parseZypperLULines(tt.in)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("Error has occurred, err: %s\ntt.in: %v", err, tt.in)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		for name, ePack := range tt.out {
 | 
			
		||||
			if !reflect.DeepEqual(ePack, packages[name]) {
 | 
			
		||||
				e := pp.Sprintf("%v", ePack)
 | 
			
		||||
				a := pp.Sprintf("%v", packages[name])
 | 
			
		||||
				t.Errorf("expected %s, actual %s", e, a)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestScanUpdatablePackage(t *testing.T) {
 | 
			
		||||
	r := newSUSE(config.ServerInfo{})
 | 
			
		||||
	r.Distro = config.Distro{Family: "sles"}
 | 
			
		||||
	stdout := `v | SLES12-SP2-Updates                          | SUSEConnect                   | 0.3.0-19.8.1                | 0.3.1-19.11.2               | x86_64`
 | 
			
		||||
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		in  string
 | 
			
		||||
		out models.Package
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			stdout,
 | 
			
		||||
			models.Package{
 | 
			
		||||
				Name:       "SUSEConnect",
 | 
			
		||||
				NewVersion: "0.3.1",
 | 
			
		||||
				NewRelease: "19.11.2",
 | 
			
		||||
				Arch:       "x86_64",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, tt := range tests {
 | 
			
		||||
		pack, err := r.parseZypperLUOneLine(tt.in)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("Error has occurred, err: %s\ntt.in: %v", err, tt.in)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		if !reflect.DeepEqual(*pack, tt.out) {
 | 
			
		||||
			e := pp.Sprintf("%v", tt.out)
 | 
			
		||||
			a := pp.Sprintf("%v", pack)
 | 
			
		||||
			t.Errorf("expected %s, actual %s", e, a)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										69
									
								
								scan/utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								scan/utils.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
/* 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 <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package scan
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/future-architect/vuls/config"
 | 
			
		||||
	"github.com/future-architect/vuls/models"
 | 
			
		||||
	"github.com/future-architect/vuls/util"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func isRunningKernel(pack models.Package, family string, kernel models.Kernel) (isKernel, running bool) {
 | 
			
		||||
	switch family {
 | 
			
		||||
	case config.SUSEEnterpriseServer:
 | 
			
		||||
		if pack.Name == "kernel-default" {
 | 
			
		||||
			// Remove the last period and later because uname don't show that.
 | 
			
		||||
			ss := strings.Split(pack.Release, ".")
 | 
			
		||||
			rel := strings.Join(ss[0:len(ss)-1], ".")
 | 
			
		||||
			ver := fmt.Sprintf("%s-%s-default", pack.Version, rel)
 | 
			
		||||
			return true, kernel.Release == ver
 | 
			
		||||
		}
 | 
			
		||||
		return false, false
 | 
			
		||||
 | 
			
		||||
	case config.RedHat, config.Oracle, config.CentOS, config.Amazon:
 | 
			
		||||
		if pack.Name == "kernel" {
 | 
			
		||||
			ver := fmt.Sprintf("%s-%s.%s", pack.Version, pack.Release, pack.Arch)
 | 
			
		||||
			return true, kernel.Release == ver
 | 
			
		||||
		}
 | 
			
		||||
		return false, false
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		util.Log.Warnf("Reboot required is not implemented yet: %s, %s", family, kernel)
 | 
			
		||||
	}
 | 
			
		||||
	return false, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func rpmQa(distro config.Distro) string {
 | 
			
		||||
	const old = "rpm -qa --queryformat '%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH}\n'"
 | 
			
		||||
	const new = "rpm -qa --queryformat '%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH}\n'"
 | 
			
		||||
	switch distro.Family {
 | 
			
		||||
	case config.SUSEEnterpriseServer:
 | 
			
		||||
		if v, _ := distro.MajorVersion(); v < 12 {
 | 
			
		||||
			return old
 | 
			
		||||
		}
 | 
			
		||||
		return new
 | 
			
		||||
	default:
 | 
			
		||||
		if v, _ := distro.MajorVersion(); v < 6 {
 | 
			
		||||
			return old
 | 
			
		||||
		}
 | 
			
		||||
		return new
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										117
									
								
								scan/utils_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								scan/utils_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
			
		||||
/* 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 <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
package scan
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/future-architect/vuls/config"
 | 
			
		||||
	"github.com/future-architect/vuls/models"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestIsRunningKernelSUSE(t *testing.T) {
 | 
			
		||||
	r := newSUSE(config.ServerInfo{})
 | 
			
		||||
	r.Distro = config.Distro{Family: config.SUSEEnterpriseServer}
 | 
			
		||||
 | 
			
		||||
	kernel := models.Kernel{
 | 
			
		||||
		Release: "4.4.74-92.35-default",
 | 
			
		||||
		Version: "",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		pack     models.Package
 | 
			
		||||
		family   string
 | 
			
		||||
		kernel   models.Kernel
 | 
			
		||||
		expected bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			pack: models.Package{
 | 
			
		||||
				Name:    "kernel-default",
 | 
			
		||||
				Version: "4.4.74",
 | 
			
		||||
				Release: "92.35.1",
 | 
			
		||||
				Arch:    "x86_64",
 | 
			
		||||
			},
 | 
			
		||||
			family:   config.SUSEEnterpriseServer,
 | 
			
		||||
			kernel:   kernel,
 | 
			
		||||
			expected: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			pack: models.Package{
 | 
			
		||||
				Name:    "kernel-default",
 | 
			
		||||
				Version: "4.4.59",
 | 
			
		||||
				Release: "92.20.2",
 | 
			
		||||
				Arch:    "x86_64",
 | 
			
		||||
			},
 | 
			
		||||
			family:   config.SUSEEnterpriseServer,
 | 
			
		||||
			kernel:   kernel,
 | 
			
		||||
			expected: false,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, tt := range tests {
 | 
			
		||||
		_, actual := isRunningKernel(tt.pack, tt.family, tt.kernel)
 | 
			
		||||
		if tt.expected != actual {
 | 
			
		||||
			t.Errorf("[%d] expected %t, actual %t", i, tt.expected, actual)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestIsRunningKernelRedHatLikeLinux(t *testing.T) {
 | 
			
		||||
	r := newRedhat(config.ServerInfo{})
 | 
			
		||||
	r.Distro = config.Distro{Family: config.Amazon}
 | 
			
		||||
 | 
			
		||||
	kernel := models.Kernel{
 | 
			
		||||
		Release: "4.9.43-17.38.amzn1.x86_64",
 | 
			
		||||
		Version: "",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		pack     models.Package
 | 
			
		||||
		family   string
 | 
			
		||||
		kernel   models.Kernel
 | 
			
		||||
		expected bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			pack: models.Package{
 | 
			
		||||
				Name:    "kernel",
 | 
			
		||||
				Version: "4.9.43",
 | 
			
		||||
				Release: "17.38.amzn1",
 | 
			
		||||
				Arch:    "x86_64",
 | 
			
		||||
			},
 | 
			
		||||
			family:   config.Amazon,
 | 
			
		||||
			kernel:   kernel,
 | 
			
		||||
			expected: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			pack: models.Package{
 | 
			
		||||
				Name:    "kernel",
 | 
			
		||||
				Version: "4.9.38",
 | 
			
		||||
				Release: "16.35.amzn1",
 | 
			
		||||
				Arch:    "x86_64",
 | 
			
		||||
			},
 | 
			
		||||
			family:   config.Amazon,
 | 
			
		||||
			kernel:   kernel,
 | 
			
		||||
			expected: false,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, tt := range tests {
 | 
			
		||||
		_, actual := isRunningKernel(tt.pack, tt.family, tt.kernel)
 | 
			
		||||
		if tt.expected != actual {
 | 
			
		||||
			t.Errorf("[%d] expected %t, actual %t", i, tt.expected, actual)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user