feat: init nightly vuls for blackhat
This commit is contained in:
490
pkg/db/boltdb/boltdb.go
Normal file
490
pkg/db/boltdb/boltdb.go
Normal file
@@ -0,0 +1,490 @@
|
||||
package boltdb
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"golang.org/x/exp/maps"
|
||||
|
||||
"github.com/future-architect/vuls/pkg/db/types"
|
||||
)
|
||||
|
||||
type options struct {
|
||||
}
|
||||
|
||||
type Option interface {
|
||||
apply(*options)
|
||||
}
|
||||
|
||||
type DB struct {
|
||||
conn *bolt.DB
|
||||
}
|
||||
|
||||
func Open(dbPath string, debug bool, opts ...Option) (*DB, error) {
|
||||
db, err := bolt.Open(dbPath, 0666, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "open boltdb")
|
||||
}
|
||||
return &DB{conn: db}, nil
|
||||
}
|
||||
|
||||
func (db *DB) Close() error {
|
||||
if db.conn == nil {
|
||||
return nil
|
||||
}
|
||||
if err := db.conn.Close(); err != nil {
|
||||
return errors.Wrap(err, "close boltdb")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutVulnerability(src, key string, value types.Vulnerability) error {
|
||||
bucket, id, found := strings.Cut(key, ":")
|
||||
if !found {
|
||||
return errors.Errorf(`unexpected key. accepts: "vulnerability:<Vulnerability ID>, received: "%s"`, key)
|
||||
}
|
||||
if err := db.conn.Update(func(tx *bolt.Tx) error {
|
||||
b, err := tx.CreateBucketIfNotExists([]byte(bucket))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s bucket", bucket)
|
||||
}
|
||||
|
||||
vb, err := b.CreateBucketIfNotExists([]byte(id))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s/%s bucket", bucket, id)
|
||||
}
|
||||
|
||||
bs, err := json.MarshalIndent(value, "", " ")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshal json")
|
||||
}
|
||||
|
||||
if err := vb.Put([]byte(src), bs); err != nil {
|
||||
return errors.Wrapf(err, "put %%s/%s/%s", bucket, id, src)
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "update db")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutPackage(src, key string, value map[string]types.Packages) error {
|
||||
if err := db.conn.Update(func(tx *bolt.Tx) error {
|
||||
name, version, found := strings.Cut(key, ":")
|
||||
if !found && name == "" {
|
||||
return errors.Errorf(`unexpected key. accepts: "<osname>(:<version>)", received: "%s"`, key)
|
||||
}
|
||||
|
||||
bucket := name
|
||||
b, err := tx.CreateBucketIfNotExists([]byte(name))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s bucket", name)
|
||||
}
|
||||
switch name {
|
||||
case "arch", "freebsd", "gentoo":
|
||||
case "redhat":
|
||||
if version == "" {
|
||||
return errors.Errorf(`unexpected key. accepts: "<osname>:<version>", received: "%s"`, key)
|
||||
}
|
||||
b, err = b.CreateBucketIfNotExists([]byte(version[:1]))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s/%s bucket", name, version[:1])
|
||||
}
|
||||
b, err = b.CreateBucketIfNotExists([]byte(version))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s/%s/%s bucket", name, version[:1], version)
|
||||
}
|
||||
bucket = fmt.Sprintf("%s/%s/%s", name, version[:1], version)
|
||||
default:
|
||||
if version == "" {
|
||||
return errors.Errorf(`unexpected key. accepts: "<osname>:<version>", received: "%s"`, key)
|
||||
}
|
||||
b, err = b.CreateBucketIfNotExists([]byte(version))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "crate %s/%s bucket", name, version)
|
||||
}
|
||||
bucket = fmt.Sprintf("%s/%s", name, version)
|
||||
}
|
||||
|
||||
for n, v := range value {
|
||||
pb, err := b.CreateBucketIfNotExists([]byte(n))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s/%s bucket", bucket, n)
|
||||
}
|
||||
|
||||
vb, err := pb.CreateBucketIfNotExists([]byte(v.ID))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s/%s/%s bucket", bucket, n, v.ID)
|
||||
}
|
||||
|
||||
var p map[string]types.Package
|
||||
bs := vb.Get([]byte(src))
|
||||
if len(bs) > 0 {
|
||||
if err := json.Unmarshal(bs, &p); err != nil {
|
||||
return errors.Wrap(err, "unmarshal json")
|
||||
}
|
||||
} else {
|
||||
p = map[string]types.Package{}
|
||||
}
|
||||
maps.Copy(p, v.Package)
|
||||
bs, err = json.MarshalIndent(p, "", " ")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshal json")
|
||||
}
|
||||
|
||||
if err := vb.Put([]byte(src), bs); err != nil {
|
||||
return errors.Wrapf(err, "put %s", key)
|
||||
}
|
||||
}
|
||||
|
||||
if name == "windows" {
|
||||
kbToProduct := map[string][]string{}
|
||||
for n, ps := range value {
|
||||
for _, p := range ps.Package {
|
||||
for _, v := range p.Version {
|
||||
if _, err := strconv.Atoi(v[0].Version); err != nil {
|
||||
continue
|
||||
}
|
||||
kbToProduct[v[0].Version] = append(kbToProduct[v[0].Version], n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b, err := tx.CreateBucketIfNotExists([]byte("windows_kb_to_product"))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "create windows_kb_to_product bucket")
|
||||
}
|
||||
|
||||
if version == "" {
|
||||
return errors.Errorf(`unexpected key. accepts: "<osname>:<version>", received: "%s"`, key)
|
||||
}
|
||||
b, err = b.CreateBucketIfNotExists([]byte(version))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s/%s bucket", name, version)
|
||||
}
|
||||
|
||||
for kb, ps := range kbToProduct {
|
||||
bs, err := json.Marshal(ps)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshal json")
|
||||
}
|
||||
b.Put([]byte(kb), bs)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "update db")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutCPEConfiguration(src, key string, value map[string]types.CPEConfigurations) error {
|
||||
if err := db.conn.Update(func(tx *bolt.Tx) error {
|
||||
b, err := tx.CreateBucketIfNotExists([]byte(key))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s bucket", key)
|
||||
}
|
||||
|
||||
for pvp, c := range value {
|
||||
pvpb, err := b.CreateBucketIfNotExists([]byte(pvp))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s/%s bucket", key, pvp)
|
||||
}
|
||||
|
||||
vb, err := pvpb.CreateBucketIfNotExists([]byte(c.ID))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s/%s/%s bucket", key, pvp, c.ID)
|
||||
}
|
||||
|
||||
var v map[string][]types.CPEConfiguration
|
||||
bs := vb.Get([]byte(src))
|
||||
if len(bs) > 0 {
|
||||
if err := json.Unmarshal(bs, &v); err != nil {
|
||||
return errors.Wrap(err, "unmarshal json")
|
||||
}
|
||||
} else {
|
||||
v = map[string][]types.CPEConfiguration{}
|
||||
}
|
||||
maps.Copy(v, c.Configuration)
|
||||
bs, err = json.MarshalIndent(v, "", " ")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshal json")
|
||||
}
|
||||
|
||||
if err := vb.Put([]byte(src), bs); err != nil {
|
||||
return errors.Wrapf(err, "put %s", key)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "update db")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutRedHatRepoToCPE(src, key string, value types.RepositoryToCPE) error {
|
||||
if err := db.conn.Update(func(tx *bolt.Tx) error {
|
||||
name, version, found := strings.Cut(key, ":")
|
||||
if !found && name == "" {
|
||||
return errors.Errorf(`unexpected key. accepts: "redhat_cpe:<version>", received: "%s"`, key)
|
||||
}
|
||||
|
||||
b, err := tx.CreateBucketIfNotExists([]byte(name))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s bucket", name)
|
||||
}
|
||||
|
||||
b, err = b.CreateBucketIfNotExists([]byte(version[:1]))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s/%s bucket", name, version[:1])
|
||||
}
|
||||
|
||||
b, err = b.CreateBucketIfNotExists([]byte(version))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s/%s/%s bucket", name, version[:1], version)
|
||||
}
|
||||
|
||||
for repo, cpes := range value {
|
||||
rb, err := b.CreateBucketIfNotExists([]byte(repo))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s/%s/%s/%s bucket", name, version[:1], version, repo)
|
||||
}
|
||||
|
||||
bs, err := json.MarshalIndent(cpes, "", " ")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshal json")
|
||||
}
|
||||
|
||||
if err := rb.Put([]byte(src), bs); err != nil {
|
||||
return errors.Wrapf(err, "put %s", key)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "update db")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutWindowsSupercedence(src, key string, value types.Supercedence) error {
|
||||
if err := db.conn.Update(func(tx *bolt.Tx) error {
|
||||
b, err := tx.CreateBucketIfNotExists([]byte(key))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s bucket", key)
|
||||
}
|
||||
for kb, supercedences := range value {
|
||||
kbb, err := b.CreateBucketIfNotExists([]byte(kb))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "create %s/%s bucket", key, kb)
|
||||
}
|
||||
bs, err := json.Marshal(supercedences)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshal json")
|
||||
}
|
||||
|
||||
if err := kbb.Put([]byte(src), bs); err != nil {
|
||||
return errors.Wrapf(err, "put %s", key)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "update db")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) GetVulnerability(ids []string) (map[string]map[string]types.Vulnerability, error) {
|
||||
r := map[string]map[string]types.Vulnerability{}
|
||||
if err := db.conn.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte("vulnerability"))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
for _, id := range ids {
|
||||
vb := b.Bucket([]byte(id))
|
||||
if vb == nil {
|
||||
return nil
|
||||
}
|
||||
r[string(id)] = map[string]types.Vulnerability{}
|
||||
if err := vb.ForEach(func(src, bs []byte) error {
|
||||
var v types.Vulnerability
|
||||
if err := json.Unmarshal(bs, &v); err != nil {
|
||||
return errors.Wrapf(err, "decode %s/%s", string(id), string(src))
|
||||
}
|
||||
r[string(id)][string(src)] = v
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetPackage(family, release string, name string) (map[string]map[string]map[string]types.Package, error) {
|
||||
r := map[string]map[string]map[string]types.Package{}
|
||||
if err := db.conn.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(family))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
switch family {
|
||||
case "debian", "ubuntu", "windows":
|
||||
b = b.Bucket([]byte(release))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
b = b.Bucket([]byte(name))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := b.ForEach(func(cveid, _ []byte) error {
|
||||
vb := b.Bucket(cveid)
|
||||
r[string(cveid)] = map[string]map[string]types.Package{}
|
||||
if err := vb.ForEach(func(src, bs []byte) error {
|
||||
var v map[string]types.Package
|
||||
if err := json.Unmarshal(bs, &v); err != nil {
|
||||
return errors.Wrapf(err, "decode %s/%s", string(cveid), string(src))
|
||||
}
|
||||
r[string(cveid)][string(src)] = v
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetCPEConfiguration(partvendorproduct string) (map[string]map[string]map[string][]types.CPEConfiguration, error) {
|
||||
r := map[string]map[string]map[string][]types.CPEConfiguration{}
|
||||
if err := db.conn.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte("cpe"))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
b = b.Bucket([]byte(partvendorproduct))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := b.ForEach(func(cveid, _ []byte) error {
|
||||
vb := b.Bucket(cveid)
|
||||
r[string(cveid)] = map[string]map[string][]types.CPEConfiguration{}
|
||||
if err := vb.ForEach(func(src, bs []byte) error {
|
||||
var v map[string][]types.CPEConfiguration
|
||||
if err := json.Unmarshal(bs, &v); err != nil {
|
||||
return errors.Wrapf(err, "decode cpe/%s/%s/%s", partvendorproduct, string(cveid), string(src))
|
||||
}
|
||||
r[string(cveid)][string(src)] = v
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetSupercedence(kbs []string) (map[string][]string, error) {
|
||||
r := map[string][]string{}
|
||||
if err := db.conn.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte("windows_supercedence"))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
for _, kb := range kbs {
|
||||
kbb := b.Bucket([]byte(kb))
|
||||
if kbb == nil {
|
||||
continue
|
||||
}
|
||||
if err := kbb.ForEach(func(_, v []byte) error {
|
||||
var ss []string
|
||||
if err := json.Unmarshal(v, &ss); err != nil {
|
||||
return errors.Wrapf(err, "decode windows_supercedence/%s", kb)
|
||||
}
|
||||
r[kb] = append(r[kb], ss...)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetKBtoProduct(release string, kbs []string) ([]string, error) {
|
||||
var r []string
|
||||
if err := db.conn.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte("windows_kb_to_product"))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
b = b.Bucket([]byte(release))
|
||||
if b == nil {
|
||||
return nil
|
||||
}
|
||||
for _, kb := range kbs {
|
||||
if bs := b.Get([]byte(kb)); len(bs) > 0 {
|
||||
var ps []string
|
||||
if err := json.Unmarshal(bs, &ps); err != nil {
|
||||
return errors.Wrapf(err, "decode windows_kb_to_product/%s/%s", release, kb)
|
||||
}
|
||||
r = append(r, ps...)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
149
pkg/db/db.go
Normal file
149
pkg/db/db.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/future-architect/vuls/pkg/db/boltdb"
|
||||
"github.com/future-architect/vuls/pkg/db/rdb"
|
||||
"github.com/future-architect/vuls/pkg/db/redis"
|
||||
"github.com/future-architect/vuls/pkg/db/types"
|
||||
)
|
||||
|
||||
type options struct {
|
||||
}
|
||||
|
||||
type Option interface {
|
||||
apply(*options)
|
||||
}
|
||||
|
||||
type DB struct {
|
||||
name string
|
||||
driver Driver
|
||||
}
|
||||
|
||||
type Driver interface {
|
||||
Close() error
|
||||
|
||||
PutVulnerability(string, string, types.Vulnerability) error
|
||||
PutPackage(string, string, map[string]types.Packages) error
|
||||
PutCPEConfiguration(string, string, map[string]types.CPEConfigurations) error
|
||||
PutRedHatRepoToCPE(string, string, types.RepositoryToCPE) error
|
||||
PutWindowsSupercedence(string, string, types.Supercedence) error
|
||||
|
||||
GetVulnerability([]string) (map[string]map[string]types.Vulnerability, error)
|
||||
GetPackage(string, string, string) (map[string]map[string]map[string]types.Package, error)
|
||||
GetCPEConfiguration(string) (map[string]map[string]map[string][]types.CPEConfiguration, error)
|
||||
GetSupercedence([]string) (map[string][]string, error)
|
||||
GetKBtoProduct(string, []string) ([]string, error)
|
||||
}
|
||||
|
||||
func (db *DB) Name() string {
|
||||
return db.name
|
||||
}
|
||||
|
||||
func Open(dbType, dbPath string, debug bool, opts ...Option) (*DB, error) {
|
||||
switch dbType {
|
||||
case "boltdb":
|
||||
d, err := boltdb.Open(dbPath, debug)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "open boltdb")
|
||||
}
|
||||
return &DB{name: dbType, driver: d}, nil
|
||||
case "sqlite3", "mysql", "postgres":
|
||||
d, err := rdb.Open(dbType, dbPath, debug)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "open rdb")
|
||||
}
|
||||
return &DB{name: dbType, driver: d}, nil
|
||||
case "redis":
|
||||
d, err := redis.Open(dbPath, debug)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "open rdb")
|
||||
}
|
||||
return &DB{name: dbType, driver: d}, nil
|
||||
default:
|
||||
return nil, errors.Errorf(`unexpected dbType. accepts: ["boltdb", "sqlite3", "mysql", "postgres", "redis"], received: "%s"`, dbType)
|
||||
}
|
||||
}
|
||||
|
||||
func (db *DB) Close() error {
|
||||
if err := db.driver.Close(); err != nil {
|
||||
return errors.Wrapf(err, "close %s", db.name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutVulnerability(src, key string, value types.Vulnerability) error {
|
||||
if err := db.driver.PutVulnerability(src, key, value); err != nil {
|
||||
return errors.Wrapf(err, "put vulnerability")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutPackage(src, key string, value map[string]types.Packages) error {
|
||||
if err := db.driver.PutPackage(src, key, value); err != nil {
|
||||
return errors.Wrapf(err, "put package")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutCPEConfiguration(src, key string, value map[string]types.CPEConfigurations) error {
|
||||
if err := db.driver.PutCPEConfiguration(src, key, value); err != nil {
|
||||
return errors.Wrapf(err, "put cpe configuration")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutRedHatRepoToCPE(src, key string, value types.RepositoryToCPE) error {
|
||||
if err := db.driver.PutRedHatRepoToCPE(src, key, value); err != nil {
|
||||
return errors.Wrap(err, "put repository to cpe")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutWindowsSupercedence(src, key string, value types.Supercedence) error {
|
||||
if err := db.driver.PutWindowsSupercedence(src, key, value); err != nil {
|
||||
return errors.Wrap(err, "put supercedence")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) GetVulnerability(ids []string) (map[string]map[string]types.Vulnerability, error) {
|
||||
rs, err := db.driver.GetVulnerability(ids)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "get vulnerability")
|
||||
}
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetPackage(family, release string, name string) (map[string]map[string]map[string]types.Package, error) {
|
||||
rs, err := db.driver.GetPackage(family, release, name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "get package")
|
||||
}
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetCPEConfiguration(partvendorproduct string) (map[string]map[string]map[string][]types.CPEConfiguration, error) {
|
||||
rs, err := db.driver.GetCPEConfiguration(partvendorproduct)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "get cpe configuration")
|
||||
}
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetSupercedence(kb []string) (map[string][]string, error) {
|
||||
rs, err := db.driver.GetSupercedence(kb)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get supercedence")
|
||||
}
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetKBtoProduct(release string, kb []string) ([]string, error) {
|
||||
rs, err := db.driver.GetKBtoProduct(release, kb)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get product from kb")
|
||||
}
|
||||
return rs, nil
|
||||
}
|
||||
110
pkg/db/rdb/rdb.go
Normal file
110
pkg/db/rdb/rdb.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package rdb
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
_ "modernc.org/sqlite"
|
||||
|
||||
"github.com/future-architect/vuls/pkg/db/types"
|
||||
)
|
||||
|
||||
type options struct {
|
||||
}
|
||||
|
||||
type Option interface {
|
||||
apply(*options)
|
||||
}
|
||||
|
||||
type DB struct {
|
||||
conn *gorm.DB
|
||||
}
|
||||
|
||||
func Open(dbType, dbPath string, debug bool, opts ...Option) (*DB, error) {
|
||||
switch dbType {
|
||||
case "sqlite3":
|
||||
// db, err := gorm.Open(sqlite.Open(dbPath))
|
||||
db := &gorm.DB{}
|
||||
conn, err := sql.Open("sqlite", dbPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "open sqlite3")
|
||||
}
|
||||
db.ConnPool = conn
|
||||
return &DB{conn: db}, nil
|
||||
case "mysql":
|
||||
db, err := gorm.Open(mysql.Open(dbPath))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "open mysql")
|
||||
}
|
||||
return &DB{conn: db}, nil
|
||||
case "postgres":
|
||||
db, err := gorm.Open(postgres.Open(dbPath))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "open postgres")
|
||||
}
|
||||
return &DB{conn: db}, nil
|
||||
default:
|
||||
return nil, errors.Errorf(`unexpected dbType. accepts: ["sqlite3", "mysql", "postgres"], received: "%s"`, dbType)
|
||||
}
|
||||
}
|
||||
|
||||
func (db *DB) Close() error {
|
||||
if db.conn == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
sqlDB *sql.DB
|
||||
err error
|
||||
)
|
||||
if sqlDB, err = db.conn.DB(); err != nil {
|
||||
return errors.Wrap(err, "get *sql.DB")
|
||||
}
|
||||
if err := sqlDB.Close(); err != nil {
|
||||
return errors.Wrap(err, "close *sql.DB")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutVulnerability(src, key string, value types.Vulnerability) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutPackage(src, key string, value map[string]types.Packages) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutCPEConfiguration(src, key string, value map[string]types.CPEConfigurations) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutRedHatRepoToCPE(src, key string, value types.RepositoryToCPE) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutWindowsSupercedence(src, key string, value types.Supercedence) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) GetVulnerability(ids []string) (map[string]map[string]types.Vulnerability, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetPackage(family, release string, name string) (map[string]map[string]map[string]types.Package, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetCPEConfiguration(partvendorproduct string) (map[string]map[string]map[string][]types.CPEConfiguration, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetSupercedence(kb []string) (map[string][]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetKBtoProduct(elease string, kb []string) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
77
pkg/db/redis/redis.go
Normal file
77
pkg/db/redis/redis.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"github.com/go-redis/redis/v9"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/future-architect/vuls/pkg/db/types"
|
||||
)
|
||||
|
||||
type options struct {
|
||||
}
|
||||
|
||||
type Option interface {
|
||||
apply(*options)
|
||||
}
|
||||
|
||||
type DB struct {
|
||||
conn *redis.Client
|
||||
}
|
||||
|
||||
func Open(dbPath string, debug bool, opts ...Option) (*DB, error) {
|
||||
redisOpts, err := redis.ParseURL(dbPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parse redis URL")
|
||||
}
|
||||
return &DB{conn: redis.NewClient(redisOpts)}, nil
|
||||
}
|
||||
|
||||
func (db *DB) Close() error {
|
||||
if db.conn == nil {
|
||||
return nil
|
||||
}
|
||||
if err := db.conn.Close(); err != nil {
|
||||
return errors.Wrap(err, "close redis")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutVulnerability(src, key string, value types.Vulnerability) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutPackage(src, key string, value map[string]types.Packages) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutCPEConfiguration(src, key string, value map[string]types.CPEConfigurations) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutRedHatRepoToCPE(src, key string, value types.RepositoryToCPE) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) PutWindowsSupercedence(src, key string, value types.Supercedence) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) GetVulnerability(ids []string) (map[string]map[string]types.Vulnerability, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetPackage(family, release string, name string) (map[string]map[string]map[string]types.Package, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetCPEConfiguration(partvendorproduct string) (map[string]map[string]map[string][]types.CPEConfiguration, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetSupercedence(kb []string) (map[string][]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetKBtoProduct(release string, kb []string) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
85
pkg/db/types/types.go
Normal file
85
pkg/db/types/types.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package types
|
||||
|
||||
import "time"
|
||||
|
||||
type Vulnerability struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Advisory []string `json:"advisory,omitempty"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
CVSS []CVSS `json:"cvss,omitempty"`
|
||||
EPSS *EPSS `json:"epss,omitempty"`
|
||||
CWE []CWE `json:"cwe,omitempty"`
|
||||
Metasploit []Metasploit `json:"metasploit,omitempty"`
|
||||
Exploit []Exploit `json:"exploit,omitempty"`
|
||||
KEV bool `json:"kev,omitempty"`
|
||||
Published *time.Time `json:"published,omitempty"`
|
||||
Modified *time.Time `json:"modified,omitempty"`
|
||||
Reference []string `json:"reference,omitempty"`
|
||||
}
|
||||
|
||||
type CVSS struct {
|
||||
Source string `json:"source,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
Vector string `json:"vector,omitempty"`
|
||||
Score *float64 `json:"score,omitempty"`
|
||||
Severity string `json:"severity,omitempty"`
|
||||
}
|
||||
|
||||
type EPSS struct {
|
||||
EPSS *float64 `json:"epss,omitempty"`
|
||||
Percentile *float64 `json:"percentile,omitempty"`
|
||||
}
|
||||
|
||||
type CWE struct {
|
||||
Source []string `json:"source,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
type Metasploit struct {
|
||||
Title string `json:"title,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
type Exploit struct {
|
||||
Source []string `json:"source,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
type CPEConfigurations struct {
|
||||
ID string `json:"-,omitempty"`
|
||||
Configuration map[string][]CPEConfiguration `json:"configuration,omitempty"`
|
||||
}
|
||||
|
||||
type CPEConfiguration struct {
|
||||
Vulnerable CPE `json:"vulnerable,omitempty"`
|
||||
RunningOn []CPE `json:"running_on,omitempty"`
|
||||
}
|
||||
|
||||
type CPE struct {
|
||||
CPEVersion string `json:"cpe_version,omitempty"`
|
||||
CPE string `json:"cpe,omitempty"`
|
||||
Version []Version `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
type Packages struct {
|
||||
ID string `json:"-,omitempty"`
|
||||
Package map[string]Package `json:"package,omitempty"`
|
||||
}
|
||||
|
||||
type Package struct {
|
||||
Status string `json:"status,omitempty"`
|
||||
Version [][]Version `json:"version,omitempty"`
|
||||
Arch []string `json:"arch,omitempty"`
|
||||
Repository string `json:"repository,omitempty"`
|
||||
CPE []string `json:"cpe,omitempty"`
|
||||
}
|
||||
|
||||
type Version struct {
|
||||
Operator string `json:"operator,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
type RepositoryToCPE map[string][]string
|
||||
|
||||
type Supercedence map[string][]string
|
||||
1
pkg/db/util/util.go
Normal file
1
pkg/db/util/util.go
Normal file
@@ -0,0 +1 @@
|
||||
package util
|
||||
Reference in New Issue
Block a user