mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
## Addresses #15999 - [x] Added/updated tests - [ ] Manual QA for all new/changed functionality --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
105 lines
2.6 KiB
Go
105 lines
2.6 KiB
Go
// Copyright (c) Facebook, Inc. and its affiliates.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package cvefeed
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
// Dictionary is a slice of entries
|
|
type Dictionary map[string]Vuln
|
|
|
|
// Override amends entries in Dictionary with configurations from Dictionary d2;
|
|
// CVE will be matched if it matches the original config of d and does not match the config of d2.
|
|
func (d *Dictionary) Override(d2 Dictionary) {
|
|
if d == nil {
|
|
return
|
|
}
|
|
if *d == nil {
|
|
*d = make(Dictionary)
|
|
}
|
|
for k, cve := range d2 {
|
|
if _, ok := (*d)[k]; ok {
|
|
(*d)[k] = OverrideVuln((*d)[k], cve)
|
|
}
|
|
}
|
|
}
|
|
|
|
// LoadJSONDictionary parses dictionary from multiple NVD vulnerability feed JSON files
|
|
func LoadJSONDictionary(paths ...string) (Dictionary, error) {
|
|
return LoadFeed(loadJSONFile, paths...)
|
|
}
|
|
|
|
// LoadFeed calls loadFunc for each file in paths and returns the combined outputs in a Dictionary.
|
|
func LoadFeed(loadFunc func(string) ([]Vuln, error), paths ...string) (Dictionary, error) {
|
|
dict := make(Dictionary)
|
|
var wg sync.WaitGroup
|
|
done := make(chan struct{})
|
|
errDone := make(chan struct{})
|
|
dictChan := make(chan []Vuln, 1)
|
|
errChan := make(chan error, 1)
|
|
for _, path := range paths {
|
|
wg.Add(1)
|
|
go func(path string) {
|
|
defer wg.Done()
|
|
feed, err := loadFunc(path)
|
|
if err != nil {
|
|
errChan <- fmt.Errorf("dictionary: failed to load feed %q: %v", path, err)
|
|
return
|
|
}
|
|
dictChan <- feed
|
|
}(path)
|
|
}
|
|
go func() {
|
|
for d := range dictChan {
|
|
for _, cve := range d {
|
|
if cveid := cve.ID(); cveid != "" {
|
|
dict[cveid] = cve
|
|
}
|
|
}
|
|
}
|
|
close(done)
|
|
}()
|
|
var errs []string
|
|
go func() {
|
|
for e := range errChan {
|
|
errs = append(errs, e.Error())
|
|
}
|
|
close(errDone)
|
|
}()
|
|
wg.Wait()
|
|
close(dictChan)
|
|
close(errChan)
|
|
<-done
|
|
<-errDone
|
|
if len(errs) > 0 {
|
|
return dict, errors.New(strings.Join(errs, "\n"))
|
|
}
|
|
return dict, nil
|
|
}
|
|
|
|
// loadJSONFile parses dictionary from NVD vulnerability feed JSON file
|
|
func loadJSONFile(path string) ([]Vuln, error) {
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("dictionary: failed to load feed %q: %v", path, err)
|
|
}
|
|
defer f.Close()
|
|
return ParseJSON(f)
|
|
}
|