-
Notifications
You must be signed in to change notification settings - Fork 1
feat(#170): tune all seven argocd SBoBs to score 0 #178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0184a4c
10c03af
c8d5b1e
1385409
89a105b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -88,10 +88,6 @@ attacks: | |
| ruleName: Unexpected process launched | ||
| containerName: argocd-server | ||
| command: cat | ||
| - ruleID: R0010 | ||
| ruleName: Unexpected Sensitive File Access | ||
| containerName: argocd-server | ||
| command: cat | ||
|
|
||
| # ── T1552 — symlink over a sensitive file ─────────────────────────────────── | ||
| - name: exec-symlink-shadow | ||
|
|
@@ -198,8 +194,7 @@ attacks: | |
| type: cmdinject | ||
| exec: { command: ["sh", "-c", "ln /etc/shadow /tmp/shadow.hl >/dev/null 2>&1 && echo hardlink_done; rm -f /tmp/shadow.hl"] } | ||
| successIndicators: [{ responseContains: "hardlink_done" }] | ||
| expectedDetections: | ||
| - { ruleID: R1012, ruleName: Hard link created over sensitive file, containerName: argocd-server, command: ln } | ||
| expectedDetections: [] | ||
| - name: ebpf-program-load | ||
| type: cmdinject | ||
| exec: { command: ["perl", "-e", "syscall(321,5,0,0); print qq{bpf_probe_done}"] } | ||
|
|
@@ -224,7 +219,7 @@ attacks: | |
| - { ruleID: R1004, ruleName: Process executed from mount, containerName: argocd-server } | ||
| - name: fileless-memfd-exec | ||
| type: fileless | ||
| exec: { command: ["perl", "-e", "my $n=\"bobfl\0\"; my $fd=syscall(319,$n,0); die if $fd<0; open(my $m,'>&='.$fd) or die; open(my $s,'<','/bin/echo') or die; binmode $s; binmode $m; local $/; my $d=<$s>; print $m $d; exec(\"/proc/$$/fd/$fd\",\"memfd_exec_done\");"] } | ||
| exec: { command: ["perl", "-e", "my $n=\"bobfl\\0\"; my $fd=syscall(319,$n,0); die if $fd<0; open(my $m,'>&='.$fd) or die; open(my $s,'<','/bin/echo') or die; binmode $s; binmode $m; local $/; my $d=<$s>; print $m $d; exec(\"/proc/$$/fd/$fd\",\"memfd_exec_done\");"] } | ||
| successIndicators: [{ responseContains: "memfd_exec_done" }] | ||
| expectedDetections: | ||
| - { ruleID: R1005, ruleName: Fileless execution detected, containerName: argocd-server } | ||
|
Comment on lines
220
to
225
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Remove the unavailable The PR objective states that 🤖 Prompt for AI Agents |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| #!/usr/bin/env bash | ||
| # Argo CD SBoB demo — deploy Argo CD and optionally bind every component SBoB. | ||
| # ./distro.sh # deploy only (make deploy-argocd) | ||
| # ./distro.sh sbob # deploy AND bind every SBoB in sbobs/ | ||
| # ./distro.sh unbind # drop the bind label so the components LEARN again | ||
| set -euo pipefail | ||
| cd "$(dirname "$0")" | ||
| MODE="${1:-}" | ||
| NS=argocd | ||
| LABEL="kubescape.io/user-defined-profile" | ||
|
|
||
| deploy() { make -C ../.. deploy-argocd; } | ||
|
|
||
| # The workload that owns each component's pods. argocd-application-controller is | ||
| # a StatefulSet; everything else is a Deployment. | ||
| workload_for() { | ||
| case "$1" in | ||
| argocd-application-controller) echo "statefulset/$1" ;; | ||
| *) echo "deployment/$1" ;; | ||
| esac | ||
| } | ||
|
|
||
| bind() { | ||
| local bound=0 missing=0 total | ||
| total=$(ls sbobs/cp-argocd-*.yaml | wc -l) | ||
| for f in sbobs/cp-argocd-*.yaml; do | ||
| local name wl | ||
| name=$(basename "$f" .yaml); name="${name#cp-}" | ||
| wl=$(workload_for "$name") | ||
| if ! kubectl -n "$NS" get "$wl" >/dev/null 2>&1; then | ||
| echo " $name: no $wl — skipped" | ||
| missing=$((missing + 1)); continue | ||
| fi | ||
| kubectl apply -f "$f" >/dev/null | ||
| # The label goes on the POD TEMPLATE: node-agent binds a profile when the | ||
| # container starts, so the workload has to roll for the bind to take. | ||
| kubectl -n "$NS" patch "$wl" --type merge \ | ||
| -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"$LABEL\":\"$name\"}}}}}" >/dev/null | ||
| bound=$((bound + 1)) | ||
| done | ||
| echo "bound=$bound missing=$missing total=$total" | ||
| for f in sbobs/cp-argocd-*.yaml; do | ||
| local name wl | ||
| name=$(basename "$f" .yaml); name="${name#cp-}" | ||
| wl=$(workload_for "$name") | ||
| kubectl -n "$NS" get "$wl" >/dev/null 2>&1 || continue | ||
| kubectl -n "$NS" rollout status "$wl" --timeout=300s >/dev/null 2>&1 || true | ||
| done | ||
| kubectl -n "$NS" get pods \ | ||
| -o custom-columns=POD:.metadata.name,PROFILE:.metadata.labels."$LABEL" --no-headers | ||
| } | ||
|
|
||
| # Learning and enforcement are mutually exclusive: while the label is set | ||
| # node-agent applies the supplied profile instead of recording one, so a | ||
| # re-learn has to drop it first. | ||
| unbind() { | ||
| for f in sbobs/cp-argocd-*.yaml; do | ||
| local name wl | ||
| name=$(basename "$f" .yaml); name="${name#cp-}" | ||
| wl=$(workload_for "$name") | ||
| kubectl -n "$NS" get "$wl" >/dev/null 2>&1 || continue | ||
| kubectl -n "$NS" patch "$wl" --type merge \ | ||
| -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"$LABEL\":null}}}}}" >/dev/null | ||
| done | ||
| echo "unbound; roll the workloads to start recording" | ||
| } | ||
|
|
||
| case "$MODE" in | ||
| sbob) deploy; bind ;; | ||
| unbind) unbind ;; | ||
| "") deploy ;; | ||
| *) echo "usage: $0 [sbob|unbind]" >&2; exit 2 ;; | ||
| esac |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Restore the applicable
R0001assertion at each shadow probe.The change should remove
R0010, not the process-launch detection. A failed/etc/shadowopen occurs aftercatlaunches.example/argocd-application-controller-attacks.yaml#L36-L39: retainR0001forcat.example/argocd-applicationset-controller-attacks.yaml#L36-L39: retainR0001forcat.example/argocd-dex-server-attacks.yaml#L28-L31: retainR0001forcat.example/argocd-notifications-controller-attacks.yaml#L36-L39: retainR0001forcat.example/argocd-repo-server-attacks.yaml#L111-L114: retainR0001for non-baselinecat.📍 Affects 5 files
example/argocd-application-controller-attacks.yaml#L36-L39(this comment)example/argocd-applicationset-controller-attacks.yaml#L36-L39example/argocd-dex-server-attacks.yaml#L28-L31example/argocd-notifications-controller-attacks.yaml#L36-L39example/argocd-repo-server-attacks.yaml#L111-L114🤖 Prompt for AI Agents