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/bad.sh
is denied with auditing due toaudit 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###
# ###COPYRIGHT###
# ###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=10.0.2.15 lport=46314
faddr=10.0.2.16 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
A
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
A
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
A
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
A
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
I
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
S
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