mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** For #43769 # Details Adds methods to collect data for the `cve` dataset. As with all sets this is collected at hourly granularity, but unlike the `uptime` set, the `cve` set uses the "snapshot" strategy so that we record at most one change (the most recent) per hour. For this first iteration, we are _recording_ data for all CVEs (i.e., which hosts were exposed to which CVEs at a given time), but we are only _reporting_ a subset of CVEs for the dashboard chart. See [this comment](https://github.com/fleetdm/fleet/pull/44124#discussion_r3155554405) for more info. # Checklist for submitter If some of the following don't apply, delete the relevant line. - [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/guides/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), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. ## Testing - [X] Added/updated automated tests - [X] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [X] QA'd all new/changed functionality manually - [X] Spot-checked the CVEs chosen by the `trackedCVESoftwareMatchers` and didn't find any outside of the expected - [X] With [front-end PR](https://github.com/fleetdm/fleet/pull/44261), generated chart: <img width="706" height="421" alt="image" src="https://github.com/user-attachments/assets/539d9877-6573-4406-a159-1d2a711a045f" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Host vulnerability (CVE) chart added to the dashboard; CVE chart data collection is now active. * Critical CVE tracking surfaces high-severity vulnerabilities. * **Improvements** * CVE chart refreshes every 3 hours (was daily) for more timely insights. * Snapshot collection reconciles and closes prior data during empty runs to keep charts accurate. * CVE queries may produce zero datapoints when no tracked CVEs exist, without affecting other metrics. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
56 lines
2.1 KiB
Go
56 lines
2.1 KiB
Go
package chart
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/chart/api"
|
|
)
|
|
|
|
// uptimeRecentlySeenWindow must match the cron schedule cadence so each sample
|
|
// reflects activity since the last run.
|
|
const uptimeRecentlySeenWindow = 10 * time.Minute
|
|
|
|
// UptimeDataset implements api.Dataset for host uptime tracking.
|
|
type UptimeDataset struct{}
|
|
|
|
func (u *UptimeDataset) Name() string { return "uptime" }
|
|
func (u *UptimeDataset) DefaultResolutionHours() int { return 3 }
|
|
func (u *UptimeDataset) SampleStrategy() api.SampleStrategy { return api.SampleStrategyAccumulate }
|
|
func (u *UptimeDataset) DefaultVisualization() string { return "checkerboard" }
|
|
|
|
func (u *UptimeDataset) Collect(ctx context.Context, store api.DatasetStore, now time.Time) error {
|
|
hostIDs, err := store.FindRecentlySeenHostIDs(ctx, now.Add(-uptimeRecentlySeenWindow))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(hostIDs) == 0 {
|
|
return nil
|
|
}
|
|
bucketStart := now.UTC().Truncate(time.Hour)
|
|
return store.RecordBucketData(ctx, u.Name(), bucketStart, time.Hour, u.SampleStrategy(),
|
|
// The empty string key means "all entities" since uptime isn't tracked per host.
|
|
// The value is a bitmap of host IDs that were active in this bucket.
|
|
map[string][]byte{"": HostIDsToBlob(hostIDs)})
|
|
}
|
|
|
|
// CVEDataset implements api.Dataset for host CVE tracking.
|
|
type CVEDataset struct{}
|
|
|
|
func (c *CVEDataset) Name() string { return "cve" }
|
|
func (c *CVEDataset) DefaultResolutionHours() int { return 3 }
|
|
func (c *CVEDataset) SampleStrategy() api.SampleStrategy { return api.SampleStrategySnapshot }
|
|
func (c *CVEDataset) DefaultVisualization() string { return "line" }
|
|
|
|
func (c *CVEDataset) Collect(ctx context.Context, store api.DatasetStore, now time.Time) error {
|
|
hostIDsByCVE, err := store.AffectedHostIDsByCVE(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
bitmaps := make(map[string][]byte, len(hostIDsByCVE))
|
|
for cve, hostIDs := range hostIDsByCVE {
|
|
bitmaps[cve] = HostIDsToBlob(hostIDs)
|
|
}
|
|
bucketStart := now.UTC().Truncate(time.Hour)
|
|
return store.RecordBucketData(ctx, c.Name(), bucketStart, time.Hour, c.SampleStrategy(), bitmaps)
|
|
}
|