๐ŸŽ New User? Get 20% off your first purchase with code NEWUSER20 ยท โšก Instant download ยท ๐Ÿ”’ Secure checkout Register Now โ†’
Menu

Categories

AppArmor Profile Security Check: Ubuntu/Debian Guide

AppArmor Profile Security Check: Ubuntu/Debian Guide

AppArmor is the mandatory access control framework that Ubuntu, Debian, and openSUSE ship enabled by default โ€” and that most administrators never look at twice. A correctly configured AppArmor profile contains the damage of a compromised process: a hijacked nginx cannot read /etc/shadow, a backdoored cron job cannot dial out on arbitrary ports. This guide covers how to inventory profiles, switch between modes, troubleshoot denials, and write a custom profile that survives package upgrades.

Confirm AppArmor is actually enforcing

sudo aa-status
sudo aa-status --enabled && echo enabled
cat /sys/kernel/security/apparmor/profiles | head
sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx     # set one profile to enforce

Healthy aa-status output: "X profiles are loaded", "Y profiles are in enforce mode", "Z processes have profiles defined". A server with all profiles in complain mode is in audit-only โ€” denials are logged but not blocked.

The four operational modes

  • enforce โ€” denials are blocked and logged. The default for most shipped profiles.
  • complain โ€” denials are logged but allowed. Useful when developing a profile.
  • audit โ€” every access is logged (noisy; for forensics only).
  • disable โ€” profile is loaded but inactive. Equivalent to no profile.
sudo aa-enforce  /etc/apparmor.d/usr.sbin.nginx
sudo aa-complain /etc/apparmor.d/usr.sbin.nginx
sudo aa-disable  /etc/apparmor.d/usr.sbin.nginx
sudo aa-status | grep nginx

Inventory: which processes are confined

sudo aa-status --enforced
sudo aa-status --complaining
ps -eZ | head                                # process security context
cat /proc/$(pgrep -f nginx | head -1)/attr/current

The last command shows the AppArmor context of a running process. An entry like /usr/sbin/nginx (enforce) means active enforcement; an empty result or unconfined means the binary runs without restriction.

Troubleshooting denials

When a confined service starts misbehaving after an update, check the kernel log:

sudo dmesg | grep -i 'apparmor.*DENIED'
sudo journalctl -k --since today | grep apparmor
sudo aa-notify -s 1 -v                       # last day of denials with summary

Each denial shows: operation (e.g. open, exec, capable), profile, name (the path or capability), and requested_mask. Read the line, decide whether to allow or fix the application, then update the profile.

Adding allowed paths to a profile

Profiles live in /etc/apparmor.d/. Convention: filename is the binary path with / replaced by . โ€” /usr/sbin/nginx becomes /etc/apparmor.d/usr.sbin.nginx. To allow nginx to write a new log directory:

sudo $EDITOR /etc/apparmor.d/local/usr.sbin.nginx
# add: /var/log/myapp/** rw,
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx

Always edit the local/ include, not the main file โ€” distribution upgrades overwrite the main profile, and your edits survive in local/.

Generating a profile from scratch

sudo aa-genprof /usr/local/bin/myapp
# in another terminal: exercise the application
# back in the wizard: choose 'S' to scan denials, 'A' to allow, 'F' to finish

aa-genprof watches kernel denials in real time and proposes allow rules. After saving, switch the profile to enforce and re-test. Iterate with aa-logprof when the application gains new behaviour.

Profile syntax cheatsheet

/usr/local/bin/myapp {
  # capabilities
  capability net_bind_service,
  capability dac_override,

  # files
  /etc/myapp/**         r,
  /var/log/myapp/**     rw,
  /var/lib/myapp/**     rwk,        # k = file locking
  /usr/lib/x86_64-linux-gnu/** mr,  # m = mmap, r = read

  # network
  network inet stream,
  network inet dgram,

  # signals
  signal (send) peer=unconfined,

  # subprocess (run /bin/sh under its own profile or unconfined)
  /bin/sh ix,                        # ix = inherit profile
}

Container considerations

Docker on Ubuntu/Debian applies the docker-default profile to every container by default. Override per-container with --security-opt apparmor=my-profile. To audit:

docker info | grep -i apparmor
sudo aa-status | grep docker
docker run --security-opt apparmor=docker-default nginx

The audit script

#!/bin/bash
echo "== AppArmor mode =="
aa-status --enabled && echo enabled
echo "== Profile counts =="
aa-status | grep -E 'profiles are|processes are'
echo "== Profiles in complain mode =="
aa-status --complaining
echo "== Running unconfined processes (interesting ones) =="
aa-status --process-mixed | grep -E 'sshd|nginx|apache|postgres|mysql' || echo "all confined"
echo "== Recent denials =="
journalctl -k --since '24 hours ago' | grep -c 'apparmor=.DENIED.'

Common pitfalls

  • Disabling AppArmor entirely as a "fix" for one denial โ€” you lose the protection for every other binary.
  • Editing the upstream profile file; distribution upgrades silently revert your changes.
  • Leaving a profile in complain after debugging; the host appears protected but is not.
  • Forgetting to apparmor_parser -r after editing โ€” the kernel keeps the old profile loaded.

AppArmor is high-leverage security: ten minutes per service to write or extend a profile blocks an entire class of post-exploitation movement. Audit your profiles monthly, ship denial counts to your monitoring, and treat every unconfined process on a hardened server as a follow-up ticket.

Share this article:
Dargslan Editorial Team (Dargslan)
About the Author

Dargslan Editorial Team (Dargslan)

Collective of Software Developers, System Administrators, DevOps Engineers, and IT Authors

Dargslan is an independent technology publishing collective formed by experienced software developers, system administrators, and IT specialists.

The Dargslan editorial team works collaboratively to create practical, hands-on technology books focused on real-world use cases. Each publication is developed, reviewed, and...

Programming Languages Linux Administration Web Development Cybersecurity Networking

Stay Updated

Subscribe to our newsletter for the latest tutorials, tips, and exclusive offers.