Skip to content

Commit

Permalink
add workload deny list for dumps (#18967)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gui774ume authored Sep 29, 2023
1 parent 6ed5c9c commit 68900e5
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 11 deletions.
1 change: 1 addition & 0 deletions pkg/config/system_probe_cws.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func initCWSSystemProbeConfig(cfg Config) {
cfg.BindEnvAndSetDefault("runtime_security_config.activity_dump.silent_workloads.delay", "10s")
cfg.BindEnvAndSetDefault("runtime_security_config.activity_dump.silent_workloads.ticker", "10s")
cfg.BindEnvAndSetDefault("runtime_security_config.activity_dump.auto_suppression.enabled", false)
cfg.BindEnvAndSetDefault("runtime_security_config.activity_dump.workload_deny_list", []string{})

// CWS - SBOM
cfg.BindEnvAndSetDefault("runtime_security_config.sbom.enabled", false)
Expand Down
8 changes: 6 additions & 2 deletions pkg/security/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ type RuntimeSecurityConfig struct {
ActivityDumpSyscallMonitorPeriod time.Duration
// ActivityDumpMaxDumpCountPerWorkload defines the maximum amount of dumps that the agent should send for a workload
ActivityDumpMaxDumpCountPerWorkload int
// ActivityDumpWorkloadDenyList defines the list of workloads for which we shouldn't generate dumps. Workloads should
// be provided as strings in the following format "{image_name}:[{image_tag}|*]". If "*" is provided instead of a
// specific image tag, then the entry will match any workload with the input {image_name} regardless of their tag.
ActivityDumpWorkloadDenyList []string
// ActivityDumpTagRulesEnabled enable the tagging of nodes with matched rules (only for rules having the tag ruleset:threat_score)
ActivityDumpTagRulesEnabled bool
// ActivityDumpSilentWorkloadsDelay defines the minimum amount of time to wait before the activity dump manager will start tracing silent workloads
Expand Down Expand Up @@ -273,8 +277,8 @@ func NewRuntimeSecurityConfig() (*RuntimeSecurityConfig, error) {
ActivityDumpTagRulesEnabled: coreconfig.SystemProbe.GetBool("runtime_security_config.activity_dump.tag_rules.enabled"),
ActivityDumpSilentWorkloadsDelay: coreconfig.SystemProbe.GetDuration("runtime_security_config.activity_dump.silent_workloads.delay"),
ActivityDumpSilentWorkloadsTicker: coreconfig.SystemProbe.GetDuration("runtime_security_config.activity_dump.silent_workloads.ticker"),

ActivityDumpAutoSuppressionEnabled: coreconfig.SystemProbe.GetBool("runtime_security_config.security_profile.anomaly_detection.auto_suppression.enabled"),
ActivityDumpWorkloadDenyList: coreconfig.SystemProbe.GetStringSlice("runtime_security_config.activity_dump.workload_deny_list"),
ActivityDumpAutoSuppressionEnabled: coreconfig.SystemProbe.GetBool("runtime_security_config.security_profile.anomaly_detection.auto_suppression.enabled"),
// activity dump dynamic fields
ActivityDumpMaxDumpSize: func() int {
mds := coreconfig.SystemProbe.GetInt("runtime_security_config.activity_dump.max_dump_size")
Expand Down
3 changes: 3 additions & 0 deletions pkg/security/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,9 @@ var (
// MetricActivityDumpNotYetProfiledWorkload is the name of the metric used to report the count of workload not yet profiled
// Tags: -
MetricActivityDumpNotYetProfiledWorkload = newAgentMetric(".activity_dump.not_yet_profiled_workload")
// MetricActivityDumpWorkloadDenyListHits is the name of the metric used to report the count of dumps that were dismissed because their workload is in the deny list
// Tags: -
MetricActivityDumpWorkloadDenyListHits = newRuntimeMetric(".activity_dump.workload_deny_list_hits")
// MetricActivityDumpLocalStorageCount is the name of the metric used to count the number of dumps stored locally
// Tags: -
MetricActivityDumpLocalStorageCount = newAgentMetric(".activity_dump.local_storage.count")
Expand Down
3 changes: 3 additions & 0 deletions pkg/security/resolvers/cgroup/model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ func (ws *WorkloadSelector) IsReady() bool {

// Match returns true if the input selector matches the current selector
func (ws *WorkloadSelector) Match(selector WorkloadSelector) bool {
if ws.Tag == "*" || selector.Tag == "*" {
return ws.Image == selector.Image
}
return ws.Image == selector.Image && ws.Tag == selector.Tag
}

Expand Down
56 changes: 47 additions & 9 deletions pkg/security/security_profile/dump/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ type ActivityDumpManager struct {
activityDumpsConfigMap *ebpf.Map
ignoreFromSnapshot map[string]bool

dumpLimiter *lru.Cache[cgroupModel.WorkloadSelector, *atomic.Uint64]
dumpLimiter *lru.Cache[cgroupModel.WorkloadSelector, *atomic.Uint64]
workloadDenyList []cgroupModel.WorkloadSelector
workloadDenyListHits *atomic.Uint64

activeDumps []*ActivityDump
snapshotQueue chan *ActivityDump
Expand Down Expand Up @@ -194,29 +196,44 @@ func (adm *ActivityDumpManager) resolveTags() {
seclog.Warnf("couldn't resolve activity dump tags (will try again later): %v", err)
}

if !ad.countedByLimiter {
// check if we should discard this dump based on the manager dump limiter
selector := ad.GetWorkloadSelector()
if selector == nil {
// wait for the tags
continue
// check if we should discard this dump based on the manager dump limiter or the deny list
selector := ad.GetWorkloadSelector()
if selector == nil {
// wait for the tags
continue
}

shouldFinalize := false

// check if the workload is in the deny list
for _, entry := range adm.workloadDenyList {
if entry.Match(*selector) {
shouldFinalize = true
adm.workloadDenyListHits.Inc()
break
}
}

if !shouldFinalize && !ad.countedByLimiter {
counter, ok := adm.dumpLimiter.Get(*selector)
if !ok {
counter = atomic.NewUint64(0)
adm.dumpLimiter.Add(*selector, counter)
}

if counter.Load() >= uint64(ad.adm.config.RuntimeSecurity.ActivityDumpMaxDumpCountPerWorkload) {
ad.Finalize(true)
adm.RemoveDump(ad)
shouldFinalize = true
adm.dropMaxDumpReached.Inc()
} else {
ad.countedByLimiter = true
counter.Add(1)
}
}

if shouldFinalize {
ad.Finalize(true)
adm.RemoveDump(ad)
}
}
}

Expand Down Expand Up @@ -266,6 +283,19 @@ func NewActivityDumpManager(config *config.Config, statsdClient statsd.ClientInt
return nil, fmt.Errorf("couldn't create dump limiter: %w", err)
}

var denyList []cgroupModel.WorkloadSelector
for _, entry := range config.RuntimeSecurity.ActivityDumpWorkloadDenyList {
split := strings.Split(entry, ":")
if len(split) != 2 {
return nil, fmt.Errorf("invalid activity_dump.workload_deny_list parameter: expecting following format \"{image_name}:[{image_tag}|*]\"")
}
selectorTmp, err := cgroupModel.NewWorkloadSelector(split[0], split[1])
if err != nil {
return nil, fmt.Errorf("invalid workload selector in activity_dump.workload_deny_list: %w", err)
}
denyList = append(denyList, selectorTmp)
}

adm := &ActivityDumpManager{
config: config,
statsdClient: statsdClient,
Expand All @@ -283,6 +313,8 @@ func NewActivityDumpManager(config *config.Config, statsdClient statsd.ClientInt
snapshotQueue: make(chan *ActivityDump, 100),
ignoreFromSnapshot: make(map[string]bool),
dumpLimiter: limiter,
workloadDenyList: denyList,
workloadDenyListHits: atomic.NewUint64(0),
pathsReducer: activity_tree.NewPathsReducer(),
}

Expand Down Expand Up @@ -701,6 +733,12 @@ func (adm *ActivityDumpManager) SendStats() error {
}
}

if value := adm.workloadDenyListHits.Swap(0); value > 0 {
if err := adm.statsdClient.Count(metrics.MetricActivityDumpWorkloadDenyListHits, int64(value), nil, 1.0); err != nil {
return fmt.Errorf("couldn't send %s metric: %w", metrics.MetricActivityDumpWorkloadDenyListHits, err)
}
}

return nil
}

Expand Down

0 comments on commit 68900e5

Please sign in to comment.