Permalink
Switch branches/tags
Nothing to show
Find file Copy path
625c034 Feb 10, 2017
1 contributor

Users who have contributed to this file

270 lines (222 sloc) 13.2 KB

Docker Engine Security Cheat Sheet

Docker security tools

Bane

Custom AppArmor profile generator for Docker containers, available at https://github.com/jfrazelle/bane.

Docker Bench for Security

Docker Bench for Security is a script that checks for all the automatable tests included in the CIS Docker 1.13 Benchmark. Docker Bench for Security is available at https://dockerbench.com.

docker-covenant

Enforcing basic security policies. Available at https://github.com/konstruktoid/docker-covenant.

dockertarsum

Like the system sum utilites (md5sum, sha1sum, sha256sum, etc), this is a command line tool to get the fixed time checksum of docker image layers. dockertarsum is available at https://github.com/vbatts/docker-utils#dockertarsum.

drydock

drydock provides a flexible way of assessing the security of your Docker daemon configuration and containers using editable audit templates. Available at https://github.com/zuBux/drydock.

Notary

The Notary project comprises a server and a client for running and interacting with trusted collections. See https://github.com/docker/notary.

Docker daemon options

--icc=false Use --link on run instead.
--selinux-enabled Enable if using SELinux.
--default-ulimit Set strict limits as default, it’s overwritten by --ulimit on run.
--tlsverify Enable TLS, see Protecting the Docker daemon Socket with HTTPS. genCert.sh is a script to automatically generate certificates.
--userns-remap=default Enable user namespace.
--authorization-plugin Use authorization plugin to manage access to the Docker daemon.
--disable-legacy-registry Disable legacy registry.
--live-restore Allows the Docker daemon to exit, be upgraded, or recover from a crash without affecting running containers.

/usr/bin/dockerd --userns-remap=default --disable-legacy-registry --live-restore --icc=false -s overlay2 --tlsverify --tlscacert=/etc/ssl/docker/ca.pem --tlscert=/etc/ssl/docker/server-cert.pem --tlskey=/etc/ssl/docker/server-key.pem --icc=false --default-ulimit nproc=512:1024 --default-ulimit nofile=50:100 -H=0.0.0.0:2376 -H fd://

Docker run options

Capabilities

--cap-drop=all Drop all capabilities by default.
--cap-add net_admin Allow only needed.

Using capsh

~$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                           NAMES
82ae0cd169d3        nginx:latest        "nginx -g 'daemon of   About an hour ago   Up About an hour    443/tcp, 0.0.0.0:8080->80/tcp   nginx
~$ docker exec $(docker ps -q) pgrep -a nginx
1 nginx: master process nginx -g daemon off;
9 nginx: worker process
~$ docker exec $(docker ps -q) cat /proc/1/status | grep CapEff | awk '{print $NF}'
00000000a80425fb
~$ capsh --decode=00000000a80425fb | echo "--cap-drop=all --cap-add={$(sed -e 's/.*=//' -e 's/cap_//g')}"
--cap-drop=all --cap-add={chown,dac_override,fowner,fsetid,kill,setgid,setuid,setpcap,net_bind_service,net_raw,sys_chroot,mknod,audit_write,setfcap}

Using getpcaps

~$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                           NAMES
82ae0cd169d3        nginx:latest        "nginx -g 'daemon of   About an hour ago   Up About an hour    443/tcp, 0.0.0.0:8080->80/tcp   nginx
~$ docker exec $(docker ps -q) pgrep -a nginx
1 nginx: master process nginx -g daemon off;
9 nginx: worker process
~$ export getTMP=$(mktemp XXXXXX) && docker exec $(docker ps -q) /sbin/getpcaps 1 2> $getTMP && sudo echo "--cap-drop=all --cap-add={$(sed -e 's/.*= //' -e 's/cap_//g' -e 's/+eip//g' $getTMP)}"
--cap-drop=all --cap-add={chown,dac_override,fowner,fsetid,kill,setgid,setuid,setpcap,net_bind_service,net_raw,sys_chroot,mknod,audit_write,setfcap}

For reference:

~$ curl https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/capability.h | grep " CAP_" | awk '{print $2, $3}'

Cgroups

--cgroup-parent Parent cgroup for the container.

Devices

--device Mount read-only if required.

Labels

--security-opt="apparmor:profile" Set the AppArmor profile to be applied to the container.
--security-opt="label:type:TYPE" Set the SELinux label to be applied to the container.
--security-opt="no-new-privileges" Disable container processes from gaining new privileges.

Log and logging drivers

-v /dev/log:/dev/log
--log-driver Send container logs to other systems such as Syslog, see https://docs.docker.com/reference/logging/overview/.

Memory and CPU limits

--cpu-shares CPU shares (relative weight).
--cpu-period Limit CPU CFS (Completely Fair Scheduler) period.
--cpu-quota Limit CPU CFS (Completely Fair Scheduler) quota.
--cpuset-cpus CPUs in which to allow execution (0-3, 0,1).
--cpuset-mems MEMs in which to allow execution (0-3, 0,1).
--kernel-memory Kernel memory limit.
-m, --memory Memory limit.
--memory-reservation Memory soft limit.
--memory-swap Total memory (memory + swap), '-1' to disable swap.
--ulimit Set the ulimit on the specific container.

Networking

-p IP:host_port:container_port or -p IP::port Specify the external interface.

Seccomp

--security-opt seccomp:/path/to/seccomp/profile.json See Seccomp security profiles for Docker, genSeccomp.sh is a basice profile generator.

Time

-v /etc/localtime:/etc/localtime:ro

Tmpfs

--read-only --tmpfs /run --tmpfs /tmp See Making Docker images read-only in production

Trust

--disable-content-trust See Content trust in Docker

User

-u, --user Run as a unprivileged user.

Volumes and mounting

--read-only Mount container root filesystem as read only.
-v /volume:ro Mount volumes read only if possible.

Dockerfile example - Container

FROM alpine:3.3 (1)

ENV VERSION 1.11.2
ENV SHA256 8c2e0c35e3cda11706f54b2d46c2521a6e9026a7b13c7d4b8ae1f3a706fc55e1 (2)

WORKDIR /usr/bin

RUN apk update && \
    apk upgrade && \ (3)
    apk --update add coreutils wget ca-certificates && \
    wget https://get.docker.com/builds/Linux/x86_64/docker-$VERSION.tgz && \
    wget https://get.docker.com/builds/Linux/x86_64/docker-$VERSION.tgz.sha256 && \
    sha256sum -c docker-$VERSION.tgz.sha256 && \ (4)
    echo "$SHA256 docker-$VERSION.tgz" | sha256sum -c - && \ (4)
    tar -xzvf docker-$VERSION.tgz -C /tmp && \
    mv /tmp/docker/docker . && \
    chmod u+x docker* && \
    rm -rf /tmp/docker* && \ (5)
    apk del wget ca-certificates && \ (5)
    rm -rf /var/cache/apk/* docker-$VERSION.tgz docker-$VERSION.tgz.sha256 (5)

COPY ./docker-garby.sh /docker-garby.sh (6)

ENTRYPOINT ["/bin/sh", "/docker-garby.sh"]
  1. Do we trust the remote repository? Is there any reason we’re not using a homebuilt base image?

  2. Hash to verify downloaded file

  3. Keep the container up-to-date

  4. Verify downloaded files

  5. Remove unused applications and unnecessary directories

  6. COPY local files, ADD remote files

  7. Create an unprivileged USER if possibe

  8. GnuPG sign the commit, git -s -S -m '…​'

Dockerfile example - Image

FROM scratch (1)
ADD ./wheezy-1603172157.txz / (2)
ENV SHA 00c3cc1b8968d3b5acf2ac9fc1e36f2aa30dfd4ff44a35d8d3bd1948914d722d (3)

ONBUILD RUN apt-get update && apt-get -y upgrade (4)
  1. Use scratch

  2. Add a compressed, minimal, base

  3. Hash for the above base

  4. Force containers based on this image to keep up-to-date

  5. GnuPG sign the commit, git -s -S -m '…​'

Docker run example

~$ export CAP="--cap-drop all --cap-add net_admin"

If root user is required:
~$ docker run --rm -v /etc/localtime:/etc/localtime:ro -v /dev/log:/dev/log $CAP --name <NAME> -t <IMAGE>

Unpriv user if possible:
~$ docker run --rm -u dockeru -v /etc/localtime:/etc/localtime:ro -v /dev/log:/dev/log $CAP --name <NAME> -t <IMAGE>

Running Polipo with an Apparmor profile, read-only root system, no capabilites and tmpfs:

$ docker run --restart="always" --name polipo --security-opt="apparmor:docker-polipo" -d -p 8123:8123 --cap-drop=all --read-only --tmpfs /tmp:rw,nosuid,nodev,noexec,size=100m --tmpfs /var/log:rw,nosuid,nodev,noexec --tmpfs /var/cache:rw,nosuid,noexec,nodev --tmpfs /run:rw,noexec,nodev,nosuid konstruktoid/polipo proxyAddress=::0 allowedClients=192.168.1.0/24
$ docker exec -ti polipo mount | grep tmpfs
tmpfs on /dev type tmpfs (ro,mode=755)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,relatime,mode=755)
shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k)
tmpfs on /var/log type tmpfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /run type tmpfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,noexec,relatime,size=102400k)
tmpfs on /var/cache type tmpfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /proc/kcore type tmpfs (ro,mode=755)
tmpfs on /proc/timer_stats type tmpfs (ro,mode=755)
$ docker exec -ti polipo touch /test
touch: cannot touch `/test': Read-only file system
$ docker exec -ti polipo touch /var/tmp/test
touch: cannot touch `/var/tmp/test': Read-only file system
$ docker exec -ti polipo touch /tmp/test
$ docker exec -ti polipo touch /var/cache/polipo/test
$ docker exec -ti polipo ls -l /var/cache/polipo
total 0
drwx------ 2 polipo polipo   80 Jan 16 21:08 cdn.tentonhammer.com
drwx------ 2 polipo polipo   60 Jan 16 21:08 cnn.com
drwx------ 2 polipo polipo  120 Jan 16 21:08 data.cnn.com
drwx------ 2 polipo polipo  300 Jan 16 21:08 edition.cnn.com
drwx------ 2 polipo polipo  480 Jan 16 21:08 edition.i.cdn.cnn.com
drwx------ 2 polipo polipo   60 Jan 16 21:08 elitistjerks.com
drwx------ 2 polipo polipo   60 Jan 16 21:08 eweek.com
drwx------ 2 polipo polipo  660 Jan 16 21:08 forums.elitistjerks.com
drwx------ 2 polipo polipo   60 Jan 16 21:08 imdb.com
drwx------ 2 polipo polipo   80 Jan 16 21:08 imp.admarketplace.net
drwx------ 2 polipo polipo   80 Jan 16 21:08 odb.outbrain.com
drwx------ 2 polipo polipo   60 Jan 16 21:08 slashdot.com
drwx------ 2 polipo polipo   80 Jan 16 21:08 slashdot.org
drwx------ 2 polipo polipo  240 Jan 16 21:08 sponsored.eweek.com
drwx------ 2 polipo polipo 1740 Jan 16 21:08 static.images-di.se
drwx------ 2 polipo polipo   60 Jan 16 21:05 stats.pagefair.net
-rw-r--r-- 1 polipo polipo    0 Jan 16 21:00 test
drwx------ 2 polipo polipo   60 Jan 16 21:08 www.cnn.com
drwx------ 2 polipo polipo 1360 Jan 16 21:08 www.di.se
drwx------ 2 polipo polipo 1220 Jan 16 21:08 www.eweek.com
drwx------ 2 polipo polipo   60 Jan 16 21:08 www.imdb.com
drwx------ 2 polipo polipo   60 Jan 16 21:08 z-ecx.images-amazon.com
drwx------ 2 polipo polipo  200 Jan 16 21:08 z.cdn.turner.com

Garbage collection

docker prune

docker-gc