How to create an AppArmor Profile in ubuntu 20.04

Introduction to AppArmor Profiles

AppArmor profiles are simple text files. Absolute paths as well as file globbing can be used when specifying file access. Most file access rules specify the type of access which is allowed: ‘r’ (read), ‘w’ (write), ‘m’ (memory map as executable), ‘k’ (file locking), ‘l’ (creation hard links), and ‘ix’ to execute another program with the new program inheriting policy. Other file access rules also exist such as ‘Px’ (execute under another profile, after cleaning the environment), ‘Cx’ (execute under a child profile, after cleaning the environment), and ‘Ux’ (execute unconfined, after cleaning the environment).

AppArmor supports access controls for:

  • files
  • Linux capabilities
  • network
  • mount, remount and umount
  • pivot_root
  • ptrace
  • signal
  • DBus
  • unix domain sockets

In addition:

  • variables (eg @{HOME} can be defined and manipulated outside the profile (#include <tunables/global> for @{PROC} and @{HOME})
  • explicit deny rules are supported to override allow rules (eg access to @{HOME}/bin/ is denied with auditing due to audit deny @{HOME}/bin/** mrwkl, even though general access to @{HOME} is permitted with @{HOME}/** rw,)
  • include files are supported to ease development and simplify profiles (ie #include <abstractions/base>, #include <abstractions/nameservice>, #include <abstractions/user-tmp>)

To get started, let’s install some useful AppArmor utilities and the application that we want to confine:

sudo apt install apparmor-easyprof apparmor-notify apparmor-utils certspotter

Generating a basic profile

The easiest way to get started is to create a skeleton profile, set AppArmor to complain mode for your target and then use the aa-logprof tool to evaluate the denials.

We’ll use aa-easyprof to generate the skeleton policy; let’s see what it generates (be sure to specify the absolute path to the application):

$ aa-easyprof /usr/bin/certspotter
# vim:syntax=apparmor
# AppArmor policy for certspotter
# ###AUTHOR###
# ###COMMENT###

#include <tunables/global>

# No template variables specified

"/usr/bin/certspotter" {
#include <abstractions/base>

# No abstractions specified

# No policy groups specified

# No read paths specified

# No write paths specified

Looks pretty basic, so let’s write that output into the profile file (the name of the file can be anything; it is the contents of the file which matter):

$ aa-easyprof /usr/bin/certspotter > usr.bin.certspotter
$ sudo mv usr.bin.certspotter /etc/apparmor.d

and then load the profile into the kernel:

$ sudo apparmor_parser -r /etc/apparmor.d/usr.bin.certspotter

Trying to run certspotter, results in an immediate (safe) crash.

$ certspotter
certspotter: /home/testuser/.certspotter/watchlist: 
open /home/testuser/.certspotter/watchlist permission denied

This basic profile doesn’t allow certspotter access to resources it needs, so let’s look at the AppArmor denial messages to see what went wrong.


AppArmor Denials and Complain Mode

AppArmor denials are logged to /var/log/syslog (or /var/log/audit/audit.log for non-DBus policy violations if auditd is installed). The kernel will rate limit AppArmor denials which can cause problems while profiling. You can avoid this by installing auditd or by adjusting rate limiting in the kernel:

$ sudo sysctl -w kernel.printk_ratelimit=0

Another way to to view AppArmor denials is by using the aa-notify tool. aa-notify is a very simple program that will report any new AppArmor denials by consulting /var/log/syslog (or /var/log/audit/audit.log if auditd is installed). For example,

$ /usr/bin/aa-notify -s 1 -v

will show any AppArmor denials within the last day.

We are going to take the easy route to develop this profile and use the aa-logprof tool to evaluate the log entries that AppArmor makes in complain mode, so let’s set the AppArmor profile for certspotter to complain mode for this policy so that we can see what is happening.

$ sudo aa-complain certspotter

Now let’s try running certspotter again:

$ certspotter

It immediately starts generating AppArmor entries in the logs that look like this:

Feb 23 13:34:24 tutorials audit[18643]: AVC apparmor="ALLOWED" 
operation="recvmsg" profile="/usr/bin/certspotter" 
pid=18643 comm="certspotter" laddr= lport=46314 
faddr= fport=443 family="inet" sock_type="stream" 
protocol=6 requested_mast="receive" denied_mask="receive"

because we haven’t yet created the profile rules to allow it to access the network.

Using aa-logprof to Refine the Profile

The aa-logprof tool will parse the AppArmor messages and suggest policy rules which would permit certspotter to run under confinement.

$ sudo aa-logprof
Reading log entries from /var/log/syslog.
Updating AppArmor profiles in /etc/apparmor.d.
Complain-mode changes:

Profile: /usr/bin/certspotter
Path: /proc/sys/net/core/somaxconn
New Mode: r
Severity: 6

[1 - /proc/sys/net/core/somaxconn r,]
(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / 
(N) ew / Audi(t) / Abo(r)t / (F)inish


There is no problem with letting certspotter read this file which specifies the maximum number of open socket connections, so we type A to allow it.

Profile: /usr/bin/certspotter
Path: /etc/nsswitch.conf
New Mode: r
Severity: unknown

[1 - #include <abstractions/nameservice>]
2 - /etc/nsswitch.conf r,
(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension 
/ (N) ew / Audi(t) / Abo(r)t / (F)inish


certspotter uses the network to retrieve information from the certificate transparency logs. We have the choice to either specifically allow this first network related access or to use the existing nameservice abstraction which grants common access patterns. You can review the details of the abstraction in /etc/apparmor.d/abstractions/nameservice. This access pattern makes sense for certspotter, so let’s allow it.

Profile: /usr/bin/certspotter
Path: /proc/sys/kernel/hostname
New Mode: r
Severity: 6

[1 - /proc/sys/kernel/hostname r,]
(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / 
(N) ew / Audi(t) / Abo(r)t / (F)inish


We don’t have a problem with certspotter knowing the system’s hostname, so let’s Allow it.

Profile: /usr/bin/certspotter
Path: /home/testuser/.certspotter/watchlist
New Mode: r
Severity: 4

[1 - /home/*/.certspotter/watchlist r,]
2 - /home/testuser/.certspotter/watchlist r,
(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension /
 (N) ew / Audi(t) / Abo(r)t / (F)inish


certspotter reads the watchlist to determine which domains to monitor. We want certspotter to work for all users of the system and not just ourselves, so suggested rule 1 is better than rule 2. However we also know that certspotter uses the .certspotter directory to write information that it discovers, its lock file and other data, so this ‘r’ rule will be insufficient. Additionally, we would prefer to use the @{HOME} tunable rather than the globbed path. For now, let’s accept it as a placeholder and take a TODO to touch it up later.

Profile: /usr/bin/certspotter
Path: /home/testuser/.certspotter/version
New Mode: r
Severity: 4

[1 - /home/*/.certspotter/version r,]
2 - /home/testuser/.certspotter/version r,
(A)llow / [(D)eny] / (I)gnore / (G)lob / Glob with (E)xtension / (N) ew / 
Audi(t) / Abo(r)t / (F)inish

When we touch up the watchlist rule, we should cover all of these entries about files in $HOME/.certspotter, so we will Ignore these suggested rules for now.

<rule suggestions for other files in $HOME/.certspotter omitted>

Enforce-mode changes:

= Change Local Profiles =
The following local profiles were changed. Would you like to save them?

[1 - /usr/bin/certspotter]
(S)ave Changes / Save Selec(t)ed Profile / [(V)iew Changes] / View Change b/w 
(C)lean profiles / Abo(r)t

When you Save the profile, aa-logprof automatically causes the profile to be reloaded which immediately silences all of the AppArmor messages about certspotter using the network.


Hand Editing the Profile

Let’s go back and touch up the profile to allow certspotter to read and write from the $HOME/.certspotter directory.

$ sudo vi /etc/apparmor.d/usr.bin.certspotter

let’s change the /home/*/.certspotter/watchlist r, line to owner @{HOME}/.certspotter/** rw,. The ** glob means certspotter can now read and write to all files, directories and all paths under the current user’s .certspotter directory in their home directory. You can take this opportunity to touch up the ###AUTHOR###, ###COPYRIGHT###, and ###COMMENT### placeholders with your preferred information. Reload the policy once again:

$ sudo apparmor_parser -r /etc/apparmor.d/usr.bin.certspotter

Next Post Previous Post
No Comment
Add Comment
comment url