fleet/cmd/cpe/generate.go
Tomas Touceda 46b0b7765b
Issue 1435 software to cpe (#1488)
* WIP

* WIP

* Make path optional and fix tests

* Add first generate

* Move to nvd package

* remove replace

* Re-add replace

* It's path, not file name

* Change how db path is set and use etag

* Fix typos

* Make db generation faster

* Remove quotes

* Doesn't like comments

* Samitize etag and save to file

* Refactor some things and improve writing of etagenv

* Compress file and truncate amount of items for faster testing

* Remove quotes

* Try to improve performance

* Ignore truncate error if not exists

* Minor cleanup and make sqlite have cpe prefix

* Simplify code and test sync

* Add VCR for sync test

* Check for nvdRelease nil

* Add test for the actual translation

* Address review comments

* Rename generate command because we'll have a cve one too

* Move to its own dir

* Address review comments
2021-07-29 13:10:34 -03:00

85 lines
1.7 KiB
Go

package main
import (
"compress/gzip"
"fmt"
"io"
"net/http"
"os"
"path"
"strings"
"github.com/facebookincubator/nvdtools/cpedict"
"github.com/fleetdm/fleet/v4/server/vulnerabilities"
)
func panicif(err error) {
if err != nil {
panic(err)
}
}
func main() {
fmt.Println("Starting CPE sqlite generation")
cwd, err := os.Getwd()
panicif(err)
fmt.Println("CWD:", cwd)
resp, err := http.Get("https://nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml.gz")
panicif(err)
defer resp.Body.Close()
remoteEtag := getSanitizedEtag(resp)
fmt.Println("Got ETag:", remoteEtag)
nvdRelease, err := vulnerabilities.GetLatestNVDRelease(nil)
panicif(err)
if nvdRelease != nil && nvdRelease.Etag == remoteEtag {
fmt.Println("No updates. Exiting...")
return
}
fmt.Println("Needs updating. Generating...")
gr, err := gzip.NewReader(resp.Body)
panicif(err)
defer gr.Close()
cpeDict, err := cpedict.Decode(gr)
panicif(err)
fmt.Println("Generating DB...")
dbPath := path.Join(cwd, fmt.Sprintf("cpe-%s.sqlite", remoteEtag))
err = vulnerabilities.GenerateCPEDB(dbPath, cpeDict)
panicif(err)
fmt.Println("Compressing db...")
compressedDB, err := os.Create(fmt.Sprintf("%s.gz", dbPath))
panicif(err)
db, err := os.Open(dbPath)
w := gzip.NewWriter(compressedDB)
_, err = io.Copy(w, db)
panicif(err)
w.Close()
compressedDB.Close()
file, err := os.Create(path.Join(cwd, "etagenv"))
panicif(err)
file.WriteString(fmt.Sprintf(`ETAG=%s`, remoteEtag))
file.Close()
fmt.Println("Done.")
}
func getSanitizedEtag(resp *http.Response) string {
etag := resp.Header.Get("Etag")
etag = strings.TrimPrefix(strings.TrimSuffix(etag, `"`), `"`)
etag = strings.Replace(etag, ":", "", -1)
return etag
}