81 KiB
81 KiB
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<string,string> │ │ │
│ │ │ annotations: map<string,string> │ │ │
│ │ │ 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/<pid>/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<caller_addr>, │ │ │
│ │ │ total_latency_ns: u64, │ │ │
│ │ │ max_latency_ns: u64, │ │ │
│ │ │ sample_stack: Option<StackTrace>, │ │ │
│ │ │ 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 │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────────┘
Related Documentation
- Policy Engine Data Pipeline - How runtime feeds policy
- Reachability Drift Alert Flow - Runtime-triggered alerts
- Signals Module Architecture - Signals module dossier
- Zastava Architecture - Container observer dossier