diff --git a/KubeArmor/BPF/enforcer.bpf.c b/KubeArmor/BPF/enforcer.bpf.c index 9e5c94bb28..fca8b52e26 100644 --- a/KubeArmor/BPF/enforcer.bpf.c +++ b/KubeArmor/BPF/enforcer.bpf.c @@ -253,6 +253,9 @@ int BPF_PROG(enforce_proc, struct linux_binprm *bprm, int ret) { return ret; ringbuf: + if (get_kubearmor_config(_ALERT_THROTTLING) && should_drop_alerts_per_container(okey)) { + return retval; + } task_info = bpf_ringbuf_reserve(&kubearmor_events, sizeof(event), 0); if (!task_info) { @@ -394,10 +397,15 @@ static inline int match_net_rules(int type, int protocol, u32 eventID) { return 0; ringbuf: + if (get_kubearmor_config(_ALERT_THROTTLING) && should_drop_alerts_per_container(okey)) { + return retval; + } + task_info = bpf_ringbuf_reserve(&kubearmor_events, sizeof(event), 0); if (!task_info) { return retval; } + // Clearing arrays to avoid garbage values to be parsed __builtin_memset(task_info->data.path, 0, sizeof(task_info->data.path)); __builtin_memset(task_info->data.source, 0, sizeof(task_info->data.source)); @@ -557,10 +565,15 @@ int BPF_PROG(enforce_cap, const struct cred *cred, struct user_namespace *ns, return 0; ringbuf: + if (get_kubearmor_config(_ALERT_THROTTLING) && should_drop_alerts_per_container(okey)) { + return retval; + } + task_info = bpf_ringbuf_reserve(&kubearmor_events, sizeof(event), 0); if (!task_info) { return retval; } + // Clearing arrays to avoid garbage values to be parsed __builtin_memset(task_info->data.path, 0, sizeof(task_info->data.path)); __builtin_memset(task_info->data.source, 0, sizeof(task_info->data.source)); diff --git a/KubeArmor/BPF/shared.h b/KubeArmor/BPF/shared.h index 62be336587..5051d2ed4e 100644 --- a/KubeArmor/BPF/shared.h +++ b/KubeArmor/BPF/shared.h @@ -6,9 +6,11 @@ #include "vmlinux.h" #include "vmlinux_macro.h" +#include "syscalls.h" #include #include #include +#include "throttling.h" char LICENSE[] SEC("license") = "Dual BSD/GPL"; #define EPERM 13 @@ -72,11 +74,6 @@ struct { __uint(max_entries, 3); } bufk SEC(".maps"); -struct outer_key { - u32 pid_ns; - u32 mnt_ns; -}; - typedef struct { u64 ts; @@ -122,6 +119,24 @@ struct data_t { u8 filemask; }; +enum +{ + _ALERT_THROTTLING = 3, + _MAX_ALERT_PER_SEC = 4, + _THROTTLE_SEC = 5, +}; + +struct kaconfig +{ + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, u32); + __type(value, u32); + __uint(max_entries, 16); + __uint(pinning, LIBBPF_PIN_BY_NAME); +}; + +struct kaconfig kubearmor_config SEC(".maps"); + struct outer_hash { __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); __uint(max_entries, 256); @@ -297,6 +312,84 @@ static __always_inline u32 init_context(event *event_data) { return 0; } + +static __always_inline u32 get_kubearmor_config(u32 config) +{ + u32 *value = bpf_map_lookup_elem(&kubearmor_config, &config); + if (!value) + { + return 0; + } + + return *value; +} + +// To check if subsequent alerts should be dropped per container +static __always_inline bool should_drop_alerts_per_container(struct outer_key okey) { + u64 current_timestamp = bpf_ktime_get_ns(); + + struct outer_key key = { + .pid_ns = okey.pid_ns, + .mnt_ns = okey.mnt_ns + }; + + struct alert_throttle_state *state = bpf_map_lookup_elem(&kubearmor_alert_throttle, &key); + + if (!state) { + struct alert_throttle_state new_state = { + .event_count = 1, + .first_event_timestamp = current_timestamp, + .throttle = 0 + }; + + bpf_map_update_elem(&kubearmor_alert_throttle, &key, &new_state, BPF_ANY); + return false; + } + + u64 throttle_sec = (u64)get_kubearmor_config(_THROTTLE_SEC); + u64 throttle_nsec = throttle_sec * 1000000000L; + u64 maxAlert = (u64)get_kubearmor_config(_MAX_ALERT_PER_SEC); + + if (state->throttle) { + u64 time_difference = current_timestamp - state->first_event_timestamp; + if (time_difference < throttle_nsec) { + return true; + } + } + + u64 time_difference = current_timestamp - state->first_event_timestamp; + + if (time_difference >= 1000000000L) { // 1 second + state->first_event_timestamp = current_timestamp; + state->event_count = 1; + state->throttle = 0; + } else { + state->event_count++; + } + + if (state->event_count > maxAlert) { + state->event_count = 0; + state->throttle = 1; + bpf_map_update_elem(&kubearmor_alert_throttle, &key, state, BPF_ANY); + + // Generating Throttling Alert + event *event_data = bpf_ringbuf_reserve(&kubearmor_events, sizeof(event), 0); + if (!event_data) { + // Failed to reserve + return true; + } + init_context(event_data); + event_data->event_id = _DROPPING_ALERT; + event_data->retval = 0; + bpf_ringbuf_submit(event_data, 0); + + return true; + } + + bpf_map_update_elem(&kubearmor_alert_throttle, &key, state, BPF_ANY); + return false; +} + static bool is_owner(struct file *file_p) { kuid_t owner = BPF_CORE_READ(file_p, f_inode, i_uid); unsigned int z = bpf_get_current_uid_gid(); @@ -599,6 +692,10 @@ static inline int match_and_enforce_path_hooks(struct path *f_path, u32 id, return 0; ringbuf: + if (get_kubearmor_config(_ALERT_THROTTLING) && should_drop_alerts_per_container(okey)) { + return retval; + } + task_info = bpf_ringbuf_reserve(&kubearmor_events, sizeof(event), 0); if (!task_info) { // Failed to reserve, doing policy enforcement without alert diff --git a/KubeArmor/BPF/syscalls.h b/KubeArmor/BPF/syscalls.h index bae88561b4..0e29d27a93 100644 --- a/KubeArmor/BPF/syscalls.h +++ b/KubeArmor/BPF/syscalls.h @@ -31,6 +31,9 @@ enum // capabilities _CAPABLE = 464, + // dropping alert + _DROPPING_ALERT = 0, + }; #endif /* __SYSCALLS_H */ \ No newline at end of file diff --git a/KubeArmor/BPF/system_monitor.c b/KubeArmor/BPF/system_monitor.c index 5fd125b751..1682f88572 100644 --- a/KubeArmor/BPF/system_monitor.c +++ b/KubeArmor/BPF/system_monitor.c @@ -46,6 +46,9 @@ #include #include +#include "syscalls.h" +#include "throttling.h" + #ifdef RHEL_RELEASE_CODE #if (RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(8, 0)) @@ -175,8 +178,6 @@ enum _SYS_RMDIR = 84, _SYS_PTRACE = 101, - // lsm - _SECURITY_BPRM_CHECK = 352, // accept/connect _TCP_CONNECT = 400, @@ -312,12 +313,6 @@ enum _IGNORE_SYSCALL = 1, }; -struct outer_key -{ - u32 pid_ns; - u32 mnt_ns; -}; - struct visibility { __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); @@ -342,6 +337,9 @@ enum _MONITOR_HOST = 0, _MONITOR_CONTAINER = 1, _ENFORCER_BPFLSM = 2, + _ALERT_THROTTLING = 3, + _MAX_ALERT_PER_SEC = 4, + _THROTTLE_SEC = 5, }; struct kaconfig @@ -500,6 +498,12 @@ static __always_inline u32 remove_pid_ns() { // container if (get_task_ns_pid(task) == 1) { + u32 mnt_ns = get_task_mnt_ns_id(task); + struct outer_key key = { + .pid_ns = pid_ns, + .mnt_ns = mnt_ns + }; + bpf_map_delete_elem(&kubearmor_alert_throttle, &key); bpf_map_delete_elem(&pid_ns_map, &pid_ns); return 0; } @@ -1038,6 +1042,79 @@ static __always_inline u32 init_context(sys_context_t *context) return 0; } +// == Alert Throttling == // + +// 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) { + u64 current_timestamp = bpf_ktime_get_ns(); + + struct outer_key key = { + .pid_ns = context->pid_id, + .mnt_ns = context->mnt_id + }; + + struct alert_throttle_state *state = bpf_map_lookup_elem(&kubearmor_alert_throttle, &key); + + if (!state) { + struct alert_throttle_state new_state = { + .event_count = 1, + .first_event_timestamp = current_timestamp, + .throttle = 0 + }; + + bpf_map_update_elem(&kubearmor_alert_throttle, &key, &new_state, BPF_ANY); + return false; + } + + u64 throttle_sec = (u64)get_kubearmor_config(_THROTTLE_SEC); + u64 throttle_nsec = throttle_sec * 1000000000L; + u64 max = (u64)get_kubearmor_config(_MAX_ALERT_PER_SEC); + + if (state->throttle) { + u64 time_difference = current_timestamp - state->first_event_timestamp; + if (time_difference < throttle_nsec) { + return true; + } + } + + u64 time_difference = current_timestamp - state->first_event_timestamp; + + if (time_difference >= 1000000000L) { // 1 second + state->first_event_timestamp = current_timestamp; + state->event_count = 1; + state->throttle = 0; + } else { + state->event_count++; + } + + if (state->event_count > max) { + state->event_count = 0; + state->throttle = 1; + bpf_map_update_elem(&kubearmor_alert_throttle, &key, state, BPF_ANY); + + // Generating Throttling Alert + context->event_id = _DROPPING_ALERT; + set_buffer_offset(DATA_BUF_TYPE, sizeof(sys_context_t)); + + bufs_t *bufs_p = get_buffer(DATA_BUF_TYPE); + if (bufs_p == NULL) { + return 0; + } + + save_context_to_buffer(bufs_p, (void *)context); + + if (types != 0) { + save_args_to_buffer(types, args); + } + + events_perf_submit(ctx); + return true; + } + + bpf_map_update_elem(&kubearmor_alert_throttle, &key, state, BPF_ANY); + return false; +} + SEC("kprobe/security_path_mknod") int kprobe__security_path_mknod(struct pt_regs *ctx) { @@ -1224,6 +1301,13 @@ int kretprobe__execve(struct pt_regs *ctx) return 0; } + u32 types; + args_t args = {}; + if (context.retval < 0 && !get_kubearmor_config(_ENFORCER_BPFLSM) && get_kubearmor_config(_ALERT_THROTTLING) && should_drop_alerts_per_container(&context, ctx, types, &args)) + { + return 0; + } + set_buffer_offset(DATA_BUF_TYPE, sizeof(sys_context_t)); bufs_t *bufs_p = get_buffer(DATA_BUF_TYPE); @@ -1328,6 +1412,14 @@ int kretprobe__execveat(struct pt_regs *ctx) return 0; } + u32 types; + args_t args = {}; + + if (context.retval < 0 && !get_kubearmor_config(_ENFORCER_BPFLSM) && get_kubearmor_config(_ALERT_THROTTLING) && should_drop_alerts_per_container(&context, ctx, types, &args)) + { + return 0; + } + set_buffer_offset(DATA_BUF_TYPE, sizeof(sys_context_t)); bufs_t *bufs_p = get_buffer(DATA_BUF_TYPE); @@ -1501,6 +1593,11 @@ static __always_inline int trace_ret_generic(u32 id, struct pt_regs *ctx, u64 ty context.oid = owner.val; } + if (context.retval < 0 && !get_kubearmor_config(_ENFORCER_BPFLSM) && get_kubearmor_config(_ALERT_THROTTLING) && should_drop_alerts_per_container(&context, ctx, types, &args)) + { + return 0; + } + set_buffer_offset(DATA_BUF_TYPE, sizeof(sys_context_t)); bufs_t *bufs_p = get_buffer(DATA_BUF_TYPE); @@ -1810,6 +1907,11 @@ int sys_exit_openat(struct tracepoint_syscalls_sys_exit_t *args) return 0; } + if (context.retval < 0 && !get_kubearmor_config(_ENFORCER_BPFLSM) && get_kubearmor_config(_ALERT_THROTTLING) && should_drop_alerts_per_container(&context, (struct pt_regs *)args, types, &orig_args)) + { + return 0; + } + set_buffer_offset(DATA_BUF_TYPE, sizeof(sys_context_t)); bufs_t *bufs_p = get_buffer(DATA_BUF_TYPE); @@ -1963,6 +2065,12 @@ int kprobe__tcp_connect(struct pt_regs *ctx) } args.args[0] = (unsigned long)conn.skc_prot->name; + + if (context.retval < 0 && !get_kubearmor_config(_ENFORCER_BPFLSM) && get_kubearmor_config(_ALERT_THROTTLING) && should_drop_alerts_per_container(&context, ctx, types, &args)) + { + return 0; + } + set_buffer_offset(DATA_BUF_TYPE, sizeof(sys_context_t)); bufs_t *bufs_p = get_buffer(DATA_BUF_TYPE); if (bufs_p == NULL) @@ -2041,6 +2149,12 @@ int kretprobe__inet_csk_accept(struct pt_regs *ctx) } args.args[0] = (unsigned long)conn.skc_prot->name; + + if (context.retval < 0 && !get_kubearmor_config(_ENFORCER_BPFLSM) && get_kubearmor_config(_ALERT_THROTTLING) && should_drop_alerts_per_container(&context, ctx, types, &args)) + { + return 0; + } + set_buffer_offset(DATA_BUF_TYPE, sizeof(sys_context_t)); bufs_t *bufs_p = get_buffer(DATA_BUF_TYPE); if (bufs_p == NULL) diff --git a/KubeArmor/BPF/throttling.h b/KubeArmor/BPF/throttling.h new file mode 100644 index 0000000000..5af306c938 --- /dev/null +++ b/KubeArmor/BPF/throttling.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright 2024 Authors of KubeArmor */ + +#ifndef __THROTTLING_H +#define __THROTTLING_H + +struct alert_throttle_state { + u64 first_event_timestamp; + u64 event_count; + u64 throttle; +}; + +struct outer_key { + u32 pid_ns; + u32 mnt_ns; +}; + +struct alert { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 256); + __uint(key_size, sizeof(struct outer_key)); + __uint(value_size, sizeof(struct alert_throttle_state)); + __uint(pinning, LIBBPF_PIN_BY_NAME); +}; + +struct alert kubearmor_alert_throttle SEC(".maps"); + +#endif /* __THROTTLING_H */ \ No newline at end of file diff --git a/KubeArmor/common/common.go b/KubeArmor/common/common.go index 1f1b3a78c3..284a549838 100644 --- a/KubeArmor/common/common.go +++ b/KubeArmor/common/common.go @@ -28,6 +28,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +// OuterKey struct +type OuterKey struct { + PidNs uint32 + MntNs uint32 +} + // ============ // // == Common == // // ============ // @@ -588,3 +594,8 @@ func GetLabelsFromString(labelString string) (map[string]string, []string) { return labelsMap, labelsSlice } + +// provide current timestamp +func GetCurrentTimeStamp() uint64 { + return uint64(time.Now().UnixNano()) +} diff --git a/KubeArmor/config/config.go b/KubeArmor/config/config.go index b172b1ef7a..1b81c7fb3c 100644 --- a/KubeArmor/config/config.go +++ b/KubeArmor/config/config.go @@ -55,6 +55,10 @@ type KubearmorConfig struct { InitTimeout string // Timeout for main thread init stages 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 } // GlobalCfg Global configuration for Kubearmor @@ -96,6 +100,9 @@ const ( ConfigDefaultPostureLogs string = "defaultPostureLogs" ConfigInitTimeout string = "initTimeout" ConfigStateAgent string = "enableKubeArmorStateAgent" + ConfigAlertThrottling string = "alertThrottling" + ConfigMaxAlertPerSec string = "maxAlertPerSec" + ConfigThrottleSec string = "throttleSec" ) func readCmdLineParams() { @@ -144,6 +151,12 @@ func readCmdLineParams() { stateAgent := flag.Bool(ConfigStateAgent, false, "enabling KubeArmor State Agent client") + alertThrottling := flag.Bool(ConfigAlertThrottling, false, "enabling Alert Throttling") + + maxAlertPerSec := flag.Int(ConfigMaxAlertPerSec, 10, "Maximum alerts allowed per second") + + throttleSec := flag.Int(ConfigThrottleSec, 30, "Time period for which subsequent alerts will be dropped (in sec)") + flags := []string{} flag.VisitAll(func(f *flag.Flag) { kv := fmt.Sprintf("%s:%v", f.Name, f.Value) @@ -197,6 +210,10 @@ func readCmdLineParams() { viper.SetDefault(ConfigInitTimeout, *initTimeout) viper.SetDefault(ConfigStateAgent, *stateAgent) + + viper.SetDefault(ConfigAlertThrottling, *alertThrottling) + viper.SetDefault(ConfigMaxAlertPerSec, *maxAlertPerSec) + viper.SetDefault(ConfigThrottleSec, *throttleSec) } // LoadConfig Load configuration @@ -292,6 +309,10 @@ func LoadConfig() error { GlobalCfg.StateAgent = viper.GetBool(ConfigStateAgent) + GlobalCfg.AlertThrottling = viper.GetBool(ConfigAlertThrottling) + GlobalCfg.MaxAlertPerSec = viper.GetInt(ConfigMaxAlertPerSec) + GlobalCfg.ThrottleSec = viper.GetInt(ConfigThrottleSec) + kg.Printf("Final Configuration [%+v]", GlobalCfg) return nil diff --git a/KubeArmor/core/containerdHandler.go b/KubeArmor/core/containerdHandler.go index 33c67e5fec..23c3e8a5e8 100644 --- a/KubeArmor/core/containerdHandler.go +++ b/KubeArmor/core/containerdHandler.go @@ -456,6 +456,12 @@ func (dm *KubeArmorDaemon) UpdateContainerdContainer(ctx context.Context, contai } if dm.SystemMonitor != nil && cfg.GlobalCfg.Policy { + // for throttling + dm.SystemMonitor.Logger.ContainerNsKey[containerID] = common.OuterKey{ + MntNs: container.MntNS, + PidNs: container.PidNS, + } + // update NsMap dm.SystemMonitor.AddContainerIDToNsMap(containerID, container.NamespaceName, container.PidNS, container.MntNS) dm.RuntimeEnforcer.RegisterContainer(containerID, container.PidNS, container.MntNS) @@ -525,6 +531,9 @@ func (dm *KubeArmorDaemon) UpdateContainerdContainer(ctx context.Context, contai dm.EndPointsLock.Unlock() if dm.SystemMonitor != nil && cfg.GlobalCfg.Policy { + outkey := dm.SystemMonitor.Logger.ContainerNsKey[containerID] + dm.Logger.DeleteAlertMapKey(outkey) + delete(dm.SystemMonitor.Logger.ContainerNsKey, containerID) // update NsMap dm.SystemMonitor.DeleteContainerIDFromNsMap(containerID, container.NamespaceName, container.PidNS, container.MntNS) dm.RuntimeEnforcer.UnregisterContainer(containerID) diff --git a/KubeArmor/core/crioHandler.go b/KubeArmor/core/crioHandler.go index 1c967fbb67..89cc41e0d7 100644 --- a/KubeArmor/core/crioHandler.go +++ b/KubeArmor/core/crioHandler.go @@ -11,6 +11,7 @@ import ( "strconv" "time" + "github.com/kubearmor/KubeArmor/KubeArmor/common" kl "github.com/kubearmor/KubeArmor/KubeArmor/common" cfg "github.com/kubearmor/KubeArmor/KubeArmor/config" kg "github.com/kubearmor/KubeArmor/KubeArmor/log" @@ -265,6 +266,12 @@ func (dm *KubeArmorDaemon) UpdateCrioContainer(ctx context.Context, containerID, } if dm.SystemMonitor != nil && cfg.GlobalCfg.Policy { + // for throttling + dm.SystemMonitor.Logger.ContainerNsKey[containerID] = common.OuterKey{ + MntNs: container.MntNS, + PidNs: container.PidNS, + } + // update NsMap dm.SystemMonitor.AddContainerIDToNsMap(containerID, container.NamespaceName, container.PidNS, container.MntNS) dm.RuntimeEnforcer.RegisterContainer(containerID, container.PidNS, container.MntNS) @@ -320,6 +327,9 @@ func (dm *KubeArmorDaemon) UpdateCrioContainer(ctx context.Context, containerID, dm.EndPointsLock.Unlock() if dm.SystemMonitor != nil && cfg.GlobalCfg.Policy { + outkey := dm.SystemMonitor.Logger.ContainerNsKey[containerID] + dm.Logger.DeleteAlertMapKey(outkey) + delete(dm.SystemMonitor.Logger.ContainerNsKey, containerID) // update NsMap dm.SystemMonitor.DeleteContainerIDFromNsMap(containerID, container.NamespaceName, container.PidNS, container.MntNS) dm.RuntimeEnforcer.UnregisterContainer(containerID) diff --git a/KubeArmor/core/dockerHandler.go b/KubeArmor/core/dockerHandler.go index 131657041d..87980df627 100644 --- a/KubeArmor/core/dockerHandler.go +++ b/KubeArmor/core/dockerHandler.go @@ -421,6 +421,12 @@ func (dm *KubeArmorDaemon) GetAlreadyDeployedDockerContainers() { } if dm.SystemMonitor != nil && cfg.GlobalCfg.Policy { + // for throttling + dm.SystemMonitor.Logger.ContainerNsKey[container.ContainerID] = common.OuterKey{ + MntNs: container.MntNS, + PidNs: container.PidNS, + } + // update NsMap dm.SystemMonitor.AddContainerIDToNsMap(container.ContainerID, container.NamespaceName, container.PidNS, container.MntNS) dm.RuntimeEnforcer.RegisterContainer(container.ContainerID, container.PidNS, container.MntNS) @@ -600,6 +606,12 @@ func (dm *KubeArmorDaemon) UpdateDockerContainer(containerID, action string) { } if dm.SystemMonitor != nil && cfg.GlobalCfg.Policy { + // for throttling + dm.SystemMonitor.Logger.ContainerNsKey[containerID] = common.OuterKey{ + MntNs: container.MntNS, + PidNs: container.PidNS, + } + // update NsMap dm.SystemMonitor.AddContainerIDToNsMap(containerID, container.NamespaceName, container.PidNS, container.MntNS) dm.RuntimeEnforcer.RegisterContainer(containerID, container.PidNS, container.MntNS) @@ -681,6 +693,9 @@ func (dm *KubeArmorDaemon) UpdateDockerContainer(containerID, action string) { } if dm.SystemMonitor != nil && cfg.GlobalCfg.Policy { + outkey := dm.SystemMonitor.Logger.ContainerNsKey[containerID] + dm.Logger.DeleteAlertMapKey(outkey) + delete(dm.SystemMonitor.Logger.ContainerNsKey, containerID) // update NsMap dm.SystemMonitor.DeleteContainerIDFromNsMap(containerID, container.NamespaceName, container.PidNS, container.MntNS) dm.RuntimeEnforcer.UnregisterContainer(containerID) diff --git a/KubeArmor/core/kubeArmor.go b/KubeArmor/core/kubeArmor.go index b51a7c1296..5537e0869e 100644 --- a/KubeArmor/core/kubeArmor.go +++ b/KubeArmor/core/kubeArmor.go @@ -13,6 +13,7 @@ import ( "syscall" "time" + "github.com/kubearmor/KubeArmor/KubeArmor/common" kl "github.com/kubearmor/KubeArmor/KubeArmor/common" cfg "github.com/kubearmor/KubeArmor/KubeArmor/config" kg "github.com/kubearmor/KubeArmor/KubeArmor/log" @@ -561,6 +562,8 @@ func KubeArmor() { enableContainerPolicy := true + dm.SystemMonitor.Logger.ContainerNsKey = make(map[string]common.OuterKey) + // Un-orchestrated workloads if !dm.K8sEnabled && cfg.GlobalCfg.Policy { diff --git a/KubeArmor/core/kubeUpdate.go b/KubeArmor/core/kubeUpdate.go index ce8e2d3315..80b9bf0c98 100644 --- a/KubeArmor/core/kubeUpdate.go +++ b/KubeArmor/core/kubeUpdate.go @@ -10,6 +10,7 @@ import ( "io" "os" "sort" + "strconv" "strings" "time" @@ -2378,6 +2379,7 @@ func (dm *KubeArmorDaemon) WatchConfigMap() cache.InformerSynced { cmNS := dm.GetConfigMapNS() + var err error registration, err := informer.AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { if cm, ok := obj.(*corev1.ConfigMap); ok && cm.Namespace == cmNS { @@ -2396,6 +2398,19 @@ func (dm *KubeArmorDaemon) WatchConfigMap() cache.InformerSynced { NetworkAction: cfg.GlobalCfg.DefaultNetworkPosture, CapabilitiesAction: cfg.GlobalCfg.DefaultCapabilitiesPosture, } + 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]) + if err != nil { + dm.Logger.Warnf("Error: %s", err) + } + cfg.GlobalCfg.ThrottleSec, err = strconv.Atoi(cm.Data[cfg.ConfigThrottleSec]) + if err != nil { + dm.Logger.Warnf("Error: %s", err) + } + dm.SystemMonitor.UpdateThrottlingConfig() + dm.Logger.Printf("Current Global Posture is %v", currentGlobalPosture) dm.UpdateGlobalPosture(globalPosture) @@ -2429,6 +2444,19 @@ func (dm *KubeArmorDaemon) WatchConfigMap() cache.InformerSynced { dm.updatEndpointsWithCM(cm, "MODIFIED") // update visibility for namespaces dm.updateVisibilityWithCM(cm, "MODIFIED") + + 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]) + if err != nil { + dm.Logger.Warnf("Error: %s", err) + } + cfg.GlobalCfg.ThrottleSec, err = strconv.Atoi(cm.Data[cfg.ConfigThrottleSec]) + if err != nil { + dm.Logger.Warnf("Error: %s", err) + } + dm.SystemMonitor.UpdateThrottlingConfig() } }, DeleteFunc: func(obj interface{}) { diff --git a/KubeArmor/enforcer/bpflsm/enforcer.go b/KubeArmor/enforcer/bpflsm/enforcer.go index 47cb33b9f8..39e3ac5d2e 100644 --- a/KubeArmor/enforcer/bpflsm/enforcer.go +++ b/KubeArmor/enforcer/bpflsm/enforcer.go @@ -34,8 +34,10 @@ import ( type BPFEnforcer struct { Logger *fd.Feeder - InnerMapSpec *ebpf.MapSpec - BPFContainerMap *ebpf.Map + InnerMapSpec *ebpf.MapSpec + // InnerMapSpec *ebpf.MapSpec + BPFContainerMap *ebpf.Map + BPFContainerThrottleMap *ebpf.Map // events Events *ringbuf.Reader @@ -95,6 +97,21 @@ func NewBPFEnforcer(node tp.Node, pinpath string, logger *fd.Feeder, monitor *mo return be, err } + be.BPFContainerThrottleMap, err = ebpf.NewMapWithOptions(&ebpf.MapSpec{ + Type: ebpf.Hash, + KeySize: 8, + ValueSize: 24, + MaxEntries: 256, + Pinning: ebpf.PinByName, + Name: "kubearmor_alert_throttle", + }, ebpf.MapOptions{ + PinPath: pinpath, + }) + if err != nil { + be.Logger.Errf("error creating kubearmor_alert_throttle map: %s", err) + return be, err + } + if err := loadEnforcerObjects(&be.obj, &ebpf.CollectionOptions{ Maps: ebpf.MapOptions{ PinPath: pinpath, @@ -354,6 +371,12 @@ func (be *BPFEnforcer) TraceEvents() { log.Operation = "Capabilities" log.Resource = mon.Capabilities[int32(event.Data.Path[1])] log.Data = "lsm=" + mon.GetSyscallName(int32(event.EventID)) + " " + log.Resource + + case mon.DropAlert: + log.Operation = "AlertThreshold" + log.Type = "SystemEvent" + log.MaxAlertsPerSec = int32(cfg.GlobalCfg.MaxAlertPerSec) + log.DroppingAlertsInterval = int32(cfg.GlobalCfg.ThrottleSec) } // fallback logic if we don't receive source from BuildLogBase() if len(log.Source) == 0 { @@ -436,6 +459,17 @@ func (be *BPFEnforcer) DestroyBPFEnforcer() error { } } + if be.BPFContainerThrottleMap != nil { + if err := be.BPFContainerThrottleMap.Unpin(); err != nil { + be.Logger.Err(err.Error()) + errBPFCleanUp = errors.Join(errBPFCleanUp, err) + } + if err := be.BPFContainerThrottleMap.Close(); err != nil { + be.Logger.Err(err.Error()) + errBPFCleanUp = errors.Join(errBPFCleanUp, err) + } + } + be.ContainerMapLock.Unlock() if be.Events != nil { diff --git a/KubeArmor/enforcer/bpflsm/enforcer_bpfeb.go b/KubeArmor/enforcer/bpflsm/enforcer_bpfeb.go index 2567087499..e9821c3bf6 100644 --- a/KubeArmor/enforcer/bpflsm/enforcer_bpfeb.go +++ b/KubeArmor/enforcer/bpflsm/enforcer_bpfeb.go @@ -73,11 +73,13 @@ type enforcerProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type enforcerMapSpecs struct { - Bufk *ebpf.MapSpec `ebpf:"bufk"` - Bufs *ebpf.MapSpec `ebpf:"bufs"` - BufsOff *ebpf.MapSpec `ebpf:"bufs_off"` - KubearmorContainers *ebpf.MapSpec `ebpf:"kubearmor_containers"` - KubearmorEvents *ebpf.MapSpec `ebpf:"kubearmor_events"` + Bufk *ebpf.MapSpec `ebpf:"bufk"` + Bufs *ebpf.MapSpec `ebpf:"bufs"` + BufsOff *ebpf.MapSpec `ebpf:"bufs_off"` + KubearmorAlertThrottle *ebpf.MapSpec `ebpf:"kubearmor_alert_throttle"` + KubearmorConfig *ebpf.MapSpec `ebpf:"kubearmor_config"` + KubearmorContainers *ebpf.MapSpec `ebpf:"kubearmor_containers"` + KubearmorEvents *ebpf.MapSpec `ebpf:"kubearmor_events"` } // enforcerObjects contains all objects after they have been loaded into the kernel. @@ -99,11 +101,13 @@ func (o *enforcerObjects) Close() error { // // It can be passed to loadEnforcerObjects or ebpf.CollectionSpec.LoadAndAssign. type enforcerMaps struct { - Bufk *ebpf.Map `ebpf:"bufk"` - Bufs *ebpf.Map `ebpf:"bufs"` - BufsOff *ebpf.Map `ebpf:"bufs_off"` - KubearmorContainers *ebpf.Map `ebpf:"kubearmor_containers"` - KubearmorEvents *ebpf.Map `ebpf:"kubearmor_events"` + Bufk *ebpf.Map `ebpf:"bufk"` + Bufs *ebpf.Map `ebpf:"bufs"` + BufsOff *ebpf.Map `ebpf:"bufs_off"` + KubearmorAlertThrottle *ebpf.Map `ebpf:"kubearmor_alert_throttle"` + KubearmorConfig *ebpf.Map `ebpf:"kubearmor_config"` + KubearmorContainers *ebpf.Map `ebpf:"kubearmor_containers"` + KubearmorEvents *ebpf.Map `ebpf:"kubearmor_events"` } func (m *enforcerMaps) Close() error { @@ -111,6 +115,8 @@ func (m *enforcerMaps) Close() error { m.Bufk, m.Bufs, m.BufsOff, + m.KubearmorAlertThrottle, + m.KubearmorConfig, m.KubearmorContainers, m.KubearmorEvents, ) diff --git a/KubeArmor/enforcer/bpflsm/enforcer_bpfeb.o b/KubeArmor/enforcer/bpflsm/enforcer_bpfeb.o index b3779c6ab4..ea523dfe09 100644 Binary files a/KubeArmor/enforcer/bpflsm/enforcer_bpfeb.o and b/KubeArmor/enforcer/bpflsm/enforcer_bpfeb.o differ diff --git a/KubeArmor/enforcer/bpflsm/enforcer_bpfel.go b/KubeArmor/enforcer/bpflsm/enforcer_bpfel.go index c20bbee4b6..b453aa6407 100644 --- a/KubeArmor/enforcer/bpflsm/enforcer_bpfel.go +++ b/KubeArmor/enforcer/bpflsm/enforcer_bpfel.go @@ -73,11 +73,13 @@ type enforcerProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type enforcerMapSpecs struct { - Bufk *ebpf.MapSpec `ebpf:"bufk"` - Bufs *ebpf.MapSpec `ebpf:"bufs"` - BufsOff *ebpf.MapSpec `ebpf:"bufs_off"` - KubearmorContainers *ebpf.MapSpec `ebpf:"kubearmor_containers"` - KubearmorEvents *ebpf.MapSpec `ebpf:"kubearmor_events"` + Bufk *ebpf.MapSpec `ebpf:"bufk"` + Bufs *ebpf.MapSpec `ebpf:"bufs"` + BufsOff *ebpf.MapSpec `ebpf:"bufs_off"` + KubearmorAlertThrottle *ebpf.MapSpec `ebpf:"kubearmor_alert_throttle"` + KubearmorConfig *ebpf.MapSpec `ebpf:"kubearmor_config"` + KubearmorContainers *ebpf.MapSpec `ebpf:"kubearmor_containers"` + KubearmorEvents *ebpf.MapSpec `ebpf:"kubearmor_events"` } // enforcerObjects contains all objects after they have been loaded into the kernel. @@ -99,11 +101,13 @@ func (o *enforcerObjects) Close() error { // // It can be passed to loadEnforcerObjects or ebpf.CollectionSpec.LoadAndAssign. type enforcerMaps struct { - Bufk *ebpf.Map `ebpf:"bufk"` - Bufs *ebpf.Map `ebpf:"bufs"` - BufsOff *ebpf.Map `ebpf:"bufs_off"` - KubearmorContainers *ebpf.Map `ebpf:"kubearmor_containers"` - KubearmorEvents *ebpf.Map `ebpf:"kubearmor_events"` + Bufk *ebpf.Map `ebpf:"bufk"` + Bufs *ebpf.Map `ebpf:"bufs"` + BufsOff *ebpf.Map `ebpf:"bufs_off"` + KubearmorAlertThrottle *ebpf.Map `ebpf:"kubearmor_alert_throttle"` + KubearmorConfig *ebpf.Map `ebpf:"kubearmor_config"` + KubearmorContainers *ebpf.Map `ebpf:"kubearmor_containers"` + KubearmorEvents *ebpf.Map `ebpf:"kubearmor_events"` } func (m *enforcerMaps) Close() error { @@ -111,6 +115,8 @@ func (m *enforcerMaps) Close() error { m.Bufk, m.Bufs, m.BufsOff, + m.KubearmorAlertThrottle, + m.KubearmorConfig, m.KubearmorContainers, m.KubearmorEvents, ) diff --git a/KubeArmor/enforcer/bpflsm/enforcer_bpfel.o b/KubeArmor/enforcer/bpflsm/enforcer_bpfel.o index 2d0b366580..33db5b1ca1 100644 Binary files a/KubeArmor/enforcer/bpflsm/enforcer_bpfel.o and b/KubeArmor/enforcer/bpflsm/enforcer_bpfel.o differ diff --git a/KubeArmor/enforcer/bpflsm/enforcer_path_bpfeb.go b/KubeArmor/enforcer/bpflsm/enforcer_path_bpfeb.go index fab8c03764..313edfa427 100644 --- a/KubeArmor/enforcer/bpflsm/enforcer_path_bpfeb.go +++ b/KubeArmor/enforcer/bpflsm/enforcer_path_bpfeb.go @@ -77,11 +77,13 @@ type enforcer_pathProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type enforcer_pathMapSpecs struct { - Bufk *ebpf.MapSpec `ebpf:"bufk"` - Bufs *ebpf.MapSpec `ebpf:"bufs"` - BufsOff *ebpf.MapSpec `ebpf:"bufs_off"` - KubearmorContainers *ebpf.MapSpec `ebpf:"kubearmor_containers"` - KubearmorEvents *ebpf.MapSpec `ebpf:"kubearmor_events"` + Bufk *ebpf.MapSpec `ebpf:"bufk"` + Bufs *ebpf.MapSpec `ebpf:"bufs"` + BufsOff *ebpf.MapSpec `ebpf:"bufs_off"` + KubearmorAlertThrottle *ebpf.MapSpec `ebpf:"kubearmor_alert_throttle"` + KubearmorConfig *ebpf.MapSpec `ebpf:"kubearmor_config"` + KubearmorContainers *ebpf.MapSpec `ebpf:"kubearmor_containers"` + KubearmorEvents *ebpf.MapSpec `ebpf:"kubearmor_events"` } // enforcer_pathObjects contains all objects after they have been loaded into the kernel. @@ -103,11 +105,13 @@ func (o *enforcer_pathObjects) Close() error { // // It can be passed to loadEnforcer_pathObjects or ebpf.CollectionSpec.LoadAndAssign. type enforcer_pathMaps struct { - Bufk *ebpf.Map `ebpf:"bufk"` - Bufs *ebpf.Map `ebpf:"bufs"` - BufsOff *ebpf.Map `ebpf:"bufs_off"` - KubearmorContainers *ebpf.Map `ebpf:"kubearmor_containers"` - KubearmorEvents *ebpf.Map `ebpf:"kubearmor_events"` + Bufk *ebpf.Map `ebpf:"bufk"` + Bufs *ebpf.Map `ebpf:"bufs"` + BufsOff *ebpf.Map `ebpf:"bufs_off"` + KubearmorAlertThrottle *ebpf.Map `ebpf:"kubearmor_alert_throttle"` + KubearmorConfig *ebpf.Map `ebpf:"kubearmor_config"` + KubearmorContainers *ebpf.Map `ebpf:"kubearmor_containers"` + KubearmorEvents *ebpf.Map `ebpf:"kubearmor_events"` } func (m *enforcer_pathMaps) Close() error { @@ -115,6 +119,8 @@ func (m *enforcer_pathMaps) Close() error { m.Bufk, m.Bufs, m.BufsOff, + m.KubearmorAlertThrottle, + m.KubearmorConfig, m.KubearmorContainers, m.KubearmorEvents, ) diff --git a/KubeArmor/enforcer/bpflsm/enforcer_path_bpfeb.o b/KubeArmor/enforcer/bpflsm/enforcer_path_bpfeb.o index 88e3ea7791..1f73cb1700 100644 Binary files a/KubeArmor/enforcer/bpflsm/enforcer_path_bpfeb.o and b/KubeArmor/enforcer/bpflsm/enforcer_path_bpfeb.o differ diff --git a/KubeArmor/enforcer/bpflsm/enforcer_path_bpfel.go b/KubeArmor/enforcer/bpflsm/enforcer_path_bpfel.go index 6a0e156ed2..a1e9861c0c 100644 --- a/KubeArmor/enforcer/bpflsm/enforcer_path_bpfel.go +++ b/KubeArmor/enforcer/bpflsm/enforcer_path_bpfel.go @@ -77,11 +77,13 @@ type enforcer_pathProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type enforcer_pathMapSpecs struct { - Bufk *ebpf.MapSpec `ebpf:"bufk"` - Bufs *ebpf.MapSpec `ebpf:"bufs"` - BufsOff *ebpf.MapSpec `ebpf:"bufs_off"` - KubearmorContainers *ebpf.MapSpec `ebpf:"kubearmor_containers"` - KubearmorEvents *ebpf.MapSpec `ebpf:"kubearmor_events"` + Bufk *ebpf.MapSpec `ebpf:"bufk"` + Bufs *ebpf.MapSpec `ebpf:"bufs"` + BufsOff *ebpf.MapSpec `ebpf:"bufs_off"` + KubearmorAlertThrottle *ebpf.MapSpec `ebpf:"kubearmor_alert_throttle"` + KubearmorConfig *ebpf.MapSpec `ebpf:"kubearmor_config"` + KubearmorContainers *ebpf.MapSpec `ebpf:"kubearmor_containers"` + KubearmorEvents *ebpf.MapSpec `ebpf:"kubearmor_events"` } // enforcer_pathObjects contains all objects after they have been loaded into the kernel. @@ -103,11 +105,13 @@ func (o *enforcer_pathObjects) Close() error { // // It can be passed to loadEnforcer_pathObjects or ebpf.CollectionSpec.LoadAndAssign. type enforcer_pathMaps struct { - Bufk *ebpf.Map `ebpf:"bufk"` - Bufs *ebpf.Map `ebpf:"bufs"` - BufsOff *ebpf.Map `ebpf:"bufs_off"` - KubearmorContainers *ebpf.Map `ebpf:"kubearmor_containers"` - KubearmorEvents *ebpf.Map `ebpf:"kubearmor_events"` + Bufk *ebpf.Map `ebpf:"bufk"` + Bufs *ebpf.Map `ebpf:"bufs"` + BufsOff *ebpf.Map `ebpf:"bufs_off"` + KubearmorAlertThrottle *ebpf.Map `ebpf:"kubearmor_alert_throttle"` + KubearmorConfig *ebpf.Map `ebpf:"kubearmor_config"` + KubearmorContainers *ebpf.Map `ebpf:"kubearmor_containers"` + KubearmorEvents *ebpf.Map `ebpf:"kubearmor_events"` } func (m *enforcer_pathMaps) Close() error { @@ -115,6 +119,8 @@ func (m *enforcer_pathMaps) Close() error { m.Bufk, m.Bufs, m.BufsOff, + m.KubearmorAlertThrottle, + m.KubearmorConfig, m.KubearmorContainers, m.KubearmorEvents, ) diff --git a/KubeArmor/enforcer/bpflsm/enforcer_path_bpfel.o b/KubeArmor/enforcer/bpflsm/enforcer_path_bpfel.o index d18dfd3ccd..9cf9923363 100644 Binary files a/KubeArmor/enforcer/bpflsm/enforcer_path_bpfel.o and b/KubeArmor/enforcer/bpflsm/enforcer_path_bpfel.o differ diff --git a/KubeArmor/enforcer/bpflsm/mapHelpers.go b/KubeArmor/enforcer/bpflsm/mapHelpers.go index c721daf887..bdb7734f6f 100644 --- a/KubeArmor/enforcer/bpflsm/mapHelpers.go +++ b/KubeArmor/enforcer/bpflsm/mapHelpers.go @@ -75,7 +75,12 @@ func (be *BPFEnforcer) DeleteContainerInnerMap(containerID string) { if be.ContainerMap[containerID].Map != nil { if err := be.BPFContainerMap.Delete(be.ContainerMap[containerID].Key); err != nil { if !errors.Is(err, os.ErrNotExist) { - be.Logger.Errf("error deleting container %s from outer map: %s", containerID, err.Error()) + be.Logger.Errf("error deleting container %s from outer map in kubearmor_containers map: %s", containerID, err.Error()) + } + } + if err := be.BPFContainerThrottleMap.Delete(be.ContainerMap[containerID].Key); err != nil { + if !errors.Is(err, os.ErrNotExist) { + be.Logger.Errf("error deleting container %s from outer map in kubearmor_alert_throttle map: %s", containerID, err.Error()) } } if err := be.ContainerMap[containerID].Map.Close(); err != nil { diff --git a/KubeArmor/feeder/feeder.go b/KubeArmor/feeder/feeder.go index 570f2fdc81..8917b3d0d3 100644 --- a/KubeArmor/feeder/feeder.go +++ b/KubeArmor/feeder/feeder.go @@ -15,6 +15,7 @@ import ( "sync" "time" + "github.com/kubearmor/KubeArmor/KubeArmor/common" kl "github.com/kubearmor/KubeArmor/KubeArmor/common" "github.com/kubearmor/KubeArmor/KubeArmor/config" cfg "github.com/kubearmor/KubeArmor/KubeArmor/config" @@ -192,6 +193,17 @@ type BaseFeeder struct { LogServer *grpc.Server } +type OuterKey struct { + PidNs uint32 + MntNs uint32 +} + +type AlertThrottleState struct { + FirstEventTimestamp uint64 + EventCount uint64 + Throttle bool +} + // Feeder Structure type Feeder struct { BaseFeeder @@ -205,6 +217,10 @@ type Feeder struct { // DefaultPosture (namespace -> postures) DefaultPostures map[string]tp.DefaultPosture DefaultPosturesLock *sync.Mutex + + AlertMap map[OuterKey]AlertThrottleState + + ContainerNsKey map[string]common.OuterKey } // NewFeeder Function @@ -562,7 +578,7 @@ func (fd *Feeder) PushLog(log tp.Log) { } // gRPC output - if log.Type == "MatchedPolicy" || log.Type == "MatchedHostPolicy" { + if log.Type == "MatchedPolicy" || log.Type == "MatchedHostPolicy" || log.Type == "SystemEvent" { pbAlert := pb.Alert{} pbAlert.Timestamp = log.Timestamp @@ -640,6 +656,8 @@ func (fd *Feeder) PushLog(log tp.Log) { } pbAlert.Result = log.Result + pbAlert.MaxAlertsPerSec = log.MaxAlertsPerSec + pbAlert.DroppingAlertsInterval = log.DroppingAlertsInterval fd.EventStructs.AlertLock.Lock() defer fd.EventStructs.AlertLock.Unlock() @@ -744,3 +762,62 @@ func loadTLSCredentials(ip string) (credentials.TransportCredentials, error) { creds, err := cert.NewTlsCredentialManager(&tlsConfig).CreateTlsServerCredentials() return creds, err } + +func (fd *Feeder) ShouldDropAlertsPerContainer(pidNs, mntNs uint32) (bool, bool) { + currentTimestamp := kl.GetCurrentTimeStamp() + + key := OuterKey{ + PidNs: pidNs, + MntNs: mntNs, + } + + if fd.AlertMap == nil { + fd.AlertMap = make(map[OuterKey]AlertThrottleState) + } + + state, ok := fd.AlertMap[key] + + if !ok { + newState := AlertThrottleState{ + EventCount: 1, + FirstEventTimestamp: currentTimestamp, + Throttle: false, + } + fd.AlertMap[key] = newState + return false, false + } + + throttleSec := uint64(cfg.GlobalCfg.ThrottleSec) * 1000000000 // Throttle duration in nanoseconds + maxAlertPerSec := uint64(cfg.GlobalCfg.MaxAlertPerSec) + + if state.Throttle { + timeDifference := currentTimestamp - state.FirstEventTimestamp + if timeDifference < throttleSec { + return true, true + } + } + + timeDifference := currentTimestamp - state.FirstEventTimestamp + + if timeDifference >= 1000000000 { // 1 second + state.FirstEventTimestamp = currentTimestamp + state.EventCount = 1 + state.Throttle = false + } else { + state.EventCount++ + } + + if state.EventCount > maxAlertPerSec { + state.EventCount = 0 + state.Throttle = true + fd.AlertMap[key] = state + return true, false + } + + fd.AlertMap[key] = state + return false, false +} + +func (fd *Feeder) DeleteAlertMapKey(outkey kl.OuterKey) { + delete(fd.AlertMap, OuterKey{PidNs: outkey.PidNs, MntNs: outkey.MntNs}) +} diff --git a/KubeArmor/feeder/policyMatcher.go b/KubeArmor/feeder/policyMatcher.go index c241c3943e..21946457bb 100644 --- a/KubeArmor/feeder/policyMatcher.go +++ b/KubeArmor/feeder/policyMatcher.go @@ -1007,6 +1007,9 @@ func (fd *Feeder) UpdateMatchedPolicy(log tp.Log) tp.Log { fd.DefaultPosturesLock.Lock() defer fd.DefaultPosturesLock.Unlock() if log.Result == "Passed" || log.Result == "Operation not permitted" || log.Result == "Permission denied" { + if log.Type == "SystemEvent" { + return log + } fd.SecurityPoliciesLock.RLock() key := cfg.GlobalCfg.Host @@ -1727,6 +1730,20 @@ 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 @@ -1756,6 +1773,20 @@ 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 } } diff --git a/KubeArmor/main.go b/KubeArmor/main.go index 66c356ddb7..963157ca39 100644 --- a/KubeArmor/main.go +++ b/KubeArmor/main.go @@ -44,7 +44,7 @@ func main() { // initial clean up bpfMapsDir := "/sys/fs/bpf/" - bpfMapsName := []string{"kubearmor_config", "kubearmor_events", "kubearmor_containers", "kubearmor_visibility"} + bpfMapsName := []string{"kubearmor_config", "kubearmor_events", "kubearmor_containers", "kubearmor_visibility", "kubearmor_alert_throttle"} for _, mp := range bpfMapsName { path := bpfMapsDir + mp /* This should not be triggered in ideal cases, diff --git a/KubeArmor/monitor/logUpdate.go b/KubeArmor/monitor/logUpdate.go index f8ba6ca560..619979a9b5 100644 --- a/KubeArmor/monitor/logUpdate.go +++ b/KubeArmor/monitor/logUpdate.go @@ -9,6 +9,7 @@ import ( "strings" kl "github.com/kubearmor/KubeArmor/KubeArmor/common" + cfg "github.com/kubearmor/KubeArmor/KubeArmor/config" tp "github.com/kubearmor/KubeArmor/KubeArmor/types" ) @@ -71,25 +72,27 @@ func (mon *SystemMonitor) BuildLogBase(eventID int32, msg ContextCombined, readl log.CapabilitiesVisibilityEnabled = mon.Node.CapabilitiesVisibilityEnabled } - log.HostPPID = int32(msg.ContextSys.HostPPID) - log.HostPID = int32(msg.ContextSys.HostPID) + if eventID != int32(DropAlert) { + log.HostPPID = int32(msg.ContextSys.HostPPID) + log.HostPID = int32(msg.ContextSys.HostPID) - log.PPID = int32(msg.ContextSys.PPID) - log.PID = int32(msg.ContextSys.PID) - log.UID = int32(msg.ContextSys.UID) + log.PPID = int32(msg.ContextSys.PPID) + log.PID = int32(msg.ContextSys.PID) + log.UID = int32(msg.ContextSys.UID) - log.ProcessName = mon.GetExecPath(msg.ContainerID, msg.ContextSys, readlink) - log.ParentProcessName = mon.GetParentExecPath(msg.ContainerID, msg.ContextSys, readlink) + log.ProcessName = mon.GetExecPath(msg.ContainerID, msg.ContextSys, readlink) + log.ParentProcessName = mon.GetParentExecPath(msg.ContainerID, msg.ContextSys, readlink) - if msg.ContextSys.EventID == SysExecve || msg.ContextSys.EventID == SysExecveAt { - log.Source = mon.GetParentExecPath(msg.ContainerID, msg.ContextSys, readlink) - } else { - log.Source = mon.GetCommand(msg.ContainerID, msg.ContextSys, readlink) - } + if msg.ContextSys.EventID == SysExecve || msg.ContextSys.EventID == SysExecveAt { + log.Source = mon.GetParentExecPath(msg.ContainerID, msg.ContextSys, readlink) + } else { + log.Source = mon.GetCommand(msg.ContainerID, msg.ContextSys, readlink) + } - log.Cwd = strings.TrimRight(string(msg.ContextSys.Cwd[:]), "\x00") + "/" - log.TTY = strings.TrimRight(string(msg.ContextSys.TTY[:]), "\x00") - log.OID = int32(msg.ContextSys.OID) + log.Cwd = strings.TrimRight(string(msg.ContextSys.Cwd[:]), "\x00") + "/" + log.TTY = strings.TrimRight(string(msg.ContextSys.TTY[:]), "\x00") + log.OID = int32(msg.ContextSys.OID) + } return log } @@ -510,6 +513,12 @@ func (mon *SystemMonitor) UpdateLogs() { log.Resource = "" log.Data = "syscall=" + GetSyscallName(int32(msg.ContextSys.EventID)) + " fd=" + fd + case DropAlert: // throttling alert + log.Operation = "AlertThreshold" + log.Type = "SystemEvent" + log.MaxAlertsPerSec = int32(cfg.GlobalCfg.MaxAlertPerSec) + log.DroppingAlertsInterval = int32(cfg.GlobalCfg.ThrottleSec) + default: continue } diff --git a/KubeArmor/monitor/syscalls_amd64.go b/KubeArmor/monitor/syscalls_amd64.go index 7e1202fc18..bd85e380ca 100644 --- a/KubeArmor/monitor/syscalls_amd64.go +++ b/KubeArmor/monitor/syscalls_amd64.go @@ -61,6 +61,8 @@ const ( SocketAccept = 463 Capable = 464 + + DropAlert = 0 ) var syscalls = map[int32]string{ diff --git a/KubeArmor/monitor/syscalls_arm64.go b/KubeArmor/monitor/syscalls_arm64.go index b1d35948a5..c190303868 100644 --- a/KubeArmor/monitor/syscalls_arm64.go +++ b/KubeArmor/monitor/syscalls_arm64.go @@ -64,6 +64,7 @@ const ( SocketAccept = 463 Capable = 464 + DropAlert = 0 ) var syscalls = map[int32]string{ diff --git a/KubeArmor/monitor/systemMonitor.go b/KubeArmor/monitor/systemMonitor.go index 95565c2c70..a144ff0c3a 100644 --- a/KubeArmor/monitor/systemMonitor.go +++ b/KubeArmor/monitor/systemMonitor.go @@ -251,6 +251,8 @@ func (mon *SystemMonitor) initBPFMaps() error { } } + mon.UpdateThrottlingConfig() + return errors.Join(errviz, errconfig) } @@ -279,6 +281,20 @@ func (mon *SystemMonitor) DestroyBPFMaps() { } } +func (mon *SystemMonitor) UpdateThrottlingConfig() { + if cfg.GlobalCfg.AlertThrottling { + if err := mon.BpfConfigMap.Update(uint32(3), uint32(1), cle.UpdateAny); err != nil { + mon.Logger.Errf("Error Updating System Monitor Config Map to enable alert throttling : %s", err.Error()) + } + } + if err := mon.BpfConfigMap.Update(uint32(4), uint32(cfg.GlobalCfg.MaxAlertPerSec), cle.UpdateAny); err != nil { + mon.Logger.Errf("Error Updating System Monitor Config Map to set max alerts per sec : %s", err.Error()) + } + if err := mon.BpfConfigMap.Update(uint32(5), uint32(cfg.GlobalCfg.ThrottleSec), cle.UpdateAny); err != nil { + mon.Logger.Errf("Error Updating System Monitor Config Map to set time interval for dropping subsequent alerts : %s", err.Error()) + } +} + // UpdateNsKeyMap Function func (mon *SystemMonitor) UpdateNsKeyMap(action string, nsKey NsKey, visibility tp.Visibility) { var err error diff --git a/KubeArmor/types/types.go b/KubeArmor/types/types.go index 20b9e2cf5f..31767cdcdc 100644 --- a/KubeArmor/types/types.go +++ b/KubeArmor/types/types.go @@ -259,17 +259,18 @@ type Log struct { Message string `json:"message,omitempty"` // log - Type string `json:"type"` - Source string `json:"source"` - Operation string `json:"operation"` - Resource string `json:"resource"` - Cwd string `json:"cwd"` - TTY string `json:"tty,omitempty"` - OID int32 `json:"oid"` - Data string `json:"data,omitempty"` - Action string `json:"action,omitempty"` - Result string `json:"result"` - + Type string `json:"type"` + Source string `json:"source"` + Operation string `json:"operation"` + Resource string `json:"resource"` + Cwd string `json:"cwd"` + TTY string `json:"tty,omitempty"` + OID int32 `json:"oid"` + Data string `json:"data,omitempty"` + Action string `json:"action,omitempty"` + Result string `json:"result"` + MaxAlertsPerSec int32 `json:"MaxAlertsPerSec,omitempty"` + DroppingAlertsInterval int32 `json:"DroppingAlertsInterval,omitempty"` // == // PolicyEnabled int `json:"policyEnabled,omitempty"` diff --git a/deployments/helm/KubeArmor/README.md b/deployments/helm/KubeArmor/README.md index c9a842b4b3..8008780862 100644 --- a/deployments/helm/KubeArmor/README.md +++ b/deployments/helm/KubeArmor/README.md @@ -44,6 +44,8 @@ helm upgrade --install kubearmor . -n kubearmor --create-namespace ``` $ sudo ./kubearmor -h Usage of ./kubearmor: + -alertThrottling + enabling Alert Throttling -bpfFsPath string Path to the BPF filesystem to use for storing maps (default "/sys/fs/bpf") -cluster string @@ -84,8 +86,12 @@ Usage of ./kubearmor: log file path, {path|stdout|none} (default "none") -lsm string lsm preference order to use, available lsms [bpf, apparmor, selinux] (default "bpf,apparmor,selinux") + -maxAlertPerSec int + Maximum alerts allowed per second (default 10) -seLinuxProfileDir string SELinux profile directory (default "/tmp/kubearmor.selinux") + -throttleSec int + Time period for which subsequent alerts will be dropped (in sec) (default 30) -visibility string Container Visibility to use, available visibility [process,file,network,capabilities,none] (default "process,network") ``` diff --git a/deployments/helm/KubeArmor/templates/configmap.yaml b/deployments/helm/KubeArmor/templates/configmap.yaml index 2bac64bd7c..43f14ead54 100644 --- a/deployments/helm/KubeArmor/templates/configmap.yaml +++ b/deployments/helm/KubeArmor/templates/configmap.yaml @@ -4,6 +4,9 @@ data: defaultCapabilitiesPosture: {{ .Values.kubearmorConfigMap.defaultCapabilitiesPosture }} defaultNetworkPosture: {{ .Values.kubearmorConfigMap.defaultNetworkPosture }} visibility: {{ .Values.kubearmorConfigMap.visibility }} + alertThrottling: {{ .Values.kubearmorConfigMap.alertThrottling }} + maxAlertPerSec: {{ .Values.kubearmorConfigMap.maxAlertPerSec }} + throttleSec: {{ .Values.kubearmorConfigMap.throttleSec }} kind: ConfigMap metadata: labels: diff --git a/deployments/helm/KubeArmor/values.yaml b/deployments/helm/KubeArmor/values.yaml index 3df4460f4f..409befa0ef 100644 --- a/deployments/helm/KubeArmor/values.yaml +++ b/deployments/helm/KubeArmor/values.yaml @@ -94,6 +94,9 @@ kubearmorConfigMap: defaultCapabilitiesPosture: audit defaultNetworkPosture: audit visibility: process,network + alertThrottling: false + maxAlertPerSec: 10 + throttleSec: 30 #volume mounts and volumes kubearmor: diff --git a/deployments/helm/KubeArmorOperator/crds/operator.kubearmor.com_kubearmorconfigs.yaml b/deployments/helm/KubeArmorOperator/crds/operator.kubearmor.com_kubearmorconfigs.yaml index e179add2bb..f1dac2062b 100644 --- a/deployments/helm/KubeArmorOperator/crds/operator.kubearmor.com_kubearmorconfigs.yaml +++ b/deployments/helm/KubeArmorOperator/crds/operator.kubearmor.com_kubearmorconfigs.yaml @@ -133,6 +133,12 @@ spec: type: object seccompEnabled: type: boolean + alertThrottling: + type: boolean + maxAlertPerSec: + type: integer + throttleSec: + type: integer tls: properties: enable: diff --git a/deployments/helm/KubeArmorOperator/values.yaml b/deployments/helm/KubeArmorOperator/values.yaml index f069271113..ad47707ba2 100644 --- a/deployments/helm/KubeArmorOperator/values.yaml +++ b/deployments/helm/KubeArmorOperator/values.yaml @@ -46,6 +46,9 @@ kubearmorConfig: enableStdOutAlerts: false enableStdOutMsgs: false seccompEnabled: true + alertThrottling: false + maxAlertPerSec: 10 + throttleSec: 30 # DO NOT CHANGE THIS VALUES # changing these values will require code changes with the operator diff --git a/deployments/operator/operator.yaml b/deployments/operator/operator.yaml index 09785ab19a..f3bacad8b1 100644 --- a/deployments/operator/operator.yaml +++ b/deployments/operator/operator.yaml @@ -132,6 +132,12 @@ spec: type: object seccompEnabled: type: boolean + alertThrottling: + type: boolean + maxAlertPerSec: + type: integer + throttleSec: + type: integer tls: properties: enable: diff --git a/getting-started/alert_throttling.md b/getting-started/alert_throttling.md new file mode 100644 index 0000000000..ec0cb81a91 --- /dev/null +++ b/getting-started/alert_throttling.md @@ -0,0 +1,40 @@ +# Alert Throttling + +Alert throttling is necessary to prevent overwhelming recipients with a flood of notifications. KubeArmor may bombard users with excessive alerts, leading to alert fatigue, where users become desensitized to notifications. Current throttling implementation is based on the frequency of the alerts. + +> **Note** Alert Throttling is done per container, it's not system wide. + +### Usage + +Throttling conditions can be configured through the config map, `kubearmor-config` or `KubeArmorConfig` object in case of deployment through operator. + +Three configurable conditions for throttling are: + +1. enabling alert throttling, by default alert throttling will not be available. In order to enable throttling we need to set `alertThrottling` to `true`. + +2. set the threshold frequency for the alerts generated, by default it is set to `10` alerts(after enabling throttling), which means 10 alerts would be allowed to be generated per second. After the threshold frequency is crossed an alert will be generated which will notify that threshold frequency is crossed and for next few seconds we will not recieve alerts for this container. In order to set threshold frequency we need to set `maxAlertPerSec` to an int value, which decribes the number of maximum alerts that could be generated per sec. + +3. set the timer for throttling, which means for how many seconds we want alerts to be stopped after it crossed the threshold frequency, by default it is set to `30` seconds(after enabling throttling). After the threshold frequency is crossed an alert will be generated which will notify that threshold frequency is crossed. In order to set the throttling timer we need to set `throttleSec` to an int value, which decribes the number of seconds for which subsequent alerts would be dropped. + +> **Note** Throttling will be done per container, therefore, threshold frequency will be calculated per container. If threshold frequency is crossed for one conatiner other containers will still provide alerts unless they also cross the threshold frequency. + +Throttling alert after crossing the threshold frequency for a `wordpress` container will look like: +``` +ClusterName: default +HostName: prateek +NamespaceName: wordpress-mysql +PodName: wordpress-586468bf4f-8bf6x +Labels: app=wordpress +ContainerName: wordpress +ContainerID: a4e3d52aeda8a0256d3c8ad819ec1bc6b61e4fa6f6d68858196d5195b5765d9f +ContainerImage: docker.io/library/wordpress:4.8-apache@sha256:6216f64ab88fc51d311e38c7f69ca3f9aaba621492b4f1fa93ddf63093768845 +Type: SystemEvent +Operation: AlertThreshold +Enforcer: BPFLSM +Result: Passed +DroppingAlertsInterval: 30 +MaxAlertsPerSec: 2 +Owner: map[Name:wordpress Namespace:wordpress-mysql Ref:Deployment] +PPID: 0 +UID: 0 +``` \ No newline at end of file diff --git a/pkg/KubeArmorOperator/api/operator.kubearmor.com/v1/kubearmorconfig_types.go b/pkg/KubeArmorOperator/api/operator.kubearmor.com/v1/kubearmorconfig_types.go index a5f276e4a4..c6698c2286 100644 --- a/pkg/KubeArmorOperator/api/operator.kubearmor.com/v1/kubearmorconfig_types.go +++ b/pkg/KubeArmorOperator/api/operator.kubearmor.com/v1/kubearmorconfig_types.go @@ -63,6 +63,12 @@ type KubeArmorConfigSpec struct { EnableStdOutMsgs bool `json:"enableStdOutMsgs,omitempty"` // +kubebuilder:validation:Optional SeccompEnabled bool `json:"seccompEnabled,omitempty"` + // +kubebuilder:validation:Optional + AlertThrottling bool `json:"alertThrottling,omitempty"` + // +kubebuilder:validation:Optional + MaxAlertPerSec int `json:"maxAlertPerSec,omitempty"` + // +kubebuilder:validation:Optional + ThrottleSec int `json:"throttleSec,omitempty"` } // KubeArmorConfigStatus defines the observed state of KubeArmorConfig diff --git a/pkg/KubeArmorOperator/common/defaults.go b/pkg/KubeArmorOperator/common/defaults.go index 9a7fe88adc..1f1e4605a6 100644 --- a/pkg/KubeArmorOperator/common/defaults.go +++ b/pkg/KubeArmorOperator/common/defaults.go @@ -76,6 +76,9 @@ var ( ConfigDefaultCapabilitiesPosture string = "defaultCapabilitiesPosture" ConfigDefaultNetworkPosture string = "defaultNetworkPosture" ConfigDefaultPostureLogs string = "defaultPostureLogs" + ConfigAlertThrottling string = "alertThrottling" + ConfigMaxAlertPerSec string = "maxAlertPerSec" + ConfigThrottleSec string = "throttleSec" //KubearmorRelayEnvVariables @@ -121,6 +124,9 @@ var ConfigMapData = map[string]string{ ConfigDefaultNetworkPosture: "audit", ConfigVisibility: "process,network,capabilities", ConfigDefaultPostureLogs: "true", + ConfigAlertThrottling: "false", + ConfigMaxAlertPerSec: "10", + ConfigThrottleSec: "30", } var ConfigDefaultSeccompEnabled = "false" diff --git a/pkg/KubeArmorOperator/config/crd/bases/operator.kubearmor.com_kubearmorconfigs.yaml b/pkg/KubeArmorOperator/config/crd/bases/operator.kubearmor.com_kubearmorconfigs.yaml index e179add2bb..f1dac2062b 100644 --- a/pkg/KubeArmorOperator/config/crd/bases/operator.kubearmor.com_kubearmorconfigs.yaml +++ b/pkg/KubeArmorOperator/config/crd/bases/operator.kubearmor.com_kubearmorconfigs.yaml @@ -133,6 +133,12 @@ spec: type: object seccompEnabled: type: boolean + alertThrottling: + type: boolean + maxAlertPerSec: + type: integer + throttleSec: + type: integer tls: properties: enable: diff --git a/pkg/KubeArmorOperator/config/samples/kubearmor-test.yaml b/pkg/KubeArmorOperator/config/samples/kubearmor-test.yaml index 5d551999ee..22038c4c5c 100644 --- a/pkg/KubeArmorOperator/config/samples/kubearmor-test.yaml +++ b/pkg/KubeArmorOperator/config/samples/kubearmor-test.yaml @@ -15,6 +15,9 @@ spec: defaultNetworkPosture: block defaultVisibility: process,file,network,capabilities seccompEnabled: false + alertThrottling: false + maxAlertPerSec: 10 + throttleSec: 30 kubearmorImage: image: kubearmor/kubearmor:latest imagePullPolicy: Never diff --git a/pkg/KubeArmorOperator/config/samples/sample-config.yml b/pkg/KubeArmorOperator/config/samples/sample-config.yml index c14a0fc57c..93bfce1e3e 100644 --- a/pkg/KubeArmorOperator/config/samples/sample-config.yml +++ b/pkg/KubeArmorOperator/config/samples/sample-config.yml @@ -18,6 +18,9 @@ spec: enableStdOutAlerts: false enableStdOutMsgs: false seccompEnabled: false + alertThrottling: false + maxAlertPerSec: 10 + throttleSec: 30 kubearmorImage: image: kubearmor/kubearmor:stable imagePullPolicy: Always diff --git a/pkg/KubeArmorOperator/internal/controller/cluster.go b/pkg/KubeArmorOperator/internal/controller/cluster.go index 2f68935c39..b1fb2082be 100644 --- a/pkg/KubeArmorOperator/internal/controller/cluster.go +++ b/pkg/KubeArmorOperator/internal/controller/cluster.go @@ -784,6 +784,27 @@ func UpdateConfigMapData(config *opv1.KubeArmorConfigSpec) bool { updated = true } } + AlertThrottlingEnabled := strconv.FormatBool(config.AlertThrottling) + if AlertThrottlingEnabled != "" { + if common.ConfigMapData[common.ConfigAlertThrottling] != AlertThrottlingEnabled { + common.ConfigMapData[common.ConfigAlertThrottling] = AlertThrottlingEnabled + updated = true + } + } + MaxAlertPerSec := strconv.FormatInt(int64(config.MaxAlertPerSec), 10) + if MaxAlertPerSec != "" { + if common.ConfigMapData[common.ConfigMaxAlertPerSec] != MaxAlertPerSec { + common.ConfigMapData[common.ConfigMaxAlertPerSec] = MaxAlertPerSec + updated = true + } + } + ThrottleSec := strconv.FormatInt(int64(config.ThrottleSec), 10) + if MaxAlertPerSec != "" { + if common.ConfigMapData[common.ConfigThrottleSec] != ThrottleSec { + common.ConfigMapData[common.ConfigThrottleSec] = ThrottleSec + updated = true + } + } return updated } diff --git a/protobuf/kubearmor.pb.go b/protobuf/kubearmor.pb.go index 618a08ce5c..9241a89808 100644 --- a/protobuf/kubearmor.pb.go +++ b/protobuf/kubearmor.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 -// protoc v4.25.3 +// protoc-gen-go v1.27.1 +// protoc v3.19.4 // source: kubearmor.proto package protobuf @@ -242,39 +242,41 @@ type Alert struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Timestamp int64 `protobuf:"varint,1,opt,name=Timestamp,proto3" json:"Timestamp,omitempty"` - UpdatedTime string `protobuf:"bytes,2,opt,name=UpdatedTime,proto3" json:"UpdatedTime,omitempty"` - ClusterName string `protobuf:"bytes,3,opt,name=ClusterName,proto3" json:"ClusterName,omitempty"` - HostName string `protobuf:"bytes,4,opt,name=HostName,proto3" json:"HostName,omitempty"` - NamespaceName string `protobuf:"bytes,5,opt,name=NamespaceName,proto3" json:"NamespaceName,omitempty"` - Owner *Podowner `protobuf:"bytes,31,opt,name=Owner,proto3" json:"Owner,omitempty"` - PodName string `protobuf:"bytes,6,opt,name=PodName,proto3" json:"PodName,omitempty"` - Labels string `protobuf:"bytes,29,opt,name=Labels,proto3" json:"Labels,omitempty"` - ContainerID string `protobuf:"bytes,7,opt,name=ContainerID,proto3" json:"ContainerID,omitempty"` - ContainerName string `protobuf:"bytes,8,opt,name=ContainerName,proto3" json:"ContainerName,omitempty"` - ContainerImage string `protobuf:"bytes,24,opt,name=ContainerImage,proto3" json:"ContainerImage,omitempty"` - HostPPID int32 `protobuf:"varint,27,opt,name=HostPPID,proto3" json:"HostPPID,omitempty"` - HostPID int32 `protobuf:"varint,9,opt,name=HostPID,proto3" json:"HostPID,omitempty"` - PPID int32 `protobuf:"varint,10,opt,name=PPID,proto3" json:"PPID,"` - PID int32 `protobuf:"varint,11,opt,name=PID,proto3" json:"PID,omitempty"` - UID int32 `protobuf:"varint,12,opt,name=UID,proto3" json:"UID,"` - ParentProcessName string `protobuf:"bytes,25,opt,name=ParentProcessName,proto3" json:"ParentProcessName,omitempty"` - ProcessName string `protobuf:"bytes,26,opt,name=ProcessName,proto3" json:"ProcessName,omitempty"` - PolicyName string `protobuf:"bytes,13,opt,name=PolicyName,proto3" json:"PolicyName,omitempty"` - Severity string `protobuf:"bytes,14,opt,name=Severity,proto3" json:"Severity,omitempty"` - Tags string `protobuf:"bytes,15,opt,name=Tags,proto3" json:"Tags,omitempty"` - ATags []string `protobuf:"bytes,30,rep,name=ATags,proto3" json:"ATags,omitempty"` - Message string `protobuf:"bytes,16,opt,name=Message,proto3" json:"Message,omitempty"` - Type string `protobuf:"bytes,17,opt,name=Type,proto3" json:"Type,omitempty"` - Source string `protobuf:"bytes,18,opt,name=Source,proto3" json:"Source,omitempty"` - Operation string `protobuf:"bytes,19,opt,name=Operation,proto3" json:"Operation,omitempty"` - Resource string `protobuf:"bytes,20,opt,name=Resource,proto3" json:"Resource,omitempty"` - Data string `protobuf:"bytes,21,opt,name=Data,proto3" json:"Data,omitempty"` - Enforcer string `protobuf:"bytes,28,opt,name=Enforcer,proto3" json:"Enforcer,omitempty"` - Action string `protobuf:"bytes,22,opt,name=Action,proto3" json:"Action,omitempty"` - Result string `protobuf:"bytes,23,opt,name=Result,proto3" json:"Result,omitempty"` - Cwd string `protobuf:"bytes,32,opt,name=Cwd,proto3" json:"Cwd,omitempty"` - TTY string `protobuf:"bytes,33,opt,name=TTY,proto3" json:"TTY,omitempty"` + Timestamp int64 `protobuf:"varint,1,opt,name=Timestamp,proto3" json:"Timestamp,omitempty"` + UpdatedTime string `protobuf:"bytes,2,opt,name=UpdatedTime,proto3" json:"UpdatedTime,omitempty"` + ClusterName string `protobuf:"bytes,3,opt,name=ClusterName,proto3" json:"ClusterName,omitempty"` + HostName string `protobuf:"bytes,4,opt,name=HostName,proto3" json:"HostName,omitempty"` + NamespaceName string `protobuf:"bytes,5,opt,name=NamespaceName,proto3" json:"NamespaceName,omitempty"` + Owner *Podowner `protobuf:"bytes,31,opt,name=Owner,proto3" json:"Owner,omitempty"` + PodName string `protobuf:"bytes,6,opt,name=PodName,proto3" json:"PodName,omitempty"` + Labels string `protobuf:"bytes,29,opt,name=Labels,proto3" json:"Labels,omitempty"` + ContainerID string `protobuf:"bytes,7,opt,name=ContainerID,proto3" json:"ContainerID,omitempty"` + ContainerName string `protobuf:"bytes,8,opt,name=ContainerName,proto3" json:"ContainerName,omitempty"` + ContainerImage string `protobuf:"bytes,24,opt,name=ContainerImage,proto3" json:"ContainerImage,omitempty"` + HostPPID int32 `protobuf:"varint,27,opt,name=HostPPID,proto3" json:"HostPPID,omitempty"` + HostPID int32 `protobuf:"varint,9,opt,name=HostPID,proto3" json:"HostPID,omitempty"` + PPID int32 `protobuf:"varint,10,opt,name=PPID,proto3" json:"PPID,"` + PID int32 `protobuf:"varint,11,opt,name=PID,proto3" json:"PID,omitempty"` + UID int32 `protobuf:"varint,12,opt,name=UID,proto3" json:"UID,"` + ParentProcessName string `protobuf:"bytes,25,opt,name=ParentProcessName,proto3" json:"ParentProcessName,omitempty"` + ProcessName string `protobuf:"bytes,26,opt,name=ProcessName,proto3" json:"ProcessName,omitempty"` + PolicyName string `protobuf:"bytes,13,opt,name=PolicyName,proto3" json:"PolicyName,omitempty"` + Severity string `protobuf:"bytes,14,opt,name=Severity,proto3" json:"Severity,omitempty"` + Tags string `protobuf:"bytes,15,opt,name=Tags,proto3" json:"Tags,omitempty"` + ATags []string `protobuf:"bytes,30,rep,name=ATags,proto3" json:"ATags,omitempty"` + Message string `protobuf:"bytes,16,opt,name=Message,proto3" json:"Message,omitempty"` + Type string `protobuf:"bytes,17,opt,name=Type,proto3" json:"Type,omitempty"` + Source string `protobuf:"bytes,18,opt,name=Source,proto3" json:"Source,omitempty"` + Operation string `protobuf:"bytes,19,opt,name=Operation,proto3" json:"Operation,omitempty"` + Resource string `protobuf:"bytes,20,opt,name=Resource,proto3" json:"Resource,omitempty"` + Data string `protobuf:"bytes,21,opt,name=Data,proto3" json:"Data,omitempty"` + Enforcer string `protobuf:"bytes,28,opt,name=Enforcer,proto3" json:"Enforcer,omitempty"` + Action string `protobuf:"bytes,22,opt,name=Action,proto3" json:"Action,omitempty"` + Result string `protobuf:"bytes,23,opt,name=Result,proto3" json:"Result,omitempty"` + Cwd string `protobuf:"bytes,32,opt,name=Cwd,proto3" json:"Cwd,omitempty"` + TTY string `protobuf:"bytes,33,opt,name=TTY,proto3" json:"TTY,omitempty"` + MaxAlertsPerSec int32 `protobuf:"varint,34,opt,name=MaxAlertsPerSec,proto3" json:"MaxAlertsPerSec,omitempty"` + DroppingAlertsInterval int32 `protobuf:"varint,35,opt,name=DroppingAlertsInterval,proto3" json:"DroppingAlertsInterval,omitempty"` } func (x *Alert) Reset() { @@ -540,6 +542,20 @@ func (x *Alert) GetTTY() string { return "" } +func (x *Alert) GetMaxAlertsPerSec() int32 { + if x != nil { + return x.MaxAlertsPerSec + } + return 0 +} + +func (x *Alert) GetDroppingAlertsInterval() int32 { + if x != nil { + return x.DroppingAlertsInterval + } + return 0 +} + // log struct type Log struct { state protoimpl.MessageState @@ -910,7 +926,7 @@ var file_kubearmor_proto_rawDesc = []byte{ 0x52, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x9d, 0x07, 0x0a, 0x05, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x12, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0xff, 0x07, 0x0a, 0x05, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x20, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, @@ -968,77 +984,83 @@ var file_kubearmor_proto_rawDesc = []byte{ 0x75, 0x6c, 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x43, 0x77, 0x64, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x43, 0x77, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x54, 0x59, 0x18, 0x21, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x54, 0x54, 0x59, 0x22, 0xe7, 0x05, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, 0x1c, 0x0a, - 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x20, 0x0a, 0x0b, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x20, 0x0a, - 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x1a, 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x26, 0x0a, 0x05, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, 0x50, 0x6f, 0x64, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x52, 0x05, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x6f, 0x64, - 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x50, 0x6f, 0x64, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x17, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x24, 0x0a, - 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x49, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x50, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, - 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, - 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x50, 0x72, 0x6f, - 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x48, - 0x6f, 0x73, 0x74, 0x50, 0x50, 0x49, 0x44, 0x18, 0x16, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x48, - 0x6f, 0x73, 0x74, 0x50, 0x50, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x48, 0x6f, 0x73, 0x74, 0x50, - 0x49, 0x44, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x49, - 0x44, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x50, 0x49, 0x44, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x04, 0x50, 0x50, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x50, 0x49, 0x44, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x03, 0x50, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x49, 0x44, 0x18, 0x0c, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x55, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, - 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, - 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, - 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x44, - 0x61, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x12, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x43, - 0x77, 0x64, 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x43, 0x77, 0x64, 0x12, 0x10, 0x0a, - 0x03, 0x54, 0x54, 0x59, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x54, 0x54, 0x59, 0x22, - 0x28, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x16, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x26, 0x0a, 0x0c, 0x52, 0x65, 0x70, - 0x6c, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x74, - 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x52, 0x65, 0x74, 0x76, 0x61, - 0x6c, 0x32, 0xef, 0x01, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x39, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, - 0x14, 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x14, 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, 0x52, - 0x65, 0x70, 0x6c, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3a, 0x0a, 0x0d, 0x57, - 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x66, - 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x1a, 0x0f, 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x30, 0x01, 0x12, 0x36, 0x0a, 0x0b, 0x57, 0x61, 0x74, 0x63, 0x68, - 0x41, 0x6c, 0x65, 0x72, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x0d, - 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x30, 0x01, 0x12, - 0x32, 0x0a, 0x09, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x66, - 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x1a, 0x0b, 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, 0x4c, 0x6f, - 0x67, 0x30, 0x01, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x61, 0x72, 0x6d, 0x6f, 0x72, 0x2f, 0x4b, 0x75, 0x62, 0x65, - 0x41, 0x72, 0x6d, 0x6f, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x03, 0x54, 0x54, 0x59, 0x12, 0x28, 0x0a, 0x0f, 0x4d, 0x61, 0x78, 0x41, 0x6c, 0x65, 0x72, + 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x18, 0x22, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, + 0x4d, 0x61, 0x78, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x12, + 0x36, 0x0a, 0x16, 0x44, 0x72, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x41, 0x6c, 0x65, 0x72, 0x74, + 0x73, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x23, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x16, 0x44, 0x72, 0x6f, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x73, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0xe7, 0x05, 0x0a, 0x03, 0x4c, 0x6f, 0x67, 0x12, + 0x1c, 0x0a, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x20, 0x0a, + 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, + 0x20, 0x0a, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, + 0x0d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x18, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, 0x50, 0x6f, 0x64, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x52, 0x05, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x50, + 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x50, 0x6f, + 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, + 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x20, 0x0a, + 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, + 0x24, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, + 0x11, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, + 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, + 0x08, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x50, 0x49, 0x44, 0x18, 0x16, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x08, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x50, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x48, 0x6f, 0x73, + 0x74, 0x50, 0x49, 0x44, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x48, 0x6f, 0x73, 0x74, + 0x50, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x50, 0x49, 0x44, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x04, 0x50, 0x50, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x50, 0x49, 0x44, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x50, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x49, 0x44, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x55, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x54, + 0x79, 0x70, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x44, 0x61, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, + 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x10, 0x0a, + 0x03, 0x43, 0x77, 0x64, 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x43, 0x77, 0x64, 0x12, + 0x10, 0x0a, 0x03, 0x54, 0x54, 0x59, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x54, 0x54, + 0x59, 0x22, 0x28, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x26, 0x0a, 0x0c, 0x52, + 0x65, 0x70, 0x6c, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x52, + 0x65, 0x74, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x52, 0x65, 0x74, + 0x76, 0x61, 0x6c, 0x32, 0xef, 0x01, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x12, 0x14, 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, 0x4e, 0x6f, 0x6e, 0x63, 0x65, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x14, 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, + 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3a, 0x0a, + 0x0d, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x16, + 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x0f, 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x30, 0x01, 0x12, 0x36, 0x0a, 0x0b, 0x57, 0x61, 0x74, + 0x63, 0x68, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, + 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x1a, 0x0d, 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x30, + 0x01, 0x12, 0x32, 0x0a, 0x09, 0x57, 0x61, 0x74, 0x63, 0x68, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x16, + 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x0b, 0x2e, 0x66, 0x65, 0x65, 0x64, 0x65, 0x72, 0x2e, + 0x4c, 0x6f, 0x67, 0x30, 0x01, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x61, 0x72, 0x6d, 0x6f, 0x72, 0x2f, 0x4b, 0x75, + 0x62, 0x65, 0x41, 0x72, 0x6d, 0x6f, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/protobuf/kubearmor.proto b/protobuf/kubearmor.proto index 3a360edcc9..ad4e57daf4 100644 --- a/protobuf/kubearmor.proto +++ b/protobuf/kubearmor.proto @@ -75,6 +75,8 @@ message Alert { string Result = 23; string Cwd = 32; string TTY = 33; + int32 MaxAlertsPerSec = 34; + int32 DroppingAlertsInterval = 35; } // log struct diff --git a/protobuf/kubearmor_grpc.pb.go b/protobuf/kubearmor_grpc.pb.go index d0111374bd..c97d4115fb 100644 --- a/protobuf/kubearmor_grpc.pb.go +++ b/protobuf/kubearmor_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc v4.25.3 +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.19.4 // source: kubearmor.proto package protobuf @@ -18,13 +18,6 @@ import ( // Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 -const ( - LogService_HealthCheck_FullMethodName = "/feeder.LogService/HealthCheck" - LogService_WatchMessages_FullMethodName = "/feeder.LogService/WatchMessages" - LogService_WatchAlerts_FullMethodName = "/feeder.LogService/WatchAlerts" - LogService_WatchLogs_FullMethodName = "/feeder.LogService/WatchLogs" -) - // LogServiceClient is the client API for LogService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. @@ -46,7 +39,7 @@ func NewLogServiceClient(cc grpc.ClientConnInterface) LogServiceClient { func (c *logServiceClient) HealthCheck(ctx context.Context, in *NonceMessage, opts ...grpc.CallOption) (*ReplyMessage, error) { out := new(ReplyMessage) - err := c.cc.Invoke(ctx, LogService_HealthCheck_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/feeder.LogService/HealthCheck", in, out, opts...) if err != nil { return nil, err } @@ -54,7 +47,7 @@ func (c *logServiceClient) HealthCheck(ctx context.Context, in *NonceMessage, op } func (c *logServiceClient) WatchMessages(ctx context.Context, in *RequestMessage, opts ...grpc.CallOption) (LogService_WatchMessagesClient, error) { - stream, err := c.cc.NewStream(ctx, &LogService_ServiceDesc.Streams[0], LogService_WatchMessages_FullMethodName, opts...) + stream, err := c.cc.NewStream(ctx, &LogService_ServiceDesc.Streams[0], "/feeder.LogService/WatchMessages", opts...) if err != nil { return nil, err } @@ -86,7 +79,7 @@ func (x *logServiceWatchMessagesClient) Recv() (*Message, error) { } func (c *logServiceClient) WatchAlerts(ctx context.Context, in *RequestMessage, opts ...grpc.CallOption) (LogService_WatchAlertsClient, error) { - stream, err := c.cc.NewStream(ctx, &LogService_ServiceDesc.Streams[1], LogService_WatchAlerts_FullMethodName, opts...) + stream, err := c.cc.NewStream(ctx, &LogService_ServiceDesc.Streams[1], "/feeder.LogService/WatchAlerts", opts...) if err != nil { return nil, err } @@ -118,7 +111,7 @@ func (x *logServiceWatchAlertsClient) Recv() (*Alert, error) { } func (c *logServiceClient) WatchLogs(ctx context.Context, in *RequestMessage, opts ...grpc.CallOption) (LogService_WatchLogsClient, error) { - stream, err := c.cc.NewStream(ctx, &LogService_ServiceDesc.Streams[2], LogService_WatchLogs_FullMethodName, opts...) + stream, err := c.cc.NewStream(ctx, &LogService_ServiceDesc.Streams[2], "/feeder.LogService/WatchLogs", opts...) if err != nil { return nil, err } @@ -198,7 +191,7 @@ func _LogService_HealthCheck_Handler(srv interface{}, ctx context.Context, dec f } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: LogService_HealthCheck_FullMethodName, + FullMethod: "/feeder.LogService/HealthCheck", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(LogServiceServer).HealthCheck(ctx, req.(*NonceMessage)) diff --git a/tests/k8s_env/smoke/smoke_test.go b/tests/k8s_env/smoke/smoke_test.go index f2ce1e453c..f3aee3f410 100644 --- a/tests/k8s_env/smoke/smoke_test.go +++ b/tests/k8s_env/smoke/smoke_test.go @@ -330,5 +330,4 @@ var _ = Describe("Smoke", func() { Expect(alerts[0].Result).To(Equal("Passed")) }) }) - }) diff --git a/tests/k8s_env/throttling/res/ksp-wordpress-block-process.yaml b/tests/k8s_env/throttling/res/ksp-wordpress-block-process.yaml new file mode 100644 index 0000000000..f51892fa83 --- /dev/null +++ b/tests/k8s_env/throttling/res/ksp-wordpress-block-process.yaml @@ -0,0 +1,20 @@ +apiVersion: security.kubearmor.com/v1 +kind: KubeArmorPolicy +metadata: + name: ksp-wordpress-block-process + namespace: wordpress-mysql +spec: + severity: 3 + selector: + matchLabels: + app: wordpress + process: + matchPaths: + - path: /usr/bin/apt + - path: /usr/bin/apt-get + + # apt update + # apt-get update + + action: + Block diff --git a/tests/k8s_env/throttling/res/wordpress-mysql-deployment.yaml b/tests/k8s_env/throttling/res/wordpress-mysql-deployment.yaml new file mode 100644 index 0000000000..7dea05439e --- /dev/null +++ b/tests/k8s_env/throttling/res/wordpress-mysql-deployment.yaml @@ -0,0 +1,100 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: wordpress-mysql +--- +apiVersion: v1 +kind: Service +metadata: + name: wordpress + namespace: wordpress-mysql + labels: + app: wordpress +spec: + selector: + app: wordpress + type: NodePort + ports: + - port: 80 + targetPort: 80 + nodePort: 30080 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: wordpress + namespace: wordpress-mysql + labels: + app: wordpress +spec: + replicas: 1 + selector: + matchLabels: + app: wordpress + template: + metadata: + labels: + app: wordpress + # annotations: + # kubearmor-policy: enabled + # container.apparmor.security.beta.kubernetes.io/wordpress: localhost/kubearmor-wordpress-mysql-wordpress + spec: + containers: + - name: wordpress + image: wordpress:4.8-apache + env: + - name: WORDPRESS_DB_HOST + value: mysql + - name: WORDPRESS_DB_PASSWORD + value: root-password + securityContext: + allowPrivilegeEscalation: true + capabilities: + add: ["NET_RAW"] + ports: + - name: wordpress + containerPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: mysql + namespace: wordpress-mysql + labels: + app: mysql +spec: + selector: + app: mysql + ports: + - port: 3306 + targetPort: 3306 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mysql + namespace: wordpress-mysql + labels: + app: mysql +spec: + replicas: 1 + selector: + matchLabels: + app: mysql + template: + metadata: + labels: + app: mysql + # annotations: + # kubearmor-policy: enabled + # container.apparmor.security.beta.kubernetes.io/mysql: localhost/kubearmor-wordpress-mysql-mysql + spec: + containers: + - name: mysql + image: mysql:5.6 + env: + - name: MYSQL_ROOT_PASSWORD + value: root-password + ports: + - name: mysql + containerPort: 3306 diff --git a/tests/k8s_env/throttling/throttling_suite_test.go b/tests/k8s_env/throttling/throttling_suite_test.go new file mode 100644 index 0000000000..d4300fb516 --- /dev/null +++ b/tests/k8s_env/throttling/throttling_suite_test.go @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of KubeArmor + +package throttling_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestThrottling(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Throttling Suite") +} diff --git a/tests/k8s_env/throttling/throttling_test.go b/tests/k8s_env/throttling/throttling_test.go new file mode 100644 index 0000000000..bfacaa17d1 --- /dev/null +++ b/tests/k8s_env/throttling/throttling_test.go @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Authors of KubeArmor + +package throttling + +import ( + "fmt" + "time" + + . "github.com/kubearmor/KubeArmor/tests/util" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = BeforeSuite(func() { + // install wordpress-mysql app + err := K8sApply([]string{"res/wordpress-mysql-deployment.yaml"}) + Expect(err).To(BeNil()) + + // delete all KSPs + err = DeleteAllKsp() + Expect(err).To(BeNil()) +}) + +var _ = AfterSuite(func() { + // Delete wordpress-mysql app + err := K8sDelete([]string{"res/wordpress-mysql-deployment.yaml"}) + Expect(err).To(BeNil()) + DeleteKAConfigMap() +}) + +func getWpsqlPod(name string, ant string) string { + pods, err := K8sGetPods(name, "wordpress-mysql", []string{ant}, 60) + Expect(err).To(BeNil()) + Expect(len(pods)).To(Equal(1)) + return pods[0] +} + +var _ = Describe("Smoke", func() { + var wp string + + BeforeEach(func() { + wp = getWpsqlPod("wordpress-", "kubearmor-policy: enabled") + }) + + AfterEach(func() { + KarmorLogStop() + err := DeleteAllKsp() + Expect(err).To(BeNil()) + // wait for policy deletion + time.Sleep(5 * time.Second) + }) + + Describe("Alert Throttling", func() { + + It("enabled with new throttling conditions", func() { + // enable throttling and change throttling condition using configmap + cm := NewDefaultConfigMapData() + cm.AlertThrottling = "true" + cm.MaxAlertPerSec = "2" + cm.ThrottleSec = "60" + cm.Visibility = "process,network,file,capabilities" + err := cm.CreateKAConfigMap() // will create a configMap with new throttling condition + Expect(err).To(BeNil()) + + // Apply policy + err = K8sApplyFile("res/ksp-wordpress-block-process.yaml") + Expect(err).To(BeNil()) + + // Start Kubearmor Logs + err = KarmorLogStart("all", "wordpress-mysql", "AlertThreshold", wp) + Expect(err).To(BeNil()) + + // wait for policy creation + time.Sleep(5 * time.Second) + + sout, _, err := K8sExecInPod(wp, "wordpress-mysql", + []string{"bash", "-c", "count=0; while [ $count -lt 5 ]; do apt; count=$((count + 1)); done;"}) + Expect(err).To(BeNil()) + fmt.Printf("OUTPUT: %s\n", sout) + Expect(sout).To(MatchRegexp("apt.*Permission denied")) + + // check policy violation alert + _, alerts, err := KarmorGetLogs(5*time.Second, 1) + Expect(err).To(BeNil()) + fmt.Printf("throttling alert :%v\n", alerts) + Expect(len(alerts)).ToNot(Equal(0)) + Expect(alerts[0].Type).To(Equal("SystemEvent")) + Expect(alerts[0].Operation).To(Equal("AlertThreshold")) + + // Start Kubearmor Logs + err = KarmorLogStart("all", "wordpress-mysql", "", wp) + Expect(err).To(BeNil()) + + // check for throttling, alerts should not be genrated + sout, _, err = K8sExecInPod(wp, "wordpress-mysql", + []string{"bash", "-c", "apt update"}) + Expect(err).To(BeNil()) + fmt.Printf("---START---\n%s---END---\n", sout) + Expect(sout).To(MatchRegexp("apt.*Permission denied")) + + _, alerts, err = KarmorGetLogs(5*time.Second, 1) + Expect(err).To(BeNil()) + fmt.Printf("throttling alert :%v\n", alerts) + Expect(len(alerts)).To(BeNumerically("==", 0)) + }) + }) +}) diff --git a/tests/util/kartutil.go b/tests/util/kartutil.go index 3de0f43d30..467c10fa58 100644 --- a/tests/util/kartutil.go +++ b/tests/util/kartutil.go @@ -9,7 +9,6 @@ import ( "encoding/json" "errors" "fmt" - gomegaTypes "github.com/onsi/gomega/types" "math/rand" "os" "os/exec" @@ -17,6 +16,8 @@ import ( "strings" "time" + gomegaTypes "github.com/onsi/gomega/types" + kcV1 "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/api/security.kubearmor.com/v1" kcScheme "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/client/clientset/versioned/scheme" kc "github.com/kubearmor/KubeArmor/pkg/KubeArmorController/client/clientset/versioned/typed/security.kubearmor.com/v1" @@ -47,6 +48,9 @@ type ConfigMapData struct { DefaultFilePosture string DefaultCapabilitiesPosture string DefaultNetworkPosture string + AlertThrottling string + MaxAlertPerSec string + ThrottleSec string } // GetK8sClient function return instance of k8s client @@ -102,6 +106,9 @@ func NewDefaultConfigMapData() *ConfigMapData { data.DefaultFilePosture = "audit" data.DefaultCapabilitiesPosture = "audit" data.DefaultNetworkPosture = "audit" + data.AlertThrottling = "false" + data.MaxAlertPerSec = "10" + data.ThrottleSec = "30" return data } @@ -127,6 +134,9 @@ func (data *ConfigMapData) CreateKAConfigMap() error { "defaultFilePosture": data.DefaultFilePosture, "defaultCapabilitiesPosture": data.DefaultCapabilitiesPosture, "defaultNetworkPosture": data.DefaultNetworkPosture, + "alertThrottling": data.AlertThrottling, + "maxAlertPerSec": data.MaxAlertPerSec, + "throttleSec": data.ThrottleSec, }, }