feat: models and indexes for package inventory and CVE findings

Adds server_packages, vuln_findings and vuln_alert_rules to
ScopedCollections rather than to a separate deletion list. purgeInstance
derives its collection list from that registry, so instance deletion
follows automatically and there is no second copy to drift.
This commit is contained in:
2026-08-06 11:59:00 +01:00
parent c277ecff44
commit 3a6d24fe0e
5 changed files with 230 additions and 0 deletions
@@ -40,6 +40,9 @@ var ScopedCollections = []string{
"console_sessions",
"audit_logs",
"auth_providers",
"server_packages",
"vuln_findings",
"vuln_alert_rules",
}
// collectionRenames maps the two collections whose names change. Ordered so the
+62
View File
@@ -0,0 +1,62 @@
package services
import (
"context"
"log"
"gitea.hostxtra.co.uk/mrhid6/vantage/server/internal/db"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)
// EnsureVulnIndexes declares the indexes for package inventory and findings.
//
// It warns rather than being fatal, matching EnsureSecretIndexes and
// EnsureWorkflowIndexes: a missing index degrades these queries to a collection
// scan, which is no reason to refuse to serve the fleet.
func EnsureVulnIndexes() error {
ctx := context.Background()
pkgIdx := []mongo.IndexModel{
{
Keys: bson.D{{Key: "instance_id", Value: 1}, {Key: "server_id", Value: 1}},
Options: options.Index().SetUnique(true),
},
// Multikey, for fleet-wide package search: "who runs openssl 3.0.2?"
{Keys: bson.D{{Key: "instance_id", Value: 1}, {Key: "packages.name", Value: 1}}},
// The scheduler's only query. Deliberately unscoped: it sweeps the whole
// deployment on the leader, not one tenant.
{Keys: bson.D{{Key: "scan_pending", Value: 1}}},
}
if _, err := db.Col("server_packages").Indexes().CreateMany(ctx, pkgIdx); err != nil {
log.Printf("warning: server_packages indexes: %v", err)
}
findingIdx := []mongo.IndexModel{
{
// This key is what makes a rescan an idempotent upsert rather than a
// duplicate factory, and what lets first_seen survive a rescan.
Keys: bson.D{
{Key: "instance_id", Value: 1},
{Key: "server_id", Value: 1},
{Key: "cve_id", Value: 1},
{Key: "package_name", Value: 1},
},
Options: options.Index().SetUnique(true),
},
{Keys: bson.D{{Key: "instance_id", Value: 1}, {Key: "state", Value: 1}, {Key: "severity", Value: 1}}},
{Keys: bson.D{{Key: "instance_id", Value: 1}, {Key: "cve_id", Value: 1}}},
}
if _, err := db.Col("vuln_findings").Indexes().CreateMany(ctx, findingIdx); err != nil {
log.Printf("warning: vuln_findings indexes: %v", err)
}
if _, err := db.Col("vuln_alert_rules").Indexes().CreateOne(ctx, mongo.IndexModel{
Keys: bson.D{{Key: "instance_id", Value: 1}},
}); err != nil {
log.Printf("warning: vuln_alert_rules indexes: %v", err)
}
return nil
}