-
-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
336 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
package commands | ||
|
||
import ( | ||
"encoding/json" | ||
"os" | ||
|
||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
"github.com/vulsio/go-cve-dictionary/db" | ||
log "github.com/vulsio/go-cve-dictionary/log" | ||
"github.com/vulsio/go-cve-dictionary/models" | ||
"golang.org/x/xerrors" | ||
) | ||
|
||
var searchCmd = &cobra.Command{ | ||
Use: "search", | ||
Short: "Search for Vulnerability in the dictionary", | ||
Long: "Search for Vulnerability in the dictionary", | ||
} | ||
|
||
var searchCVECmd = &cobra.Command{ | ||
Use: "cve", | ||
Short: "Search for Vulnerability in the dictionary by CVEID", | ||
Long: "Search for Vulnerability in the dictionary by CVEID", | ||
RunE: searchCVE, | ||
} | ||
|
||
var searchCPECmd = &cobra.Command{ | ||
Use: "cpe", | ||
Short: "Search for Vulnerability in the dictionary by CPE", | ||
Long: "Search for Vulnerability in the dictionary by CPE", | ||
Args: cobra.ExactArgs(1), | ||
RunE: searchCPE, | ||
} | ||
|
||
func searchCVE(_ *cobra.Command, args []string) error { | ||
if err := log.SetLogger(viper.GetBool("log-to-file"), viper.GetString("log-dir"), viper.GetBool("debug"), viper.GetBool("log-json")); err != nil { | ||
return xerrors.Errorf("Failed to SetLogger. err: %w", err) | ||
} | ||
|
||
driver, err := db.NewDB(viper.GetString("dbtype"), viper.GetString("dbpath"), viper.GetBool("debug-sql"), db.Option{}) | ||
if err != nil { | ||
if xerrors.Is(err, db.ErrDBLocked) { | ||
return xerrors.Errorf("Failed to open DB. Close DB connection before fetching. err: %w", err) | ||
} | ||
return xerrors.Errorf("Failed to open DB. err: %w", err) | ||
} | ||
|
||
fetchMeta, err := driver.GetFetchMeta() | ||
if err != nil { | ||
return xerrors.Errorf("Failed to get FetchMeta from DB. err: %w", err) | ||
} | ||
if fetchMeta.OutDated() { | ||
return xerrors.Errorf("Failed to start server. err: SchemaVersion is old. SchemaVersion: %+v", map[string]uint{"latest": models.LatestSchemaVersion, "DB": fetchMeta.SchemaVersion}) | ||
} | ||
|
||
count := 0 | ||
nvdCount, err := driver.CountNvd() | ||
if err != nil { | ||
log.Errorf("Failed to count NVD table: %s", err) | ||
return err | ||
} | ||
count += nvdCount | ||
|
||
jvnCount, err := driver.CountJvn() | ||
if err != nil { | ||
log.Errorf("Failed to count JVN table: %s", err) | ||
return err | ||
} | ||
count += jvnCount | ||
|
||
fortinetCount, err := driver.CountFortinet() | ||
if err != nil { | ||
log.Errorf("Failed to count Fortinet table: %s", err) | ||
return err | ||
} | ||
count += fortinetCount | ||
|
||
if count == 0 { | ||
log.Infof("No Vulnerability data found. Run the below command to fetch data from NVD, JVN, Fortinet") | ||
log.Infof("") | ||
log.Infof(" go-cve-dictionary fetch nvd") | ||
log.Infof(" go-cve-dictionary fetch jvn") | ||
log.Infof(" go-cve-dictionary fetch fortinet") | ||
log.Infof("") | ||
return nil | ||
} | ||
|
||
enc := json.NewEncoder(os.Stdout) | ||
enc.SetIndent("", " ") | ||
switch len(args) { | ||
case 0: | ||
cveids, err := driver.GetCveIDs() | ||
if err != nil { | ||
return xerrors.Errorf("Failed to get All CVEIDs. err: %w", err) | ||
} | ||
if err := enc.Encode(cveids); err != nil { | ||
return xerrors.Errorf("Failed to encode All CVEIDs. err: %w", err) | ||
} | ||
case 1: | ||
d, err := driver.Get(args[0]) | ||
if err != nil { | ||
return xerrors.Errorf("Failed to get CVEDetail by CVEID. err: %w", err) | ||
} | ||
if err := enc.Encode(d); err != nil { | ||
return xerrors.Errorf("Failed to encode CVEDetail by CVEID. err: %w", err) | ||
} | ||
default: | ||
ds, err := driver.GetMulti(args) | ||
if err != nil { | ||
return xerrors.Errorf("Failed to get CVEDetails by CVEIDs. err: %w", err) | ||
} | ||
if err := enc.Encode(ds); err != nil { | ||
return xerrors.Errorf("Failed to encode CVEDetails by CVEIDs. err: %w", err) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func searchCPE(_ *cobra.Command, args []string) error { | ||
if err := log.SetLogger(viper.GetBool("log-to-file"), viper.GetString("log-dir"), viper.GetBool("debug"), viper.GetBool("log-json")); err != nil { | ||
return xerrors.Errorf("Failed to SetLogger. err: %w", err) | ||
} | ||
|
||
driver, err := db.NewDB(viper.GetString("dbtype"), viper.GetString("dbpath"), viper.GetBool("debug-sql"), db.Option{}) | ||
if err != nil { | ||
if xerrors.Is(err, db.ErrDBLocked) { | ||
return xerrors.Errorf("Failed to open DB. Close DB connection before fetching. err: %w", err) | ||
} | ||
return xerrors.Errorf("Failed to open DB. err: %w", err) | ||
} | ||
|
||
fetchMeta, err := driver.GetFetchMeta() | ||
if err != nil { | ||
return xerrors.Errorf("Failed to get FetchMeta from DB. err: %w", err) | ||
} | ||
if fetchMeta.OutDated() { | ||
return xerrors.Errorf("Failed to start server. err: SchemaVersion is old. SchemaVersion: %+v", map[string]uint{"latest": models.LatestSchemaVersion, "DB": fetchMeta.SchemaVersion}) | ||
} | ||
|
||
count := 0 | ||
nvdCount, err := driver.CountNvd() | ||
if err != nil { | ||
log.Errorf("Failed to count NVD table: %s", err) | ||
return err | ||
} | ||
count += nvdCount | ||
|
||
jvnCount, err := driver.CountJvn() | ||
if err != nil { | ||
log.Errorf("Failed to count JVN table: %s", err) | ||
return err | ||
} | ||
count += jvnCount | ||
|
||
fortinetCount, err := driver.CountFortinet() | ||
if err != nil { | ||
log.Errorf("Failed to count Fortinet table: %s", err) | ||
return err | ||
} | ||
count += fortinetCount | ||
|
||
if count == 0 { | ||
log.Infof("No Vulnerability data found. Run the below command to fetch data from NVD, JVN, Fortinet") | ||
log.Infof("") | ||
log.Infof(" go-cve-dictionary fetch nvd") | ||
log.Infof(" go-cve-dictionary fetch jvn") | ||
log.Infof(" go-cve-dictionary fetch fortinet") | ||
log.Infof("") | ||
return nil | ||
} | ||
|
||
enc := json.NewEncoder(os.Stdout) | ||
enc.SetIndent("", " ") | ||
if viper.GetBool("cveid-only") { | ||
nvds, jvns, fortinets, err := driver.GetCveIDsByCpeURI(args[0]) | ||
if err != nil { | ||
return xerrors.Errorf("Failed to Get CVEIDs by CPE URI. err: %w", err) | ||
} | ||
if err := enc.Encode(map[string][]string{"NVD": nvds, "JVN": jvns, "Fortinet": fortinets}); err != nil { | ||
return xerrors.Errorf("Failed to encode CVEIDs by CPE URI. err: %w", err) | ||
} | ||
return nil | ||
} | ||
cveDetails, err := driver.GetByCpeURI(args[0]) | ||
if err != nil { | ||
return xerrors.Errorf("Failed to Get CVEDetails by CPE URI. err: %w", err) | ||
} | ||
if err := enc.Encode(cveDetails); err != nil { | ||
return xerrors.Errorf("Failed to encode CVEDetails by CPE URI. err: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func init() { | ||
RootCmd.AddCommand(searchCmd) | ||
searchCmd.AddCommand(searchCVECmd, searchCPECmd) | ||
|
||
searchCPECmd.PersistentFlags().Bool("cveid-only", false, "show only CVEID in search results") | ||
_ = viper.BindPFlag("cveid-only", searchCPECmd.PersistentFlags().Lookup("cveid-only")) | ||
} |