# Runtime Agents Architecture ## Overview This document describes the runtime observation layer in StellaOps, including eBPF-based kernel instrumentation, container lifecycle monitoring, and signal aggregation. Runtime evidence provides the highest-confidence reachability determination for policy decisions. --- ## Runtime Observation Stack ``` ┌─────────────────────────────────────────────────────────────────────────────────────┐ │ RUNTIME OBSERVATION STACK │ └─────────────────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────────────────┐ │ APPLICATION LAYER │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Container 1 │ │ Container 2 │ │ Container 3 │ │ Container N │ │ │ │ (app:v1) │ │ (api:v2) │ │ (worker) │ │ (...) │ │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │ │ │ │ │ │ │ └────────────────┴────────────────┴────────────────┘ │ │ │ │ │ [Function Calls] │ │ [System Calls] │ │ [Network I/O] │ │ │ │ └────────────────────────────────────┼────────────────────────────────────────────────┘ │ ┌────────────────────────────────────┼────────────────────────────────────────────────┐ │ KERNEL SPACE │ │ │ │ │ ┌─────────────────┐ ┌────────▼────────┐ ┌─────────────────┐ │ │ │ kprobes │ │ eBPF VM │ │ tracepoints │ │ │ │ (syscalls) │◄───┤ (verified │───►│ (scheduler, │ │ │ │ │ │ bytecode) │ │ network) │ │ │ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ │ │ │ │ │ │ └──────────────────────┼──────────────────────┘ │ │ │ │ │ ┌───────────────▼───────────────┐ │ │ │ eBPF Ring Buffer │ │ │ │ (per-CPU, lock-free) │ │ │ └───────────────┬───────────────┘ │ │ │ │ └────────────────────────────────────┼────────────────────────────────────────────────┘ │ │ [perf events] │ ┌────────────────────────────────────┼────────────────────────────────────────────────┐ │ USER SPACE │ │ │ │ │ ┌─────────────────────▼─────────────────────┐ │ │ │ RuntimeSignalCollector │ │ │ │ (StellaOps.Signals) │ │ │ ├───────────────────────────────────────────┤ │ │ │ • Perf event polling │ │ │ │ • Symbol resolution (DWARF/kallsyms) │ │ │ │ • Stack unwinding │ │ │ │ • Container ID correlation (cgroup) │ │ │ │ • Event batching and compression │ │ │ └─────────────────────┬─────────────────────┘ │ │ │ │ │ ┌─────────────────────▼─────────────────────┐ │ │ │ ZastavaObserver │ │ │ │ (Container Lifecycle) │ │ │ ├───────────────────────────────────────────┤ │ │ │ • Container create/start/stop events │ │ │ │ • Image digest extraction │ │ │ │ • Runtime posture evaluation │ │ │ │ • Label/annotation parsing │ │ │ └─────────────────────┬─────────────────────┘ │ │ │ │ │ ┌─────────────────────▼─────────────────────┐ │ │ │ RuntimeSignalNormalizer │ │ │ │ (Event Processing) │ │ │ ├───────────────────────────────────────────┤ │ │ │ • Deduplicate events │ │ │ │ • Aggregate call counts │ │ │ │ • Map to package PURLs │ │ │ │ • Enrich with SBOM context │ │ │ └─────────────────────┬─────────────────────┘ │ │ │ │ └────────────────────────────────────┼────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────────────────┐ │ STORAGE LAYER │ │ │ │ ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ Hot Symbol Index │ │ │ │ (PostgreSQL: signals.hot_symbols) │ │ │ │ │ │ │ │ image_digest │ function_name │ purl │ invocation_count │ last_observed │ │ │ │ ─────────────┼───────────────┼──────┼──────────────────┼───────────────── │ │ │ │ sha256:abc.. │ lodash.merge │ npm/..│ 1,247 │ 2024-12-29T10:00 │ │ │ │ sha256:abc.. │ lodash.get │ npm/..│ 8,923 │ 2024-12-29T10:01 │ │ │ │ sha256:def.. │ axios.request │ npm/..│ 456 │ 2024-12-29T09:55 │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────────────┘ ``` --- ## eBPF Agent Architecture ### Probe Types ``` ┌─────────────────────────────────────────────────────────────────────────────────────┐ │ eBPF PROBE TYPES │ ├─────────────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ KPROBES / KRETPROBES │ │ │ │ │ │ │ │ Purpose: Trace kernel function entry/exit │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Syscall Tracing │ │ │ │ │ │ │ │ │ │ │ │ kprobe/sys_execve → New process execution │ │ │ │ │ │ kprobe/sys_openat → File access │ │ │ │ │ │ kprobe/sys_connect → Network connection │ │ │ │ │ │ kprobe/sys_socket → Socket creation │ │ │ │ │ │ kprobe/sys_read → File/socket reads │ │ │ │ │ │ kprobe/sys_write → File/socket writes │ │ │ │ │ │ kprobe/sys_mmap → Memory mapping │ │ │ │ │ │ kprobe/sys_clone → Process/thread creation │ │ │ │ │ │ │ │ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ TRACEPOINTS │ │ │ │ │ │ │ │ Purpose: Stable kernel instrumentation points │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Category │ Tracepoint │ Data │ │ │ │ │ │ ──────────────────┼───────────────────────────┼──────────────────│ │ │ │ │ │ Scheduler │ sched:sched_process_exec │ New execution │ │ │ │ │ │ Scheduler │ sched:sched_switch │ Context switch │ │ │ │ │ │ Network │ net:net_dev_xmit │ Packet TX │ │ │ │ │ │ Network │ sock:inet_sock_set_state │ TCP state │ │ │ │ │ │ Filesystem │ ext4:ext4_da_write_begin │ Write start │ │ │ │ │ │ Memory │ kmem:kmalloc │ Allocation │ │ │ │ │ │ Security │ security:security_* │ LSM hooks │ │ │ │ │ │ │ │ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ UPROBES │ │ │ │ │ │ │ │ Purpose: Trace userspace function entry/exit │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Library/Function Tracing │ │ │ │ │ │ │ │ │ │ │ │ uprobe:/lib/x86_64-linux-gnu/libc.so.6:malloc │ │ │ │ │ │ uprobe:/usr/lib/libssl.so:SSL_read │ │ │ │ │ │ uprobe:/usr/lib/libcrypto.so:EVP_EncryptFinal │ │ │ │ │ │ uprobe:/path/to/app:vulnerable_function │ │ │ │ │ │ │ │ │ │ │ │ Dynamic attachment based on: │ │ │ │ │ │ • SBOM analysis (known vulnerable functions) │ │ │ │ │ │ • Static call graph (entry points to vulnerable code) │ │ │ │ │ │ • Symbol resolution from DWARF/debug info │ │ │ │ │ │ │ │ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ USDT PROBES │ │ │ │ │ │ │ │ Purpose: User Statically Defined Tracing (application-level) │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Runtime-Specific Probes │ │ │ │ │ │ │ │ │ │ │ │ Node.js: │ │ │ │ │ │ usdt:/usr/bin/node:http__server__request │ │ │ │ │ │ usdt:/usr/bin/node:gc__start │ │ │ │ │ │ │ │ │ │ │ │ Python: │ │ │ │ │ │ usdt:/usr/bin/python3:function__entry │ │ │ │ │ │ usdt:/usr/bin/python3:function__return │ │ │ │ │ │ │ │ │ │ │ │ JVM: │ │ │ │ │ │ usdt:libjvm.so:method__entry │ │ │ │ │ │ usdt:libjvm.so:gc__begin │ │ │ │ │ │ │ │ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────────────┘ ``` ### Event Data Structures ``` ┌─────────────────────────────────────────────────────────────────────────────────────┐ │ eBPF EVENT DATA STRUCTURES │ ├─────────────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ FunctionCallEvent │ │ │ │ │ │ │ │ struct function_call_event { │ │ │ │ u64 timestamp_ns; // Kernel monotonic timestamp │ │ │ │ u32 pid; // Process ID │ │ │ │ u32 tid; // Thread ID │ │ │ │ u64 cgroup_id; // Container cgroup (for correlation) │ │ │ │ u32 uid; // User ID │ │ │ │ char comm[16]; // Process name │ │ │ │ char func_name[64]; // Function name (if resolved) │ │ │ │ u64 func_addr; // Function address (for offline resolution) │ │ │ │ u64 caller_addr; // Return address (call site) │ │ │ │ u64 stack_id; // Stack trace ID (BPF_MAP_TYPE_STACK_TRACE) │ │ │ │ u64 latency_ns; // Function execution time (kretprobe) │ │ │ │ u8 event_type; // ENTRY(0), EXIT(1), ERROR(2) │ │ │ │ }; │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ SyscallEvent │ │ │ │ │ │ │ │ struct syscall_event { │ │ │ │ u64 timestamp_ns; // Kernel monotonic timestamp │ │ │ │ u32 pid; // Process ID │ │ │ │ u32 tid; // Thread ID │ │ │ │ u64 cgroup_id; // Container cgroup │ │ │ │ u32 syscall_nr; // Syscall number │ │ │ │ u64 args[6]; // Syscall arguments │ │ │ │ i64 ret; // Return value │ │ │ │ u64 latency_ns; // Syscall duration │ │ │ │ u64 stack_id; // Stack trace ID │ │ │ │ }; │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ NetworkEvent │ │ │ │ │ │ │ │ struct network_event { │ │ │ │ u64 timestamp_ns; │ │ │ │ u32 pid; │ │ │ │ u64 cgroup_id; │ │ │ │ u8 protocol; // TCP(6), UDP(17) │ │ │ │ u8 direction; // INBOUND(0), OUTBOUND(1) │ │ │ │ u32 src_addr; // Source IPv4 (or first 4 bytes of IPv6) │ │ │ │ u32 dst_addr; // Destination IPv4 │ │ │ │ u16 src_port; │ │ │ │ u16 dst_port; │ │ │ │ u64 bytes; // Data transferred │ │ │ │ u8 state; // TCP state (ESTABLISHED, SYN_SENT, etc.) │ │ │ │ }; │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────────────┘ ``` --- ## Zastava Container Observer ``` ┌─────────────────────────────────────────────────────────────────────────────────────┐ │ ZASTAVA CONTAINER OBSERVER │ ├─────────────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ ARCHITECTURE │ │ │ │ │ │ │ │ ┌─────────────────────────────────┐ │ │ │ │ │ Container Runtime │ │ │ │ │ │ ┌─────────┐ ┌─────────────────┐│ │ │ │ │ │ │ Docker │ │ containerd ││ │ │ │ │ │ │ Engine │ │ ││ │ │ │ │ │ └────┬────┘ └────────┬────────┘│ │ │ │ │ │ │ │ │ │ │ │ │ └───────┼───────────────┼─────────┘ │ │ │ │ │ │ │ │ │ │ ┌──────────▼───────────────▼──────────┐ │ │ │ │ │ ZastavaObserver │ │ │ │ │ │ (Event Subscriber) │ │ │ │ │ ├─────────────────────────────────────┤ │ │ │ │ │ │ │ │ │ │ │ Connects to: │ │ │ │ │ │ • /var/run/docker.sock │ │ │ │ │ │ • /run/containerd/containerd.sock │ │ │ │ │ │ • /run/crio/crio.sock │ │ │ │ │ │ │ │ │ │ │ │ Listens for: │ │ │ │ │ │ • container.create │ │ │ │ │ │ • container.start │ │ │ │ │ │ • container.stop │ │ │ │ │ │ • container.die │ │ │ │ │ │ • image.pull │ │ │ │ │ │ │ │ │ │ │ └────────────────┬────────────────────┘ │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ ┌─────────────────────────────────────┐ │ │ │ │ │ ContainerLifecycleEvent │ │ │ │ │ ├─────────────────────────────────────┤ │ │ │ │ │ event_type: CREATE|START|STOP|DIE │ │ │ │ │ │ container_id: string │ │ │ │ │ │ image_ref: string │ │ │ │ │ │ image_digest: sha256:... │ │ │ │ │ │ labels: map │ │ │ │ │ │ annotations: map │ │ │ │ │ │ env_vars: string[] (filtered) │ │ │ │ │ │ pid: u32 (on start) │ │ │ │ │ │ cgroup_path: string │ │ │ │ │ │ started_at: timestamp │ │ │ │ │ │ stopped_at: timestamp │ │ │ │ │ │ exit_code: i32 │ │ │ │ │ │ oom_killed: bool │ │ │ │ │ └─────────────────────────────────────┘ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ RUNTIME POSTURE EVALUATION │ │ │ │ │ │ │ │ On container START, Zastava evaluates the runtime observation posture: │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Posture │ Observation Level │ Prerequisites │ │ │ │ │ ├───────────────────────┼──────────────────────┼─────────────────────┤ │ │ │ │ │ None │ No observation │ eBPF disabled │ │ │ │ │ │ Passive │ Lifecycle only │ Docker socket only │ │ │ │ │ │ ActiveTracing │ Syscalls + network │ eBPF + kprobes │ │ │ │ │ │ EbpfDeep │ + function calls │ + uprobes enabled │ │ │ │ │ │ FullInstrumentation │ + USDT + coverage │ + debug symbols │ │ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ Posture is determined by: │ │ │ │ 1. Kernel capabilities (CAP_BPF, CAP_SYS_ADMIN) │ │ │ │ 2. Available probe types │ │ │ │ 3. Container annotations (stellaops.io/observe-level) │ │ │ │ 4. Image debug symbol availability │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────────────┘ ``` --- ## Signal Processing Pipeline ``` ┌─────────────────────────────────────────────────────────────────────────────────────┐ │ SIGNAL PROCESSING PIPELINE │ ├─────────────────────────────────────────────────────────────────────────────────────┤ │ │ │ Raw Events │ │ (millions/sec) │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ STAGE 1: FILTERING │ │ │ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ In-Kernel Filtering (eBPF maps) │ │ │ │ │ │ │ │ │ │ │ │ • Filter by cgroup_id (only monitored containers) │ │ │ │ │ │ • Filter by syscall type (only security-relevant) │ │ │ │ │ │ • Rate limiting per-container (prevent flood) │ │ │ │ │ │ • Sampling for high-frequency events │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────┬──────────────┘ │ │ │ │ │ Filtered Events │ │ │ (thousands/sec) │ │ │ │◄────────────────────────────────────────────────────────┘ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ STAGE 2: ENRICHMENT │ │ │ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Symbol Resolution │ │ │ │ │ │ │ │ │ │ │ │ func_addr: 0x7f3a4b5c6d7e │ │ │ │ │ │ ↓ │ │ │ │ │ │ Resolve via: │ │ │ │ │ │ 1. /proc//maps (memory mappings) │ │ │ │ │ │ 2. Symbol table cache (from SBOM binaries) │ │ │ │ │ │ 3. DWARF debug info (if available) │ │ │ │ │ │ 4. kallsyms (for kernel symbols) │ │ │ │ │ │ ↓ │ │ │ │ │ │ func_name: "lodash.template" │ │ │ │ │ │ module: "/app/node_modules/lodash/lodash.js" │ │ │ │ │ │ purl: "pkg:npm/lodash@4.17.20" │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Container Correlation │ │ │ │ │ │ │ │ │ │ │ │ cgroup_id: 12345678 │ │ │ │ │ │ ↓ │ │ │ │ │ │ Lookup in Zastava registry: │ │ │ │ │ │ ↓ │ │ │ │ │ │ container_id: "abc123def456" │ │ │ │ │ │ image_digest: "sha256:789..." │ │ │ │ │ │ scan_id: "scan-xyz" (from label) │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────┬──────────────────┘ │ │ │ │ │ Enriched Events │ │ │ (hundreds/sec) │ │ │ │◄─────────────────────────────────────────────────────┘ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ STAGE 3: AGGREGATION │ │ │ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Time-Window Aggregation (1-minute windows) │ │ │ │ │ │ │ │ │ │ │ │ Key: (image_digest, purl, function_name) │ │ │ │ │ │ Value: AggregatedMetrics { │ │ │ │ │ │ invocation_count: u64, │ │ │ │ │ │ unique_callers: HashSet, │ │ │ │ │ │ total_latency_ns: u64, │ │ │ │ │ │ max_latency_ns: u64, │ │ │ │ │ │ sample_stack: Option, │ │ │ │ │ │ first_seen: Timestamp, │ │ │ │ │ │ last_seen: Timestamp, │ │ │ │ │ │ } │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────┬──────────────────┘ │ │ │ │ │ Aggregated Records │ │ │ (per function per minute) │ │ │ │◄─────────────────────────────────────────────────────┘ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────────────────┐ │ │ │ STAGE 4: PERSISTENCE │ │ │ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ PostgreSQL: signals.hot_symbols │ │ │ │ │ │ │ │ │ │ │ │ INSERT INTO signals.hot_symbols │ │ │ │ │ │ (image_digest, function_name, purl, invocation_count, ...) │ │ │ │ │ │ ON CONFLICT (image_digest, function_name) │ │ │ │ │ │ DO UPDATE SET │ │ │ │ │ │ invocation_count = hot_symbols.invocation_count + EXCLUDED.count,│ │ │ │ │ │ last_observed = EXCLUDED.last_observed, │ │ │ │ │ │ sample_stack = COALESCE(EXCLUDED.sample_stack, hot_symbols....) │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────────────┘ ``` --- ## Hot Symbol Index Schema ``` ┌─────────────────────────────────────────────────────────────────────────────────────┐ │ HOT SYMBOL INDEX SCHEMA │ ├─────────────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ TABLE: signals.hot_symbols │ │ │ │ │ │ │ │ CREATE TABLE signals.hot_symbols ( │ │ │ │ -- Identity │ │ │ │ id BIGSERIAL PRIMARY KEY, │ │ │ │ image_digest TEXT NOT NULL, │ │ │ │ function_name TEXT NOT NULL, │ │ │ │ module TEXT, -- Library/file containing func │ │ │ │ purl TEXT, -- Package URL for module │ │ │ │ │ │ │ │ -- Observation metrics │ │ │ │ invocation_count BIGINT DEFAULT 0, │ │ │ │ unique_callers INTEGER DEFAULT 0, │ │ │ │ total_latency_ns BIGINT DEFAULT 0, │ │ │ │ max_latency_ns BIGINT DEFAULT 0, │ │ │ │ │ │ │ │ -- Timestamps │ │ │ │ first_observed TIMESTAMPTZ NOT NULL DEFAULT NOW(), │ │ │ │ last_observed TIMESTAMPTZ NOT NULL DEFAULT NOW(), │ │ │ │ │ │ │ │ -- Sample data │ │ │ │ sample_stack JSONB, -- Representative stack trace │ │ │ │ sample_args JSONB, -- Sample arguments (if captured) │ │ │ │ │ │ │ │ -- Constraints │ │ │ │ CONSTRAINT hot_symbols_unique UNIQUE (image_digest, function_name) │ │ │ │ ); │ │ │ │ │ │ │ │ -- Indexes │ │ │ │ CREATE INDEX idx_hot_symbols_purl ON signals.hot_symbols(purl); │ │ │ │ CREATE INDEX idx_hot_symbols_count ON signals.hot_symbols(invocation_count);│ │ │ │ CREATE INDEX idx_hot_symbols_last ON signals.hot_symbols(last_observed); │ │ │ │ CREATE INDEX idx_hot_symbols_image ON signals.hot_symbols(image_digest); │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ QUERY EXAMPLES │ │ │ │ │ │ │ │ -- Is vulnerable function observed at runtime? │ │ │ │ SELECT EXISTS ( │ │ │ │ SELECT 1 FROM signals.hot_symbols │ │ │ │ WHERE image_digest = $1 │ │ │ │ AND purl = $2 │ │ │ │ AND function_name = $3 │ │ │ │ AND invocation_count > 0 │ │ │ │ ); │ │ │ │ │ │ │ │ -- Get all observed functions for a vulnerable package │ │ │ │ SELECT function_name, invocation_count, last_observed, sample_stack │ │ │ │ FROM signals.hot_symbols │ │ │ │ WHERE image_digest = $1 AND purl = $2 │ │ │ │ ORDER BY invocation_count DESC; │ │ │ │ │ │ │ │ -- Hot path analysis (most called functions) │ │ │ │ SELECT purl, function_name, SUM(invocation_count) as total_calls │ │ │ │ FROM signals.hot_symbols │ │ │ │ WHERE image_digest = $1 │ │ │ │ GROUP BY purl, function_name │ │ │ │ ORDER BY total_calls DESC │ │ │ │ LIMIT 100; │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────────────┘ ``` --- ## Runtime Evidence Integration ``` ┌─────────────────────────────────────────────────────────────────────────────────────┐ │ RUNTIME EVIDENCE → POLICY ENGINE │ ├─────────────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ REACHABILITY STATE MAPPING │ │ │ │ │ │ │ │ Runtime Evidence → Reachability State │ │ │ │ ───────────────────────────────────────────────────────────────────────── │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ │ │ │ │ │ │ Function observed at runtime → DynamicReachable │ │ │ │ │ │ (invocation_count > 0) (confidence: 0.90) │ │ │ │ │ │ │ │ │ │ │ │ Function observed + exploit path → LiveExploitPath │ │ │ │ │ │ (confirmed vulnerable flow) (confidence: 1.00) │ │ │ │ │ │ │ │ │ │ │ │ Package imported but function → PotentiallyReachable │ │ │ │ │ │ not observed (long window) (confidence: 0.50) │ │ │ │ │ │ │ │ │ │ │ │ No runtime observation → (defer to static analysis) │ │ │ │ │ │ (posture = None) │ │ │ │ │ │ │ │ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ CONFIDENCE FACTOR CALCULATION │ │ │ │ │ │ │ │ The Runtime factor (RTS) in confidence scoring: │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Scenario │ RTS Score │ Weight: 0.25 │ │ │ │ │ │ ──────────────────────────────────┼───────────┼───────────────── │ │ │ │ │ │ High frequency observation │ 1.00 │ Strong evidence │ │ │ │ │ │ (invocation_count > 1000/day) │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ Moderate observation │ 0.80 │ Confirmed used │ │ │ │ │ │ (invocation_count > 0) │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ No observation (neutral) │ 0.50 │ Inconclusive │ │ │ │ │ │ (posture active, no calls) │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ No observation (long window) │ 0.20 │ Likely unused │ │ │ │ │ │ (>30 days, no calls) │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ No runtime posture │ 0.50 │ Cannot determine │ │ │ │ │ │ (eBPF not available) │ │ │ │ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ EVIDENCE CHAIN │ │ │ │ │ │ │ │ When runtime observation is available: │ │ │ │ │ │ │ │ Evidence { │ │ │ │ source: "signals/hot_symbols", │ │ │ │ evidence_type: "runtime_observation", │ │ │ │ data: { │ │ │ │ image_digest: "sha256:abc...", │ │ │ │ purl: "pkg:npm/lodash@4.17.20", │ │ │ │ function: "lodash.template", │ │ │ │ invocation_count: 1247, │ │ │ │ observation_window: "2024-12-01T00:00:00Z/2024-12-29T00:00:00Z", │ │ │ │ sample_stack: [ ... ] │ │ │ │ }, │ │ │ │ confidence: 0.90, │ │ │ │ timestamp: "2024-12-29T10:30:00Z" │ │ │ │ } │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────────────┘ ``` --- ## Deployment Considerations ``` ┌─────────────────────────────────────────────────────────────────────────────────────┐ │ DEPLOYMENT CONSIDERATIONS │ ├─────────────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ KERNEL REQUIREMENTS │ │ │ │ │ │ │ │ Minimum: Linux 5.8+ (BPF_LINK, ring buffer support) │ │ │ │ Recommended: Linux 5.15+ (BTF, CO-RE) │ │ │ │ │ │ │ │ Required kernel config: │ │ │ │ • CONFIG_BPF=y │ │ │ │ • CONFIG_BPF_SYSCALL=y │ │ │ │ • CONFIG_BPF_JIT=y │ │ │ │ • CONFIG_HAVE_EBPF_JIT=y │ │ │ │ • CONFIG_DEBUG_INFO_BTF=y (for CO-RE) │ │ │ │ • CONFIG_UPROBE_EVENTS=y (for uprobes) │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ CONTAINER PRIVILEGES │ │ │ │ │ │ │ │ Agent container requires: │ │ │ │ │ │ │ │ securityContext: │ │ │ │ privileged: true # For eBPF loading │ │ │ │ # OR use capabilities: │ │ │ │ capabilities: │ │ │ │ add: │ │ │ │ - SYS_ADMIN # BPF program loading │ │ │ │ - SYS_PTRACE # Stack unwinding │ │ │ │ - SYS_RESOURCE # RLIMIT_MEMLOCK │ │ │ │ - NET_ADMIN # Network probes │ │ │ │ - BPF # BPF operations (5.8+) │ │ │ │ - PERFMON # Performance monitoring (5.8+) │ │ │ │ │ │ │ │ Volume mounts: │ │ │ │ - /sys/kernel/debug (debugfs, for kprobes) │ │ │ │ - /var/run/docker.sock (container events) │ │ │ │ - /proc (process info) │ │ │ │ - /sys/fs/bpf (BPF filesystem, optional) │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ PERFORMANCE IMPACT │ │ │ │ │ │ │ │ Overhead by probe type: │ │ │ │ │ │ │ │ ┌────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Probe Type │ Latency Added │ CPU Overhead │ Memory │ │ │ │ │ │ ────────────────┼──────────────────┼──────────────┼──────────────│ │ │ │ │ │ kprobe │ ~100-500ns │ <0.5% │ ~1MB/probe │ │ │ │ │ │ tracepoint │ ~50-100ns │ <0.2% │ ~500KB/tp │ │ │ │ │ │ uprobe │ ~1-5us │ 1-3%* │ ~1MB/probe │ │ │ │ │ │ USDT │ ~500ns-2us │ <1% │ ~1MB/probe │ │ │ │ │ │ │ │ │ │ │ │ * uprobe overhead depends on call frequency │ │ │ │ │ └────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ Mitigation strategies: │ │ │ │ • Selective probe attachment (only observed containers) │ │ │ │ • In-kernel filtering (reduce userspace events) │ │ │ │ • Sampling for high-frequency events │ │ │ │ • Per-container rate limiting │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────────────┘ ``` --- ## Tetragon Integration ``` ┌─────────────────────────────────────────────────────────────────────────────────────┐ │ TETRAGON eBPF INTEGRATION │ ├─────────────────────────────────────────────────────────────────────────────────────┤ │ │ │ Tetragon provides kernel-level security observability via eBPF TracingPolicies. │ │ StellaOps integrates Tetragon as a complementary runtime observation source. │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ ARCHITECTURE │ │ │ │ │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Tetragon Daemon (DaemonSet) │ │ │ │ │ │ │ │ │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ │ │ │ │ kprobe │ │ tracepoint │ │ uprobe │ │ │ │ │ │ │ │ (syscalls) │ │ (scheduler) │ │ (userspace) │ │ │ │ │ │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─────────────────┼─────────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ ┌─────────▼─────────┐ │ │ │ │ │ │ │ TracingPolicy │ │ │ │ │ │ │ │ CRD Enforcement │ │ │ │ │ │ │ └─────────┬─────────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ ┌─────────▼─────────┐ │ │ │ │ │ │ │ Export API │ │ │ │ │ │ │ │ (gRPC/HTTP) │ │ │ │ │ │ │ └─────────┬─────────┘ │ │ │ │ │ │ │ │ │ │ │ │ └────────────────────────────┼────────────────────────────────────────┘ │ │ │ │ │ │ │ │ │ ┌─────────▼─────────┐ │ │ │ │ │ StellaOps Agent │ │ │ │ │ │ (Tetragon) │ │ │ │ │ └─────────┬─────────┘ │ │ │ │ │ │ │ │ │ ┌────────────────────────────┼───────────────────────────────────────┐ │ │ │ │ │ │ │ │ │ │ │ │ ┌─────────────┐ ┌───────▼───────┐ ┌─────────────┐ │ │ │ │ │ │ │ Privacy │ │ Event │ │ Frame │ │ │ │ │ │ │ │ Filter │──│ Adapter │──│ Canonicalizer │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─────────────┘ └───────────────┘ └──────┬──────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ ┌───────────────────────────────────────────┼────────────────┐ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ┌─────────────────┐ ┌───────────────▼────────────┐ │ │ │ │ │ │ │ │ │ Hot Symbol │ │ Witness │ │ │ │ │ │ │ │ │ │ Bridge │ │ Bridge │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────────┬────────┘ └──────────────┬─────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └───────────┼─────────────────────────────┼──────────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ └───────────────┼─────────────────────────────┼─────────────────────┘ │ │ │ │ │ │ │ │ │ │ ┌─────────▼─────────┐ ┌─────────────▼───────────┐ │ │ │ │ │ signals.hot_symbols│ │ RuntimeWitnessGenerator │ │ │ │ │ │ (PostgreSQL) │ │ (Signing Pipeline) │ │ │ │ │ └────────────────────┘ └─────────────────────────┘ │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ TRACINGPOLICY CONFIGURATION │ │ │ │ │ │ │ │ The StellaOps TracingPolicy captures: │ │ │ │ │ │ │ │ • Process execution (execve) with full arguments │ │ │ │ • Network connections (connect, socket) │ │ │ │ • File operations (open, read, write) │ │ │ │ • Kernel and user-space stack traces │ │ │ │ │ │ │ │ Namespace selectors: stella-ops-*, application namespaces │ │ │ │ Pod selectors: Via labels (stellaops.io/observe=true) │ │ │ │ │ │ │ │ Policy file: devops/manifests/tetragon/stella-ops-tracing-policy.yaml │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ COMPONENT RESPONSIBILITIES │ │ │ │ │ │ │ │ TetragonAgentCapability: │ │ │ │ • Connects to Tetragon Export API (gRPC) │ │ │ │ • Implements IAgentCapability interface │ │ │ │ • Supports start/stop collection, status, flush tasks │ │ │ │ • Health checks via Tetragon health endpoint │ │ │ │ │ │ │ │ TetragonEventAdapter: │ │ │ │ • Converts TetragonEvent to RuntimeCallEvent format │ │ │ │ • Maps stack frames to canonical symbols │ │ │ │ • Extracts process/container context │ │ │ │ │ │ │ │ TetragonFrameCanonicalizer: │ │ │ │ • Resolves Build-ID for binaries │ │ │ │ • Demangles C++, Rust, Go symbol names │ │ │ │ • Computes function IDs matching static analysis │ │ │ │ • Format: buildid:function+offset │ │ │ │ │ │ │ │ TetragonHotSymbolBridge: │ │ │ │ • Records observations to hot_symbols index │ │ │ │ • Time-window aggregation (1-minute windows) │ │ │ │ • Confidence scoring (0.20-1.00 range) │ │ │ │ │ │ │ │ TetragonWitnessBridge: │ │ │ │ • Buffers observations by claim_id │ │ │ │ • Emits to RuntimeWitnessGenerator │ │ │ │ • Implements backpressure via SemaphoreSlim │ │ │ │ │ │ │ │ TetragonPrivacyFilter: │ │ │ │ • Argument redaction (passwords, tokens, PII) │ │ │ │ • Symbol-ID-only mode for privacy-sensitive envs │ │ │ │ • Namespace allowlisting │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ TETRAGON vs SIGNALS COMPARISON │ │ │ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Aspect │ Signals (Native) │ Tetragon Integration │ │ │ │ │ │ ─────────────────┼──────────────────────┼────────────────────────│ │ │ │ │ │ Deployment │ Custom eBPF agent │ Standard Tetragon │ │ │ │ │ │ Configuration │ Code-level │ TracingPolicy CRD │ │ │ │ │ │ Policy management │ Recompile │ K8s-native (kubectl) │ │ │ │ │ │ Stack capture │ Custom unwinding │ Built-in │ │ │ │ │ │ Ecosystem │ StellaOps only │ CNCF, broad adoption │ │ │ │ │ │ Use case │ Deep integration │ Standard compliance │ │ │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ Recommendation: Use Tetragon for Kubernetes environments with compliance │ │ │ │ requirements. Use native Signals for maximum control and non-K8s estates. │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────────────┐ │ │ │ PERFORMANCE TARGETS │ │ │ │ │ │ │ │ Target KPIs for Tetragon integration: │ │ │ │ │ │ │ │ ┌──────────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Metric │ Target │ Measurement │ │ │ │ │ │ ─────────────────────────┼──────────────────┼──────────────────────│ │ │ │ │ │ CPU overhead │ <5% │ Per monitored pod │ │ │ │ │ │ Memory overhead (agent) │ <100MB │ Agent container │ │ │ │ │ │ Capture latency (P95) │ <100ms │ Event to hot_symbols │ │ │ │ │ │ Throughput │ >10,000 events/s │ Per agent instance │ │ │ │ │ │ Privacy filter overhead │ <10% │ Compared to baseline │ │ │ │ │ │ Frame canonicalization │ <10ms per frame │ With symbol resolve │ │ │ │ │ │ Function ID computation │ <0.1ms per call │ Hash + format │ │ │ │ │ │ Demangling throughput │ >100,000 sym/s │ Mixed C++/Rust/Go │ │ │ │ │ └──────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ Benchmarks: src/RuntimeInstrumentation/StellaOps.RuntimeInstrumentation. │ │ │ │ Tetragon.Tests/Benchmarks/TetragonPerformanceBenchmarks.cs │ │ │ │ │ │ │ └──────────────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────────────┘ ``` --- ## Tetragon Deployment Guide ### Prerequisites 1. **Kubernetes cluster** with Linux nodes (kernel 5.8+) 2. **Tetragon installed** via Helm or operator 3. **StellaOps control plane** deployed ### Installation Steps ```bash # 1. Install Tetragon (if not already installed) helm repo add cilium https://helm.cilium.io helm install tetragon cilium/tetragon -n kube-system # 2. Apply StellaOps TracingPolicy kubectl apply -f devops/manifests/tetragon/stella-ops-tracing-policy.yaml # 3. Deploy StellaOps Tetragon Agent kubectl apply -f devops/manifests/tetragon/stella-ops-tetragon-agent-daemonset.yaml # 4. Verify deployment kubectl get pods -n stella-ops -l app=stella-ops-tetragon-agent kubectl logs -n stella-ops -l app=stella-ops-tetragon-agent --tail=50 ``` ### Configuration The Tetragon agent is configured via ConfigMap: ```yaml apiVersion: v1 kind: ConfigMap metadata: name: stella-ops-tetragon-config namespace: stella-ops data: config.yaml: | tetragon: address: "tetragon.kube-system.svc:54321" connectionTimeout: 30s hotSymbols: aggregationWindowSeconds: 60 minConfidenceThreshold: 0.2 flushIntervalSeconds: 30 privacy: redactArguments: true useDefaultRedactionPatterns: true symbolIdOnlyMode: false allowedNamespaces: - stella-ops-workloads - default ``` ### Monitoring The agent exposes Prometheus metrics at `:8080/metrics`: - `tetragon_events_total` - Total events received - `tetragon_events_filtered` - Events dropped by privacy filter - `tetragon_hotsymbols_flushed` - Hot symbols written to DB - `tetragon_witness_generated` - Runtime witnesses generated - `tetragon_latency_seconds` - Event processing latency histogram --- ## Related Documentation - [Policy Engine Data Pipeline](policy-engine-data-pipeline.md) - How runtime feeds policy - [Reachability Drift Alert Flow](../../flows/19-reachability-drift-alert-flow.md) - Runtime-triggered alerts - [Signals Module Architecture](../../modules/signals/architecture.md) - Signals module dossier - [Zastava Architecture](../../modules/zastava/architecture.md) - Container observer dossier - [Tetragon Integration Sprint](../../implplan/SPRINT_20260118_019_Infra_tetragon_integration.md) - Implementation details