From d07dca4b1a1bc4ddbc2b7aa7dc53e9b2b6949107 Mon Sep 17 00:00:00 2001 From: Mauro Ezequiel Moltrasio Date: Fri, 27 Feb 2026 10:47:04 +0100 Subject: [PATCH 1/2] docs: add CLAUDE.md for Claude Code guidance Add comprehensive documentation for future Claude Code instances working in this repository. Includes project overview, workspace structure, architecture patterns, and common commands for building, running, and testing. Emphasizes pytest integration tests in tests/ directory as the preferred testing approach for agents (no sudo required). Assisted-by: Claude Sonnet 4.5 --- CLAUDE.md | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..25a1b516 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,174 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +fact (File ACTivity) is a file integrity monitoring tool designed for PCI DSS compliance. It's implemented as a BPF agent that: +- Attaches BPF programs to LSM (Linux Security Module) hooks in the kernel +- Receives file system events from the kernel via ring buffers +- Enriches events with process and file metadata +- Outputs events via gRPC or JSON for further processing +- Supports hot-reload of configuration via SIGHUP +- Exposes Prometheus metrics + +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. + +## Workspace Structure + +This is a Cargo workspace with three main crates: + +- **fact**: Main binary that loads BPF programs, processes events, and handles output + - `src/bpf/`: Rust code for loading and managing BPF programs (uses aya library) + - `src/event/`: Event processing and enrichment logic + - `src/config/`: Configuration parsing and hot-reload via `Reloader` + - `src/output/`: gRPC and JSON output handlers + - `src/metrics/`: Prometheus metrics exporter + - `src/host_scanner.rs`: Scans host for existing files on startup + +- **fact-api**: gRPC API definitions generated from protobuf files in `third_party/stackrox/proto` + +- **fact-ebpf**: BPF program implementation + - `src/bpf/*.c`: C code for BPF programs that attach to LSM hooks + - `src/lib.rs`: Rust bindings and types for BPF maps/events + - Build script compiles C code to BPF bytecode + +## Key Architecture Patterns + +### Event Flow +1. Kernel LSM hooks trigger BPF programs (in `fact-ebpf/src/bpf/main.c`) +2. BPF programs write events to ring buffer +3. `Bpf` worker (in `fact/src/bpf/mod.rs`) reads from ring buffer, sends to channel +4. `HostScanner` (in `fact/src/host_scanner.rs`) enriches events with process info +5. Output handlers (in `fact/src/output/`) send to gRPC or stdout as JSON + +### Build Integration +- Cargo build scripts (`build.rs` files) automatically compile BPF C code +- BPF object files are embedded in the Rust binary +- No manual BPF compilation needed for normal development + +### Configuration +- Config loaded from YAML files or environment variables/CLI args +- `Reloader` monitors for SIGHUP and reloads config without restart +- Paths to monitor can be specified via `--paths` or `FACT_PATHS` + +## Common Commands + +### Building +```sh +# Standard build +cargo build + +# Release build (optimized) +cargo build --release + +# Check without building +cargo check +``` + +### Running +```sh +# Run with sudo (required for BPF) +cargo run --release --config 'target."cfg(all())".runner="sudo -E"' + +# With path monitoring +cargo run --release --config 'target."cfg(all())".runner="sudo -E"' -- -p /etc -p /var/log + +# Skip pre-flight checks (if LSM hook detection fails) +cargo run --release --config 'target."cfg(all())".runner="sudo -E"' -- --skip-pre-flight +``` + +### Testing + +**For agents/automated testing, prefer using pytest integration tests** (no sudo required): + +```sh +# Set up Python virtual environment (first time only) +python3 -m venv .venv +source .venv/bin/activate +pip install -r tests/requirements.txt + +# Build container image first +make image + +# Run integration tests with pytest (recommended for agents) +cd tests/ +pytest --image="" # e.g., pytest --image="quay.io/stackrox-io/fact:latest" + +# Run specific test file +pytest test_file_open.py --image="" +``` + +**Rust unit tests** (for development): + +```sh +# Run Rust unit tests (excludes BPF tests, no sudo needed) +cargo test + +# Run BPF-specific unit tests (requires sudo, avoid in automated workflows) +cargo test --config 'target."cfg(all())".runner="sudo -E"' --features=bpf-test +``` + +**Other test targets**: + +```sh +# Run integration tests via Make (uses ansible, requires VMs) +make integration-tests + +# Run performance tests +make performance-tests +``` + +### Formatting +```sh +# Format Rust and C code +make format + +# Check formatting without modifying files +make format-check +``` + +### Container Image +```sh +# Build container image +make image + +# Build mock server for testing +make mock-server +``` + +### IDE Support for BPF C Code +Generate `compile_commands.json` for clangd on x86_64: +```sh +bear -- clang -target bpf -O2 -g -c -Wall -Werror -D__TARGET_ARCH_x86_64 fact-ebpf/src/bpf/main.c -o /dev/null +``` +For arm64, use `-D__TARGET_ARCH_aarch64` instead. + +## Development Workflow + +### Making Changes to BPF Code +1. Edit C files in `fact-ebpf/src/bpf/` +2. Follow existing patterns in `main.c` for LSM hook attachments +3. Format with `make -C fact-ebpf format` +4. Test with `cargo test --features=bpf-test` (requires sudo) + +### Making Changes to Event Processing +1. Event definitions are in `fact-ebpf/src/bpf/events.h` (C) and `fact-ebpf/src/lib.rs` (Rust bindings) +2. Processing logic is in `fact/src/event/mod.rs` and `fact/src/event/process.rs` +3. Changes to event structure require updates to both C and Rust definitions + +### Configuration Changes +1. Configuration schema is in `fact/src/config/mod.rs` +2. Hot-reload logic is in `fact/src/config/reloader.rs` +3. Add unit tests in `fact/src/config/tests.rs` + +## Important Notes + +- **Preferred testing for agents**: Use pytest integration tests in `tests/` directory (no sudo required) +- **Python environment**: All Python dependencies must be installed in a virtual environment at `.venv` +- All BPF operations require root/sudo privileges (avoid in automated testing when possible) +- The `bpf-test` feature gates tests that load actual BPF programs and requires sudo +- Build scripts handle BPF compilation automatically - no need to run clang manually +- Pytest integration tests require a built container image (use `make image` first) +- The project uses `sudo -E` to preserve environment variables when running with elevated privileges +- SIGHUP triggers configuration reload without restarting the process From 5fa5c1653ac63bb57eb1d33d2e4c46ec7e56a663 Mon Sep 17 00:00:00 2001 From: Mauro Ezequiel Moltrasio Date: Fri, 27 Feb 2026 12:19:18 +0100 Subject: [PATCH 2/2] chore: specify Assisted-by tag for Claude Code commits Use the attribution setting for commits to add the `Assisted-by` trailer when Claude creates a commit. Add .claude/*.local.* pattern to .gitignore to exclude Claude Code local configuration files from version control. Assisted-by: Claude Sonnet 4.5 --- .claude/settings.json | 5 +++++ .gitignore | 3 +++ 2 files changed, 8 insertions(+) create mode 100644 .claude/settings.json diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 00000000..a261616c --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,5 @@ +{ + "attribution": { + "commit": "Assisted-by: {agentVersion}" + } +} diff --git a/.gitignore b/.gitignore index 624a65d1..f0fa92bd 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ logs/ # clangd and compilation database .cache/ compile_commands.json + +# Claude local configuration +.claude/*.local.*