aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/cmd.go105
-rw-r--r--cmd/update.go62
2 files changed, 166 insertions, 1 deletions
diff --git a/cmd/cmd.go b/cmd/cmd.go
index 1619a71..fd195aa 100644
--- a/cmd/cmd.go
+++ b/cmd/cmd.go
@@ -2,12 +2,18 @@
package cmd
import (
+ "compress/gzip"
"encoding/json"
+ "encoding/xml"
+ "github.com/pablotron/cvez/cisa"
+ "github.com/pablotron/cvez/cpedict"
+ "github.com/pablotron/cvez/cpematch"
"github.com/pablotron/cvez/datadir"
"github.com/pablotron/cvez/dbstore"
"github.com/pablotron/cvez/nvdmirror"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
+ nvd_feed "github.com/pablotron/cvez/feed"
"os"
"path/filepath"
"strings"
@@ -87,3 +93,102 @@ func init() {
rootCmd.AddCommand(cvssCmd)
rootCmd.AddCommand(updateCmd)
}
+
+// read gzipped file, pass reader to callback.
+func gzOpen(path string, fn func(*gzip.Reader)) {
+ f, err := os.Open(path)
+ if err != nil {
+ log.Error().Err(err).Msg("Open")
+ os.Exit(-1)
+ }
+ defer f.Close()
+
+ // create gzip reader
+ r, err := gzip.NewReader(f)
+ if err != nil {
+ log.Error().Err(err).Msg("NewReader")
+ os.Exit(-1)
+ }
+
+ fn(r)
+}
+
+// read gzipped json, pass decoder to callback
+func jsonGzOpen(path string, fn func(*json.Decoder)) {
+ gzOpen(path, func(r *gzip.Reader) {
+ fn(json.NewDecoder(r))
+ })
+}
+
+// read gzipped xml, pass decoder to callback
+func xmlGzOpen(path string, fn func(*xml.Decoder)) {
+ gzOpen(path, func(r *gzip.Reader) {
+ fn(xml.NewDecoder(r))
+ })
+}
+
+// Read feed from file.
+func getFeed(path string) nvd_feed.Feed {
+ var feed nvd_feed.Feed
+
+ jsonGzOpen(path, func(d *json.Decoder) {
+ if err := d.Decode(&feed); err != nil {
+ log.Error().Err(err).Msg("Decode")
+ os.Exit(-1)
+ }
+ })
+
+ // return feed
+ return feed
+}
+
+// Read cpe matches from file.
+func getCpeMatches(path string) cpematch.Matches {
+ var matches cpematch.Matches
+
+ jsonGzOpen(path, func(d *json.Decoder) {
+ if err := d.Decode(&matches); err != nil {
+ log.Error().Err(err).Msg("Decode")
+ os.Exit(-1)
+ }
+ })
+
+ // return matches
+ return matches
+}
+
+// Read cpe dictionary from file.
+func getCpeDict(path string) cpedict.Dictionary {
+ var dict cpedict.Dictionary
+
+ xmlGzOpen(path, func(d *xml.Decoder) {
+ if err := d.Decode(&dict); err != nil {
+ log.Error().Err(err).Msg("Decode")
+ os.Exit(-1)
+ }
+ })
+
+ // return dictionary
+ return dict
+}
+
+// Read cisa catalog from file.
+func getCisaCatalog(path string) cisa.Catalog {
+ f, err := os.Open(path)
+ if err != nil {
+ log.Error().Err(err).Msg("Open")
+ os.Exit(-1)
+ }
+ defer f.Close()
+
+ // create decoder, decode catalog
+ var cat cisa.Catalog
+ d := json.NewDecoder(f)
+ if err = d.Decode(&cat); err != nil {
+ log.Error().Err(err).Msg("Decode")
+ os.Exit(-1)
+ }
+
+ // return catalog
+ return cat
+}
diff --git a/cmd/update.go b/cmd/update.go
index b6f2882..86e6c7a 100644
--- a/cmd/update.go
+++ b/cmd/update.go
@@ -2,8 +2,14 @@ package cmd
import (
// "encoding/json"
+ "context"
+ "github.com/pablotron/cvez/cisa"
"github.com/pablotron/cvez/nvdmirror"
+ "github.com/rs/zerolog/log"
"github.com/spf13/cobra"
+ nvd_feed "github.com/pablotron/cvez/feed"
+ "os"
+ "path/filepath"
)
var updateCmd = &cobra.Command{
@@ -28,6 +34,60 @@ var updateCmd = &cobra.Command{
// sync data, get updates
updates := nvdmirror.Sync(config, &cache, cacheDir)
- jsonEncode(updates)
+ if len(updates) > 0 {
+ // connect to db
+ ctx := context.Background()
+ db := getDb()
+
+ // build list of feeds to add
+ log.Info().Msg("load feeds")
+ var feeds []nvd_feed.Feed
+ for _, row := range(updates) {
+ if row.Type == nvdmirror.UpdateCveYear {
+ feeds = append(feeds, getFeed(filepath.Join(cacheDir, row.Path)))
+ }
+ }
+
+ if len(feeds) > 0 {
+ log.Info().Msg("AddCveFeeds")
+ if _, err := db.AddCveFeeds(ctx, feeds); err != nil {
+ // FIXME: failing like this leaves an invalid cache
+ log.Error().Err(err).Msg("AddCveFeeds")
+ os.Exit(-1)
+ }
+ }
+
+ // process cpe dictionary before cpe matches to prevent FK
+ // constraint violations
+ for _, row := range(updates) {
+ if row.Type == nvdmirror.UpdateCpeDict {
+ log.Info().Msg("AddCpeDictionary")
+ dict := getCpeDict(filepath.Join(cacheDir, row.Path))
+ if err := db.AddCpeDictionary(ctx, dict); err != nil {
+ log.Error().Err(err).Msg("AddCpeDictionary")
+ os.Exit(-1)
+ }
+ }
+ }
+
+ for _, row := range(updates) {
+ switch row.Type {
+ case nvdmirror.UpdateCpeMatch:
+ log.Info().Msg("AddCpeMatches")
+ matches := getCpeMatches(filepath.Join(cacheDir, row.Path))
+ if err := db.AddCpeMatches(ctx, matches); err != nil {
+ log.Error().Err(err).Msg("AddCpeMatches")
+ os.Exit(-1)
+ }
+ case nvdmirror.UpdateCisaKevc:
+ log.Info().Msg("AddCisaCatalogs")
+ cat := getCisaCatalog(filepath.Join(cacheDir, row.Path))
+ if _, err := db.AddCisaCatalogs(ctx, []cisa.Catalog { cat }); err != nil {
+ log.Error().Err(err).Msg("AddCisaCatalogs")
+ os.Exit(-1)
+ }
+ }
+ }
+ }
},
}