Documentation ¶
Index ¶
- Constants
- Variables
- func IsNotFound(err error) bool
- func IsPageEnd(err error) bool
- func IsUnexpectedError(err error) bool
- type Config
- type DB
- type Keyword
- type Mongo
- func (mdb *Mongo) Connect(ctx context.Context, uri string) (err error)
- func (mdb *Mongo) Disconnect(ctx context.Context) error
- func (mdb Mongo) GetCPEByKeyword(ctx context.Context, keyword Keyword, opts ...QueryOptions) (*Result[schema.Cpe], error)
- func (mdb Mongo) GetCPEByMatchString(ctx context.Context, cpeNameMatchString string, opts ...QueryOptions) (*Result[schema.Cpe], error)
- func (mdb Mongo) GetCPEByName(ctx context.Context, cpeName string) (*schema.Cpe, error)
- func (mdb Mongo) GetCVEByCPE(ctx context.Context, cpeName string, opts ...QueryOptions) (*Result[schema.Cve], error)
- func (mdb Mongo) GetCVEByID(ctx context.Context, cveId string) (*schema.Cve, error)
- func (mdb Mongo) GetCVEByKeyword(ctx context.Context, keyword Keyword, opts ...QueryOptions) (*Result[schema.Cve], error)
- func (Mongo) ID() string
- func (mdb Mongo) Init(ctx context.Context) error
- func (mdb Mongo) IsConnected(ctx context.Context) error
- func (mdb Mongo) UpsertCPE(ctx context.Context, cpe schema.Cpe) (upserted bool, err error)
- func (mdb Mongo) UpsertCPEs(ctx context.Context, cpes []schema.Cpe) (upsertCnt int, err error)
- func (mdb Mongo) UpsertCVE(ctx context.Context, cve schema.Cve) (upserted bool, err error)
- func (mdb Mongo) UpsertCVEs(ctx context.Context, cves []schema.Cve) (upsertedCnt int, err error)
- type MongoOptions
- type NVDUnit
- type NvdCpeDB
- type NvdCveDB
- type QueryConfig
- type QueryOptions
- type Result
Constants ¶
const ( // DefaultTimeout is the default timeout for each db operation DefaultTimeout = 10 * time.Second // GetSizeUnlimited is the constant to indicate that there's no size limit for db return record size. GetSizeUnlimited = -1 )
const ( MongoDBID = "mongo" // DBNvd is the database name of nvd service DBNvd = "nvd" // CltCve and CltCpe are collection name in 'DBNvd' CltCve = "cve" CltCpe = "cpe" MongoTLSTemplate = "mongodb://%s:%s@%s/nvd?tls=true&replicaSet=rs0&retryWrites=false" )
Variables ¶
var ( // ErrNotFound is general not found error for all structs that implement Nvd[Cve|Cpe]DB interface // It is expected to return this error if the input is not found in the table ErrNotFound = errors.New("not found") // ErrPageEnd is the error to indicate that the start index is larger than the total number of entries ErrPageEnd = errors.New("page end") )
var ( // DefaultGetMongoURI is the url template to connect to local testing mongo db, // query string of URI might be different when connecting to db with different authenication method DefaultGetMongoURI = func(user, pwd, endpoint string) string { return fmt.Sprintf("mongodb://%s:%s@%s/nvd?authSource=admin", user, pwd, endpoint) } )
Functions ¶
func IsNotFound ¶
IsNotFound checks whether the error belongs to data not found in database
func IsUnexpectedError ¶
IsUnexpectedError checkes whether the error belongs to unexpected error in database
Types ¶
type Config ¶
Config is the general(default) config to initialize the collection or control the db logic.
type DB ¶
type DB interface { ID() string Init(ctx context.Context) error Connect(ctx context.Context, uri string) error Disconnect(ctx context.Context) error IsConnected(ctx context.Context) error }
DB is the interface to record information and handle general operations such as connect and disconnect to database.
type Keyword ¶
type Keyword struct { // Val is the content to match Val string // ExactMatch decides whether matching all the words includes space or not. // E.g., // * Val="Hello World" and `ExactMatch=true`: matches with "Hello World" // * Val="Hello World" and `ExactMatch=false`: matches with "Hello" AND "World" ExactMatch bool }
Keyword defines how a keyword matches with the description of CVE or CPE
type Mongo ¶
type Mongo struct {
// contains filtered or unexported fields
}
Mongo is the db client to handle mongo db operations
func NewMongo ¶
func NewMongo(user, pwd, endpoint string, opts ...MongoOptions) (*Mongo, error)
NewMongo initializes db client to interact with mongo db
func (*Mongo) Disconnect ¶
Disconnect closes connection to database
func (Mongo) GetCPEByKeyword ¶
func (mdb Mongo) GetCPEByKeyword(ctx context.Context, keyword Keyword, opts ...QueryOptions) (*Result[schema.Cpe], error)
GetCPEByKeyword searchs with text index in 'nvd.cpe' ('titles.title' and 'refs.ref') to find match keyword It is the same as using mongo query
db.cpe.find({ $text: { $search: "<keyword>" } });
Usage:
// find cpes that contains "Hello" AND "World" in Titles or References db.GetCPEByKeyword(ctx, Keyword{Val: "Hello World", ExactMatch: false}) // find cpes that contains "Hello World" in Titles or References db.GetCPEByKeyword(ctx, Keyword{Val: "Hello World", ExactMatch: true})
func (Mongo) GetCPEByMatchString ¶
func (mdb Mongo) GetCPEByMatchString(ctx context.Context, cpeNameMatchString string, opts ...QueryOptions) (*Result[schema.Cpe], error)
GetCPEByMatchString get CPEs by CPEMatchString which is prefix of full CPE 2.3 Name.
E.g., cpe:2.3:*:Microsoft, cpe:2.3:o:microsoft:windows_10:1511
It matches the value in db based on parsed CPE (schema.CPEParsed) which store each part in different fields. For the incoming cpeNameMatchString, we try to match the parts that contains meaningful values ('*' and '-' is excluded), and returns with CPEs that matches all of the values.
E.g. 1, cpeNameMatchString=cpe:2.3:*:Microsoft, matches CPEs with vendor=Microsoft E.g. 2, cpeNameMatchString=cpe:2.3:o:microsoft:windows_10, matches CPEs with part=o, vendor=microsoft and product=windows_10
func (Mongo) GetCPEByName ¶
GetCPEByName get CPE by CPEName (E.g., `cpe:2.3:a:rusqlite_project:rusqlite:0.18.0:*:*:*:*:*:*:*`)
- When CPE is found in `nvd.cpe`: return the detail information of cpe
- When CPE is not found in `nvd.cpe`: return ErrNotFound
func (Mongo) GetCVEByCPE ¶
func (mdb Mongo) GetCVEByCPE(ctx context.Context, cpeName string, opts ...QueryOptions) (*Result[schema.Cve], error)
GetCVEByCPE returns CVE with cpe name To query with $regex to the index 'nodes.cpeMatch.criteria' which has relatively poor performance
{ "configurations": { "$elemMatch": { "nodes.cpeMatch.criteria": { "$regex": "^<cpe name product prefix>" } } } }
To leverage the index 'nodes.cpeMatch.criteriaProductPrefix' generated from us, the query becomes
{ "configurations": { "$elemMatch": { "nodes.cpeMatch.criteriaProductPrefix": { "$eq": "<cpe name product prefix>" } } } }
func (Mongo) GetCVEByID ¶
GetCVEByID get CVE by CVEID (E.g., CVE-2001-0131)
- When CVE is found in `nvd.cve`: return the detail information of cve
- When CVE is not found in `nvd.cve`: return ErrNotFound
func (Mongo) GetCVEByKeyword ¶
func (mdb Mongo) GetCVEByKeyword(ctx context.Context, keyword Keyword, opts ...QueryOptions) (*Result[schema.Cve], error)
GetCVEByKeyword searchs with text index in 'nvd.cve' ('descriptions.value') to find match keyword. It is the same as using mongo query
db.cve.find({ $text: { $search: "<keyword>" } });
Usage:
// find cves that contains "Hello" AND "World" in Descriptions db.GetCVEByKeyword(ctx, Keyword{Val: "Hello World", ExactMatch: false}) // find cves that contains "Hello World" in Descriptions db.GetCVEByKeyword(ctx, Keyword{Val: "Hello World", ExactMatch: true})
func (Mongo) Init ¶
Init creates collections and TTL indexes and text indexes for NVD service. It should be only used when initializing environment.
The same mongo command as below:
$ use nvd; $ db.cve.createIndex({ "cveId": 1 }, { unique: true, name: "cveId" }); $ db.cve.createIndex({ "configurations.nodes.cpeMatch.criteria": 1 }, { name: "cpeName" }); $ db.cve.createIndex({ "configurations.nodes.cpeMatch.criteriaProductPrefix": 1 }, { name: "cpeNameProductPrefix" }); $ db.cve.createIndex({ "descriptions.value": "text" }, { name: "keyword" }); $ db.cpe.createIndex({ "cpeName": 1 }, { unique: true, name: "cpeName" }); $ db.cpe.createIndex({ "titles.title": "text", "refs.ref": "text" }, { name: "keyword" });
func (Mongo) IsConnected ¶
IsConnected checks if mongo db is reachable, which is expected to be used for health check endpoint
func (Mongo) UpsertCPE ¶
UpsertCPE inserts or replaces an CPE record in 'nvd.cpe' collection. It Replaces when the incoming CPE record contains latest 'lastModified'. Since mitre does not contain 'lastModified', it might be empty for some stale record.
It use string comparison since all the value in "lastModified" is converted to same time format, and empty 'lastModified' is less than 'lastModified' that contains any value when using string comparison, which is reasonable when sorting 'lastModified' in descending order.
The first return value shows whether the the cve has been upserted after this function.
func (Mongo) UpsertCPEs ¶
UpsertCPEs upserts CPEs to 'nvd.cpe' collection in batch
func (Mongo) UpsertCVE ¶
UpsertCVE inserts or replaces an CVE record in 'nvd.cve' collection. It replaces when the incoming CVE record contains latest 'lastModified'.
It use string comparison since all the value in "lastModified" is converted to same time format, and the first return value shows whether the the cve has been upserted after this function
type MongoOptions ¶
MongoOptions is the options of Mongo client
func MongoClientOptions ¶
func MongoClientOptions(opts ...*options.ClientOptions) MongoOptions
MongoClientOptions appends additional mongo options to client
func MongoConfig ¶
func MongoConfig(cfg Config) MongoOptions
MongoConfig is expected to use only in testing to mock the client
func MongoGetURI ¶
func MongoGetURI(fn func(user, pwd, endpoint string) string) MongoOptions
MongoGetURI overwrites default function to get uri to connect to database
func MongoTestClient ¶
func MongoTestClient(client *mongo.Client) MongoOptions
MongoTestClient is expected to use only in testing to mock the client
type NVDUnit ¶
NVDUnit is the interface to define the possible type of response, which is either CVE or CPE
type NvdCpeDB ¶
type NvdCpeDB interface { GetCPEByName(ctx context.Context, cpeName string) (*schema.Cpe, error) GetCPEByMatchString(ctx context.Context, cpeNameMatchString string, opts ...QueryOptions) (*Result[schema.Cpe], error) GetCPEByKeyword(ctx context.Context, keyword Keyword, opts ...QueryOptions) (*Result[schema.Cpe], error) }
NvdCpeDB is the interface to define the operations related to NVD API for CPE
type NvdCveDB ¶
type NvdCveDB interface { GetCVEByID(ctx context.Context, cveId string) (*schema.Cve, error) GetCVEByCPE(ctx context.Context, cpeName string, opts ...QueryOptions) (*Result[schema.Cve], error) GetCVEByKeyword(ctx context.Context, keywords Keyword, opts ...QueryOptions) (*Result[schema.Cve], error) }
NvdCveDB is the interface to define the operations related to NVD API for CVE
type QueryConfig ¶
QueryConfig is the config for each DB query Use options to stay flexible for future extension
func GetQueryConfig ¶
func GetQueryConfig(opts ...QueryOptions) (QueryConfig, error)
GetQueryConfig gets the query config with given options, use default value in Config if not specified
type QueryOptions ¶
type QueryOptions func(*QueryConfig) error
func Size ¶
func Size(size int) QueryOptions
func StartWith ¶
func StartWith(start int) QueryOptions
type Result ¶
type Result[T NVDUnit] struct { Total, Start, Size int Entries []T // result entries from start to start+size }
Result is the result of a query, including the total number of entries, the start index, the size of the result. Since the result is paginated, the entries are the entries from start to start+size. While total is the total number before pagination.
func (Result[T]) Filter ¶
Filter filters the entries with the given function, which is used for complex conditions which is implemented by the caller with code after getting the result from database. It is expected to be invoke before pagination.
func (Result[T]) GetPaginated ¶
GetPaginated gets the paginated result from the result based on given start and size. start and size should be checked before calling this function. * start should be 0 or positive number * size should be positive number