Add example to apparmor docs

Signed-off-by: Jess Frazelle <jess@mesosphere.com>
This commit is contained in:
Jess Frazelle 2016-04-07 12:05:16 -07:00
parent 1fbdd354c2
commit 80d63e2e11
No known key found for this signature in database
GPG key ID: 18F3685C0022BFF3

View file

@ -20,8 +20,8 @@ Docker automatically loads container profiles. The Docker binary installs
a `docker-default` profile in the `/etc/apparmor.d/docker` file. This profile a `docker-default` profile in the `/etc/apparmor.d/docker` file. This profile
is used on containers, _not_ on the Docker Daemon. is used on containers, _not_ on the Docker Daemon.
A profile for the Docker Engine Daemon exists but it is not currently installed A profile for the Docker Engine daemon exists but it is not currently installed
with the deb packages. If you are interested in the source for the Daemon with the `deb` packages. If you are interested in the source for the daemon
profile, it is located in profile, it is located in
[contrib/apparmor](https://github.com/docker/docker/tree/master/contrib/apparmor) [contrib/apparmor](https://github.com/docker/docker/tree/master/contrib/apparmor)
in the Docker Engine source repository. in the Docker Engine source repository.
@ -72,15 +72,15 @@ explicitly specifies the default policy:
$ docker run --rm -it --security-opt apparmor=docker-default hello-world $ docker run --rm -it --security-opt apparmor=docker-default hello-world
``` ```
## Loading and Unloading Profiles ## Load and unload profiles
To load a new profile into AppArmor, for use with containers: To load a new profile into AppArmor for use with containers:
``` ```bash
$ apparmor_parser -r -W /path/to/your_profile $ apparmor_parser -r -W /path/to/your_profile
``` ```
Then you can run the custom profile with `--security-opt` like so: Then, run the custom profile with `--security-opt` like so:
```bash ```bash
$ docker run --rm -it --security-opt apparmor=your_profile hello-world $ docker run --rm -it --security-opt apparmor=your_profile hello-world
@ -97,39 +97,174 @@ $ apparmor_parser -R /path/to/profile
$ /etc/init.d/apparmor start $ /etc/init.d/apparmor start
``` ```
## Debugging AppArmor ### Resources for writing profiles
### Using `dmesg` The syntax for file globbing in AppArmor is a bit different than some other
globbing implementations. It is highly suggested you take a look at some of the
below resources with regard to AppArmor profile syntax.
- [Quick Profile Language](http://wiki.apparmor.net/index.php/QuickProfileLanguage)
- [Globbing Syntax](http://wiki.apparmor.net/index.php/AppArmor_Core_Policy_Reference#AppArmor_globbing_syntax)
## Nginx example profile
In this example, you create a custom AppArmor profile for Nginx. Below is the
custom profile.
```
#include <tunables/global>
profile docker-nginx flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
network inet tcp,
network inet udp,
network inet icmp,
deny network raw,
deny network packet,
file,
umount,
deny /bin/** wl,
deny /boot/** wl,
deny /dev/** wl,
deny /etc/** wl,
deny /home/** wl,
deny /lib/** wl,
deny /lib64/** wl,
deny /media/** wl,
deny /mnt/** wl,
deny /opt/** wl,
deny /proc/** wl,
deny /root/** wl,
deny /sbin/** wl,
deny /srv/** wl,
deny /tmp/** wl,
deny /sys/** wl,
deny /usr/** wl,
audit /** w,
/var/run/nginx.pid w,
/usr/sbin/nginx ix,
deny /bin/dash mrwklx,
deny /bin/sh mrwklx,
deny /usr/bin/top mrwklx,
capability chown,
capability dac_override,
capability setuid,
capability setgid,
capability net_bind_service,
deny @{PROC}/{*,**^[0-9*],sys/kernel/shm*} wkx,
deny @{PROC}/sysrq-trigger rwklx,
deny @{PROC}/mem rwklx,
deny @{PROC}/kmem rwklx,
deny @{PROC}/kcore rwklx,
deny mount,
deny /sys/[^f]*/** wklx,
deny /sys/f[^s]*/** wklx,
deny /sys/fs/[^c]*/** wklx,
deny /sys/fs/c[^g]*/** wklx,
deny /sys/fs/cg[^r]*/** wklx,
deny /sys/firmware/efi/efivars/** rwklx,
deny /sys/kernel/security/** rwklx,
}
```
1. Save the custom profile to disk in the
`/etc/apparmor.d/containers/docker-nginx` file.
The file path in this example is not a requirement. In production, you could
use another.
2. Load the profile.
```bash
$ sudo apparmor_parser -r -W /etc/apparmor.d/containers/docker-nginx
```
3. Run a container with the profile.
To run nginx in detached mode:
```bash
$ docker run --security-opt "apparmor=docker-nginx" \
-p 80:80 -d --name apparmor-nginx nginx
```
4. Exec into the running container
```bash
$ docker exec -it apparmor-nginx bash
```
5. Try some operations to test the profile.
```bash
root@6da5a2a930b9:~# ping 8.8.8.8
ping: Lacking privilege for raw socket.
root@6da5a2a930b9:/# top
bash: /usr/bin/top: Permission denied
root@6da5a2a930b9:~# touch ~/thing
touch: cannot touch 'thing': Permission denied
root@6da5a2a930b9:/# sh
bash: /bin/sh: Permission denied
root@6da5a2a930b9:/# dash
bash: /bin/dash: Permission denied
```
Congrats! You just deployed a container secured with a custom apparmor profile!
## Debug AppArmor
You can use `demsg` to debug problems and `aa-status` check the loaded profiles.
### Use dmesg
Here are some helpful tips for debugging any problems you might be facing with Here are some helpful tips for debugging any problems you might be facing with
regard to AppArmor. regard to AppArmor.
AppArmor sends quite verbose messaging to `dmesg`. Usually an AppArmor line AppArmor sends quite verbose messaging to `dmesg`. Usually an AppArmor line
will look like the following: looks like the following:
``` ```
[ 5442.864673] audit: type=1400 audit(1453830992.845:37): apparmor="ALLOWED" operation="open" profile="/usr/bin/docker" name="/home/jessie/docker/man/man1/docker-attach.1" pid=10923 comm="docker" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0 [ 5442.864673] audit: type=1400 audit(1453830992.845:37): apparmor="ALLOWED" operation="open" profile="/usr/bin/docker" name="/home/jessie/docker/man/man1/docker-attach.1" pid=10923 comm="docker" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
``` ```
In the above example, the you can see `profile=/usr/bin/docker`. This means the In the above example, you can see `profile=/usr/bin/docker`. This means the
user has the `docker-engine` (Docker Engine Daemon) profile loaded. user has the `docker-engine` (Docker Engine Daemon) profile loaded.
> **Note:** On version of Ubuntu > 14.04 this is all fine and well, but Trusty > **Note:** On version of Ubuntu > 14.04 this is all fine and well, but Trusty
> users might run into some issues when trying to `docker exec`. > users might run into some issues when trying to `docker exec`.
Let's look at another log line: Look at another log line:
``` ```
[ 3256.689120] type=1400 audit(1405454041.341:73): apparmor="DENIED" operation="ptrace" profile="docker-default" pid=17651 comm="docker" requested_mask="receive" denied_mask="receive" [ 3256.689120] type=1400 audit(1405454041.341:73): apparmor="DENIED" operation="ptrace" profile="docker-default" pid=17651 comm="docker" requested_mask="receive" denied_mask="receive"
``` ```
This time the profile is `docker-default`, which is run on containers by This time the profile is `docker-default`, which is run on containers by
default unless in `privileged` mode. It is telling us, that apparmor has denied default unless in `privileged` mode. This line shows that apparmor has denied
`ptrace` in the container. This is great. `ptrace` in the container. This is exactly as expected.
### Using `aa-status` ### Use aa-status
If you need to check which profiles are loaded you can use `aa-status`. The If you need to check which profiles are loaded, you can use `aa-status`. The
output looks like: output looks like:
```bash ```bash
@ -162,17 +297,17 @@ apparmor module is loaded.
0 processes are unconfined but have a profile defined. 0 processes are unconfined but have a profile defined.
``` ```
In the above output you can tell that the `docker-default` profile running on The above output shows that the `docker-default` profile running on various
various container PIDs is in `enforce` mode. This means AppArmor will actively container PIDs is in `enforce` mode. This means AppArmor is actively blocking
block and audit in `dmesg` anything outside the bounds of the `docker-default` and auditing in `dmesg` anything outside the bounds of the `docker-default`
profile. profile.
The output above also shows the `/usr/bin/docker` (Docker Engine Daemon) The output above also shows the `/usr/bin/docker` (Docker Engine daemon) profile
profile is running in `complain` mode. This means AppArmor will _only_ log to is running in `complain` mode. This means AppArmor _only_ logs to `dmesg`
`dmesg` activity outside the bounds of the profile. (Except in the case of activity outside the bounds of the profile. (Except in the case of Ubuntu
Ubuntu Trusty, where we have seen some interesting behaviors being enforced.) Trusty, where some interesting behaviors are enforced.)
## Contributing to AppArmor code in Docker ## Contribute Docker's AppArmor code
Advanced users and package managers can find a profile for `/usr/bin/docker` Advanced users and package managers can find a profile for `/usr/bin/docker`
(Docker Engine Daemon) underneath (Docker Engine Daemon) underneath