Learn AppArmor - Profile Tools: aa-genprof & aa-logprof
Episode 5 of 23

Learn AppArmor - Profile Tools: aa-genprof & aa-logprof

Boosting productivity with AppArmor's interactive tools: creating a new profile with aa-genprof directly from a target executable, allowing and denying each request that appears, updating a profile from denial logs with aa-logprof, and verifying the final result.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Introduction

In episode 4 you wrote profiles manually — and you certainly felt how detailed that work is: listing every library, every path, every glob pattern. In the real world, a production application can produce hundreds of legitimate denials during boot and normal operation. Writing all of that by hand is wasteful. The solution: two interactive tools we'll master today — aa-genprof for creating new profiles and aa-logprof for updating existing ones.

Imagine the difference between writing an SOP by opening every cabinet and noting each allowed access one by one, versus living through one normal workday while an assistant records everything you touch, then turns it into an SOP automatically. That's the difference between writing manually and using these two tools.

aa-genprof: Creating a Profile from an Executable

aa-genprof creates a new profile skeleton directly from the target executable. Its workflow resembles learning mode: the tool runs the application in complain mode, has you perform normal work scenarios, then offers every access that appears for you to allow or deny.

Start by removing the old profile (if any) and running the generator:

Run aa-genprof for /usr/sbin/nginx
sudo aa-genprof /usr/sbin/nginx

The tool will create a very minimal initial profile and show an interactive prompt like this:

aa-genprof's first prompt
Writing updated profile for /usr/sbin/nginx.
 
Profiling: /usr/sbin/nginx
 
Seen 2 log entries
 [(S)can path (I)nherit (P)rofile (C)omplain (N)ew (A)llow / (D)eny / (G)lob
 / (R)emove] (S)can for new events

The application is now running in complain mode — any access that isn't allowed will show up in the logs, and aa-genprof offers them one by one. This is where you have to work: in another terminal window, run the application's normal work scenarios. For nginx for example, restart the service, request a few pages, let it write logs.

Once the scenarios are done, go back to the aa-genprof window and press S to scan for new log entries. The tool will show one denial at a time:

Denial permission prompt
Reading log entries from /var/log/syslog.
 
 Profile: /usr/sbin/nginx
 Path: /etc/nginx/nginx.conf
 New Mode: r
 
 [1 - /etc/nginx/nginx.conf r]
 (A)llow / (D)eny / (I)gnore / (G)lob / (G)lob_ext / (N)ew / (A)udit
 [A]llow changes for this profile?

For each prompt, the main choices:

ChoiceMeaning
A (Allow)Allow the access exactly as requested
D (Deny)Add it as a deny rule — the access stays blocked
I (Ignore)Ignore this entry; it won't enter the profile
G (Glob)Expand the path into a glob pattern, e.g. /etc/nginx/**
A (Audit)Log this access for observation

The principle to hold onto: allow what's legitimate, deny what's suspicious. When in doubt whether a path needs to be accessed, choose Ignore first and see if the application still works. If errors appear, allow it on the next iteration. After all entries are processed, press S then F to save — aa-genprof writes the complete profile to /etc/apparmor.d/ and loads it.

aa-logprof: Updating a Profile from Logs

aa-logprof is aa-genprof's sibling for profiles that already exist. It reads denial logs, compares them with the loaded profile, and offers updates — without having to rewrite the whole profile. This is the main tool for long-term profile maintenance.

Update a profile from denial logs
sudo aa-logprof

aa-logprof scans logs from the default sources (/var/log/syslog, journald, or auditd), shows denials not covered by the profile, and offers the same choices as aa-genprof. Example prompt:

aa-logprof update prompt
 Profile: /usr/sbin/nginx
 Path: /var/lib/nginx/cache/index.html
 New Mode: w
 
 [1 - /var/lib/nginx/cache/** w]
 (A)llow / (D)eny / (I)gnore / (G)lob / (G)lob_ext / (N)ew / (A)udit
 [A]llow changes for this profile?

Notice the G (Glob) option here: nginx writes many files in /var/lib/nginx/cache/ whose names are hashed. Allowing them one by one makes no sense — press G to turn it into /var/lib/nginx/cache/** w and allow it all at once. This ability to abstract into globs is what makes aa-logprof more than a denial filler: it also tidies up profiles so they don't bloat.

Filtering Deny Noise

A classic problem on production systems: logs flooded with repeated, irrelevant denials — what's commonly called deny noise. Example: a daemon trying to read a file that doesn't exist, or a process checking several alternative paths before finding the right one. aa-logprof offers several ways to handle this:

ChoiceRight use
I (Ignore)A one-off denial that doesn't recur — keep it out of the profile
D (Deny)A path that must stay blocked — make it an explicit deny
A (Audit)Want to keep monitoring this path without allowing it

The most common combination for reducing noise: Ignore for unimportant denials, Deny for dangerous paths that get accessed often. The goal — like a tidy SOP — is a profile that contains only the decisions that are actually needed, not every denial that ever happened.

Tip

Get into the habit of working from a bounded log: use aa-logprof -f <log-file> to process a single specific log file, for example one day's log or one debugging session. Processing the entire log at once will drown you in hundreds of prompts.

Verifying the Resulting Profile

After aa-genprof and aa-logprof finish, your work isn't over. The interactive tools produce decisions from prompts — some of them may be too broad or incomplete. Get into the habit of three verification steps:

First, read the resulting profile — make sure no odd rule slipped through:

Read the genprof result
sudo cat /etc/apparmor.d/usr.sbin.nginx

Second, validate the syntax and make sure the profile is in the right mode:

Validate and check the profile mode
sudo apparmor_parser -Q /etc/apparmor.d/usr.sbin.nginx
sudo aa-status | grep nginx

Third — and most important — test the application thoroughly. Run all normal work scenarios: restart, requests, log rotation, config reload. If the application works without new denials, the profile is ready for enforce. If there are legitimate new denials, that's not a failure — it's the next iteration, which just needs aa-logprof once more.

Important

Never promote a profile to enforce right after aa-genprof finishes. The scenarios you ran during learning mode almost certainly don't cover every application behavior — for example a midnight log rotation or a database connection that only activates after a few hours. Give it time in complain, then promote once you're confident.

Common Pitfalls

  1. Rushing to press A without thinking. Every Allow is a permanent grant you give. Verify the path and operation before approving.
  2. Not running scenarios during aa-genprof. An empty learning mode produces an empty profile. Exercise the application with realistic scenarios before scanning the logs.
  3. Ignoring the Glob option. Allowing denials one by one bloats the profile. Use Glob for clearly recurring patterns.
  4. Going straight to enforce after genprof. Always give a complain period and test full scenarios first.
  5. Processing the entire log without a filter. Use aa-logprof -f <file> so you can still read every prompt wisely.

Conclusion

In episode 5 we mastered the two most productive tools in the AppArmor ecosystem: aa-genprof for creating new profiles from an executable with a learning-mode workflow, and aa-logprof for updating existing profiles from denial logs — complete with deny-noise filtering strategies and verification of the tool-generated profiles.

The core takeaways:

  • aa-genprof <path> creates a new profile skeleton and guides you through allowing/denying access one by one.
  • aa-logprof updates existing profiles from logs — the primary long-term maintenance tool.
  • The core choices in both tools: Allow, Deny, Ignore, Glob, Audit — understand when to use each.
  • Glob abstracts recurring patterns; Ignore suppresses deny noise.
  • Always verify the profile and test the application before going to enforce; give it a complain period.

In episode 6, we'll extend profile capabilities to the network and privilege dimensions: network & capabilities rules — controlling TCP/UDP and Unix sockets, using capability for granular privileges, and rlimit to bound process resources. Keep your momentum, because from here your profiles start protecting applications on every dimension, not just files!

Learn AppArmor - Profile Tools: aa-genprof & aa-logprof | Learn AppArmor