Skip to content

Commit

Permalink
Merge pull request #1898 from Prateeknandle/throttle-fix-1
Browse files Browse the repository at this point in the history
fix(throttling): differentiate throttling handling for audit behaviour based on enforcer
  • Loading branch information
daemon1024 authored Dec 2, 2024
2 parents bf5d5df + 46ba761 commit 1ead4f1
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 45 deletions.
6 changes: 6 additions & 0 deletions KubeArmor/BPF/system_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,12 @@ static __always_inline u32 init_context(sys_context_t *context)
// To check if subsequent alerts should be dropped per container
static __always_inline bool should_drop_alerts_per_container(sys_context_t *context, struct pt_regs *ctx, u32 types, args_t *args) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 2, 0)

// throttling for host in case of apparmor is handled in userspace
if (context->pid_id == 0 && context->mnt_id == 0) {
return false;
}

u64 current_timestamp = bpf_ktime_get_ns();

struct outer_key key = {
Expand Down
12 changes: 6 additions & 6 deletions KubeArmor/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ type KubearmorConfig struct {

StateAgent bool // enable KubeArmor state agent

AlertThrottling bool // Enable/Disable Alert Throttling
MaxAlertPerSec int // Maximum alerts allowed per second
ThrottleSec int // Number of seconds for which subsequent alerts will be dropped
AnnotateResources bool // enable annotations by kubearmor if kubearmor-controller is not present
AlertThrottling bool // Enable/Disable Alert Throttling
MaxAlertPerSec int32 // Maximum alerts allowed per second
ThrottleSec int32 // Number of seconds for which subsequent alerts will be dropped
AnnotateResources bool // enable annotations by kubearmor if kubearmor-controller is not present

ProcFsMount string // path where procfs is hosted
}
Expand Down Expand Up @@ -325,8 +325,8 @@ func LoadConfig() error {
GlobalCfg.StateAgent = viper.GetBool(ConfigStateAgent)

GlobalCfg.AlertThrottling = viper.GetBool(ConfigAlertThrottling)
GlobalCfg.MaxAlertPerSec = viper.GetInt(ConfigMaxAlertPerSec)
GlobalCfg.ThrottleSec = viper.GetInt(ConfigThrottleSec)
GlobalCfg.MaxAlertPerSec = int32(viper.GetInt(ConfigMaxAlertPerSec))
GlobalCfg.ThrottleSec = int32(viper.GetInt(ConfigThrottleSec))
GlobalCfg.AnnotateResources = viper.GetBool(ConfigAnnotateResources)

GlobalCfg.ProcFsMount = viper.GetString(ConfigProcFsMount)
Expand Down
16 changes: 11 additions & 5 deletions KubeArmor/core/kubeUpdate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2740,16 +2740,18 @@ func (dm *KubeArmorDaemon) WatchConfigMap() cache.InformerSynced {
cfg.GlobalCfg.AlertThrottling = (cm.Data[cfg.ConfigAlertThrottling] == "true")
}
if _, ok := cm.Data[cfg.ConfigMaxAlertPerSec]; ok {
cfg.GlobalCfg.MaxAlertPerSec, err = strconv.Atoi(cm.Data[cfg.ConfigMaxAlertPerSec])
maxAlertPerSec, err := strconv.ParseInt(cm.Data[cfg.ConfigMaxAlertPerSec], 10, 32)
if err != nil {
dm.Logger.Warnf("Error: %s", err)
}
cfg.GlobalCfg.MaxAlertPerSec = int32(maxAlertPerSec)
}
if _, ok := cm.Data[cfg.ConfigMaxAlertPerSec]; ok {
cfg.GlobalCfg.ThrottleSec, err = strconv.Atoi(cm.Data[cfg.ConfigThrottleSec])
if _, ok := cm.Data[cfg.ConfigThrottleSec]; ok {
throttleSec, err := strconv.ParseInt(cm.Data[cfg.ConfigThrottleSec], 10, 32)
if err != nil {
dm.Logger.Warnf("Error: %s", err)
}
cfg.GlobalCfg.ThrottleSec = int32(throttleSec)
}
dm.SystemMonitor.UpdateThrottlingConfig()

Expand Down Expand Up @@ -2790,14 +2792,18 @@ func (dm *KubeArmorDaemon) WatchConfigMap() cache.InformerSynced {
if _, ok := cm.Data[cfg.ConfigAlertThrottling]; ok {
cfg.GlobalCfg.AlertThrottling = (cm.Data[cfg.ConfigAlertThrottling] == "true")
}
cfg.GlobalCfg.MaxAlertPerSec, err = strconv.Atoi(cm.Data[cfg.ConfigMaxAlertPerSec])

maxAlertPerSec, err := strconv.ParseInt(cm.Data[cfg.ConfigMaxAlertPerSec], 10, 32)
if err != nil {
dm.Logger.Warnf("Error: %s", err)
}
cfg.GlobalCfg.ThrottleSec, err = strconv.Atoi(cm.Data[cfg.ConfigThrottleSec])
cfg.GlobalCfg.MaxAlertPerSec = int32(maxAlertPerSec)

throttleSec, err := strconv.ParseInt(cm.Data[cfg.ConfigThrottleSec], 10, 32)
if err != nil {
dm.Logger.Warnf("Error: %s", err)
}
cfg.GlobalCfg.ThrottleSec = int32(throttleSec)
dm.SystemMonitor.UpdateThrottlingConfig()
}
},
Expand Down
4 changes: 2 additions & 2 deletions KubeArmor/enforcer/bpflsm/enforcer.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,8 +375,8 @@ func (be *BPFEnforcer) TraceEvents() {
case mon.DropAlert:
log.Operation = "AlertThreshold"
log.Type = "SystemEvent"
log.MaxAlertsPerSec = int32(cfg.GlobalCfg.MaxAlertPerSec)
log.DroppingAlertsInterval = int32(cfg.GlobalCfg.ThrottleSec)
log.MaxAlertsPerSec = cfg.GlobalCfg.MaxAlertPerSec
log.DroppingAlertsInterval = cfg.GlobalCfg.ThrottleSec
}
// fallback logic if we don't receive source from BuildLogBase()
if log.Operation != "Process" && len(log.Source) == 0 {
Expand Down
14 changes: 14 additions & 0 deletions KubeArmor/feeder/feeder.go
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,20 @@ func (fd *Feeder) PushLog(log tp.Log) {

// gRPC output
if log.Type == "MatchedPolicy" || log.Type == "MatchedHostPolicy" || log.Type == "SystemEvent" {

// checking throttling condition for "Audit" alerts when enforcer is 'eBPF Monitor'
if cfg.GlobalCfg.AlertThrottling && ((strings.Contains(log.Action, "Audit") && log.Enforcer == "eBPF Monitor") || (log.Type == "MatchedHostPolicy" && (log.Enforcer == "AppArmor" || log.Enforcer == "eBPF Monitor"))) {
nsKey := fd.ContainerNsKey[log.ContainerID]
alert, throttle := fd.ShouldDropAlertsPerContainer(nsKey.PidNs, nsKey.MntNs)
if alert && throttle {
return
} else if alert && !throttle {
log.Operation = "AlertThreshold"
log.Type = "SystemEvent"
log.MaxAlertsPerSec = cfg.GlobalCfg.MaxAlertPerSec
log.DroppingAlertsInterval = cfg.GlobalCfg.ThrottleSec
}
}
pbAlert := pb.Alert{}

pbAlert.Timestamp = log.Timestamp
Expand Down
32 changes: 2 additions & 30 deletions KubeArmor/feeder/policyMatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -1299,7 +1299,7 @@ func (fd *Feeder) UpdateMatchedPolicy(log tp.Log) tp.Log {
break // break, so that once source is matched for a log it doesn't look for other cases
}
// match sources
if (!secPolicy.IsFromSource) || (secPolicy.IsFromSource && (secPolicy.Source == log.ParentProcessName || secPolicy.Source == log.ProcessName)) {
if (!secPolicy.IsFromSource) || (secPolicy.IsFromSource && (strings.HasPrefix(log.Source, secPolicy.Source+" ") || secPolicy.Source == log.ProcessName)) {
matchedFlags := false

protocol := fetchProtocol(log.Resource)
Expand Down Expand Up @@ -1481,7 +1481,7 @@ func (fd *Feeder) UpdateMatchedPolicy(log tp.Log) tp.Log {
continue
}
// match sources
if (!secPolicy.IsFromSource) || (secPolicy.IsFromSource && (secPolicy.Source == log.ParentProcessName || secPolicy.Source == log.ProcessName)) {
if (!secPolicy.IsFromSource) || (secPolicy.IsFromSource && (strings.HasPrefix(log.Source, secPolicy.Source+" ") || secPolicy.Source == log.ProcessName)) {
skip := false

for _, matchCapability := range strings.Split(secPolicy.Resource, ",") {
Expand Down Expand Up @@ -1741,20 +1741,6 @@ func (fd *Feeder) UpdateMatchedPolicy(log tp.Log) tp.Log {
return tp.Log{}
}

// check for throttling for "Audit" alerts
if cfg.GlobalCfg.AlertThrottling && strings.Contains(log.Action, "Audit") {
nsKey := fd.ContainerNsKey[log.ContainerID]
alert, throttle := fd.ShouldDropAlertsPerContainer(nsKey.PidNs, nsKey.MntNs)
if alert && throttle {
return tp.Log{}
} else if alert && !throttle {
log.Operation = "AlertThreshold"
log.Type = "SystemEvent"
log.MaxAlertsPerSec = int32(cfg.GlobalCfg.MaxAlertPerSec)
log.DroppingAlertsInterval = int32(cfg.GlobalCfg.ThrottleSec)
}
}

return log
}
} else { // host
Expand Down Expand Up @@ -1784,20 +1770,6 @@ func (fd *Feeder) UpdateMatchedPolicy(log tp.Log) tp.Log {
return tp.Log{}
}

// check for throttling for "Audit" alerts
if cfg.GlobalCfg.AlertThrottling && strings.Contains(log.Action, "Audit") {
nsKey := fd.ContainerNsKey[log.ContainerID]
alert, throttle := fd.ShouldDropAlertsPerContainer(nsKey.PidNs, nsKey.MntNs)
if alert && throttle {
return tp.Log{}
} else if alert && !throttle {
log.Operation = "AlertThreshold"
log.Type = "SystemEvent"
log.MaxAlertsPerSec = int32(cfg.GlobalCfg.MaxAlertPerSec)
log.DroppingAlertsInterval = int32(cfg.GlobalCfg.ThrottleSec)
}
}

return log
}
}
Expand Down
4 changes: 2 additions & 2 deletions KubeArmor/monitor/logUpdate.go
Original file line number Diff line number Diff line change
Expand Up @@ -517,8 +517,8 @@ func (mon *SystemMonitor) UpdateLogs() {
case DropAlert: // throttling alert
log.Operation = "AlertThreshold"
log.Type = "SystemEvent"
log.MaxAlertsPerSec = int32(cfg.GlobalCfg.MaxAlertPerSec)
log.DroppingAlertsInterval = int32(cfg.GlobalCfg.ThrottleSec)
log.MaxAlertsPerSec = cfg.GlobalCfg.MaxAlertPerSec
log.DroppingAlertsInterval = cfg.GlobalCfg.ThrottleSec

default:
continue
Expand Down

0 comments on commit 1ead4f1

Please sign in to comment.