Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,11 @@ jobs:
fail_ci_if_error: false

- name: Generate Rules CRD
run: |
chmod +x gen.sh
./gen.sh
run: make generate-rules-crd

- name: Upload Rules CRD as artifact
uses: actions/upload-artifact@v4
with:
name: rules-crd
path: rules-crd.yaml
retention-days: 30
retention-days: 30
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.PHONY: lint-projection
.PHONY: lint-projection generate-rules-crd

generate-rules-crd:
bash ./gen.sh

lint-projection:
go run ./cmd/lint-projection ./pkg/rules
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,13 @@ go test -v ./pkg/rules/r0001-unexpected-process-launched/

## Rule Generation Script

The `gen.sh` script automatically combines all individual rule YAML files into a single CRD instance.
The `gen.sh` script automatically combines all individual rule YAML files into a single CRD instance. The
recommended entrypoint is the Make target below, which wraps the script.

### Usage

```bash
./gen.sh
make generate-rules-crd
```

### What it does
Expand Down Expand Up @@ -153,7 +154,7 @@ spec:
2. **Write the rule YAML** with proper CEL expressions
3. **Add comprehensive tests** in `rule_test.go`
4. **Test your rule** with `go test -v ./pkg/rules/your-rule/`
5. **Generate the combined CRD** with `./gen.sh`
5. **Generate the combined CRD** with `make generate-rules-crd`
6. **Deploy** the generated `rules-crd.yaml` to your Kubernetes cluster

## Testing
Expand All @@ -170,7 +171,7 @@ go test -v ./pkg/rules/r0001-unexpected-process-launched/

### Test the generation script
```bash
./gen.sh
make generate-rules-crd
# Check the generated rules-crd.yaml file
```

Expand Down
5 changes: 4 additions & 1 deletion pkg/rules/r1006-unshare-syscall/unshare-syscall.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ spec:
ruleExpression:
- eventType: "unshare"
expression: "event.pcomm != 'runc' && !ap.was_syscall_used(event.containerId, 'unshare')"
profileDependency: 2
profileDependency: 1
profileDataRequired:
syscalls:
- exact: "unshare"
severity: 5
supportPolicy: false
isTriggerAlert: true
Expand Down
65 changes: 64 additions & 1 deletion rules-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ spec:
- eventType: "exec"
expression: "!ap.was_executed(event.containerId, parse.get_exec_path(event.args, event.comm))"
profileDependency: 0
profileDataRequired:
execs: all
severity: 1
supportPolicy: false
isTriggerAlert: true
Expand Down Expand Up @@ -60,6 +62,20 @@ spec:
&&
!ap.was_path_opened(event.containerId, event.path)
profileDependency: 0
profileDataRequired:
opens:
- prefix: "/etc/"
- prefix: "/var/log/"
- prefix: "/var/run/"
- prefix: "/run/"
- prefix: "/var/spool/cron/"
- prefix: "/var/www/"
- prefix: "/var/lib/"
- prefix: "/opt/"
- prefix: "/usr/local/"
- prefix: "/app/"
- exact: "/.dockerenv"
- exact: "/proc/self/environ"
severity: 1
supportPolicy: false
isTriggerAlert: false
Expand All @@ -82,6 +98,8 @@ spec:
- eventType: "syscall"
expression: "!ap.was_syscall_used(event.containerId, event.syscallName)"
profileDependency: 0
profileDataRequired:
syscalls: all
severity: 1
supportPolicy: false
isTriggerAlert: false
Expand All @@ -103,6 +121,8 @@ spec:
- eventType: "capabilities"
expression: "!ap.was_capability_used(event.containerId, event.capName)"
profileDependency: 0
profileDataRequired:
capabilities: all
severity: 1
supportPolicy: false
isTriggerAlert: false
Expand All @@ -124,6 +144,8 @@ spec:
- eventType: "dns"
expression: "!event.name.endsWith('.svc.cluster.local.') && !nn.is_domain_in_egress(event.containerId, event.name)"
profileDependency: 0
profileDataRequired:
egressDomains: all
severity: 1
supportPolicy: false
isTriggerAlert: false
Expand Down Expand Up @@ -154,6 +176,9 @@ spec:
- /run/secrets
- /var/run/secrets
profileDependency: 0
profileDataRequired:
opens:
- suffix: "/token"
severity: 5
supportPolicy: false
isTriggerAlert: true
Expand All @@ -177,6 +202,9 @@ spec:
- eventType: "network"
expression: "event.pktType == 'OUTGOING' && k8s.is_api_server_address(event.dstAddr) && !nn.was_address_in_egress(event.containerId, event.dstAddr)"
profileDependency: 0
profileDataRequired:
execs: all
egressAddresses: all
severity: 5 # Medium
supportPolicy: false
isTriggerAlert: false
Expand Down Expand Up @@ -205,6 +233,9 @@ spec:
includePrefixes:
- /proc
profileDependency: 0 # Required
profileDataRequired:
opens:
- suffix: "/environ"
severity: 5 # Medium
supportPolicy: false
isTriggerAlert: true
Expand All @@ -227,6 +258,9 @@ spec:
- eventType: "bpf"
expression: "event.cmd == uint(5) && !ap.was_syscall_used(event.containerId, 'bpf')"
profileDependency: 1
profileDataRequired:
syscalls:
- exact: "bpf"
severity: 5
supportPolicy: false
isTriggerAlert: true
Expand All @@ -249,6 +283,9 @@ spec:
- eventType: "open"
expression: "event.path.startsWith('/etc/shadow') && !ap.was_path_opened(event.containerId, event.path)"
profileDependency: 1
profileDataRequired:
opens:
- prefix: "/etc/shadow"
severity: 5
supportPolicy: false
isTriggerAlert: true
Expand All @@ -271,6 +308,8 @@ spec:
- eventType: "network"
expression: "event.pktType == 'OUTGOING' && !net.is_private_ip(event.dstAddr) && !nn.was_address_in_egress(event.containerId, event.dstAddr)"
profileDependency: 0
profileDataRequired:
egressAddresses: all
severity: 5 # Medium
supportPolicy: false
isTriggerAlert: false
Expand Down Expand Up @@ -321,6 +360,8 @@ spec:
event.pupperlayer == true) &&
!ap.was_executed(event.containerId, parse.get_exec_path(event.args, event.comm))
profileDependency: 1
profileDataRequired:
execs: all
severity: 8
supportPolicy: false
isTriggerAlert: true
Expand Down Expand Up @@ -367,6 +408,8 @@ spec:
- eventType: "ssh"
expression: "dyn(event.srcPort) >= 32768 && dyn(event.srcPort) <= 60999 && !(dyn(event.dstPort) in [22, 2022]) && !nn.was_address_in_egress(event.containerId, event.dstIp)"
profileDependency: 1
profileDataRequired:
egressAddresses: all
severity: 5
supportPolicy: false
isTriggerAlert: true
Expand All @@ -390,6 +433,8 @@ spec:
- eventType: "exec"
expression: "!ap.was_executed(event.containerId, parse.get_exec_path(event.args, event.comm)) && k8s.get_container_mount_paths(event.namespace, event.podName, event.containerName).exists(mount, event.exepath.startsWith(mount) || parse.get_exec_path(event.args, event.comm).startsWith(mount))"
profileDependency: 1
profileDataRequired:
execs: all
severity: 5
supportPolicy: false
isTriggerAlert: true
Expand Down Expand Up @@ -432,7 +477,10 @@ spec:
ruleExpression:
- eventType: "unshare"
expression: "event.pcomm != 'runc' && !ap.was_syscall_used(event.containerId, 'unshare')"
profileDependency: 2
profileDependency: 1
profileDataRequired:
syscalls:
- exact: "unshare"
severity: 5
supportPolicy: false
isTriggerAlert: true
Expand Down Expand Up @@ -505,6 +553,8 @@ spec:
- 3333
- 45700
profileDependency: 1
profileDataRequired:
egressAddresses: all
severity: 3
supportPolicy: false
isTriggerAlert: false
Expand All @@ -529,6 +579,10 @@ spec:
- eventType: "symlink"
expression: "(event.oldPath.startsWith('/etc/shadow') || event.oldPath.startsWith('/etc/sudoers')) && !ap.was_path_opened(event.containerId, event.oldPath)"
profileDependency: 1
profileDataRequired:
opens:
- prefix: "/etc/shadow"
- prefix: "/etc/sudoers"
severity: 5
supportPolicy: true
isTriggerAlert: true
Expand All @@ -553,6 +607,9 @@ spec:
- eventType: "open"
expression: "event.path == '/etc/ld.so.preload' && has(event.flagsRaw) && event.flagsRaw != 0"
profileDependency: 1
profileDataRequired:
opens:
- exact: "/etc/ld.so.preload"
severity: 5
supportPolicy: true
isTriggerAlert: true
Expand All @@ -574,6 +631,10 @@ spec:
- eventType: "hardlink"
expression: "(event.oldPath.startsWith('/etc/shadow') || event.oldPath.startsWith('/etc/sudoers')) && !ap.was_path_opened(event.containerId, event.oldPath)"
profileDependency: 1
profileDataRequired:
opens:
- prefix: "/etc/shadow"
- prefix: "/etc/sudoers"
severity: 5
supportPolicy: true
isTriggerAlert: true
Expand Down Expand Up @@ -616,6 +677,8 @@ spec:
- eventType: "iouring"
expression: "true"
profileDependency: 0
profileDataRequired:
syscalls: all
severity: 5
supportPolicy: true
isTriggerAlert: true
Expand Down
Loading