Completes tasks 10-15 and fixes what was outstanding: - vulndb.Pull implemented with oras-go, streaming the ~50MB layer and staging both files before replacing either, so a failed pull leaves the previous database intact rather than a half-written one. - db.go: Vulnerability.Severity is a string, not trivy Severity, so the int conversion did not compile. Severity now resolves vendor (highest when vendors disagree) then NVD then unknown, and CVSS is read too. - findings.go: added sweepFixedFindings plus the fleet query, severity counts, rescan flag and accept/unaccept the API needs. - vulnrules.go: added rule CRUD and the digest builder. ResolveTargets returns []models.Server, not []string, so filterByServers was wrong. - api/vulnerabilities.go was an empty file while handlers.go registered twelve routes against it; written, grouped by CVE. - shared/mail: added the missing sender. The templates were orphaned and the HTML one was a copy of the text one, defining "subject" (which html/template would escape) and emitting no markup. render.go parses every template in init(), so a bad one panics server, admin and sitesvc at boot — go build never runs init(), which is why nothing complained. - notify: digests dispatch through their own path so SMTP gets the digest template rather than arriving dressed as a monitor alert.
52 lines
2.1 KiB
Go
52 lines
2.1 KiB
Go
package models
|
|
|
|
import (
|
|
"time"
|
|
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
)
|
|
|
|
// AlertSettings no longer carries a webhook URL or SMTP configuration of its
|
|
// own. Agent-offline alerts are delivered through notification channels, the
|
|
// same destinations monitors use, so there is one place to configure a
|
|
// destination and one place to test it.
|
|
type AlertSettings struct {
|
|
OfflineThresholdMinutes int `bson:"offline_threshold_minutes" json:"offline_threshold_minutes"`
|
|
OfflineChannelIDs []string `bson:"offline_channel_ids" json:"offline_channel_ids"`
|
|
}
|
|
|
|
type SecretsSettings struct {
|
|
ReadTokenHash string `bson:"read_token_hash,omitempty" json:"-"`
|
|
ReadTokenSet bool `bson:"-" json:"read_token_set"`
|
|
RotatedAt time.Time `bson:"rotated_at,omitempty" json:"rotated_at,omitempty"`
|
|
}
|
|
|
|
type Settings struct {
|
|
ID bson.ObjectID `bson:"_id,omitempty" json:"-"`
|
|
InstanceID string `bson:"instance_id" json:"instance_id"`
|
|
Alerts AlertSettings `bson:"alerts" json:"alerts"`
|
|
Secrets SecretsSettings `bson:"secrets" json:"secrets"`
|
|
|
|
WorkflowLogRetentionDays *int `bson:"workflow_log_retention_days,omitempty" json:"workflow_log_retention_days,omitempty"`
|
|
|
|
// LocalLoginEnabled is a pointer because it is absent on every settings
|
|
// document written before this feature existed, and a plain bool would read
|
|
// absent as disabled — turning off password login for the entire fleet at
|
|
// upgrade. Nil means enabled.
|
|
LocalLoginEnabled *bool `bson:"local_login_enabled,omitempty" json:"local_login_enabled,omitempty"`
|
|
|
|
// VulnFindingRetentionDays is a pointer for the same reason
|
|
// WorkflowLogRetentionDays is: absent must mean the default, not zero.
|
|
// Nil is 90 days, 0 is forever. Only "fixed" findings are ever swept.
|
|
VulnFindingRetentionDays *int `bson:"vuln_finding_retention_days,omitempty" json:"vuln_finding_retention_days,omitempty"`
|
|
}
|
|
|
|
// LocalLoginEnabled reads the setting with its absent-means-on default. Every
|
|
// caller must go through this rather than dereferencing the field.
|
|
func LocalLoginEnabled(s *Settings) bool {
|
|
if s == nil || s.LocalLoginEnabled == nil {
|
|
return true
|
|
}
|
|
return *s.LocalLoginEnabled
|
|
}
|