Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions central/metrics/custom/node_vulnerabilities/labels.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package node_vulnerabilities

import (
"strconv"

"github.com/stackrox/rox/central/metrics/custom/tracker"
"github.com/stackrox/rox/generated/storage"
)

var lazyLabels = []tracker.LazyLabel[*finding]{
{Label: "Cluster", Getter: func(f *finding) string { return f.node.GetClusterName() }},
{Label: "Node", Getter: func(f *finding) string { return f.node.GetName() }},
{Label: "Kernel", Getter: func(f *finding) string { return f.node.GetKernelVersion() }},
{Label: "OperatingSystem", Getter: func(f *finding) string { return f.node.GetScan().GetOperatingSystem() }},
{Label: "OSImage", Getter: func(f *finding) string { return f.node.GetOsImage() }},
{Label: "Component", Getter: func(f *finding) string { return f.component.GetName() }},
{Label: "ComponentVersion", Getter: func(f *finding) string { return f.component.GetVersion() }},

{Label: "CVE", Getter: func(f *finding) string { return f.vulnerability.GetCveBaseInfo().GetCve() }},
{Label: "CVSS", Getter: func(f *finding) string { return strconv.FormatFloat(float64(f.vulnerability.GetCvss()), 'f', 1, 32) }},
{Label: "Severity", Getter: func(f *finding) string { return f.vulnerability.GetSeverity().String() }},
{Label: "IsFixable", Getter: func(f *finding) string { return strconv.FormatBool(f.vulnerability.GetFixedBy() != "") }},
{Label: "IsSnoozed", Getter: func(f *finding) string { return strconv.FormatBool(f.vulnerability.GetSnoozed()) }},
{Label: "EPSSPercentile", Getter: func(f *finding) string {
return strconv.FormatFloat(float64(f.vulnerability.GetCveBaseInfo().GetEpss().GetEpssPercentile()), 'f', 1, 32)
}},
{Label: "EPSSProbability", Getter: func(f *finding) string {
return strconv.FormatFloat(float64(f.vulnerability.GetCveBaseInfo().GetEpss().GetEpssProbability()), 'f', 1, 32)
}},
}

type finding struct {
tracker.CommonFinding
err error
node *storage.Node
component *storage.EmbeddedNodeScanComponent
vulnerability *storage.NodeVulnerability
}

func (f *finding) GetError() error { return f.err }
50 changes: 50 additions & 0 deletions central/metrics/custom/node_vulnerabilities/tracker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package node_vulnerabilities

import (
"context"
"iter"

"github.com/pkg/errors"
"github.com/stackrox/rox/central/metrics/custom/tracker"
nodeDS "github.com/stackrox/rox/central/node/datastore"
"github.com/stackrox/rox/generated/storage"
"github.com/stackrox/rox/pkg/search"
)

func New(nodes nodeDS.DataStore) *tracker.TrackerBase[*finding] {
return tracker.MakeTrackerBase(
"node_vuln",
"node CVEs",
lazyLabels,
func(ctx context.Context, _ tracker.MetricDescriptors) iter.Seq[*finding] {
return track(ctx, nodes)
})
}

func track(ctx context.Context, ds nodeDS.DataStore) iter.Seq[*finding] {
return func(yield func(*finding) bool) {
var f finding
f.err = ds.WalkByQuery(ctx, search.EmptyQuery(), func(node *storage.Node) error {
f.node = node
if !forEachNode(yield, &f) {
return tracker.ErrStopIterator
}
return nil
})
// Report walking error.
if f.err != nil && !errors.Is(f.err, tracker.ErrStopIterator) {
yield(&f)
}
}
}

func forEachNode(yield func(*finding) bool, f *finding) bool {
for _, f.component = range f.node.GetScan().GetComponents() {
for _, f.vulnerability = range f.component.GetVulnerabilities() {
if !yield(f) {
return false
}
}
}
return true
}
11 changes: 8 additions & 3 deletions central/metrics/custom/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import (
"github.com/stackrox/rox/central/metrics/custom/clusters"
"github.com/stackrox/rox/central/metrics/custom/expiry"
"github.com/stackrox/rox/central/metrics/custom/image_vulnerabilities"
"github.com/stackrox/rox/central/metrics/custom/node_vulnerabilities"
"github.com/stackrox/rox/central/metrics/custom/policies"
"github.com/stackrox/rox/central/metrics/custom/policy_violations"
"github.com/stackrox/rox/central/metrics/custom/tracker"
custom "github.com/stackrox/rox/central/metrics/custom/tracker"
nodeDS "github.com/stackrox/rox/central/node/datastore"
policyDS "github.com/stackrox/rox/central/policy/datastore"
"github.com/stackrox/rox/central/telemetry/centralclient"
"github.com/stackrox/rox/generated/storage"
Expand All @@ -28,7 +29,7 @@ import (
)

type trackerRunner []struct {
custom.Tracker
tracker.Tracker
// getGroupConfig returns the storage configuration associated to the
// tracker.
getGroupConfig func(*storage.PrometheusMetrics) *storage.PrometheusMetrics_Group
Expand All @@ -38,11 +39,12 @@ type trackerRunner []struct {
// Returned by ValidateConfiguration() and accepted by Reconfigure(). This split
// allows the config service to dry-validate the configuration before applying
// any changes.
type RunnerConfiguration []*custom.Configuration
type RunnerConfiguration []*tracker.Configuration

type runnerDatastores struct {
deployments deploymentDS.DataStore
alerts alertDS.DataStore
nodes nodeDS.DataStore
clusters clusterDS.DataStore
policies policyDS.DataStore
expiry expiryS.Service
Expand Down Expand Up @@ -72,6 +74,9 @@ func makeRunner(ds *runnerDatastores) trackerRunner {
}, {
policy_violations.New(ds.alerts),
(*storage.PrometheusMetrics).GetPolicyViolations,
}, {
node_vulnerabilities.New(ds.nodes),
(*storage.PrometheusMetrics).GetNodeVulnerabilities,
}, {
clusters.New(ds.clusters),
withHardcodedConfiguration(60, map[string][]string{
Expand Down
2 changes: 2 additions & 0 deletions central/metrics/custom/singleton.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
configDS "github.com/stackrox/rox/central/config/datastore"
expiryS "github.com/stackrox/rox/central/credentialexpiry/service"
deploymentDS "github.com/stackrox/rox/central/deployment/datastore"
nodeDS "github.com/stackrox/rox/central/node/datastore"
policyDS "github.com/stackrox/rox/central/policy/datastore"
"github.com/stackrox/rox/generated/storage"
"github.com/stackrox/rox/pkg/logging"
Expand All @@ -34,6 +35,7 @@ func Singleton() Runner {
runner = makeRunner(&runnerDatastores{
deploymentDS.Singleton(),
alertDS.Singleton(),
nodeDS.Singleton(),
clusterDS.Singleton(),
policyDS.Singleton(),
expiryS.Singleton(),
Expand Down
5 changes: 4 additions & 1 deletion generated/api/v1/config_service.swagger.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 34 additions & 24 deletions generated/storage/config.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

90 changes: 90 additions & 0 deletions generated/storage/config_vtproto.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading