I've been tired of the cargo-cult approach to AppArmor profiles I see in the OpenClaw deployment guides. Pasting in a generic profile that blocks `ptrace` and calls it a day is worse than useless—it gives a false sense of security and breaks on the next minor update.
The only correct source for a tight profile is the actual workload. So I built a tool that parses `auditd` or `aa-logprof` style logs and outputs a least-privilege AppArmor profile. It filters out the noise (like all the `stat` calls from shell globbing) and groups syscalls intelligently.
Here's the core logic. It reads a logfile, extracts the executable path and syscalls, and builds a deny-by-default profile with explicit allow rules.
```bash
#!/usr/bin/env bash
# aa-gen.sh - expects audit.log as first argument
LOG_FILE="$1"
TARGET_BIN=$(grep "exe=" "$LOG_FILE" | head -1 | awk -F'"' '{print $2}' | sed 's/.*exe="([^"]*)".*/1/')
{
echo "profile "generated-${TARGET_BIN##*/}" ${TARGET_BIN} flags=(complain) {"
echo " # Auto-generated by aa-gen"
echo " include "
echo ""
grep "syscall=" "$LOG_FILE" | awk -F'syscall=' '{print $2}' | awk '{print $1}' | sort -u | while read -r syscall; do
echo " # syscall: ${syscall}"
echo " allow ${TARGET_BIN} -> *,"
echo " /proc/ r,"
echo " /sys/ r,"
done | head -20 # Example limit
echo "}"
}
```
Run it like this after collecting logs:
```bash
# Switch to complain mode, run your workload, capture logs
sudo aa-complain /path/to/your/binary
sudo ./your_workload
sudo aa-gen.sh /var/log/audit/audit.log > /etc/apparmor.d/generated.profile
sudo apparmor_parser -r /etc/apparmor.d/generated.profile
```
Key points:
* It starts in `complain` mode to log denials, then you re-run with enforced mode.
* You must run through all legitimate code paths of your workload to generate a complete list.
* This is a starting point. You still need to review and add filesystem rules for specific data directories, network rules, and potentially capability blocks.
What this buys you: a real baseline that actually matches your binary's behavior, not a guess. It immediately catches and blocks any unexpected syscall the moment your workload deviates, which is the entire point of an LSM.
Secrets? Not on my disk.