Docker security » History » Version 7
Peter Amstutz, 10/07/2016 03:05 PM
1 | 1 | Peter Amstutz | h1. Docker security |
---|---|---|---|
2 | |||
3 | 2 | Peter Amstutz | The fundamental Docker security issue is that a "root" (uid 0) user inside container is equivalent to "root" outside, unless steps are taken to limit container permissions. We want to disallow containers from sending data outside the private Arvados network, prevent breakout from the container, and limit access if a breakout does occur. We don't allow end users to invoke Docker directly, so we can impose security measures both in the daemon configuration and the individual container invocation. |
4 | 1 | Peter Amstutz | |
5 | Some of the knobs we have include: |
||
6 | |||
7 | h2. Setting the uid/gid of pid 1 in container |
||
8 | |||
9 | 3 | Peter Amstutz | docker run --user |
10 | |||
11 | 4 | Peter Amstutz | We can explicitly set the uid/gid of pid 1 inside the container so it is not uid 0. This overrides the USER directive of the image. One drawback is that some programs behave badly when the current uid cannot be found in /etc/passwd. |
12 | 1 | Peter Amstutz | |
13 | h2. User id mapping |
||
14 | 2 | Peter Amstutz | |
15 | 1 | Peter Amstutz | docker daemon --userns-remap |
16 | 2 | Peter Amstutz | |
17 | 3 | Peter Amstutz | User ids inside container corresponds to a different host user id. Can map uid 0 inside the container to non-root user outside the container. Processes have two sets of capabilities; one set of capabilities apply when manipulating resources inside the user namespace, a second set of capabilities apply when manipulating resources in the parent namespace. This makes it possible for a process to be "root" inside the container but "non-root" outside the container. |
18 | 1 | Peter Amstutz | |
19 | 3 | Peter Amstutz | http://man7.org/linux/man-pages/man7/user_namespaces.7.html |
20 | |||
21 | This may also be useful for working with bind-mounted directories. Mapping "root" to the host user "crunch" would mean that files written by "root" inside the container would actually be owned by "crunch" outside the container. Because user id mappings are 1:1, this would require always using the same uid inside the container (probably uid 0). |
||
22 | |||
23 | 1 | Peter Amstutz | h2. Dropping capabilities |
24 | 3 | Peter Amstutz | |
25 | 1 | Peter Amstutz | docker run --drop-cap |
26 | 2 | Peter Amstutz | |
27 | 5 | Peter Amstutz | Drop capabilities of root user inside the container ("man capabilities" for list). Dropping all capabilities effectively neuters the root user (for example, without CAP_DAC_OVERRIDE the root user is subject to the same file permission checks as regular users). Can be used to limit the scope of what "root" user can do inside the container. |
28 | 1 | Peter Amstutz | |
29 | h2. Restrict container networking |
||
30 | |||
31 | 3 | Peter Amstutz | docker run --net=none |
32 | 1 | Peter Amstutz | |
33 | 3 | Peter Amstutz | Crunch v2 communicates via arv-mount, which means most containers don't need networking to read/write to Keep. Crunch v2 policy is that networking is disabled by default but can be enabled with the runtime constraint @API: true@ (necessary for Arvados-aware containers). The Docker network bridge should be configured with firewall whitelist that limits communication to essential Arvados services (API server + Keep server). |
34 | |||
35 | 2 | Peter Amstutz | h2. Disable inter-container communication |
36 | 3 | Peter Amstutz | |
37 | 1 | Peter Amstutz | docker daemon --icc=false |
38 | |||
39 | Our containers don't need to talk to each other. |
||
40 | |||
41 | h2. Resource limits via cgroups |
||
42 | |||
43 | 2 | Peter Amstutz | Slurm can set up a cgroup (control group) to dictate resource limits, and crunch-run can instruct Docker to put the container in the cgroup set up by slurm. Note, for this to work, we may need to invoke the Docker daemon with this option: |
44 | |||
45 | 1 | Peter Amstutz | --exec-opt native.cgroupdriver=cgroupfs |
46 | |||
47 | 2 | Peter Amstutz | Further research is required to see if slurm cgroup settings are sufficient to prevent overloading the node or denial-of-service, or if we need to set other limits (for example, a limit on the number of processes inside the container to prevent forkbomb attacks.) |
48 | 1 | Peter Amstutz | |
49 | h2. Resource limits via ulimit |
||
50 | |||
51 | 2 | Peter Amstutz | We can also set ulimits on daemon invocation (--default-ulimit) and on container invocation (--ulimit). ulimit has some overlap with cgroups but the difference seems to be that most ulimit settings apply per-process rather than to a group of processes. |
52 | 1 | Peter Amstutz | |
53 | h2. seccomp |
||
54 | |||
55 | 2 | Peter Amstutz | Seccomp filters system calls that can be made by programs inside the container; many system calls it filters can also be blocked by dropping capabilities. |
56 | |||
57 | 1 | Peter Amstutz | https://docs.docker.com/engine/security/seccomp/ |
58 | |||
59 | h2. AppArmor |
||
60 | |||
61 | 6 | Peter Amstutz | Apply additional fine-grained access controls to the container, e.g. deny access to specific paths. Can be used to limit access to /proc and /sys. |
62 | 1 | Peter Amstutz | |
63 | https://docs.docker.com/engine/security/apparmor/ |
||
64 | |||
65 | h2. SELinux |
||
66 | |||
67 | docker daemon --selinux-enabled |
||
68 | |||
69 | 7 | Peter Amstutz | Enable SELinux support. I don't know exactly what that entails, but is probably similar to AppArmor in providing a mechanism for fine-grained access controls for containers. Can also be used to lock down @crunch-run@ and @arv-mount@ on the host system. |