npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
NIST CSF 2.0
MITRE ATLAS
When to Use
- When deploying kernel-level runtime security monitoring on Linux hosts or Kubernetes clusters
- When you need sub-millisecond visibility into process execution, network connections, and file access
- When traditional userspace monitoring tools introduce unacceptable performance overhead
- When building detection pipelines that require in-kernel filtering before events reach userspace
- When enforcing runtime security policies (kill process, send signal) at the kernel level
Prerequisites
- Linux kernel 5.3+ with BTF (BPF Type Format) support enabled
- Kubernetes 1.24+ cluster (for Kubernetes deployment) or standalone Linux host
- Helm 3.x installed (for Kubernetes deployment)
kubectlconfigured with cluster accesstetraCLI installed for local event streaming- Python 3.8+ with
requests,kubernetes,pyyamldependencies - Root or CAP_BPF/CAP_SYS_ADMIN capabilities for eBPF program loading
Instructions
1. Install Tetragon on Kubernetes
Deploy Tetragon via Helm to get default process lifecycle observability:
helm repo add cilium https://helm.cilium.io
helm repo update
helm install tetragon cilium/tetragon -n kube-system \
--set tetragon.enableProcessCred=true \
--set tetragon.enableProcessNs=trueVerify the installation:
kubectl get pods -n kube-system -l app.kubernetes.io/name=tetragon
kubectl logs -n kube-system -l app.kubernetes.io/name=tetragon -c export-stdout -f | head -202. Install Tetragon on Standalone Linux
For non-Kubernetes Linux hosts, install from the tarball release:
curl -LO https://github.com/cilium/tetragon/releases/latest/download/tetragon-linux-amd64.tar.gz
tar xzf tetragon-linux-amd64.tar.gz
sudo cp tetragon /usr/local/bin/
sudo cp tetra /usr/local/bin/
# Start tetragon daemon
sudo tetragon --btf /sys/kernel/btf/vmlinux &
# Stream events
tetra getevents -o compact3. Monitor Process Execution (Default)
Tetragon generates process_exec and process_exit events by default without any TracingPolicy:
# Stream process events in compact format
tetra getevents -o compact
# Stream in JSON for SIEM ingestion
tetra getevents -o json | jq '.process_exec // .process_exit'Example process_exec JSON event:
{
"process_exec": {
"process": {
"binary": "/usr/bin/curl",
"arguments": "https://malicious.example.com/payload",
"cwd": "/tmp",
"uid": 1000,
"pod": {
"namespace": "default",
"name": "webapp-7b4d9f8c6-x2k9p"
},
"parent": {
"binary": "/bin/bash",
"pid": 1234
}
}
}
}4. Author TracingPolicy for File Access Monitoring
Create a TracingPolicy CRD to monitor access to sensitive files via the sys_openat kprobe:
# file-access-monitor.yaml
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: monitor-sensitive-file-access
spec:
kprobes:
- call: "fd_install"
syscall: false
args:
- index: 0
type: "int"
- index: 1
type: "file"
selectors:
- matchArgs:
- index: 1
operator: "Prefix"
values:
- "/etc/shadow"
- "/etc/passwd"
- "/etc/sudoers"
- "/root/.ssh/"
- "/etc/kubernetes/pki/"
matchActions:
- action: PostApply and observe:
kubectl apply -f file-access-monitor.yaml
tetra getevents -o compact --process-filter "event_set:PROCESS_KPROBE"5. Author TracingPolicy for Network Connection Monitoring
Monitor outbound TCP connections using the tcp_connect kprobe:
# network-monitor.yaml
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: monitor-tcp-connections
spec:
kprobes:
- call: "tcp_connect"
syscall: false
args:
- index: 0
type: "sock"
selectors:
- matchActions:
- action: Post6. Author TracingPolicy for Privilege Escalation Detection
Detect setuid/setgid calls that may indicate privilege escalation:
# privilege-escalation-detect.yaml
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: detect-privilege-escalation
spec:
kprobes:
- call: "__sys_setuid"
syscall: false
args:
- index: 0
type: "int"
selectors:
- matchArgs:
- index: 0
operator: "Equal"
values:
- "0"
matchActions:
- action: Post
- call: "commit_creds"
syscall: false
args:
- index: 0
type: "cred"
selectors:
- matchActions:
- action: Post7. Runtime Enforcement with Sigkill Action
Block unauthorized binary execution by killing the process in-kernel:
# enforce-binary-allowlist.yaml
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: enforce-no-crypto-miners
spec:
kprobes:
- call: "sys_execve"
syscall: true
args:
- index: 0
type: "string"
selectors:
- matchArgs:
- index: 0
operator: "Postfix"
values:
- "xmrig"
- "minerd"
- "cpuminer"
- "cryptonight"
matchActions:
- action: Sigkill8. Export Events to SIEM
Configure Tetragon to export JSON events to a file sink for Fluentd/Filebeat/Vector ingestion:
# Helm values for file export
helm upgrade tetragon cilium/tetragon -n kube-system \
--set tetragon.exportFilename=/var/log/tetragon/tetragon.log \
--set tetragon.exportFileMaxSizeMB=100 \
--set tetragon.exportFileMaxBackups=5Then configure your log shipper (e.g., Filebeat) to tail /var/log/tetragon/tetragon.log and send to your SIEM.
9. Kubernetes-Aware Namespace Filtering
Use TracingPolicyNamespaced to scope monitoring to specific namespaces:
apiVersion: cilium.io/v1alpha1
kind: TracingPolicyNamespaced
metadata:
name: monitor-production-file-access
namespace: production
spec:
kprobes:
- call: "fd_install"
syscall: false
args:
- index: 0
type: "int"
- index: 1
type: "file"
selectors:
- matchArgs:
- index: 1
operator: "Prefix"
values:
- "/etc/shadow"
- "/etc/passwd"Examples
Detect Reverse Shell Connections
# reverse-shell-detect.yaml
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: detect-reverse-shells
spec:
kprobes:
- call: "tcp_connect"
syscall: false
args:
- index: 0
type: "sock"
selectors:
- matchBinaries:
- operator: "In"
values:
- "/bin/bash"
- "/bin/sh"
- "/usr/bin/python3"
- "/usr/bin/perl"
- "/usr/bin/nc"
- "/usr/bin/ncat"
matchActions:
- action: PostMonitor Container Escape Attempts
# container-escape-detect.yaml
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: detect-container-escape
spec:
kprobes:
- call: "sys_openat"
syscall: true
args:
- index: 0
type: "int"
- index: 1
type: "string"
selectors:
- matchArgs:
- index: 1
operator: "Prefix"
values:
- "/proc/1/root"
- "/proc/1/ns"
- "/sys/kernel/security"
- "/proc/sysrq-trigger"
matchActions:
- action: Post
- call: "sys_mount"
syscall: true
args:
- index: 0
type: "string"
- index: 1
type: "string"
- index: 2
type: "string"
selectors:
- matchActions:
- action: PostFull Event Pipeline: Tetragon to Elasticsearch
# Use tetra CLI to pipe events through jq into Elasticsearch
tetra getevents -o json | jq -c 'select(.process_kprobe != null)' | \
while IFS= read -r line; do
curl -s -X POST "http://elasticsearch:9200/tetragon-events/_doc" \
-H "Content-Type: application/json" \
-d "$line"
doneReferences and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md5.4 KB
API Reference: Implementing eBPF Security Monitoring with Tetragon
Tetragon Installation (Helm)
# Add Cilium Helm repo
helm repo add cilium https://helm.cilium.io
helm repo update
# Install with recommended security settings
helm install tetragon cilium/tetragon -n kube-system \
--set tetragon.enableProcessCred=true \
--set tetragon.enableProcessNs=true \
--set tetragon.exportFilename=/var/log/tetragon/tetragon.log
# Standalone Linux (non-Kubernetes)
curl -LO https://github.com/cilium/tetragon/releases/latest/download/tetragon-linux-amd64.tar.gz
sudo tetragon --btf /sys/kernel/btf/vmlinuxTracingPolicy CRD Schema
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy # or TracingPolicyNamespaced
metadata:
name: policy-name
spec:
kprobes: # List of kprobe hooks
- call: "function_name" # Kernel function to hook
syscall: true|false # Whether this is a syscall
args: # Arguments to capture
- index: 0
type: "string|int|fd|file|sock|cred|char_buf|size_t"
selectors: # In-kernel filtering
- matchArgs:
- index: 0
operator: "Equal|NotEqual|Prefix|Postfix|Mask|In|NotIn"
values: ["value1", "value2"]
matchBinaries:
- operator: "In|NotIn"
values: ["/usr/bin/binary"]
matchActions:
- action: "Post|Sigkill|Signal|Override|FollowFD|CopyFD"Common Kprobe Hook Points
| Hook Function | Syscall | Use Case |
|---|---|---|
sys_execve |
true | Process execution monitoring |
fd_install |
false | File descriptor / file open monitoring |
sys_openat |
true | File open with path |
sys_write |
true | File write monitoring |
tcp_connect |
false | Outbound TCP connections |
tcp_sendmsg |
false | TCP data sent |
__sys_setuid |
false | Privilege escalation (setuid) |
commit_creds |
false | Credential changes |
sys_mount |
true | Filesystem mount operations |
sys_ptrace |
true | Process tracing / debugging |
Argument Types
| Type | Description |
|---|---|
string |
Null-terminated string |
int |
Integer value |
fd |
File descriptor (resolved to path) |
file |
File structure (includes path) |
sock |
Socket structure (includes IP/port) |
cred |
Credentials structure (uid/gid) |
char_buf |
Character buffer (requires sizeArgIndex) |
size_t |
Size type |
Selector Operators
| Operator | Description | Example |
|---|---|---|
Equal |
Exact match | values: ["0"] |
NotEqual |
Not equal | values: ["0"] |
Prefix |
String prefix | values: ["/etc/"] |
Postfix |
String suffix | values: ["xmrig"] |
Mask |
Bitmask match | values: ["0x1"] |
In |
Value in set | values: ["/bin/bash", "/bin/sh"] |
NotIn |
Value not in set | values: ["/usr/sbin/sshd"] |
Match Actions
| Action | Description |
|---|---|
Post |
Emit event to userspace (default) |
Sigkill |
Kill the process immediately |
Signal |
Send specified signal |
Override |
Override return value |
FollowFD |
Track file descriptor across calls |
CopyFD |
Copy file descriptor info |
tetra CLI Commands
# Stream events in compact format
tetra getevents -o compact
# Stream events in JSON
tetra getevents -o json
# Filter by namespace
tetra getevents -o compact --namespace production
# Filter by pod
tetra getevents -o compact --pod webapp-7b4d9f8c6-x2k9p
# Health check
tetra status
# Version
tetra versionTetragon gRPC API
service FineGuidanceSensors {
rpc GetEvents(GetEventsRequest) returns (stream GetEventsResponse) {}
rpc GetHealth(GetHealthStatusRequest) returns (GetHealthStatusResponse) {}
}JSON Event Types
// process_exec event
{
"process_exec": {
"process": {
"exec_id": "abc123",
"pid": 1234,
"uid": 1000,
"binary": "/usr/bin/curl",
"arguments": "-O https://example.com/file",
"cwd": "/tmp",
"start_time": "2026-01-15T10:30:00Z",
"pod": {"namespace": "default", "name": "webapp-xxx"},
"parent": {"binary": "/bin/bash", "pid": 1200}
}
}
}
// process_kprobe event (triggered by TracingPolicy)
{
"process_kprobe": {
"process": {"binary": "/usr/bin/cat", "pid": 5678},
"policy_name": "monitor-sensitive-file-access",
"function_name": "fd_install",
"args": [
{"file_arg": {"path": "/etc/shadow"}}
]
}
}
// process_exit event
{
"process_exit": {
"process": {"binary": "/usr/bin/curl", "pid": 1234},
"status": 0,
"signal": ""
}
}Log Export Configuration
# Helm values for SIEM integration
tetragon:
exportFilename: /var/log/tetragon/tetragon.log
exportFileMaxSizeMB: 100
exportFileMaxBackups: 5
exportRateLimit: 1000 # events/second
exportAllowList: "" # JSON filter for allowed events
exportDenyList: "" # JSON filter for denied eventsReferences
- Tetragon Documentation: https://tetragon.io/docs/
- Tetragon GitHub: https://github.com/cilium/tetragon
- eBPF.io: https://ebpf.io/
- Cilium: https://cilium.io/
- TracingPolicy Examples: https://github.com/cilium/tetragon/tree/main/examples/tracingpolicy
- Tetragon gRPC API: https://tetragon.io/docs/reference/grpc-api/
- Isovalent Blog: https://isovalent.com/blog/
Scripts 1
agent.py26.5 KB
#!/usr/bin/env python3
"""Agent for deploying and managing eBPF security monitoring with Cilium Tetragon."""
import os
import sys
import json
import yaml
import shutil
import argparse
import subprocess
import tempfile
from datetime import datetime, timezone
TRACING_POLICY_TEMPLATE = {
"apiVersion": "cilium.io/v1alpha1",
"kind": "TracingPolicy",
"metadata": {"name": ""},
"spec": {"kprobes": []},
}
SENSITIVE_FILES = [
"/etc/shadow",
"/etc/passwd",
"/etc/sudoers",
"/etc/sudoers.d/",
"/root/.ssh/",
"/etc/kubernetes/pki/",
"/var/run/secrets/kubernetes.io/",
"/etc/ssl/private/",
]
SUSPICIOUS_BINARIES = [
"/bin/bash",
"/bin/sh",
"/usr/bin/python3",
"/usr/bin/python",
"/usr/bin/perl",
"/usr/bin/nc",
"/usr/bin/ncat",
"/usr/bin/socat",
"/usr/bin/curl",
"/usr/bin/wget",
]
CRYPTO_MINERS = [
"xmrig",
"minerd",
"cpuminer",
"cryptonight",
"stratum+tcp",
"nicehashminer",
"ethminer",
"nbminer",
]
CONTAINER_ESCAPE_PATHS = [
"/proc/1/root",
"/proc/1/ns",
"/sys/kernel/security",
"/proc/sysrq-trigger",
"/proc/kcore",
"/sys/fs/cgroup",
]
def check_prerequisites():
"""Verify that required tools are available on the system."""
results = {}
for tool in ["kubectl", "helm", "tetra"]:
results[tool] = shutil.which(tool) is not None
try:
result = subprocess.run(
["uname", "-r"], capture_output=True, text=True, timeout=5
)
kernel_version = result.stdout.strip() if result.returncode == 0 else "unknown"
except (FileNotFoundError, subprocess.TimeoutExpired):
kernel_version = "unknown"
btf_available = os.path.exists("/sys/kernel/btf/vmlinux")
results["kernel_version"] = kernel_version
results["btf_available"] = btf_available
return results
def generate_file_access_policy(
name="monitor-sensitive-file-access",
files=None,
action="Post",
namespace=None,
):
"""Generate a TracingPolicy for monitoring file access via fd_install kprobe."""
if files is None:
files = SENSITIVE_FILES
policy = {
"apiVersion": "cilium.io/v1alpha1",
"kind": "TracingPolicyNamespaced" if namespace else "TracingPolicy",
"metadata": {"name": name},
"spec": {
"kprobes": [
{
"call": "fd_install",
"syscall": False,
"args": [
{"index": 0, "type": "int"},
{"index": 1, "type": "file"},
],
"selectors": [
{
"matchArgs": [
{
"index": 1,
"operator": "Prefix",
"values": files,
}
],
"matchActions": [{"action": action}],
}
],
}
]
},
}
if namespace:
policy["metadata"]["namespace"] = namespace
return policy
def generate_network_monitor_policy(
name="monitor-tcp-connections",
binaries=None,
action="Post",
):
"""Generate a TracingPolicy for monitoring TCP connections via tcp_connect kprobe."""
kprobe = {
"call": "tcp_connect",
"syscall": False,
"args": [{"index": 0, "type": "sock"}],
"selectors": [{"matchActions": [{"action": action}]}],
}
if binaries:
kprobe["selectors"][0]["matchBinaries"] = [
{"operator": "In", "values": binaries}
]
policy = {
"apiVersion": "cilium.io/v1alpha1",
"kind": "TracingPolicy",
"metadata": {"name": name},
"spec": {"kprobes": [kprobe]},
}
return policy
def generate_privilege_escalation_policy(
name="detect-privilege-escalation",
action="Post",
):
"""Generate a TracingPolicy for detecting setuid(0) and commit_creds calls."""
policy = {
"apiVersion": "cilium.io/v1alpha1",
"kind": "TracingPolicy",
"metadata": {"name": name},
"spec": {
"kprobes": [
{
"call": "__sys_setuid",
"syscall": False,
"args": [{"index": 0, "type": "int"}],
"selectors": [
{
"matchArgs": [
{
"index": 0,
"operator": "Equal",
"values": ["0"],
}
],
"matchActions": [{"action": action}],
}
],
},
{
"call": "commit_creds",
"syscall": False,
"args": [{"index": 0, "type": "cred"}],
"selectors": [{"matchActions": [{"action": action}]}],
},
]
},
}
return policy
def generate_crypto_miner_enforcement_policy(
name="enforce-no-crypto-miners",
miners=None,
):
"""Generate a TracingPolicy that kills crypto miner processes via Sigkill."""
if miners is None:
miners = CRYPTO_MINERS
policy = {
"apiVersion": "cilium.io/v1alpha1",
"kind": "TracingPolicy",
"metadata": {"name": name},
"spec": {
"kprobes": [
{
"call": "sys_execve",
"syscall": True,
"args": [{"index": 0, "type": "string"}],
"selectors": [
{
"matchArgs": [
{
"index": 0,
"operator": "Postfix",
"values": miners,
}
],
"matchActions": [{"action": "Sigkill"}],
}
],
}
]
},
}
return policy
def generate_reverse_shell_detection_policy(
name="detect-reverse-shells",
binaries=None,
action="Post",
):
"""Generate a TracingPolicy for detecting reverse shell network connections."""
if binaries is None:
binaries = SUSPICIOUS_BINARIES
policy = {
"apiVersion": "cilium.io/v1alpha1",
"kind": "TracingPolicy",
"metadata": {"name": name},
"spec": {
"kprobes": [
{
"call": "tcp_connect",
"syscall": False,
"args": [{"index": 0, "type": "sock"}],
"selectors": [
{
"matchBinaries": [
{"operator": "In", "values": binaries}
],
"matchActions": [{"action": action}],
}
],
}
]
},
}
return policy
def generate_container_escape_policy(
name="detect-container-escape",
paths=None,
action="Post",
):
"""Generate a TracingPolicy for detecting container escape attempts."""
if paths is None:
paths = CONTAINER_ESCAPE_PATHS
policy = {
"apiVersion": "cilium.io/v1alpha1",
"kind": "TracingPolicy",
"metadata": {"name": name},
"spec": {
"kprobes": [
{
"call": "sys_openat",
"syscall": True,
"args": [
{"index": 0, "type": "int"},
{"index": 1, "type": "string"},
],
"selectors": [
{
"matchArgs": [
{
"index": 1,
"operator": "Prefix",
"values": paths,
}
],
"matchActions": [{"action": action}],
}
],
},
{
"call": "sys_mount",
"syscall": True,
"args": [
{"index": 0, "type": "string"},
{"index": 1, "type": "string"},
{"index": 2, "type": "string"},
],
"selectors": [{"matchActions": [{"action": action}]}],
},
]
},
}
return policy
def generate_write_monitoring_policy(
name="monitor-sensitive-file-writes",
paths=None,
action="Post",
):
"""Generate a TracingPolicy for monitoring file writes to sensitive paths."""
if paths is None:
paths = [
"/etc/",
"/root/",
"/var/spool/cron/",
"/etc/cron.d/",
"/etc/systemd/system/",
"/usr/lib/systemd/system/",
]
policy = {
"apiVersion": "cilium.io/v1alpha1",
"kind": "TracingPolicy",
"metadata": {"name": name},
"spec": {
"kprobes": [
{
"call": "sys_write",
"syscall": True,
"args": [
{"index": 0, "type": "fd"},
{"index": 1, "type": "char_buf",
"sizeArgIndex": 3, "returnCopy": True},
{"index": 2, "type": "size_t"},
],
"selectors": [
{
"matchArgs": [
{
"index": 0,
"operator": "Prefix",
"values": paths,
}
],
"matchActions": [{"action": action}],
}
],
}
]
},
}
return policy
def apply_policy(policy, dry_run=False):
"""Apply a TracingPolicy to the Kubernetes cluster or write to file."""
policy_yaml = yaml.dump(policy, default_flow_style=False)
if dry_run:
return {"status": "dry_run", "yaml": policy_yaml}
with tempfile.NamedTemporaryFile(
mode="w", suffix=".yaml", delete=False
) as f:
f.write(policy_yaml)
temp_path = f.name
try:
result = subprocess.run(
["kubectl", "apply", "-f", temp_path],
capture_output=True,
text=True,
timeout=30,
)
return {
"status": "applied" if result.returncode == 0 else "failed",
"stdout": result.stdout.strip(),
"stderr": result.stderr.strip(),
"yaml": policy_yaml,
}
except (FileNotFoundError, subprocess.TimeoutExpired) as e:
return {"status": "error", "error": str(e), "yaml": policy_yaml}
finally:
os.unlink(temp_path)
def list_tracing_policies():
"""List all TracingPolicy resources in the cluster."""
try:
result = subprocess.run(
["kubectl", "get", "tracingpolicies", "-o", "json"],
capture_output=True,
text=True,
timeout=30,
)
if result.returncode != 0:
return {"status": "error", "stderr": result.stderr.strip()}
policies = json.loads(result.stdout)
return {
"status": "ok",
"count": len(policies.get("items", [])),
"policies": [
{
"name": p["metadata"]["name"],
"created": p["metadata"].get("creationTimestamp", ""),
}
for p in policies.get("items", [])
],
}
except (FileNotFoundError, subprocess.TimeoutExpired, json.JSONDecodeError) as e:
return {"status": "error", "error": str(e)}
def stream_events(output_format="compact", event_filter=None, limit=100):
"""Stream Tetragon events using the tetra CLI."""
cmd = ["tetra", "getevents", "-o", output_format]
try:
proc = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
)
events = []
for i, line in enumerate(proc.stdout):
if i >= limit:
break
line = line.strip()
if not line:
continue
if output_format == "json":
try:
event = json.loads(line)
if event_filter and event_filter not in json.dumps(event):
continue
events.append(event)
except json.JSONDecodeError:
continue
else:
if event_filter and event_filter not in line:
continue
events.append(line)
proc.terminate()
return {"status": "ok", "event_count": len(events), "events": events}
except FileNotFoundError:
return {"status": "error", "error": "tetra CLI not found"}
def parse_tetragon_log(log_path, event_types=None):
"""Parse a Tetragon JSON log file and extract security-relevant events."""
if not os.path.exists(log_path):
return {"status": "error", "error": f"Log file not found: {log_path}"}
if event_types is None:
event_types = ["process_exec", "process_kprobe", "process_exit"]
events = {"total": 0, "by_type": {}}
alerts = []
with open(log_path) as f:
for line in f:
line = line.strip()
if not line:
continue
try:
event = json.loads(line)
except json.JSONDecodeError:
continue
events["total"] += 1
for etype in event_types:
if etype in event:
events["by_type"].setdefault(etype, 0)
events["by_type"][etype] += 1
if etype == "process_kprobe":
kprobe_data = event[etype]
policy_name = kprobe_data.get("policy_name", "")
func = kprobe_data.get("function_name", "")
binary = (
kprobe_data.get("process", {}).get("binary", "")
)
alerts.append(
{
"type": etype,
"policy": policy_name,
"function": func,
"binary": binary,
"time": event.get("time", ""),
}
)
return {
"status": "ok",
"events": events,
"security_alerts": alerts[:100],
}
def generate_helm_values(
enable_process_cred=True,
enable_process_ns=True,
export_file="/var/log/tetragon/tetragon.log",
export_max_size_mb=100,
export_max_backups=5,
resources_cpu="500m",
resources_memory="512Mi",
):
"""Generate Helm values YAML for Tetragon deployment."""
values = {
"tetragon": {
"enableProcessCred": enable_process_cred,
"enableProcessNs": enable_process_ns,
"exportFilename": export_file,
"exportFileMaxSizeMB": export_max_size_mb,
"exportFileMaxBackups": export_max_backups,
"resources": {
"requests": {"cpu": "100m", "memory": "128Mi"},
"limits": {"cpu": resources_cpu, "memory": resources_memory},
},
},
"tetragonOperator": {
"enabled": True,
},
"export": {
"stdout": {"enabledCommand": True, "enabledArgs": True},
},
}
return yaml.dump(values, default_flow_style=False)
def generate_full_monitoring_suite(output_dir, dry_run=False):
"""Generate a complete suite of TracingPolicies for security monitoring."""
os.makedirs(output_dir, exist_ok=True)
policies = {
"01-file-access-monitor.yaml": generate_file_access_policy(),
"02-network-monitor.yaml": generate_network_monitor_policy(),
"03-privilege-escalation-detect.yaml": generate_privilege_escalation_policy(),
"04-crypto-miner-enforcement.yaml": generate_crypto_miner_enforcement_policy(),
"05-reverse-shell-detect.yaml": generate_reverse_shell_detection_policy(),
"06-container-escape-detect.yaml": generate_container_escape_policy(),
"07-sensitive-write-monitor.yaml": generate_write_monitoring_policy(),
}
results = []
for filename, policy in policies.items():
filepath = os.path.join(output_dir, filename)
policy_yaml = yaml.dump(policy, default_flow_style=False)
with open(filepath, "w") as f:
f.write(policy_yaml)
results.append(
{
"file": filepath,
"policy_name": policy["metadata"]["name"],
"kprobe_count": len(policy["spec"]["kprobes"]),
}
)
helm_values_path = os.path.join(output_dir, "helm-values.yaml")
with open(helm_values_path, "w") as f:
f.write(generate_helm_values())
results.append({"file": helm_values_path, "type": "helm-values"})
summary = {
"generated_at": datetime.now(timezone.utc).isoformat(),
"output_dir": output_dir,
"policy_count": len(policies),
"policies": results,
"dry_run": dry_run,
}
return summary
def install_tetragon_helm(namespace="kube-system", values_file=None, dry_run=False):
"""Install or upgrade Tetragon via Helm."""
cmd = [
"helm", "upgrade", "--install", "tetragon",
"cilium/tetragon", "-n", namespace,
]
if values_file:
cmd.extend(["-f", values_file])
else:
cmd.extend([
"--set", "tetragon.enableProcessCred=true",
"--set", "tetragon.enableProcessNs=true",
])
if dry_run:
cmd.append("--dry-run")
try:
add_repo = subprocess.run(
["helm", "repo", "add", "cilium", "https://helm.cilium.io"],
capture_output=True, text=True, timeout=30,
)
subprocess.run(
["helm", "repo", "update"],
capture_output=True, text=True, timeout=60,
)
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
return {
"status": "installed" if result.returncode == 0 else "failed",
"stdout": result.stdout.strip(),
"stderr": result.stderr.strip(),
}
except (FileNotFoundError, subprocess.TimeoutExpired) as e:
return {"status": "error", "error": str(e)}
def verify_installation(namespace="kube-system"):
"""Verify Tetragon is running correctly in the cluster."""
checks = {}
try:
result = subprocess.run(
["kubectl", "get", "pods", "-n", namespace,
"-l", "app.kubernetes.io/name=tetragon",
"-o", "json"],
capture_output=True, text=True, timeout=30,
)
if result.returncode == 0:
pods = json.loads(result.stdout)
items = pods.get("items", [])
checks["pods"] = {
"count": len(items),
"statuses": [
{
"name": p["metadata"]["name"],
"phase": p["status"].get("phase", "Unknown"),
"ready": all(
c.get("ready", False)
for c in p["status"].get("containerStatuses", [])
),
}
for p in items
],
}
else:
checks["pods"] = {"error": result.stderr.strip()}
except Exception as e:
checks["pods"] = {"error": str(e)}
try:
result = subprocess.run(
["kubectl", "api-resources", "--api-group=cilium.io"],
capture_output=True, text=True, timeout=30,
)
checks["crds_available"] = "tracingpolicies" in result.stdout.lower()
except Exception:
checks["crds_available"] = False
return checks
def main():
parser = argparse.ArgumentParser(
description="eBPF Security Monitoring Agent - Cilium Tetragon"
)
parser.add_argument(
"--action",
choices=[
"check",
"install",
"generate",
"apply",
"list-policies",
"stream",
"parse-log",
"verify",
],
default="check",
help="Action to perform",
)
parser.add_argument("--output-dir", default="./tetragon-policies",
help="Directory for generated policies")
parser.add_argument("--output", default="ebpf_monitoring_report.json",
help="Output report file")
parser.add_argument("--dry-run", action="store_true",
help="Generate without applying")
parser.add_argument("--log-path", help="Path to Tetragon log file")
parser.add_argument("--event-filter", help="Filter events by keyword")
parser.add_argument("--limit", type=int, default=100,
help="Max events to stream")
parser.add_argument("--namespace", default="kube-system",
help="Kubernetes namespace")
parser.add_argument("--values-file", help="Helm values file path")
parser.add_argument("--policy-type",
choices=[
"file-access", "network", "privilege-escalation",
"crypto-miner", "reverse-shell", "container-escape",
"write-monitor", "all",
],
default="all",
help="Type of policy to generate/apply")
args = parser.parse_args()
report = {"generated_at": datetime.now(timezone.utc).isoformat(), "action": args.action}
if args.action == "check":
prereqs = check_prerequisites()
report["prerequisites"] = prereqs
print(f"[*] Kernel: {prereqs['kernel_version']}")
print(f"[*] BTF available: {prereqs['btf_available']}")
for tool in ["kubectl", "helm", "tetra"]:
status = "found" if prereqs[tool] else "NOT FOUND"
print(f"[*] {tool}: {status}")
elif args.action == "install":
print("[+] Installing Tetragon via Helm...")
result = install_tetragon_helm(
namespace=args.namespace,
values_file=args.values_file,
dry_run=args.dry_run,
)
report["install"] = result
print(f"[+] Status: {result['status']}")
elif args.action == "generate":
print(f"[+] Generating TracingPolicies to {args.output_dir}...")
suite = generate_full_monitoring_suite(args.output_dir, dry_run=args.dry_run)
report["suite"] = suite
print(f"[+] Generated {suite['policy_count']} policies")
elif args.action == "apply":
policy_generators = {
"file-access": generate_file_access_policy,
"network": generate_network_monitor_policy,
"privilege-escalation": generate_privilege_escalation_policy,
"crypto-miner": generate_crypto_miner_enforcement_policy,
"reverse-shell": generate_reverse_shell_detection_policy,
"container-escape": generate_container_escape_policy,
"write-monitor": generate_write_monitoring_policy,
}
if args.policy_type == "all":
policies_to_apply = policy_generators
else:
policies_to_apply = {args.policy_type: policy_generators[args.policy_type]}
report["applied"] = []
for ptype, generator in policies_to_apply.items():
policy = generator()
result = apply_policy(policy, dry_run=args.dry_run)
report["applied"].append({"type": ptype, "result": result})
print(f"[+] {ptype}: {result['status']}")
elif args.action == "list-policies":
result = list_tracing_policies()
report["policies"] = result
if result["status"] == "ok":
print(f"[+] Found {result['count']} TracingPolicies:")
for p in result["policies"]:
print(f" - {p['name']} (created: {p['created']})")
else:
print(f"[-] Error: {result.get('error', result.get('stderr', ''))}")
elif args.action == "stream":
print(f"[+] Streaming up to {args.limit} events...")
result = stream_events(
output_format="json",
event_filter=args.event_filter,
limit=args.limit,
)
report["events"] = result
print(f"[+] Captured {result.get('event_count', 0)} events")
elif args.action == "parse-log":
if not args.log_path:
print("[-] --log-path required for parse-log action")
sys.exit(1)
print(f"[+] Parsing log: {args.log_path}")
result = parse_tetragon_log(args.log_path)
report["log_analysis"] = result
if result["status"] == "ok":
print(f"[+] Total events: {result['events']['total']}")
for etype, count in result["events"]["by_type"].items():
print(f" {etype}: {count}")
print(f"[+] Security alerts: {len(result['security_alerts'])}")
else:
print(f"[-] Error: {result['error']}")
elif args.action == "verify":
print("[+] Verifying Tetragon installation...")
checks = verify_installation(args.namespace)
report["verification"] = checks
if "pods" in checks and isinstance(checks["pods"], dict):
pod_info = checks["pods"]
if "count" in pod_info:
print(f"[+] Tetragon pods: {pod_info['count']}")
for ps in pod_info.get("statuses", []):
ready_str = "READY" if ps["ready"] else "NOT READY"
print(f" {ps['name']}: {ps['phase']} ({ready_str})")
else:
print(f"[-] Pod check error: {pod_info.get('error', 'unknown')}")
print(f"[+] TracingPolicy CRDs available: {checks.get('crds_available', False)}")
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"[+] Report saved to {args.output}")
if __name__ == "__main__":
main()