Files
vuls/config/tomlloader.go
Kota Kanbe 0b55f94828 Improve implementation around config (#1122)
* refactor config

* fix saas config

* feat(config): scanmodule for each server in config.toml

* feat(config): enable to specify containersOnly in config.toml

* add new keys of config.toml to discover.go

* fix summary output, logging
2021-01-13 08:46:27 +09:00

244 lines
5.7 KiB
Go

package config
import (
"regexp"
"strings"
"github.com/BurntSushi/toml"
"github.com/knqyf263/go-cpe/naming"
"golang.org/x/xerrors"
)
// TOMLLoader loads config
type TOMLLoader struct {
}
// Load load the configuration TOML file specified by path arg.
func (c TOMLLoader) Load(pathToToml, keyPass string) error {
if _, err := toml.DecodeFile(pathToToml, &Conf); err != nil {
return err
}
if keyPass != "" {
Conf.Default.KeyPassword = keyPass
}
Conf.CveDict.Init()
Conf.OvalDict.Init()
Conf.Gost.Init()
Conf.Exploit.Init()
Conf.Metasploit.Init()
index := 0
for name, server := range Conf.Servers {
server.ServerName = name
if 0 < len(server.KeyPassword) {
return xerrors.Errorf("[Deprecated] KEYPASSWORD IN CONFIG FILE ARE UNSECURE. REMOVE THEM IMMEDIATELY FOR A SECURITY REASONS. THEY WILL BE REMOVED IN A FUTURE RELEASE: %s", name)
}
if err := setDefaultIfEmpty(&server, Conf.Default); err != nil {
return xerrors.Errorf("Failed to set default value to config. server: %s, err: %w", name, err)
}
if err := setScanMode(&server, Conf.Default); err != nil {
return xerrors.Errorf("Failed to set ScanMode: %w", err)
}
if err := setScanModules(&server, Conf.Default); err != nil {
return xerrors.Errorf("Failed to set ScanModule: %w", err)
}
if len(server.CpeNames) == 0 {
server.CpeNames = Conf.Default.CpeNames
}
for i, n := range server.CpeNames {
uri, err := toCpeURI(n)
if err != nil {
return xerrors.Errorf("Failed to parse CPENames %s in %s, err: %w", n, name, err)
}
server.CpeNames[i] = uri
}
for _, cve := range Conf.Default.IgnoreCves {
found := false
for _, c := range server.IgnoreCves {
if cve == c {
found = true
break
}
}
if !found {
server.IgnoreCves = append(server.IgnoreCves, cve)
}
}
for _, pkg := range Conf.Default.IgnorePkgsRegexp {
found := false
for _, p := range server.IgnorePkgsRegexp {
if pkg == p {
found = true
break
}
}
if !found {
server.IgnorePkgsRegexp = append(server.IgnorePkgsRegexp, pkg)
}
}
for _, reg := range server.IgnorePkgsRegexp {
_, err := regexp.Compile(reg)
if err != nil {
return xerrors.Errorf("Failed to parse %s in %s. err: %w", reg, name, err)
}
}
for contName, cont := range server.Containers {
for _, reg := range cont.IgnorePkgsRegexp {
_, err := regexp.Compile(reg)
if err != nil {
return xerrors.Errorf("Failed to parse %s in %s@%s. err: %w",
reg, contName, name, err)
}
}
}
for ownerRepo, githubSetting := range server.GitHubRepos {
if ss := strings.Split(ownerRepo, "/"); len(ss) != 2 {
return xerrors.Errorf("Failed to parse GitHub owner/repo: %s in %s",
ownerRepo, name)
}
if githubSetting.Token == "" {
return xerrors.Errorf("GitHub owner/repo: %s in %s token is empty",
ownerRepo, name)
}
}
if len(server.Enablerepo) == 0 {
server.Enablerepo = Conf.Default.Enablerepo
}
if len(server.Enablerepo) != 0 {
for _, repo := range server.Enablerepo {
switch repo {
case "base", "updates":
// nop
default:
return xerrors.Errorf(
"For now, enablerepo have to be base or updates: %s",
server.Enablerepo)
}
}
}
server.LogMsgAnsiColor = Colors[index%len(Colors)]
index++
Conf.Servers[name] = server
}
return nil
}
func setDefaultIfEmpty(server *ServerInfo, d ServerInfo) error {
if server.Type != ServerTypePseudo {
if len(server.Host) == 0 {
return xerrors.Errorf("server.host is empty")
}
if len(server.JumpServer) == 0 {
server.JumpServer = Conf.Default.JumpServer
}
if server.Port == "" {
if Conf.Default.Port != "" {
server.Port = Conf.Default.Port
} else {
server.Port = "22"
}
}
if server.User == "" {
if Conf.Default.User != "" {
server.User = Conf.Default.User
}
if server.Port != "local" {
return xerrors.Errorf("server.user is empty")
}
}
if server.SSHConfigPath == "" {
server.SSHConfigPath = Conf.Default.SSHConfigPath
}
if server.KeyPath == "" {
server.KeyPath = Conf.Default.KeyPath
}
if server.KeyPassword == "" {
server.KeyPassword = Conf.Default.KeyPassword
}
}
if len(server.Lockfiles) == 0 {
server.Lockfiles = Conf.Default.Lockfiles
}
if len(server.ContainersIncluded) == 0 {
server.ContainersIncluded = Conf.Default.ContainersIncluded
}
if len(server.ContainersExcluded) == 0 {
server.ContainersExcluded = Conf.Default.ContainersExcluded
}
if server.ContainerType == "" {
server.ContainerType = Conf.Default.ContainerType
}
for contName, cont := range server.Containers {
cont.IgnoreCves = append(cont.IgnoreCves, Conf.Default.IgnoreCves...)
server.Containers[contName] = cont
}
if server.OwaspDCXMLPath == "" {
server.OwaspDCXMLPath = Conf.Default.OwaspDCXMLPath
}
if server.Memo == "" {
server.Memo = Conf.Default.Memo
}
// TODO set default WordPress
if server.WordPress == nil {
server.WordPress = &WordPressConf{}
}
//TODO set nil in config re-generate in saas subcmd
if len(server.IgnoredJSONKeys) == 0 {
server.IgnoredJSONKeys = Conf.Default.IgnoredJSONKeys
}
opt := map[string]interface{}{}
for k, v := range Conf.Default.Optional {
opt[k] = v
}
for k, v := range server.Optional {
opt[k] = v
}
server.Optional = opt
return nil
}
func toCpeURI(cpename string) (string, error) {
if strings.HasPrefix(cpename, "cpe:2.3:") {
wfn, err := naming.UnbindFS(cpename)
if err != nil {
return "", err
}
return naming.BindToURI(wfn), nil
} else if strings.HasPrefix(cpename, "cpe:/") {
wfn, err := naming.UnbindURI(cpename)
if err != nil {
return "", err
}
return naming.BindToURI(wfn), nil
}
return "", xerrors.Errorf("Unknown CPE format: %s", cpename)
}