fleet/server/vulnerabilities/goval_dictionary/sync.go
Ian Littman e96c70e4c0
Pull xz'd goval-dictionary sqlite files to evaluate vulnerabilities on Amazon Linux hosts (#21506)
#20934

This is tied to https://github.com/fleetdm/vulnerabilities/pull/14; for
supported OS versions (currently Amazon Linux 1/2/2022/2023) we'll pull
XZ'd sqlite files from the vulnerabilities repo and query them to
determine what's vulnerable. See the associated issue for how I
self-QA'd this.

This replaced OVAL parsing for Amazon Linux 2, as we were using the
wrong data source there (Amazon has backported a bunch of fixes to their
own-named releases, so any RHEL fixes don't match).

Some checklist items are missing here; getting this set up in draft to
get code feedback now, and I'll push updates with e.g. docs changes, as
well ass an addition to the changes file.

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

<!-- Note that API documentation changes are now addressed by the
product design team. -->

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/Committing-Changes.md#changes-files)
for more information.
- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)
- [x] Added/updated tests
    - [x] Add tests to oval_platform
    - [x] Add sync_test
    - [x] Add database_test
- [x] Manual QA for all new/changed functionality
- [x] Update vulnerability management docs
2024-08-26 14:07:42 -05:00

89 lines
2.1 KiB
Go

package goval_dictionary
import (
"fmt"
"github.com/fleetdm/fleet/v4/pkg/download"
"github.com/fleetdm/fleet/v4/pkg/fleethttp"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/fleetdm/fleet/v4/server/vulnerabilities/nvd"
"github.com/fleetdm/fleet/v4/server/vulnerabilities/oval"
kitlog "github.com/go-kit/log"
"github.com/go-kit/log/level"
"net/http"
"net/url"
"path/filepath"
)
func Refresh(
versions *fleet.OSVersions,
vulnPath string,
logger kitlog.Logger,
) ([]oval.Platform, error) {
toDownload := whatToDownload(versions)
if len(toDownload) > 0 {
level.Debug(logger).Log("msg", "goval_dictionary-sync-downloading")
err := Sync(vulnPath, toDownload)
if err != nil {
return nil, err
}
}
return toDownload, nil
}
func Sync(dstDir string, platforms []oval.Platform) error {
client := fleethttp.NewClient()
dwn := downloadDecompressed(client)
basePath, err := nvd.GetGitHubCVEAssetPath()
if err != nil {
return err
}
for _, platform := range platforms {
if err := downloadDatabase(platform, dwn, basePath, dstDir); err != nil {
return err
}
}
return nil
}
func downloadDatabase(
platform oval.Platform,
downloader func(string, string) error,
basePath string,
vulnDir string,
) error {
dstPath := filepath.Join(vulnDir, platform.ToGovalDictionaryFilename())
if err := downloader(basePath+string(platform)+".sqlite3.xz", dstPath); err != nil {
return err
}
return nil
}
func downloadDecompressed(client *http.Client) func(string, string) error {
return func(u, dstPath string) error {
parsedUrl, err := url.Parse(u)
if err != nil {
return fmt.Errorf("url parse: %w", err)
}
if err = download.DownloadAndExtract(client, parsedUrl, dstPath); err != nil {
return fmt.Errorf("download and extract url %s: %w", parsedUrl, err)
}
return nil
}
}
func whatToDownload(osVers *fleet.OSVersions) []oval.Platform {
var r []oval.Platform
for _, os := range osVers.OSVersions {
platform := oval.NewPlatform(os.Platform, os.Name)
if platform.IsGovalDictionarySupported() {
r = append(r, platform)
}
}
return r
}