Skip to content

Commit

Permalink
Merge branch 'main' into tesla/non-k8s/dynamic-config
Browse files Browse the repository at this point in the history
  • Loading branch information
Prateeknandle committed Dec 20, 2024
2 parents 6306430 + 6bd41e2 commit 435cafc
Show file tree
Hide file tree
Showing 70 changed files with 1,375 additions and 295 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci-latest-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
runs-on: ubuntu-latest-16-cores
permissions:
id-token: write
timeout-minutes: 120
timeout-minutes: 150
steps:
- uses: actions/checkout@v3
with:
Expand Down Expand Up @@ -109,7 +109,7 @@ jobs:
- name: Test KubeArmor using Ginkgo
run: |
go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo
make
ginkgo --vv --flake-attempts=10 --timeout=10m smoke/
working-directory: ./tests/k8s_env
timeout-minutes: 30

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci-test-ginkgo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ on:
- "tests/**"
- "protobuf/**"
- ".github/workflows/ci-test-ginkgo.yml"
- "examples/multiubuntu/build/**"
- "pkg/KubeArmorOperator/**"
- "deployments/helm/**"

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci-test-ubi-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ on:
- "tests/**"
- "protobuf/**"
- ".github/workflows/ci-test-ginkgo.yml"
- "examples/multiubuntu/build/**"
- "pkg/KubeArmorOperator/**"
- "deployments/helm/**"

Expand Down
5 changes: 0 additions & 5 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ jobs:
with:
results_file: results.sarif
results_format: sarif
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecard on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
repo_token: ${{ secrets.SCORECARD_TOKEN }}

# Public repositories:
# - Publish results to OpenSSF REST API for easy access by consumers
Expand Down
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ ENV KUBEARMOR_UBI=true

LABEL name="kubearmor" \
vendor="Accuknox" \
maintainer="Barun Acharya, Ramakant Sharma" \
version=${VERSION} \
release=${VERSION} \
summary="kubearmor container image based on redhat ubi" \
Expand Down Expand Up @@ -119,6 +120,7 @@ ENV KUBEARMOR_UBI=true

LABEL name="kubearmor" \
vendor="Accuknox" \
maintainer="Barun Acharya, Ramakant Sharma" \
version=${VERSION} \
release=${VERSION} \
summary="kubearmor container image based on redhat ubi" \
Expand Down
1 change: 1 addition & 0 deletions Dockerfile.init
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ ARG VERSION=latest

LABEL name="kubearmor-init" \
vendor="Accuknox" \
maintainer="Barun Acharya, Ramakant Sharma" \
version=${VERSION} \
release=${VERSION} \
summary="kubearmor-init container image based on redhat ubi" \
Expand Down
8 changes: 5 additions & 3 deletions KubeArmor/BPF/enforcer.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ int BPF_PROG(enforce_proc, struct linux_binprm *bprm, int ret) {
if (src_offset == NULL)
fromSourceCheck = false;

void *src_ptr = &src_buf->buf[*src_offset];
void *src_ptr;
if (src_buf->buf[*src_offset]) {
src_ptr = &src_buf->buf[*src_offset];
}
if (src_ptr == NULL)
fromSourceCheck = false;

Expand Down Expand Up @@ -152,10 +155,9 @@ int BPF_PROG(enforce_proc, struct linux_binprm *bprm, int ret) {
goto decision;
}


// match exec name
struct qstr d_name;
d_name = BPF_CORE_READ(f_path.dentry,d_name);
d_name = BPF_CORE_READ(f_path.dentry, d_name);
bpf_map_update_elem(&bufk, &two, z, BPF_ANY);
bpf_probe_read_str(pk->path, MAX_STRING_SIZE, d_name.name);

Expand Down
31 changes: 16 additions & 15 deletions KubeArmor/BPF/shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@ static inline void get_outer_key(struct outer_key *pokey,
struct task_struct *t) {
pokey->pid_ns = get_task_pid_ns_id(t);
pokey->mnt_ns = get_task_mnt_ns_id(t);
// TODO: Use cgroup ns as well for host process identification to support enforcement on deployments using hostpidns
// u32 cg_ns = BPF_CORE_READ(t, nsproxy, cgroup_ns, ns).inum;
// if (pokey->pid_ns == PROC_PID_INIT_INO && cg_ns == PROC_CGROUP_INIT_INO) {
if (pokey->pid_ns == PROC_PID_INIT_INO) {
pokey->pid_ns = 0;
pokey->mnt_ns = 0;
Expand All @@ -288,20 +291,13 @@ static __always_inline u32 init_context(event *event_data) {
event_data->host_ppid = get_task_ppid(task);
event_data->host_pid = bpf_get_current_pid_tgid() >> 32;

u32 pid = get_task_ns_tgid(task);
if (event_data->host_pid == pid) { // host
event_data->pid_id = 0;
event_data->mnt_id = 0;

event_data->ppid = get_task_ppid(task);
event_data->pid = bpf_get_current_pid_tgid() >> 32;
} else { // container
event_data->pid_id = get_task_pid_ns_id(task);
event_data->mnt_id = get_task_mnt_ns_id(task);
struct outer_key okey;
get_outer_key(&okey, task);
event_data->pid_id = okey.pid_ns;
event_data->mnt_id = okey.mnt_ns;

event_data->ppid = get_task_ns_ppid(task);
event_data->pid = pid;
}
event_data->ppid = get_task_ppid(task);
event_data->pid = get_task_ns_tgid(task);

event_data->uid = bpf_get_current_uid_gid();

Expand Down Expand Up @@ -487,10 +483,15 @@ static inline int match_and_enforce_path_hooks(struct path *f_path, u32 id,
if (src_offset == NULL)
fromSourceCheck = false;

void *ptr = &src_buf->buf[*src_offset];
void *src_ptr;
if (src_buf->buf[*src_offset]) {
src_ptr = &src_buf->buf[*src_offset];
}
if (src_ptr == NULL)
fromSourceCheck = false;

if (fromSourceCheck) {
bpf_probe_read_str(store->source, MAX_STRING_SIZE, ptr);
bpf_probe_read_str(store->source, MAX_STRING_SIZE, src_ptr);

val = bpf_map_lookup_elem(inner, store);

Expand Down
84 changes: 56 additions & 28 deletions KubeArmor/BPF/system_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,48 +609,68 @@ static __always_inline int save_context_to_buffer(bufs_t *bufs_p, void *ptr)
return 0;
}

static __always_inline int save_str_to_buffer(bufs_t *bufs_p, void *ptr)
{

static __always_inline int save_str_to_buffer(bufs_t *bufs_p, void *ptr) {
u32 *off = get_buffer_offset(DATA_BUF_TYPE);

if (off == NULL)
{
if (off == NULL) {
return -1;
}

if (*off > MAX_BUFFER_SIZE - MAX_STRING_SIZE - sizeof(int))
{
return 0; // no enough space
if (*off >= MAX_BUFFER_SIZE) {
return 0;
}

u8 type = STR_T;
bpf_probe_read(&(bufs_p->buf[*off & (MAX_BUFFER_SIZE - 1)]), 1, &type);
u32 type_pos = *off;
if (type_pos >= MAX_BUFFER_SIZE || type_pos + 1 > MAX_BUFFER_SIZE) {
return 0;
}

*off += 1;
if (MAX_BUFFER_SIZE - type_pos < (1 + sizeof(int) + 1)) {
return 0;
}

if (*off > MAX_BUFFER_SIZE - MAX_STRING_SIZE - sizeof(int))
{
return 0; // no enough space
u32 size_pos = type_pos + 1;
if (size_pos >= MAX_BUFFER_SIZE ||
size_pos + sizeof(int) > MAX_BUFFER_SIZE) {
return 0;
}

int sz = bpf_probe_read_str(&(bufs_p->buf[*off + sizeof(int)]), MAX_STRING_SIZE, ptr);
if (sz > 0)
{
if (*off > MAX_BUFFER_SIZE - sizeof(int))
{
return 0; // no enough space
}
u8 type_val = STR_T;
if (bpf_probe_read(&(bufs_p->buf[type_pos]), sizeof(u8), &type_val) < 0) {
return 0;
}

u32 str_pos = size_pos + sizeof(int);
if (str_pos >= MAX_BUFFER_SIZE || str_pos + MAX_STRING_SIZE > MAX_BUFFER_SIZE) {
return 0;
}

bpf_probe_read(&(bufs_p->buf[*off]), sizeof(int), &sz);
u32 remaining_space = MAX_BUFFER_SIZE - str_pos;
u32 read_size = remaining_space;
if (read_size > MAX_STRING_SIZE) {
read_size = MAX_STRING_SIZE;
}

*off += sz + sizeof(int);
set_buffer_offset(DATA_BUF_TYPE, *off);
if (read_size < MAX_STRING_SIZE) {
return 0;
}

return sz + sizeof(int);
int sz = bpf_probe_read_str(&(bufs_p->buf[str_pos]), read_size, ptr);
if (sz <= 0) {
return 0;
}

return 0;
if (bpf_probe_read(&(bufs_p->buf[size_pos]), sizeof(int), &sz) < 0) {
return 0;
}

u32 new_off = str_pos + sz;
if (new_off > MAX_BUFFER_SIZE) {
return 0;
}

set_buffer_offset(DATA_BUF_TYPE, new_off);

return sz + sizeof(int);
}

static __always_inline bool prepend_path(struct path *path, bufs_t *string_p, int buf_type)
Expand Down Expand Up @@ -1019,7 +1039,7 @@ static __always_inline u32 init_context(sys_context_t *context)
}
}

#if (defined(BTF_SUPPORTED))
#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 2, 0) // min version that supports 1 million instructions
struct fs_struct *fs;
fs = READ_KERN(task->fs);
struct path path = READ_KERN(fs->pwd);
Expand All @@ -1046,6 +1066,13 @@ 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 Expand Up @@ -1112,6 +1139,7 @@ static __always_inline bool should_drop_alerts_per_container(sys_context_t *cont
}

bpf_map_update_elem(&kubearmor_alert_throttle, &key, state, BPF_ANY);
#endif
return false;
}

Expand Down
8 changes: 8 additions & 0 deletions KubeArmor/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"sort"
"strconv"
"strings"
"sync"
"time"

kc "github.com/kubearmor/KubeArmor/KubeArmor/config"
Expand Down Expand Up @@ -291,7 +292,11 @@ func GetCommandOutputWithoutErr(cmd string, args []string) string {
return ""
}

var wg sync.WaitGroup
wg.Add(1)

go func() {
defer wg.Done()
defer func() {
if err = stdin.Close(); err != nil {
kg.Warnf("Error closing stdin %s\n", err)
Expand All @@ -300,6 +305,9 @@ func GetCommandOutputWithoutErr(cmd string, args []string) string {
_, _ = io.WriteString(stdin, "values written to stdin are passed to cmd's standard input")
}()

// Wait for the stdin writing to complete
wg.Wait()

out, err := res.CombinedOutput()
if err != nil {
return ""
Expand Down
21 changes: 15 additions & 6 deletions KubeArmor/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ 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
}

// GlobalCfg Global configuration for Kubearmor
Expand Down Expand Up @@ -105,6 +107,7 @@ const (
ConfigMaxAlertPerSec string = "maxAlertPerSec"
ConfigThrottleSec string = "throttleSec"
ConfigAnnotateResources string = "annotateResources"
ConfigProcFsMount string = "procfsMount"
)

func readCmdLineParams() {
Expand Down Expand Up @@ -161,6 +164,8 @@ func readCmdLineParams() {

annotateResources := flag.Bool(ConfigAnnotateResources, false, "for kubearmor deployment without kubearmor-controller")

procFsMount := flag.String(ConfigProcFsMount, "/proc", "Path to the BPF filesystem to use for storing maps")

flags := []string{}
flag.VisitAll(func(f *flag.Flag) {
kv := fmt.Sprintf("%s:%v", f.Name, f.Value)
Expand Down Expand Up @@ -222,6 +227,8 @@ func readCmdLineParams() {
viper.SetDefault(ConfigThrottleSec, *throttleSec)

viper.SetDefault(ConfigAnnotateResources, *annotateResources)

viper.SetDefault(ConfigProcFsMount, *procFsMount)
}

// LoadConfig Load configuration
Expand Down Expand Up @@ -297,6 +304,8 @@ func LoadConfig() error {

GlobalCfg.AnnotateResources = viper.GetBool(ConfigAnnotateResources)

GlobalCfg.ProcFsMount = viper.GetString(ConfigProcFsMount)

LoadDynamicConfig()

kg.Printf("Final Configuration [%+v]", GlobalCfg)
Expand Down Expand Up @@ -329,6 +338,6 @@ func LoadDynamicConfig() {
GlobalCfg.DefaultPostureLogs = viper.GetBool(ConfigDefaultPostureLogs)

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))
}
Loading

0 comments on commit 435cafc

Please sign in to comment.