github.com/dpiddy/docker@v1.12.2-rc1/docs/security/apparmor.md (about) 1 <!-- [metadata]> 2 +++ 3 title = "AppArmor security profiles for Docker" 4 description = "Enabling AppArmor in Docker" 5 keywords = ["AppArmor, security, docker, documentation"] 6 [menu.main] 7 parent= "smn_secure_docker" 8 weight=5 9 +++ 10 <![end-metadata]--> 11 12 # AppArmor security profiles for Docker 13 14 AppArmor (Application Armor) is a Linux security module that protects an 15 operating system and its applications from security threats. To use it, a system 16 administrator associates an AppArmor security profile with each program. Docker 17 expects to find an AppArmor policy loaded and enforced. 18 19 Docker automatically loads container profiles. The Docker binary installs 20 a `docker-default` profile in the `/etc/apparmor.d/docker` file. This profile 21 is used on containers, _not_ on the Docker Daemon. 22 23 A profile for the Docker Engine daemon exists but it is not currently installed 24 with the `deb` packages. If you are interested in the source for the daemon 25 profile, it is located in 26 [contrib/apparmor](https://github.com/docker/docker/tree/master/contrib/apparmor) 27 in the Docker Engine source repository. 28 29 ## Understand the policies 30 31 The `docker-default` profile is the default for running containers. It is 32 moderately protective while providing wide application compatibility. The 33 profile is the following: 34 35 ``` 36 #include <tunables/global> 37 38 39 profile docker-default flags=(attach_disconnected,mediate_deleted) { 40 41 #include <abstractions/base> 42 43 44 network, 45 capability, 46 file, 47 umount, 48 49 deny @{PROC}/{*,**^[0-9*],sys/kernel/shm*} wkx, 50 deny @{PROC}/sysrq-trigger rwklx, 51 deny @{PROC}/mem rwklx, 52 deny @{PROC}/kmem rwklx, 53 deny @{PROC}/kcore rwklx, 54 55 deny mount, 56 57 deny /sys/[^f]*/** wklx, 58 deny /sys/f[^s]*/** wklx, 59 deny /sys/fs/[^c]*/** wklx, 60 deny /sys/fs/c[^g]*/** wklx, 61 deny /sys/fs/cg[^r]*/** wklx, 62 deny /sys/firmware/efi/efivars/** rwklx, 63 deny /sys/kernel/security/** rwklx, 64 } 65 ``` 66 67 When you run a container, it uses the `docker-default` policy unless you 68 override it with the `security-opt` option. For example, the following 69 explicitly specifies the default policy: 70 71 ```bash 72 $ docker run --rm -it --security-opt apparmor=docker-default hello-world 73 ``` 74 75 ## Load and unload profiles 76 77 To load a new profile into AppArmor for use with containers: 78 79 ```bash 80 $ apparmor_parser -r -W /path/to/your_profile 81 ``` 82 83 Then, run the custom profile with `--security-opt` like so: 84 85 ```bash 86 $ docker run --rm -it --security-opt apparmor=your_profile hello-world 87 ``` 88 89 To unload a profile from AppArmor: 90 91 ```bash 92 # stop apparmor 93 $ /etc/init.d/apparmor stop 94 # unload the profile 95 $ apparmor_parser -R /path/to/profile 96 # start apparmor 97 $ /etc/init.d/apparmor start 98 ``` 99 100 ### Resources for writing profiles 101 102 The syntax for file globbing in AppArmor is a bit different than some other 103 globbing implementations. It is highly suggested you take a look at some of the 104 below resources with regard to AppArmor profile syntax. 105 106 - [Quick Profile Language](http://wiki.apparmor.net/index.php/QuickProfileLanguage) 107 - [Globbing Syntax](http://wiki.apparmor.net/index.php/AppArmor_Core_Policy_Reference#AppArmor_globbing_syntax) 108 109 ## Nginx example profile 110 111 In this example, you create a custom AppArmor profile for Nginx. Below is the 112 custom profile. 113 114 ``` 115 #include <tunables/global> 116 117 118 profile docker-nginx flags=(attach_disconnected,mediate_deleted) { 119 #include <abstractions/base> 120 121 network inet tcp, 122 network inet udp, 123 network inet icmp, 124 125 deny network raw, 126 127 deny network packet, 128 129 file, 130 umount, 131 132 deny /bin/** wl, 133 deny /boot/** wl, 134 deny /dev/** wl, 135 deny /etc/** wl, 136 deny /home/** wl, 137 deny /lib/** wl, 138 deny /lib64/** wl, 139 deny /media/** wl, 140 deny /mnt/** wl, 141 deny /opt/** wl, 142 deny /proc/** wl, 143 deny /root/** wl, 144 deny /sbin/** wl, 145 deny /srv/** wl, 146 deny /tmp/** wl, 147 deny /sys/** wl, 148 deny /usr/** wl, 149 150 audit /** w, 151 152 /var/run/nginx.pid w, 153 154 /usr/sbin/nginx ix, 155 156 deny /bin/dash mrwklx, 157 deny /bin/sh mrwklx, 158 deny /usr/bin/top mrwklx, 159 160 161 capability chown, 162 capability dac_override, 163 capability setuid, 164 capability setgid, 165 capability net_bind_service, 166 167 deny @{PROC}/{*,**^[0-9*],sys/kernel/shm*} wkx, 168 deny @{PROC}/sysrq-trigger rwklx, 169 deny @{PROC}/mem rwklx, 170 deny @{PROC}/kmem rwklx, 171 deny @{PROC}/kcore rwklx, 172 deny mount, 173 deny /sys/[^f]*/** wklx, 174 deny /sys/f[^s]*/** wklx, 175 deny /sys/fs/[^c]*/** wklx, 176 deny /sys/fs/c[^g]*/** wklx, 177 deny /sys/fs/cg[^r]*/** wklx, 178 deny /sys/firmware/efi/efivars/** rwklx, 179 deny /sys/kernel/security/** rwklx, 180 } 181 ``` 182 183 1. Save the custom profile to disk in the 184 `/etc/apparmor.d/containers/docker-nginx` file. 185 186 The file path in this example is not a requirement. In production, you could 187 use another. 188 189 2. Load the profile. 190 191 ```bash 192 $ sudo apparmor_parser -r -W /etc/apparmor.d/containers/docker-nginx 193 ``` 194 195 3. Run a container with the profile. 196 197 To run nginx in detached mode: 198 199 ```bash 200 $ docker run --security-opt "apparmor=docker-nginx" \ 201 -p 80:80 -d --name apparmor-nginx nginx 202 ``` 203 204 4. Exec into the running container 205 206 ```bash 207 $ docker exec -it apparmor-nginx bash 208 ``` 209 210 5. Try some operations to test the profile. 211 212 ```bash 213 root@6da5a2a930b9:~# ping 8.8.8.8 214 ping: Lacking privilege for raw socket. 215 216 root@6da5a2a930b9:/# top 217 bash: /usr/bin/top: Permission denied 218 219 root@6da5a2a930b9:~# touch ~/thing 220 touch: cannot touch 'thing': Permission denied 221 222 root@6da5a2a930b9:/# sh 223 bash: /bin/sh: Permission denied 224 225 root@6da5a2a930b9:/# dash 226 bash: /bin/dash: Permission denied 227 ``` 228 229 230 Congrats! You just deployed a container secured with a custom apparmor profile! 231 232 233 ## Debug AppArmor 234 235 You can use `dmesg` to debug problems and `aa-status` check the loaded profiles. 236 237 ### Use dmesg 238 239 Here are some helpful tips for debugging any problems you might be facing with 240 regard to AppArmor. 241 242 AppArmor sends quite verbose messaging to `dmesg`. Usually an AppArmor line 243 looks like the following: 244 245 ``` 246 [ 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 247 ``` 248 249 In the above example, you can see `profile=/usr/bin/docker`. This means the 250 user has the `docker-engine` (Docker Engine Daemon) profile loaded. 251 252 > **Note:** On version of Ubuntu > 14.04 this is all fine and well, but Trusty 253 > users might run into some issues when trying to `docker exec`. 254 255 Look at another log line: 256 257 ``` 258 [ 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" 259 ``` 260 261 This time the profile is `docker-default`, which is run on containers by 262 default unless in `privileged` mode. This line shows that apparmor has denied 263 `ptrace` in the container. This is exactly as expected. 264 265 ### Use aa-status 266 267 If you need to check which profiles are loaded, you can use `aa-status`. The 268 output looks like: 269 270 ```bash 271 $ sudo aa-status 272 apparmor module is loaded. 273 14 profiles are loaded. 274 1 profiles are in enforce mode. 275 docker-default 276 13 profiles are in complain mode. 277 /usr/bin/docker 278 /usr/bin/docker///bin/cat 279 /usr/bin/docker///bin/ps 280 /usr/bin/docker///sbin/apparmor_parser 281 /usr/bin/docker///sbin/auplink 282 /usr/bin/docker///sbin/blkid 283 /usr/bin/docker///sbin/iptables 284 /usr/bin/docker///sbin/mke2fs 285 /usr/bin/docker///sbin/modprobe 286 /usr/bin/docker///sbin/tune2fs 287 /usr/bin/docker///sbin/xtables-multi 288 /usr/bin/docker///sbin/zfs 289 /usr/bin/docker///usr/bin/xz 290 38 processes have profiles defined. 291 37 processes are in enforce mode. 292 docker-default (6044) 293 ... 294 docker-default (31899) 295 1 processes are in complain mode. 296 /usr/bin/docker (29756) 297 0 processes are unconfined but have a profile defined. 298 ``` 299 300 The above output shows that the `docker-default` profile running on various 301 container PIDs is in `enforce` mode. This means AppArmor is actively blocking 302 and auditing in `dmesg` anything outside the bounds of the `docker-default` 303 profile. 304 305 The output above also shows the `/usr/bin/docker` (Docker Engine daemon) profile 306 is running in `complain` mode. This means AppArmor _only_ logs to `dmesg` 307 activity outside the bounds of the profile. (Except in the case of Ubuntu 308 Trusty, where some interesting behaviors are enforced.) 309 310 ## Contribute Docker's AppArmor code 311 312 Advanced users and package managers can find a profile for `/usr/bin/docker` 313 (Docker Engine Daemon) underneath 314 [contrib/apparmor](https://github.com/docker/docker/tree/master/contrib/apparmor) 315 in the Docker Engine source repository. 316 317 The `docker-default` profile for containers lives in 318 [profiles/apparmor](https://github.com/docker/docker/tree/master/profiles/apparmor).