diff --git a/README.md b/README.md
index b93acdc1..0e99983a 100644
--- a/README.md
+++ b/README.md
@@ -190,11 +190,11 @@ Select from DB where package name is golang.
-`$ goval-dictionary select --by-package redhat 7 golang x86_64`
+`$ goval-dictionary select package redhat 7 golang`
```bash
-$ goval-dictionary select --by-package redhat 7 golang x86_64
+$ goval-dictionary select package redhat 7 golang
[Apr 10 10:22:43] INFO Opening DB (sqlite3).
CVE-2015-5739
{3399 319 golang 0:1.6.3-1.el7_2.1}
@@ -422,7 +422,7 @@ CVE-YYYY-NNNN
```bash
-$ goval-dictionary select --by-cveid redhat 7 CVE-2017-6009
+$ goval-dictionary select cve-id redhat 7 CVE-2017-6009
[Apr 12 12:12:36] INFO Opening DB (sqlite3).
RHSA-2017:0837: icoutils security update (Important)
Important
@@ -625,6 +625,37 @@ Upper part format:
```
+### Usage: select advisories
+
+
+
+`Select Advisories from DB`
+
+
+```bash
+$ goval-dictionary select advisories redhat 9
+map[string][]string{
+ "RHSA-2023:6482": []string{
+ "CVE-2023-35789",
+ },
+ "RHSA-2022:8418": []string{
+ "CVE-2021-28153",
+ },
+ "RHSA-2024:0811": []string{
+ "CVE-2023-28486",
+ "CVE-2023-28487",
+ "CVE-2023-42465",
+ "CVE-2023-28486",
+ "CVE-2023-28487",
+ "CVE-2023-42465",
+ "CVE-2023-28486",
+ "CVE-2023-28487",
+ "CVE-2023-42465",
+ },
+ ...
+}
+```
+
### Usage: Start goval-dictionary as server mode
```bash
diff --git a/commands/select.go b/commands/select.go
index 337bd69f..9b2fb110 100644
--- a/commands/select.go
+++ b/commands/select.go
@@ -10,7 +10,6 @@ import (
"github.com/vulsio/goval-dictionary/config"
"github.com/vulsio/goval-dictionary/db"
- "github.com/vulsio/goval-dictionary/log"
"github.com/vulsio/goval-dictionary/models"
)
@@ -19,124 +18,145 @@ var selectCmd = &cobra.Command{
Use: "select",
Short: "Select from DB",
Long: `Select from DB`,
- RunE: executeSelect,
}
func init() {
RootCmd.AddCommand(selectCmd)
- selectCmd.PersistentFlags().Bool("by-package", false, "select OVAL by package name")
- _ = viper.BindPFlag("by-package", selectCmd.PersistentFlags().Lookup("by-package"))
+ selectCmd.AddCommand(
+ &cobra.Command{
+ Use: "package ()",
+ Short: "Select OVAL by package name",
+ Args: cobra.RangeArgs(3, 4),
+ RunE: func(_ *cobra.Command, args []string) error {
+ arch := ""
+ if len(args) == 4 {
+ switch args[0] {
+ case config.Amazon, config.Oracle, config.Fedora:
+ arch = args[3]
+ default:
+ return xerrors.Errorf("Family: %s cannot use the Architecture argument.", args[0])
+ }
+ }
- selectCmd.PersistentFlags().Bool("by-cveid", false, "select OVAL by CVE-ID")
- _ = viper.BindPFlag("by-cveid", selectCmd.PersistentFlags().Lookup("by-cveid"))
-}
+ 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 select command. err: SchemaVersion is old. SchemaVersion: %+v", map[string]uint{"latest": models.LatestSchemaVersion, "DB": fetchMeta.SchemaVersion})
+ }
+
+ dfs, err := driver.GetByPackName(args[0], args[1], args[2], arch)
+ if err != nil {
+ return xerrors.Errorf("Failed to get cve by package. err: %w", err)
+ }
+
+ for _, d := range dfs {
+ for _, cve := range d.Advisory.Cves {
+ fmt.Printf("%s\n", cve.CveID)
+ for _, pack := range d.AffectedPacks {
+ fmt.Printf(" %v\n", pack)
+ }
+ }
+ }
+ fmt.Println("------------------")
+ pp.ColoringEnabled = false
+ _, _ = pp.Println(dfs)
+
+ return nil
+ },
+ Example: `$ goval-dictionary select package ubuntu 24.04 bash
+$ goval-dictionary select package oracle 9 bash x86_64`,
+ },
+ &cobra.Command{
+ Use: "cve-id ()",
+ Short: "Select OVAL by CVE-ID",
+ Args: cobra.RangeArgs(3, 4),
+ RunE: func(_ *cobra.Command, args []string) error {
+ arch := ""
+ if len(args) == 4 {
+ switch args[0] {
+ case config.Amazon, config.Oracle, config.Fedora:
+ arch = args[3]
+ default:
+ return xerrors.Errorf("Family: %s cannot use the Architecture argument.", args[0])
+ }
+ }
+
+ 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 select command. err: SchemaVersion is old. SchemaVersion: %+v", map[string]uint{"latest": models.LatestSchemaVersion, "DB": fetchMeta.SchemaVersion})
+ }
+
+ dfs, err := driver.GetByCveID(args[0], args[1], args[2], arch)
+ if err != nil {
+ return xerrors.Errorf("Failed to get cve by cveID. err: %w", err)
+ }
+ for _, d := range dfs {
+ fmt.Printf("%s\n", d.Title)
+ fmt.Printf("%v\n", d.Advisory.Cves)
+ }
+ fmt.Println("------------------")
+ pp.ColoringEnabled = false
+ _, _ = pp.Println(dfs)
+
+ return nil
+ },
+ Example: `$ goval-dictionary select cve-id ubuntu 24.04 CVE-2024-6387
+$ goval-dictionary select cve-id oracle 9 CVE-2024-6387 x86_64`,
+ },
+ &cobra.Command{
+ Use: "advisories ",
+ Short: "List Advisories and Releated CVE-IDs",
+ Args: cobra.ExactArgs(2),
+ RunE: func(_ *cobra.Command, args []string) error {
+ 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 select command. err: SchemaVersion is old. SchemaVersion: %+v", map[string]uint{"latest": models.LatestSchemaVersion, "DB": fetchMeta.SchemaVersion})
+ }
+
+ m, err := driver.GetAdvisories(args[0], args[1])
+ if err != nil {
+ return xerrors.Errorf("Failed to get cve by cveID. err: %w", err)
+ }
+ pp.ColoringEnabled = false
+ _, _ = pp.Println(m)
+
+ return nil
+ },
+ Example: `$ goval-dictionary select advisories ubuntu 24.04`,
+ },
+ )
-func executeSelect(_ *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)
- }
-
- flagPkg := viper.GetBool("by-package")
- flagCveID := viper.GetBool("by-cveid")
-
- if (!flagPkg && !flagCveID) || (flagPkg && flagCveID) {
- return xerrors.New("Failed to select command. err: specify --by-package or --by-cveid")
- }
-
- if len(args) < 3 {
- if flagPkg {
- return xerrors.Errorf(`
- Usage:
- select OVAL by package name
- $ goval-dictionary select --by-package [osFamily] [osVersion] [Package Name] [Optional: Architecture (Oracle, Amazon Only)]
- `)
- }
- if flagCveID {
- return xerrors.Errorf(`
- Usage:
- select OVAL by CVE-ID
- $ goval-dictionary select --by-cveid [osFamily] [osVersion] [CVE-ID] [Optional: Architecture (Oracle, Amazon Only)]
- `)
- }
- } else if len(args) > 4 {
- if flagPkg {
- return xerrors.Errorf(`
- Usage:
- select OVAL by package name
- $ goval-dictionary select --by-package [osFamily] [osVersion] [Package Name] [Optional: Architecture (Oracle, Amazon Only)]
- `)
- }
- if flagCveID {
- return xerrors.Errorf(`
- Usage:
- select OVAL by CVE-ID
- $ goval-dictionary select --by-cveid [osFamily] [osVersion] [CVE-ID] [Optional: Architecture (Oracle, Amazon Only)]
- `)
- }
- }
-
- family := args[0]
- release := args[1]
- arg := args[2]
- arch := ""
- if len(args) == 4 {
- switch family {
- case config.Amazon, config.Oracle, config.Fedora:
- arch = args[3]
- default:
- return xerrors.Errorf("Family: %s cannot use the Architecture argument.", family)
- }
- }
-
- 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 select command. err: SchemaVersion is old. SchemaVersion: %+v", map[string]uint{"latest": models.LatestSchemaVersion, "DB": fetchMeta.SchemaVersion})
- }
-
- if flagPkg {
- dfs, err := driver.GetByPackName(family, release, arg, arch)
- if err != nil {
- return xerrors.Errorf("Failed to get cve by package. err: %w", err)
- }
-
- for _, d := range dfs {
- for _, cve := range d.Advisory.Cves {
- fmt.Printf("%s\n", cve.CveID)
- for _, pack := range d.AffectedPacks {
- fmt.Printf(" %v\n", pack)
- }
- }
- }
- fmt.Println("------------------")
- pp.ColoringEnabled = false
- _, _ = pp.Println(dfs)
- }
-
- if flagCveID {
- dfs, err := driver.GetByCveID(family, release, arg, arch)
- if err != nil {
- return xerrors.Errorf("Failed to get cve by cveID. err: %w", err)
- }
- for _, d := range dfs {
- fmt.Printf("%s\n", d.Title)
- fmt.Printf("%v\n", d.Advisory.Cves)
- }
- fmt.Println("------------------")
- pp.ColoringEnabled = false
- _, _ = pp.Println(dfs)
- }
-
- return nil
}
diff --git a/db/db.go b/db/db.go
index 898d6805..9e672558 100644
--- a/db/db.go
+++ b/db/db.go
@@ -23,6 +23,7 @@ type DB interface {
GetByPackName(family string, osVer string, packName string, arch string) ([]models.Definition, error)
GetByCveID(family string, osVer string, cveID string, arch string) ([]models.Definition, error)
+ GetAdvisories(family string, osVer string) (map[string][]string, error)
InsertOval(*models.Root) error
CountDefs(string, string) (int, error)
GetLastModified(string, string) (time.Time, error)
diff --git a/db/rdb.go b/db/rdb.go
index 3d47f7ad..b3e776d3 100644
--- a/db/rdb.go
+++ b/db/rdb.go
@@ -8,6 +8,7 @@ import (
"io"
"log"
"os"
+ "strings"
"time"
"github.com/cheggaaa/pb/v3"
@@ -24,6 +25,7 @@ import (
c "github.com/vulsio/goval-dictionary/config"
"github.com/vulsio/goval-dictionary/models"
+ "github.com/vulsio/goval-dictionary/util"
)
// Supported DB dialects.
@@ -296,6 +298,109 @@ func (r *RDBDriver) GetByCveID(family, osVer, cveID, arch string) ([]models.Defi
}
}
+// GetAdvisories select AdvisoryID: []CVE IDs
+func (r *RDBDriver) GetAdvisories(family, osVer string) (map[string][]string, error) {
+ family, osVer, err := formatFamilyAndOSVer(family, osVer)
+ if err != nil {
+ return nil, xerrors.Errorf("Failed to formatFamilyAndOSVer. err: %w", err)
+ }
+
+ q := r.conn.
+ Joins("JOIN roots ON roots.id = definitions.root_id AND roots.family= ? AND roots.os_version = ?", family, osVer).
+ Joins("JOIN advisories ON advisories.definition_id = definitions.id").
+ Joins("JOIN cves ON cves.advisory_id = advisories.id").
+ Preload("Advisory").
+ Preload("Advisory.Cves")
+
+ switch family {
+ case c.Debian:
+ q = q.Preload("Debian", "dsa != \"\"")
+ case c.Ubuntu:
+ q = q.Preload("References", "ref_url LIKE ?", "https://ubuntu.com/security/notices/USN-%")
+ case c.RedHat:
+ q = q.Not("definitions.definition_id LIKE ?", "oval:com.redhat.cve:def:%").Preload("References", "source = ?", "RHSA")
+ case c.Oracle:
+ q = q.Preload("References", "source = ?", "elsa")
+ case c.Amazon, c.Fedora:
+ case c.Alpine:
+ return nil, nil
+ case c.OpenSUSE, c.OpenSUSELeap, c.SUSEEnterpriseServer, c.SUSEEnterpriseDesktop:
+ q = q.Preload("References", "source = ?", "SUSE-SU")
+ default:
+ return nil, nil
+ }
+
+ defs := []models.Definition{}
+ if err := q.Find(&defs).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
+ return nil, err
+ }
+
+ m := map[string][]string{}
+ switch family {
+ case c.Debian:
+ for _, d := range defs {
+ if d.Debian == nil || d.Debian.DSA == "" {
+ continue
+ }
+ for _, cve := range d.Advisory.Cves {
+ m[d.Debian.DSA] = append(m[d.Debian.DSA], cve.CveID)
+ }
+ }
+ for k := range m {
+ m[k] = util.Unique(m[k])
+ }
+ return m, nil
+ case c.Ubuntu:
+ for _, d := range defs {
+ cves := make([]string, 0, len(d.Advisory.Cves))
+ for _, cve := range d.Advisory.Cves {
+ cves = append(cves, cve.CveID)
+ }
+ for _, r := range d.References {
+ m[strings.TrimPrefix(r.RefURL, "https://ubuntu.com/security/notices/")] = append(m[strings.TrimPrefix(r.RefURL, "https://ubuntu.com/security/notices/")], cves...)
+ }
+ }
+ for k := range m {
+ m[k] = util.Unique(m[k])
+ }
+ return m, nil
+ case c.RedHat, c.Oracle:
+ for _, d := range defs {
+ cves := make([]string, 0, len(d.Advisory.Cves))
+ for _, cve := range d.Advisory.Cves {
+ cves = append(cves, cve.CveID)
+ }
+ for _, r := range d.References {
+ m[r.RefID] = append(m[r.RefID], cves...)
+ }
+ }
+ return m, nil
+ case c.Amazon, c.Fedora:
+ for _, d := range defs {
+ for _, cve := range d.Advisory.Cves {
+ m[d.Title] = append(m[d.Title], cve.CveID)
+ }
+ }
+ return m, nil
+ case c.OpenSUSE, c.OpenSUSELeap, c.SUSEEnterpriseServer, c.SUSEEnterpriseDesktop:
+ for _, d := range defs {
+ cves := make([]string, 0, len(d.Advisory.Cves))
+ for _, cve := range d.Advisory.Cves {
+ cves = append(cves, cve.CveID)
+ }
+ for _, r := range d.References {
+ m[r.RefID] = append(m[r.RefID], cves...)
+ }
+ }
+ for k := range m {
+ m[k] = util.Unique(m[k])
+ }
+ return m, nil
+ default:
+ return nil, nil
+ }
+}
+
// InsertOval inserts OVAL
func (r *RDBDriver) InsertOval(root *models.Root) error {
family, osVer, err := formatFamilyAndOSVer(root.Family, root.OSVersion)
diff --git a/db/redis.go b/db/redis.go
index e17b94f2..e1f2eeb9 100644
--- a/db/redis.go
+++ b/db/redis.go
@@ -15,10 +15,12 @@ import (
"github.com/go-redis/redis/v8"
"github.com/inconshreveable/log15"
"github.com/spf13/viper"
+ "golang.org/x/exp/maps"
"golang.org/x/xerrors"
c "github.com/vulsio/goval-dictionary/config"
"github.com/vulsio/goval-dictionary/models"
+ "github.com/vulsio/goval-dictionary/util"
)
/**
@@ -56,6 +58,8 @@ import (
│ 3 │ OVAL#FETCHMETA │ SchemaVersion │ uint │ GET Go-Oval-Dictionary Schema Version │
├───┼─────────────────────────────┼───────────────┼───────────┼───────────────────────────────────────────┤
│ 4 │ OVAL#FETCHMETA │ LastFetchedAt │ time.Time │ GET Go-Oval-Dictionary Last Fetched Time │
+ ├───┼─────────────────────────────┼───────────────┼───────────┼───────────────────────────────────────────┤
+ │ 5 │ OVAL#$OSFAMILY#$VERSION#ADV │ $ADVISORYID │ []$CVEID │ GET CVEIDs related to Advisory ID │
└───┴─────────────────────────────┴───────────────┴───────────┴───────────────────────────────────────────┘
**/
@@ -66,6 +70,7 @@ const (
defKeyFormat = "OVAL#%s#%s#DEF"
cveKeyFormat = "OVAL#%s#%s#CVE#%s"
pkgKeyFormat = "OVAL#%s#%s#PKG#%s"
+ advKeyFormat = "OVAL#%s#%s#ADV"
depKeyFormat = "OVAL#%s#%s#DEP"
lastModifiedKeyFormat = "OVAL#%s#%s#LASTMODIFIED"
fetchMetaKey = "OVAL#FETCHMETA"
@@ -311,6 +316,31 @@ func fileterPacksByArch(packs []models.Package, arch string) []models.Package {
return filtered
}
+// GetAdvisories select AdvisoryID: []CVE IDs
+func (r *RedisDriver) GetAdvisories(family, osVer string) (map[string][]string, error) {
+ family, osVer, err := formatFamilyAndOSVer(family, osVer)
+ if err != nil {
+ return nil, xerrors.Errorf("Failed to formatFamilyAndOSVer. err: %w", err)
+ }
+
+ ctx := context.Background()
+ v, err := r.conn.HGetAll(ctx, fmt.Sprintf(advKeyFormat, family, osVer)).Result()
+ if err != nil {
+ return nil, xerrors.Errorf("Failed to HGetAll. err: %w", err)
+ }
+
+ m := map[string][]string{}
+ for adv, s := range v {
+ var cves []string
+ if err := json.Unmarshal([]byte(s), &cves); err != nil {
+ return nil, xerrors.Errorf("Failed to Unmarshal JSON. err: %w", err)
+ }
+ m[adv] = cves
+ }
+
+ return m, nil
+}
+
// InsertOval inserts OVAL
func (r *RedisDriver) InsertOval(root *models.Root) (err error) {
ctx := context.Background()
@@ -325,8 +355,89 @@ func (r *RedisDriver) InsertOval(root *models.Root) (err error) {
}
log15.Info("Refreshing...", "Family", family, "Version", osVer)
- // newDeps, oldDeps: {"DEFID": {"cves": {"CVEID": {}}, "packages": {"PACKNAME": {}}}}
- newDeps := map[string]map[string]map[string]struct{}{}
+ advs := map[string][]string{}
+ switch family {
+ case c.Debian:
+ for _, d := range root.Definitions {
+ if d.Debian == nil || d.Debian.DSA == "" {
+ continue
+ }
+ for _, cve := range d.Advisory.Cves {
+ advs[d.Debian.DSA] = append(advs[d.Debian.DSA], cve.CveID)
+ }
+ }
+ for k := range advs {
+ advs[k] = util.Unique(advs[k])
+ }
+ case c.Ubuntu:
+ for _, d := range root.Definitions {
+ cves := make([]string, 0, len(d.Advisory.Cves))
+ for _, cve := range d.Advisory.Cves {
+ cves = append(cves, cve.CveID)
+ }
+ for _, r := range d.References {
+ if strings.HasPrefix(r.RefURL, "https://ubuntu.com/security/notices/USN-") {
+ advs[strings.TrimPrefix(r.RefURL, "https://ubuntu.com/security/notices/")] = append(advs[strings.TrimPrefix(r.RefURL, "https://ubuntu.com/security/notices/")], cves...)
+ }
+ }
+ }
+ for k := range advs {
+ advs[k] = util.Unique(advs[k])
+ }
+ case c.RedHat:
+ for _, d := range root.Definitions {
+ if strings.HasPrefix(d.DefinitionID, "oval:com.redhat.cve:def:") {
+ continue
+ }
+ cves := make([]string, 0, len(d.Advisory.Cves))
+ for _, cve := range d.Advisory.Cves {
+ cves = append(cves, cve.CveID)
+ }
+ for _, r := range d.References {
+ if r.Source == "RHSA" {
+ advs[r.RefID] = append(advs[r.RefID], cves...)
+ }
+ }
+ }
+ case c.Oracle:
+ for _, d := range root.Definitions {
+ cves := make([]string, 0, len(d.Advisory.Cves))
+ for _, cve := range d.Advisory.Cves {
+ cves = append(cves, cve.CveID)
+ }
+ for _, r := range d.References {
+ if r.Source == "elsa" {
+ advs[r.RefID] = append(advs[r.RefID], cves...)
+ }
+ }
+ }
+ case c.Amazon, c.Fedora:
+ for _, d := range root.Definitions {
+ for _, cve := range d.Advisory.Cves {
+ advs[d.Title] = append(advs[d.Title], cve.CveID)
+ }
+ }
+ case c.Alpine:
+ case c.OpenSUSE, c.OpenSUSELeap, c.SUSEEnterpriseServer, c.SUSEEnterpriseDesktop:
+ for _, d := range root.Definitions {
+ cves := make([]string, 0, len(d.Advisory.Cves))
+ for _, cve := range d.Advisory.Cves {
+ cves = append(cves, cve.CveID)
+ }
+ for _, r := range d.References {
+ if r.Source == "SUSE-SU" {
+ advs[r.RefID] = append(advs[r.RefID], cves...)
+ }
+ }
+ }
+ for k := range advs {
+ advs[k] = util.Unique(advs[k])
+ }
+ default:
+ }
+
+ // newDeps, oldDeps: {"DEFID": {"cves": {"CVEID": {}}, "packages": {"PACKNAME": {}}}, "advisories": {"ADVISORYID": {}}}
+ newDeps := map[string]map[string]map[string]struct{}{"advisories": {}}
depKey := fmt.Sprintf(depKeyFormat, family, osVer)
oldDepsStr, err := r.conn.Get(ctx, depKey).Result()
if err != nil {
@@ -340,6 +451,7 @@ func (r *RedisDriver) InsertOval(root *models.Root) (err error) {
return xerrors.Errorf("Failed to unmarshal JSON. err: %w", err)
}
+ log15.Info("Insert Definitions...")
bar := pb.StartNew(len(root.Definitions)).SetWriter(func() io.Writer {
if viper.GetBool("log-json") {
return io.Discard
@@ -402,16 +514,52 @@ func (r *RedisDriver) InsertOval(root *models.Root) (err error) {
}
bar.Finish()
- pipe := r.conn.Pipeline()
- for defID, definitions := range oldDeps {
- for cveID := range definitions["cves"] {
- _ = pipe.SRem(ctx, fmt.Sprintf(cveKeyFormat, family, osVer, cveID), defID)
+ log15.Info("Insert Advisories...")
+ bar = pb.StartNew(len(advs)).SetWriter(func() io.Writer {
+ if viper.GetBool("log-json") {
+ return io.Discard
}
- for pack := range definitions["packages"] {
- _ = pipe.SRem(ctx, fmt.Sprintf(pkgKeyFormat, family, osVer, pack), defID)
+ return os.Stderr
+ }())
+ keys := maps.Keys(advs)
+ for idx := range chunkSlice(len(keys), batchSize) {
+ pipe := r.conn.Pipeline()
+ for _, adv := range keys[idx.From:idx.To] {
+ var aj []byte
+ if aj, err = json.Marshal(advs[adv]); err != nil {
+ return xerrors.Errorf("Failed to marshal json. err: %w", err)
+ }
+
+ _ = pipe.HSet(ctx, fmt.Sprintf(advKeyFormat, family, osVer), adv, string(aj))
+ newDeps["advisories"][adv] = map[string]struct{}{}
+ if _, ok := oldDeps["advisories"]; ok {
+ delete(oldDeps["advisories"], adv)
+ }
+ }
+ if _, err = pipe.Exec(ctx); err != nil {
+ return xerrors.Errorf("Failed to exec pipeline. err: %w", err)
}
- if _, ok := newDeps[defID]; !ok {
- _ = pipe.HDel(ctx, fmt.Sprintf(defKeyFormat, family, osVer), defID)
+ bar.Add(idx.To - idx.From)
+ }
+ bar.Finish()
+
+ pipe := r.conn.Pipeline()
+ for k, v := range oldDeps {
+ switch k {
+ case "advisories":
+ for advID := range v {
+ _ = pipe.HDel(ctx, fmt.Sprintf(advKeyFormat, family, osVer), advID)
+ }
+ default:
+ for cveID := range v["cves"] {
+ _ = pipe.SRem(ctx, fmt.Sprintf(cveKeyFormat, family, osVer, cveID), k)
+ }
+ for pack := range v["packages"] {
+ _ = pipe.SRem(ctx, fmt.Sprintf(pkgKeyFormat, family, osVer, pack), k)
+ }
+ if _, ok := newDeps[k]; !ok {
+ _ = pipe.HDel(ctx, fmt.Sprintf(defKeyFormat, family, osVer), k)
+ }
}
}
newDepsJSON, err := json.Marshal(newDeps)
diff --git a/models/debian/debian.go b/models/debian/debian.go
index 34a88d4b..65cada79 100644
--- a/models/debian/debian.go
+++ b/models/debian/debian.go
@@ -52,6 +52,7 @@ func ConvertToModel(root *Root) (defs []models.Definition) {
Updated: time.Date(1000, time.January, 1, 0, 0, 0, 0, time.UTC),
},
Debian: &models.Debian{
+ DSA: ovaldef.Debian.DSA,
MoreInfo: ovaldef.Debian.MoreInfo,
Date: util.ParsedOrDefaultTime([]string{"2006-01-02"}, ovaldef.Debian.Date),
},
diff --git a/models/models.go b/models/models.go
index 28243967..df6a2270 100644
--- a/models/models.go
+++ b/models/models.go
@@ -136,6 +136,7 @@ type Debian struct {
ID uint `gorm:"primary_key" json:"-"`
DefinitionID uint `gorm:"index:idx_debian_definition_id" json:"-" xml:"-"`
+ DSA string `gorm:"type:varchar(255)"`
MoreInfo string `gorm:"type:text"`
Date time.Time
diff --git a/server/server.go b/server/server.go
index 8b507bea..ddada6d5 100644
--- a/server/server.go
+++ b/server/server.go
@@ -43,6 +43,7 @@ func Start(logToFile bool, logDir string, driver db.DB) error {
e.GET("/packs/:family/:release/:pack", getByPackName(driver))
e.GET("/cves/:family/:release/:id/:arch", getByCveID(driver))
e.GET("/cves/:family/:release/:id", getByCveID(driver))
+ e.GET("/advisories/:family/:release", getAdvisories(driver))
e.GET("/count/:family/:release", countOvalDefs(driver))
e.GET("/lastmodified/:family/:release", getLastModified(driver))
// e.Post("/cpes", getByPackName(driver))
@@ -97,6 +98,20 @@ func getByCveID(driver db.DB) echo.HandlerFunc {
}
}
+func getAdvisories(driver db.DB) echo.HandlerFunc {
+ return func(c echo.Context) (err error) {
+ family := strings.ToLower(c.Param("family"))
+ release := c.Param("release")
+ log15.Debug("Params", "Family", family, "Release", release)
+
+ m, err := driver.GetAdvisories(family, release)
+ if err != nil {
+ log15.Error("Failed to get advisories.", "err", err)
+ }
+ return c.JSON(http.StatusOK, m)
+ }
+}
+
func countOvalDefs(driver db.DB) echo.HandlerFunc {
return func(c echo.Context) (err error) {
family := strings.ToLower(c.Param("family"))