diff --git a/constant/constant.go b/constant/constant.go index f394aad3..e0d2e1f0 100644 --- a/constant/constant.go +++ b/constant/constant.go @@ -17,6 +17,9 @@ const ( // CentOS is CentOS = "centos" + // Rocky is + Rocky = "Rocky" + // Fedora is // Fedora = "fedora" diff --git a/scanner/redhatbase.go b/scanner/redhatbase.go index b467f523..60d481f6 100644 --- a/scanner/redhatbase.go +++ b/scanner/redhatbase.go @@ -64,6 +64,27 @@ func detectRedhat(c config.ServerInfo) (bool, osTypeInterface) { } } + if r := exec(c, "ls /etc/rocky-release", noSudo); r.isSuccess() { + if r := exec(c, "cat /etc/rocky-release", noSudo); r.isSuccess() { + re := regexp.MustCompile(`(.*) release (\d[\d\.]*)`) + result := re.FindStringSubmatch(strings.TrimSpace(r.Stdout)) + if len(result) != 3 { + logging.Log.Warnf("Failed to parse Rocky version: %s", r) + return true, newRocky(c) + } + + release := result[2] + switch strings.ToLower(result[1]) { + case "rocky", "rocky linux": + rocky := newRocky(c) + rocky.setDistro(constant.Rocky, release) + return true, rocky + default: + logging.Log.Warnf("Failed to parse Rocky: %s", r) + } + } + } + if r := exec(c, "ls /etc/redhat-release", noSudo); r.isSuccess() { // https://www.rackaid.com/blog/how-to-determine-centos-or-red-hat-version/ // e.g. diff --git a/scanner/rocky.go b/scanner/rocky.go new file mode 100644 index 00000000..922ff71b --- /dev/null +++ b/scanner/rocky.go @@ -0,0 +1,118 @@ +package scanner + +import ( + "github.com/future-architect/vuls/config" + "github.com/future-architect/vuls/logging" + "github.com/future-architect/vuls/models" +) + +// inherit OsTypeInterface +type rocky struct { + redhatBase +} + +// NewAmazon is constructor +func newRocky(c config.ServerInfo) *rocky { + r := &rocky{ + redhatBase{ + base: base{ + osPackages: osPackages{ + Packages: models.Packages{}, + VulnInfos: models.VulnInfos{}, + }, + }, + sudo: rootPrivRocky{}, + }, + } + r.log = logging.NewNormalLogger() + r.setServerInfo(c) + return r +} + +func (o *rocky) checkScanMode() error { + return nil +} + +func (o *rocky) checkDeps() error { + if o.getServerInfo().Mode.IsFast() { + return o.execCheckDeps(o.depsFast()) + } else if o.getServerInfo().Mode.IsFastRoot() { + return o.execCheckDeps(o.depsFastRoot()) + } else { + return o.execCheckDeps(o.depsDeep()) + } +} + +func (o *rocky) depsFast() []string { + if o.getServerInfo().Mode.IsOffline() { + return []string{} + } + + // repoquery + // `rpm -qa` shows dnf-utils as yum-utils on RHEL8, CentOS8, Rocky + return []string{"yum-utils"} +} + +func (o *rocky) depsFastRoot() []string { + if o.getServerInfo().Mode.IsOffline() { + return []string{} + } + + // repoquery + // `rpm -qa` shows dnf-utils as yum-utils on RHEL8, CentOS8, Rocky + return []string{"yum-utils"} +} + +func (o *rocky) depsDeep() []string { + return o.depsFastRoot() +} + +func (o *rocky) checkIfSudoNoPasswd() error { + if o.getServerInfo().Mode.IsFast() { + return o.execCheckIfSudoNoPasswd(o.sudoNoPasswdCmdsFast()) + } else if o.getServerInfo().Mode.IsFastRoot() { + return o.execCheckIfSudoNoPasswd(o.sudoNoPasswdCmdsFastRoot()) + } else { + return o.execCheckIfSudoNoPasswd(o.sudoNoPasswdCmdsDeep()) + } +} + +func (o *rocky) sudoNoPasswdCmdsFast() []cmd { + return []cmd{} +} + +func (o *rocky) sudoNoPasswdCmdsFastRoot() []cmd { + if !o.ServerInfo.IsContainer() { + return []cmd{ + {"repoquery -h", exitStatusZero}, + {"needs-restarting", exitStatusZero}, + {"which which", exitStatusZero}, + {"stat /proc/1/exe", exitStatusZero}, + {"ls -l /proc/1/exe", exitStatusZero}, + {"cat /proc/1/maps", exitStatusZero}, + {"lsof -i -P", exitStatusZero}, + } + } + return []cmd{ + {"repoquery -h", exitStatusZero}, + {"needs-restarting", exitStatusZero}, + } +} + +func (o *rocky) sudoNoPasswdCmdsDeep() []cmd { + return o.sudoNoPasswdCmdsFastRoot() +} + +type rootPrivRocky struct{} + +func (o rootPrivRocky) repoquery() bool { + return false +} + +func (o rootPrivRocky) yumMakeCache() bool { + return false +} + +func (o rootPrivRocky) yumPS() bool { + return false +}