|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +fact (File ACTivity) is a file integrity monitoring tool designed for PCI DSS compliance. It's implemented as a BPF agent that: |
| 8 | +- Attaches BPF programs to LSM (Linux Security Module) hooks in the kernel |
| 9 | +- Receives file system events from the kernel via ring buffers |
| 10 | +- Enriches events with process and file metadata |
| 11 | +- Outputs events via gRPC or JSON for further processing |
| 12 | +- Supports hot-reload of configuration via SIGHUP |
| 13 | +- Exposes Prometheus metrics |
| 14 | + |
| 15 | +The project requires modern kernel features (BTF symbols, LSM hooks, BPF trampolines) and is tested on RHEL 9.6+/10+, RHCOS 4.16+, and Fedora CoreOS 43. |
| 16 | + |
| 17 | +## Workspace Structure |
| 18 | + |
| 19 | +This is a Cargo workspace with three main crates: |
| 20 | + |
| 21 | +- **fact**: Main binary that loads BPF programs, processes events, and handles output |
| 22 | + - `src/bpf/`: Rust code for loading and managing BPF programs (uses aya library) |
| 23 | + - `src/event/`: Event processing and enrichment logic |
| 24 | + - `src/config/`: Configuration parsing and hot-reload via `Reloader` |
| 25 | + - `src/output/`: gRPC and JSON output handlers |
| 26 | + - `src/metrics/`: Prometheus metrics exporter |
| 27 | + - `src/host_scanner.rs`: Scans host for existing files on startup |
| 28 | + |
| 29 | +- **fact-api**: gRPC API definitions generated from protobuf files in `third_party/stackrox/proto` |
| 30 | + |
| 31 | +- **fact-ebpf**: BPF program implementation |
| 32 | + - `src/bpf/*.c`: C code for BPF programs that attach to LSM hooks |
| 33 | + - `src/lib.rs`: Rust bindings and types for BPF maps/events |
| 34 | + - Build script compiles C code to BPF bytecode |
| 35 | + |
| 36 | +## Key Architecture Patterns |
| 37 | + |
| 38 | +### Event Flow |
| 39 | +1. Kernel LSM hooks trigger BPF programs (in `fact-ebpf/src/bpf/main.c`) |
| 40 | +2. BPF programs write events to ring buffer |
| 41 | +3. `Bpf` worker (in `fact/src/bpf/mod.rs`) reads from ring buffer, sends to channel |
| 42 | +4. `HostScanner` (in `fact/src/host_scanner.rs`) enriches events with process info |
| 43 | +5. Output handlers (in `fact/src/output/`) send to gRPC or stdout as JSON |
| 44 | + |
| 45 | +### Build Integration |
| 46 | +- Cargo build scripts (`build.rs` files) automatically compile BPF C code |
| 47 | +- BPF object files are embedded in the Rust binary |
| 48 | +- No manual BPF compilation needed for normal development |
| 49 | + |
| 50 | +### Configuration |
| 51 | +- Config loaded from YAML files or environment variables/CLI args |
| 52 | +- `Reloader` monitors for SIGHUP and reloads config without restart |
| 53 | +- Paths to monitor can be specified via `--paths` or `FACT_PATHS` |
| 54 | + |
| 55 | +## Common Commands |
| 56 | + |
| 57 | +### Building |
| 58 | +```sh |
| 59 | +# Standard build |
| 60 | +cargo build |
| 61 | + |
| 62 | +# Release build (optimized) |
| 63 | +cargo build --release |
| 64 | + |
| 65 | +# Check without building |
| 66 | +cargo check |
| 67 | +``` |
| 68 | + |
| 69 | +### Running |
| 70 | +```sh |
| 71 | +# Run with sudo (required for BPF) |
| 72 | +cargo run --release --config 'target."cfg(all())".runner="sudo -E"' |
| 73 | + |
| 74 | +# With path monitoring |
| 75 | +cargo run --release --config 'target."cfg(all())".runner="sudo -E"' -- -p /etc -p /var/log |
| 76 | + |
| 77 | +# Skip pre-flight checks (if LSM hook detection fails) |
| 78 | +cargo run --release --config 'target."cfg(all())".runner="sudo -E"' -- --skip-pre-flight |
| 79 | +``` |
| 80 | + |
| 81 | +### Testing |
| 82 | + |
| 83 | +**For agents/automated testing, prefer using pytest integration tests** (no sudo required): |
| 84 | + |
| 85 | +```sh |
| 86 | +# Set up Python virtual environment (first time only) |
| 87 | +python3 -m venv .venv |
| 88 | +source .venv/bin/activate |
| 89 | +pip install -r tests/requirements.txt |
| 90 | + |
| 91 | +# Build container image first |
| 92 | +make image |
| 93 | + |
| 94 | +# Run integration tests with pytest (recommended for agents) |
| 95 | +cd tests/ |
| 96 | +pytest --image="<image-tag>" # e.g., pytest --image="quay.io/stackrox-io/fact:latest" |
| 97 | + |
| 98 | +# Run specific test file |
| 99 | +pytest test_file_open.py --image="<image-tag>" |
| 100 | +``` |
| 101 | + |
| 102 | +**Rust unit tests** (for development): |
| 103 | + |
| 104 | +```sh |
| 105 | +# Run Rust unit tests (excludes BPF tests, no sudo needed) |
| 106 | +cargo test |
| 107 | + |
| 108 | +# Run BPF-specific unit tests (requires sudo, avoid in automated workflows) |
| 109 | +cargo test --config 'target."cfg(all())".runner="sudo -E"' --features=bpf-test |
| 110 | +``` |
| 111 | + |
| 112 | +**Other test targets**: |
| 113 | + |
| 114 | +```sh |
| 115 | +# Run integration tests via Make (uses ansible, requires VMs) |
| 116 | +make integration-tests |
| 117 | + |
| 118 | +# Run performance tests |
| 119 | +make performance-tests |
| 120 | +``` |
| 121 | + |
| 122 | +### Formatting |
| 123 | +```sh |
| 124 | +# Format Rust and C code |
| 125 | +make format |
| 126 | + |
| 127 | +# Check formatting without modifying files |
| 128 | +make format-check |
| 129 | +``` |
| 130 | + |
| 131 | +### Container Image |
| 132 | +```sh |
| 133 | +# Build container image |
| 134 | +make image |
| 135 | + |
| 136 | +# Build mock server for testing |
| 137 | +make mock-server |
| 138 | +``` |
| 139 | + |
| 140 | +### IDE Support for BPF C Code |
| 141 | +Generate `compile_commands.json` for clangd on x86_64: |
| 142 | +```sh |
| 143 | +bear -- clang -target bpf -O2 -g -c -Wall -Werror -D__TARGET_ARCH_x86_64 fact-ebpf/src/bpf/main.c -o /dev/null |
| 144 | +``` |
| 145 | +For arm64, use `-D__TARGET_ARCH_aarch64` instead. |
| 146 | + |
| 147 | +## Development Workflow |
| 148 | + |
| 149 | +### Making Changes to BPF Code |
| 150 | +1. Edit C files in `fact-ebpf/src/bpf/` |
| 151 | +2. Follow existing patterns in `main.c` for LSM hook attachments |
| 152 | +3. Format with `make -C fact-ebpf format` |
| 153 | +4. Test with `cargo test --features=bpf-test` (requires sudo) |
| 154 | + |
| 155 | +### Making Changes to Event Processing |
| 156 | +1. Event definitions are in `fact-ebpf/src/bpf/events.h` (C) and `fact-ebpf/src/lib.rs` (Rust bindings) |
| 157 | +2. Processing logic is in `fact/src/event/mod.rs` and `fact/src/event/process.rs` |
| 158 | +3. Changes to event structure require updates to both C and Rust definitions |
| 159 | + |
| 160 | +### Configuration Changes |
| 161 | +1. Configuration schema is in `fact/src/config/mod.rs` |
| 162 | +2. Hot-reload logic is in `fact/src/config/reloader.rs` |
| 163 | +3. Add unit tests in `fact/src/config/tests.rs` |
| 164 | + |
| 165 | +## Important Notes |
| 166 | + |
| 167 | +- **Preferred testing for agents**: Use pytest integration tests in `tests/` directory (no sudo required) |
| 168 | +- **Python environment**: All Python dependencies must be installed in a virtual environment at `.venv` |
| 169 | +- All BPF operations require root/sudo privileges (avoid in automated testing when possible) |
| 170 | +- The `bpf-test` feature gates tests that load actual BPF programs and requires sudo |
| 171 | +- Build scripts handle BPF compilation automatically - no need to run clang manually |
| 172 | +- Pytest integration tests require a built container image (use `make image` first) |
| 173 | +- The project uses `sudo -E` to preserve environment variables when running with elevated privileges |
| 174 | +- SIGHUP triggers configuration reload without restarting the process |
0 commit comments