fleet/cmd/cpe/generate_test.go
Victor Lyuboslavsky eada583ff1
Updating CPE generator to use new NVD API. (#15018)
Loom explaining changes (hit 5 min limit):
https://www.loom.com/share/e59b63bf638e4d9cad7984ef589b878d?sid=111fff75-115a-4a44-ae4f-6f25fede0d51

#14887

- [x] Need to merge fleetdm/nvd PR
https://github.com/fleetdm/nvd/pull/25 before this one.

# Checklist for submitter

- [x] Added/updated tests
- [x] Manual QA for all new/changed functionality
- Manually tested (with corresponding fleetdm/fleet changes) in my
personal fork: https://github.com/getvictor/nvd/releases

# QA Plan (must be done before merging this PR, and after merging the
nvd PR)
- [ ] Fork https://github.com/fleetdm/nvd and point `generate.yml` to
this branch.
[example](9d8e54930b/.github/workflows/generate.yml (L26))
- [ ] Add NVD_API_KEY to nvd secrets, and run the the nvd generate
GitHub action. Get key:
https://nvd.nist.gov/developers/request-an-api-key
- [ ] Compare the generated `cpe-###.sqlite.gz` to the previous one. One
way is to open it up with sqlite3 and `select * from cpe_2 order by
cpe23;` and dump results to a CSV file. Known differences are:
   - New file has ~2,500 more records
- Backslashes are handled differently for `Backpack\CRUD` and `Philips
In.Sight B120\37` products -- not a new issue since we do not support
those products right now
- `cpe:2.3🅰️moodle:moodle:4.2.0:*:*:*:*:*:*:*` -- this appears OK.
Also, it is a PHP plugin, and we don't support these currently.
- [ ] Record the existing vulnerabilities of current hosts.
- [ ] Stop any running fleet server. Delete `/tmp/vulndbs/cpe.sqlite`.
Can also delete other files there, or not delete this file -- it should
be overwritten by the new file. Also delete all rows in software_cpe and
software_cve DB tables. (Or can just spin up a fresh fleet server with
fresh DB, and re-enroll hosts (after setting the new env variable
below))
- [ ] Find the path to the generated `cpe-###.sqlite.gz` file
- [ ] Set `FLEET_VULNERABILITIES_CPE_DATABASE_URL` environment variable
to the above path, and start fleet server.
- [ ] After server's vulnerabilities cron job runs, the new
vulnerabilities should match the previous vulnerabilities
2023-11-20 16:10:00 -06:00

90 lines
2.3 KiB
Go

package main
import (
"fmt"
"github.com/jmoiron/sqlx"
"github.com/stretchr/testify/require"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
)
type mockClient struct {
response *http.Response
}
func (m *mockClient) Do(*http.Request) (*http.Response, error) {
return m.response, nil
}
func TestCPEDB(t *testing.T) {
// Find the paths of all input files in the testdata directory.
paths, err := filepath.Glob(filepath.Join("testdata", "*.json"))
if err != nil {
t.Fatal(err)
}
for _, p := range paths {
path := p
_, filename := filepath.Split(path)
testName := filename[:len(filename)-len(filepath.Ext(path))]
// Each path turns into a test: the test name is the filename without the extension.
t.Run(
testName, func(t *testing.T) {
t.Parallel()
json, err := os.ReadFile(path)
require.NoError(t, err)
// Set up HTTP response
recorder := httptest.NewRecorder()
recorder.Header().Add("Content-Type", "application/json")
_, _ = recorder.WriteString(string(json))
expectedResponse := recorder.Result()
// Create an HTTP client
client := mockClient{response: expectedResponse}
// Temporary directory, which will be automatically cleaned up
dir := t.TempDir()
// Call the function under test
dbPath := getCPEs(&client, "API_KEY", dir)
// Open up the created DB and get the rows
db, err := sqlx.Open("sqlite3", dbPath)
require.NoError(t, err)
defer db.Close()
rows, err := db.Query("SELECT * FROM cpe_2")
require.NoError(t, err)
require.NoError(t, rows.Err())
defer rows.Close()
// Convert rows to string for comparison
var result [][]string
cols, _ := rows.Columns()
for rows.Next() {
// Setting up for converting row to a string
pointers := make([]interface{}, len(cols))
container := make([]string, len(cols))
for i := range pointers {
pointers[i] = &container[i]
}
require.NoError(t, rows.Scan(pointers...))
result = append(result, container)
}
// Compare result to the <testName>.golden file
goldenFile := filepath.Join("testdata", testName+".golden")
golden, err := os.ReadFile(goldenFile)
require.NoError(t, err)
require.Equal(t, string(golden), fmt.Sprintf("%s", result))
},
)
}
}