summaryrefslogtreecommitdiff
path: root/devdocs/docker/engine%2Fsecurity%2Fapparmor%2Findex.html
diff options
context:
space:
mode:
Diffstat (limited to 'devdocs/docker/engine%2Fsecurity%2Fapparmor%2Findex.html')
-rw-r--r--devdocs/docker/engine%2Fsecurity%2Fapparmor%2Findex.html134
1 files changed, 134 insertions, 0 deletions
diff --git a/devdocs/docker/engine%2Fsecurity%2Fapparmor%2Findex.html b/devdocs/docker/engine%2Fsecurity%2Fapparmor%2Findex.html
new file mode 100644
index 00000000..a146da07
--- /dev/null
+++ b/devdocs/docker/engine%2Fsecurity%2Fapparmor%2Findex.html
@@ -0,0 +1,134 @@
+<h1>AppArmor security profiles for Docker</h1>
+
+<p>AppArmor (Application Armor) is a Linux security module that protects an operating system and its applications from security threats. To use it, a system administrator associates an AppArmor security profile with each program. Docker expects to find an AppArmor policy loaded and enforced.</p> <p>Docker automatically generates and loads a default profile for containers named <code class="language-plaintext highlighter-rouge">docker-default</code>. The Docker binary generates this profile in <code class="language-plaintext highlighter-rouge">tmpfs</code> and then loads it into the kernel.</p> <blockquote> <p><strong>Note</strong>: This profile is used on containers, <em>not</em> on the Docker Daemon.</p> </blockquote> <p>A profile for the Docker Engine daemon exists but it is not currently installed with the <code class="language-plaintext highlighter-rouge">deb</code> packages. If you are interested in the source for the daemon profile, it is located in <a href="https://github.com/moby/moby/tree/master/contrib/apparmor">contrib/apparmor</a> in the Docker Engine source repository.</p> <h2 id="understand-the-policies">Understand the policies</h2> <p>The <code class="language-plaintext highlighter-rouge">docker-default</code> profile is the default for running containers. It is moderately protective while providing wide application compatibility. The profile is generated from the following <a href="https://github.com/moby/moby/blob/master/profiles/apparmor/template.go">template</a>.</p> <p>When you run a container, it uses the <code class="language-plaintext highlighter-rouge">docker-default</code> policy unless you override it with the <code class="language-plaintext highlighter-rouge">security-opt</code> option. For example, the following explicitly specifies the default policy:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker run --rm -it --security-opt apparmor=docker-default hello-world
+</pre></div> <h2 id="load-and-unload-profiles">Load and unload profiles</h2> <p>To load a new profile into AppArmor for use with containers:</p> <div class="highlight"><pre class="highlight" data-language="">$ apparmor_parser -r -W /path/to/your_profile
+</pre></div> <p>Then, run the custom profile with <code class="language-plaintext highlighter-rouge">--security-opt</code> like so:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker run --rm -it --security-opt apparmor=your_profile hello-world
+</pre></div> <p>To unload a profile from AppArmor:</p> <div class="highlight"><pre class="highlight" data-language=""># unload the profile
+$ apparmor_parser -R /path/to/profile
+</pre></div> <h3 id="resources-for-writing-profiles">Resources for writing profiles</h3> <p>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.</p> <ul> <li><a href="https://gitlab.com/apparmor/apparmor/wikis/QuickProfileLanguage">Quick Profile Language</a></li> <li><a href="https://gitlab.com/apparmor/apparmor/wikis/AppArmor_Core_Policy_Reference#AppArmor_globbing_syntax">Globbing Syntax</a></li> </ul> <h2 id="nginx-example-profile">Nginx example profile</h2> <p>In this example, you create a custom AppArmor profile for Nginx. Below is the custom profile.</p> <div class="highlight"><pre class="highlight" data-language="">#include &lt;tunables/global&gt;
+
+
+profile docker-nginx flags=(attach_disconnected,mediate_deleted) {
+ #include &lt;abstractions/base&gt;
+
+ 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}/* w, # deny write for all files directly in /proc (not in a subdir)
+ # deny write to files not in /proc/&lt;number&gt;/** or /proc/sys/**
+ deny @{PROC}/{[^1-9],[^1-9][^0-9],[^1-9s][^0-9y][^0-9s],[^1-9][^0-9][^0-9][^0-9]*}/** w,
+ deny @{PROC}/sys/[^k]** w, # deny /proc/sys except /proc/sys/k* (effectively /proc/sys/kernel)
+ deny @{PROC}/sys/kernel/{?,??,[^s][^h][^m]**} w, # deny everything except shm* in /proc/sys/kernel/
+ 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/** rwklx,
+ deny /sys/kernel/security/** rwklx,
+}
+</pre></div> <ol> <li> <p>Save the custom profile to disk in the <code class="language-plaintext highlighter-rouge">/etc/apparmor.d/containers/docker-nginx</code> file.</p> <p>The file path in this example is not a requirement. In production, you could use another.</p> </li> <li> <p>Load the profile.</p> <div class="highlight"><pre class="highlight" data-language="">$ sudo apparmor_parser -r -W /etc/apparmor.d/containers/docker-nginx
+</pre></div> </li> <li> <p>Run a container with the profile.</p> <p>To run nginx in detached mode:</p> <div class="highlight"><pre class="highlight" data-language="">$ docker run --security-opt "apparmor=docker-nginx" \
+ -p 80:80 -d --name apparmor-nginx nginx
+</pre></div> </li> <li> <p>Exec into the running container.</p> <div class="highlight"><pre class="highlight" data-language="">$ docker container exec -it apparmor-nginx bash
+</pre></div> </li> <li> <p>Try some operations to test the profile.</p> <div class="highlight"><pre class="highlight" data-language="">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
+</pre></div> </li> </ol> <p>Congrats! You just deployed a container secured with a custom apparmor profile!</p> <h2 id="debug-apparmor">Debug AppArmor</h2> <p>You can use <code class="language-plaintext highlighter-rouge">dmesg</code> to debug problems and <code class="language-plaintext highlighter-rouge">aa-status</code> check the loaded profiles.</p> <h3 id="use-dmesg">Use dmesg</h3> <p>Here are some helpful tips for debugging any problems you might be facing with regard to AppArmor.</p> <p>AppArmor sends quite verbose messaging to <code class="language-plaintext highlighter-rouge">dmesg</code>. Usually an AppArmor line looks like the following:</p> <div class="highlight"><pre class="highlight" data-language="">[ 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
+</pre></div> <p>In the above example, you can see <code class="language-plaintext highlighter-rouge">profile=/usr/bin/docker</code>. This means the user has the <code class="language-plaintext highlighter-rouge">docker-engine</code> (Docker Engine Daemon) profile loaded.</p> <p>Look at another log line:</p> <div class="highlight"><pre class="highlight" data-language="">[ 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"
+</pre></div> <p>This time the profile is <code class="language-plaintext highlighter-rouge">docker-default</code>, which is run on containers by default unless in <code class="language-plaintext highlighter-rouge">privileged</code> mode. This line shows that apparmor has denied <code class="language-plaintext highlighter-rouge">ptrace</code> in the container. This is exactly as expected.</p> <h3 id="use-aa-status">Use aa-status</h3> <p>If you need to check which profiles are loaded, you can use <code class="language-plaintext highlighter-rouge">aa-status</code>. The output looks like:</p> <div class="highlight"><pre class="highlight" data-language="">$ sudo aa-status
+apparmor module is loaded.
+14 profiles are loaded.
+1 profiles are in enforce mode.
+ docker-default
+13 profiles are in complain mode.
+ /usr/bin/docker
+ /usr/bin/docker///bin/cat
+ /usr/bin/docker///bin/ps
+ /usr/bin/docker///sbin/apparmor_parser
+ /usr/bin/docker///sbin/auplink
+ /usr/bin/docker///sbin/blkid
+ /usr/bin/docker///sbin/iptables
+ /usr/bin/docker///sbin/mke2fs
+ /usr/bin/docker///sbin/modprobe
+ /usr/bin/docker///sbin/tune2fs
+ /usr/bin/docker///sbin/xtables-multi
+ /usr/bin/docker///sbin/zfs
+ /usr/bin/docker///usr/bin/xz
+38 processes have profiles defined.
+37 processes are in enforce mode.
+ docker-default (6044)
+ ...
+ docker-default (31899)
+1 processes are in complain mode.
+ /usr/bin/docker (29756)
+0 processes are unconfined but have a profile defined.
+</pre></div> <p>The above output shows that the <code class="language-plaintext highlighter-rouge">docker-default</code> profile running on various container PIDs is in <code class="language-plaintext highlighter-rouge">enforce</code> mode. This means AppArmor is actively blocking and auditing in <code class="language-plaintext highlighter-rouge">dmesg</code> anything outside the bounds of the <code class="language-plaintext highlighter-rouge">docker-default</code> profile.</p> <p>The output above also shows the <code class="language-plaintext highlighter-rouge">/usr/bin/docker</code> (Docker Engine daemon) profile is running in <code class="language-plaintext highlighter-rouge">complain</code> mode. This means AppArmor <em>only</em> logs to <code class="language-plaintext highlighter-rouge">dmesg</code> activity outside the bounds of the profile. (Except in the case of Ubuntu Trusty, where some interesting behaviors are enforced.)</p> <h2 id="contribute-dockers-apparmor-code">Contribute Docker’s AppArmor code</h2> <p>Advanced users and package managers can find a profile for <code class="language-plaintext highlighter-rouge">/usr/bin/docker</code> (Docker Engine Daemon) underneath <a href="https://github.com/moby/moby/tree/master/contrib/apparmor">contrib/apparmor</a> in the Docker Engine source repository.</p> <p>The <code class="language-plaintext highlighter-rouge">docker-default</code> profile for containers lives in <a href="https://github.com/moby/moby/tree/master/profiles/apparmor">profiles/apparmor</a>.</p>
+<p><a href="https://docs.docker.com/search/?q=AppArmor">AppArmor</a>, <a href="https://docs.docker.com/search/?q=security">security</a>, <a href="https://docs.docker.com/search/?q=docker">docker</a>, <a href="https://docs.docker.com/search/?q=documentation">documentation</a></p>
+<div class="_attribution">
+ <p class="_attribution-p">
+ &copy; 2019 Docker, Inc.<br>Licensed under the Apache License, Version 2.0.<br>Docker and the Docker logo are trademarks or registered trademarks of Docker, Inc. in the United States and/or other countries.<br>Docker, Inc. and other parties may also have trademark rights in other terms used herein.<br>
+ <a href="https://docs.docker.com/engine/security/apparmor/" class="_attribution-link">https://docs.docker.com/engine/security/apparmor/</a>
+ </p>
+</div>