refactor(report): initialize DB connection (#1186)

This commit is contained in:
Kota Kanbe
2021-03-02 06:34:46 +09:00
committed by GitHub
parent 3f2ac45d71
commit 1c4a12c4b7
5 changed files with 99 additions and 184 deletions

View File

@@ -14,9 +14,14 @@ import (
// VulnDictInterface is an interface of vulnsrc
type VulnDictInterface interface {
CheckHTTPHealth() error
Init()
Validate() error
IsFetchViaHTTP() bool
CheckHTTPHealth() error
GetName() string
GetType() string
GetURL() string
GetSQLite3Path() string
}
// VulnDict is a base struct of vuln dicts
@@ -33,6 +38,26 @@ type VulnDict struct {
SQLite3Path string `json:"-"`
}
// GetType returns type
func (cnf *VulnDict) GetType() string {
return cnf.Type
}
// GetName returns name
func (cnf *VulnDict) GetName() string {
return cnf.Name
}
// GetURL returns url
func (cnf *VulnDict) GetURL() string {
return cnf.URL
}
// GetSQLite3Path return the path of SQLite3
func (cnf *VulnDict) GetSQLite3Path() string {
return cnf.SQLite3Path
}
// Validate settings
func (cnf *VulnDict) Validate() error {
logging.Log.Infof("%s.type=%s, %s.url=%s, %s.SQLite3Path=%s",
@@ -48,6 +73,9 @@ func (cnf *VulnDict) Validate() error {
return xerrors.Errorf("SQLite3 path must be a *Absolute* file path. %s.SQLite3Path: %s",
cnf.Name, cnf.SQLite3Path)
}
if _, err := os.Stat(cnf.SQLite3Path); os.IsNotExist(err) {
logging.Log.Warnf("%s.SQLite3Path=%s file not found", cnf.Name, cnf.SQLite3Path)
}
case "mysql":
if cnf.URL == "" {
return xerrors.Errorf(`MySQL connection string is needed. %s.url="user:pass@tcp(localhost:3306)/dbname"`, cnf.Name)
@@ -70,6 +98,9 @@ func (cnf *VulnDict) Validate() error {
return nil
}
// Init the struct
func (cnf *VulnDict) Init() {}
func (cnf *VulnDict) setDefault(sqlite3Name string) {
if cnf.Type == "" {
cnf.Type = "sqlite3"

View File

@@ -3,10 +3,7 @@
package detector
import (
"os"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
gostdb "github.com/knqyf263/gost/db"
cvedb "github.com/kotakanbe/go-cve-dictionary/db"
ovaldb "github.com/kotakanbe/goval-dictionary/db"
@@ -24,60 +21,50 @@ type DBClient struct {
MetasploitDB metasploitdb.DB
}
// DBClientConf has a configuration of Vulnerability DBs
type DBClientConf struct {
CveDictCnf config.GoCveDictConf
OvalDictCnf config.GovalDictConf
GostCnf config.GostConf
ExploitCnf config.ExploitConf
MetasploitCnf config.MetasploitConf
DebugSQL bool
}
// NewDBClient returns db clients
func NewDBClient(cnf DBClientConf) (dbclient *DBClient, locked bool, err error) {
cveDriver, locked, err := NewCveDB(cnf)
if locked {
return nil, true, xerrors.Errorf("CveDB is locked: %s",
cnf.OvalDictCnf.SQLite3Path)
} else if err != nil {
return nil, locked, err
func NewDBClient(cveDict, ovalDict, gost, exploit, metasploit config.VulnDictInterface, debugSQL bool) (dbclient *DBClient, err error) {
for _, cnf := range []config.VulnDictInterface{cveDict, ovalDict, gost, exploit, metasploit} {
if err := cnf.Validate(); err != nil {
return nil, xerrors.Errorf("Failed to validate %s: %+v", cnf.GetName(), err)
}
if err := cnf.CheckHTTPHealth(); err != nil {
return nil, xerrors.Errorf("Run %s as server mode before reporting: %+v", cnf.GetName(), err)
}
}
ovaldb, locked, err := NewOvalDB(cnf)
cveDriver, locked, err := NewCveDB(cveDict, debugSQL)
if locked {
return nil, true, xerrors.Errorf("OvalDB is locked: %s",
cnf.OvalDictCnf.SQLite3Path)
return nil, xerrors.Errorf("SQLite3 is locked: %s", cveDict.GetSQLite3Path())
} else if err != nil {
logging.Log.Warnf("Unable to use OvalDB: %s, err: %+v",
cnf.OvalDictCnf.SQLite3Path, err)
return nil, err
}
gostdb, locked, err := NewGostDB(cnf)
ovaldb, locked, err := NewOvalDB(ovalDict, debugSQL)
if locked {
return nil, true, xerrors.Errorf("gostDB is locked: %s",
cnf.GostCnf.SQLite3Path)
return nil, xerrors.Errorf("SQLite3 is locked: %s", ovalDict.GetSQLite3Path())
} else if err != nil {
logging.Log.Warnf("Unable to use gostDB: %s, err: %+v",
cnf.GostCnf.SQLite3Path, err)
return nil, err
}
exploitdb, locked, err := NewExploitDB(cnf)
gostdb, locked, err := NewGostDB(gost, debugSQL)
if locked {
return nil, true, xerrors.Errorf("exploitDB is locked: %s",
cnf.ExploitCnf.SQLite3Path)
return nil, xerrors.Errorf("SQLite3 is locked: %s", gost.GetSQLite3Path())
} else if err != nil {
logging.Log.Warnf("Unable to use exploitDB: %s, err: %+v",
cnf.ExploitCnf.SQLite3Path, err)
return nil, err
}
metasploitdb, locked, err := NewMetasploitDB(cnf)
exploitdb, locked, err := NewExploitDB(exploit, debugSQL)
if locked {
return nil, true, xerrors.Errorf("metasploitDB is locked: %s",
cnf.MetasploitCnf.SQLite3Path)
return nil, xerrors.Errorf("SQLite3 is locked: %s", exploit.GetSQLite3Path())
} else if err != nil {
logging.Log.Warnf("Unable to use metasploitDB: %s, err: %+v",
cnf.MetasploitCnf.SQLite3Path, err)
return nil, err
}
metasploitdb, locked, err := NewMetasploitDB(metasploit, debugSQL)
if locked {
return nil, xerrors.Errorf("SQLite3 is locked: %s", metasploit.GetSQLite3Path())
} else if err != nil {
return nil, err
}
return &DBClient{
@@ -86,26 +73,19 @@ func NewDBClient(cnf DBClientConf) (dbclient *DBClient, locked bool, err error)
GostDB: gostdb,
ExploitDB: exploitdb,
MetasploitDB: metasploitdb,
}, false, nil
}, nil
}
// NewCveDB returns cve db client
func NewCveDB(cnf DBClientConf) (driver cvedb.DB, locked bool, err error) {
if cnf.CveDictCnf.IsFetchViaHTTP() {
func NewCveDB(cnf config.VulnDictInterface, debugSQL bool) (driver cvedb.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
logging.Log.Debugf("open cve-dictionary db (%s)", cnf.CveDictCnf.Type)
path := cnf.CveDictCnf.URL
if cnf.CveDictCnf.Type == "sqlite3" {
path = cnf.CveDictCnf.SQLite3Path
if _, err := os.Stat(path); os.IsNotExist(err) {
logging.Log.Warnf("--cvedb-path=%s file not found. [CPE-scan](https://vuls.io/docs/en/usage-scan-non-os-packages.html#cpe-scan) needs cve-dictionary. if you specify cpe in config.toml, fetch cve-dictionary before reporting. For details, see `https://github.com/kotakanbe/go-cve-dictionary#deploy-go-cve-dictionary`", path)
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
logging.Log.Debugf("Open cve-dictionary db (%s): %s", cnf.CveDictCnf.Type, path)
driver, locked, err = cvedb.NewDB(cnf.CveDictCnf.Type, path, cnf.DebugSQL)
driver, locked, err = cvedb.NewDB(cnf.GetType(), path, debugSQL)
if err != nil {
err = xerrors.Errorf("Failed to init CVE DB. err: %w, path: %s", err, path)
return nil, locked, err
@@ -114,22 +94,15 @@ func NewCveDB(cnf DBClientConf) (driver cvedb.DB, locked bool, err error) {
}
// NewOvalDB returns oval db client
func NewOvalDB(cnf DBClientConf) (driver ovaldb.DB, locked bool, err error) {
if cnf.OvalDictCnf.IsFetchViaHTTP() {
func NewOvalDB(cnf config.VulnDictInterface, debugSQL bool) (driver ovaldb.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.OvalDictCnf.URL
if cnf.OvalDictCnf.Type == "sqlite3" {
path = cnf.OvalDictCnf.SQLite3Path
if _, err := os.Stat(path); os.IsNotExist(err) {
logging.Log.Warnf("--ovaldb-path=%s file not found", path)
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
logging.Log.Debugf("Open oval-dictionary db (%s): %s", cnf.OvalDictCnf.Type, path)
driver, locked, err = ovaldb.NewDB("", cnf.OvalDictCnf.Type, path, cnf.DebugSQL)
driver, locked, err = ovaldb.NewDB("", cnf.GetType(), path, debugSQL)
if err != nil {
err = xerrors.Errorf("Failed to new OVAL DB. err: %w", err)
if locked {
@@ -141,22 +114,15 @@ func NewOvalDB(cnf DBClientConf) (driver ovaldb.DB, locked bool, err error) {
}
// NewGostDB returns db client for Gost
func NewGostDB(cnf DBClientConf) (driver gostdb.DB, locked bool, err error) {
if cnf.GostCnf.IsFetchViaHTTP() {
func NewGostDB(cnf config.VulnDictInterface, debugSQL bool) (driver gostdb.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.GostCnf.URL
if cnf.GostCnf.Type == "sqlite3" {
path = cnf.GostCnf.SQLite3Path
if _, err := os.Stat(path); os.IsNotExist(err) {
logging.Log.Warnf("--gostdb-path=%s file not found. Vuls can detect `patch-not-released-CVE-ID` using gost if the scan target server is Debian, RHEL or CentOS, For details, see `https://github.com/knqyf263/gost#fetch-redhat`", path)
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
logging.Log.Debugf("Open gost db (%s): %s", cnf.GostCnf.Type, path)
if driver, locked, err = gostdb.NewDB(cnf.GostCnf.Type, path, cnf.DebugSQL); err != nil {
if driver, locked, err = gostdb.NewDB(cnf.GetType(), path, debugSQL); err != nil {
if locked {
return nil, true, xerrors.Errorf("gostDB is locked. err: %w", err)
}
@@ -166,22 +132,15 @@ func NewGostDB(cnf DBClientConf) (driver gostdb.DB, locked bool, err error) {
}
// NewExploitDB returns db client for Exploit
func NewExploitDB(cnf DBClientConf) (driver exploitdb.DB, locked bool, err error) {
if cnf.ExploitCnf.IsFetchViaHTTP() {
func NewExploitDB(cnf config.VulnDictInterface, debugSQL bool) (driver exploitdb.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.ExploitCnf.URL
if cnf.ExploitCnf.Type == "sqlite3" {
path = cnf.ExploitCnf.SQLite3Path
if _, err := os.Stat(path); os.IsNotExist(err) {
logging.Log.Warnf("--exploitdb-path=%s file not found. Fetch go-exploit-db before reporting if you want to display exploit codes of detected CVE-IDs. For details, see `https://github.com/vulsio/go-exploitdb`", path)
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
logging.Log.Debugf("Open exploit db (%s): %s", cnf.ExploitCnf.Type, path)
if driver, locked, err = exploitdb.NewDB(cnf.ExploitCnf.Type, path, cnf.DebugSQL); err != nil {
if driver, locked, err = exploitdb.NewDB(cnf.GetType(), path, debugSQL); err != nil {
if locked {
return nil, true, xerrors.Errorf("exploitDB is locked. err: %w", err)
}
@@ -191,22 +150,15 @@ func NewExploitDB(cnf DBClientConf) (driver exploitdb.DB, locked bool, err error
}
// NewMetasploitDB returns db client for Metasploit
func NewMetasploitDB(cnf DBClientConf) (driver metasploitdb.DB, locked bool, err error) {
if cnf.MetasploitCnf.IsFetchViaHTTP() {
func NewMetasploitDB(cnf config.VulnDictInterface, debugSQL bool) (driver metasploitdb.DB, locked bool, err error) {
if cnf.IsFetchViaHTTP() {
return nil, false, nil
}
path := cnf.MetasploitCnf.URL
if cnf.MetasploitCnf.Type == "sqlite3" {
path = cnf.MetasploitCnf.SQLite3Path
if _, err := os.Stat(path); os.IsNotExist(err) {
logging.Log.Warnf("--msfdb-path=%s file not found. Fetch go-msfdb before reporting if you want to display metasploit modules of detected CVE-IDs. For details, see `https://github.com/takuzoo3868/go-msfdb`", path)
return nil, false, nil
}
path := cnf.GetURL()
if cnf.GetType() == "sqlite3" {
path = cnf.GetSQLite3Path()
}
logging.Log.Debugf("Open metasploit db (%s): %s", cnf.MetasploitCnf.Type, path)
if driver, locked, err = metasploitdb.NewDB(cnf.MetasploitCnf.Type, path, cnf.DebugSQL, false); err != nil {
if driver, locked, err = metasploitdb.NewDB(cnf.GetType(), path, debugSQL, false); err != nil {
if locked {
return nil, true, xerrors.Errorf("metasploitDB is locked. err: %w", err)
}

View File

@@ -243,37 +243,14 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
r.ServerInfo(), pp.Sprintf("%s", c.Conf.Servers[r.ServerName]))
}
for _, cnf := range []c.VulnDictInterface{
dbclient, err := detector.NewDBClient(
&c.Conf.CveDict,
&c.Conf.OvalDict,
&c.Conf.Gost,
&c.Conf.Exploit,
&c.Conf.Metasploit,
} {
if err := cnf.Validate(); err != nil {
logging.Log.Errorf("Failed to validate VulnDict: %+v", err)
return subcommands.ExitFailure
}
if err := cnf.CheckHTTPHealth(); err != nil {
logging.Log.Errorf("Run as server mode before reporting: %+v", err)
return subcommands.ExitFailure
}
}
// TODO move into fillcveInfos
dbclient, locked, err := detector.NewDBClient(detector.DBClientConf{
CveDictCnf: c.Conf.CveDict,
OvalDictCnf: c.Conf.OvalDict,
GostCnf: c.Conf.Gost,
ExploitCnf: c.Conf.Exploit,
MetasploitCnf: c.Conf.Metasploit,
DebugSQL: c.Conf.DebugSQL,
})
if locked {
logging.Log.Errorf("SQLite3 is locked. Close other DB connections and try again. err: %+v", err)
return subcommands.ExitFailure
}
c.Conf.DebugSQL,
)
if err != nil {
logging.Log.Errorf("Failed to init DB Clients. err: %+v", err)
return subcommands.ExitFailure
@@ -284,7 +261,6 @@ func (p *ReportCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
}
}()
// TODO pass conf by arg
if res, err = detector.Detect(*dbclient, res, dir); err != nil {
logging.Log.Errorf("%+v", err)
return subcommands.ExitFailure

View File

@@ -99,36 +99,14 @@ func (p *ServerCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}
return subcommands.ExitUsageError
}
for _, cnf := range []c.VulnDictInterface{
dbclient, err := detector.NewDBClient(
&c.Conf.CveDict,
&c.Conf.OvalDict,
&c.Conf.Gost,
&c.Conf.Exploit,
&c.Conf.Metasploit,
} {
if err := cnf.Validate(); err != nil {
logging.Log.Errorf("Failed to validate VulnDict: %+v", err)
return subcommands.ExitFailure
}
if err := cnf.CheckHTTPHealth(); err != nil {
logging.Log.Errorf("Run as server mode before reporting: %+v", err)
return subcommands.ExitFailure
}
}
dbclient, locked, err := detector.NewDBClient(detector.DBClientConf{
CveDictCnf: c.Conf.CveDict,
OvalDictCnf: c.Conf.OvalDict,
GostCnf: c.Conf.Gost,
ExploitCnf: c.Conf.Exploit,
MetasploitCnf: c.Conf.Metasploit,
DebugSQL: c.Conf.DebugSQL,
})
if locked {
logging.Log.Errorf("SQLite3 is locked. Close other DB connections and try again: %+v", err)
return subcommands.ExitFailure
}
c.Conf.DebugSQL,
)
if err != nil {
logging.Log.Errorf("Failed to init DB Clients. err: %+v", err)
return subcommands.ExitFailure

View File

@@ -138,36 +138,14 @@ func (p *TuiCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) s
}
logging.Log.Infof("Loaded: %s", dir)
for _, cnf := range []c.VulnDictInterface{
dbclient, err := detector.NewDBClient(
&c.Conf.CveDict,
&c.Conf.OvalDict,
&c.Conf.Gost,
&c.Conf.Exploit,
&c.Conf.Metasploit,
} {
if err := cnf.Validate(); err != nil {
logging.Log.Errorf("Failed to validate VulnDict: %+v", err)
return subcommands.ExitFailure
}
if err := cnf.CheckHTTPHealth(); err != nil {
logging.Log.Errorf("Run as server mode before reporting: %+v", err)
return subcommands.ExitFailure
}
}
dbclient, locked, err := detector.NewDBClient(detector.DBClientConf{
CveDictCnf: c.Conf.CveDict,
OvalDictCnf: c.Conf.OvalDict,
GostCnf: c.Conf.Gost,
ExploitCnf: c.Conf.Exploit,
MetasploitCnf: c.Conf.Metasploit,
DebugSQL: c.Conf.DebugSQL,
})
if locked {
logging.Log.Errorf("SQLite3 is locked. Close other DB connections and try again: %+v", err)
return subcommands.ExitFailure
}
c.Conf.DebugSQL,
)
if err != nil {
logging.Log.Errorf("Failed to init DB Clients. err: %+v", err)
return subcommands.ExitFailure