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).