docker-library / httpd

Docker Official Image packaging for Apache HTTP Server
https://httpd.apache.org
Apache License 2.0
310 stars 345 forks source link

Start as non-root user #102

Closed khba closed 6 years ago

khba commented 6 years ago

Hello,

In order to respect the check 4.1 from the docker security tests https://github.com/docker/docker-bench-security, is there a way to run the container without ever using root?

I know the daemon is started as root to be able to bind to privileged ports like 80 and then start child processes as the user defined in httpd.conf file (daemon or www-data usually), but from a security standpoint, that's already a problem that the container can run as root in the beginning. Is there a workaround for this to avoid using root and if possible bind on port 80?

Thanks,

tianon commented 6 years ago

Given https://github.com/moby/moby/issues/8460#issuecomment-312459310, you should be able to get pretty far:

$ docker run -it --rm --user 1000 --sysctl net.ipv4.ip_unprivileged_port_start=0 httpd
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.18.0.29. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.18.0.29. Set the 'ServerName' directive globally to suppress this message
[Tue Jul 10 20:36:16.676190 2018] [core:error] [pid 1:tid 140275100432256] (13)Permission denied: AH00099: could not create /usr/local/apache2/logs/httpd.pid
[Tue Jul 10 20:36:16.676463 2018] [core:error] [pid 1:tid 140275100432256] AH00100: httpd: could not log pid to file /usr/local/apache2/logs/httpd.pid

(Filesystem permissions are easier to deal with than kernel blocks, so this is good.)

khba commented 6 years ago

I did this : setcap + chown + User www-data inside the Dockerfile + build and the image works fine on the host as www-data:

$ docker run --rm 43dee066c55f AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message [Wed Jul 11 09:51:33.316839 2018] [mpm_event:notice] [pid 1:tid 140008104651656] AH00489: Apache/2.4.33 (Unix) configured -- resuming normal operations [Wed Jul 11 09:51:33.316997 2018] [core:notice] [pid 1:tid 140008104651656] AH00094: Command line: 'httpd -D FOREGROUND'

But when I pull the same image and run it on another node , it falls back to the first error: $ docker run --rm 43dee066c55f AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message (13)Permission denied: AH00072: make_sock: could not bind to address [::]:80 (13)Permission denied: AH00072: make_sock: could not bind to address 0.0.0.0:80

Is this binding to port 80 denied by the container's system or the host's system? Logically the "permission denied" was coming from the container's system and since we fixed that, the image should be able to run everywhere as non-root right?

Here is the Dockerfile:

FROM httpd:2.4-alpine

#Custom changes
RUN apk update;  \
          apk upgrade;
RUN apk -q add curl  \
    vim  \
    libcap ;

#Change access righs to conf, logs, bin from root to www-data
RUN chown -hR www-data:www-data /usr/local/apache2/

#setcap to bind to privileged ports as non-root
RUN setcap 'cap_net_bind_service=+ep' /usr/local/apache2/bin/httpd
RUN getcap /usr/local/apache2/bin/httpd

HEALTHCHECK --interval=60s --timeout=30s CMD nc -zv localhost 80 || exit 1
#Run as a www-data
USER www-data
tianon commented 6 years ago

Your setcap probably doesn't round-trip through the graph drivers properly.

khba commented 6 years ago

Excuse my english but I don' t really understand "Your setcap probably doesn't round-trip through the graph drivers properly", what do you mean by that? Is there a way to fix it and make the image portable?

If it means what I think, the storage driver on the node where the image is running fine is aufs, and the one where it fails is overlay2. Even if I rebuild the image on the node with overlay2, still the same. Does that mean setcap is incompatible with overlay2 storage driver? Is that normal?

Thanks,

wglambert commented 6 years ago

I'm not fully understanding your use case, you mention a node, do you mean you're using swarm and stack deploying to a node, and that this worker node is experiencing an anomaly with permissions of some sort? By my understanding you're primarily concerned with test section 4.1 of the docker-bench-security test which tests for running as normal user in the container. I'm not able to reproduce any error while deploying a stack to a swarm and testing the nodes.

Dockerfile

FROM httpd:2.4-alpine

#Custom changes
RUN apk update && apk upgrade
RUN apk -q add curl vim libcap

#Change access righs to conf, logs, bin from root to www-data
RUN chown -hR www-data:www-data /usr/local/apache2/

#setcap to bind to privileged ports as non-root
RUN setcap 'cap_net_bind_service=+ep' /usr/local/apache2/bin/httpd
RUN getcap /usr/local/apache2/bin/httpd

HEALTHCHECK --interval=60s --timeout=30s CMD nc -zv localhost 80 || exit 1
#Run as a www-data
USER www-data

docker-compose.yml

version: "3"

services:
 httpd_test:
  image: httpd_test
  deploy:
   replicas: 2
Manager node ```console $ docker stack deploy --compose-file ./docker-compose.yml httpd_test $ docker service ls ID NAME MODE REPLICAS IMAGE PORTS qenag3z7t8t5 httpd_test_httpd_test replicated 2/2 httpd_test:latest $ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION jroad5mqkzzzyf50xpgjd589i * Ayanami Ready Active Leader 18.03.1-ce 49hwm3mm3381mc9m7njn73ywi Ayanami-clone Ready Active 18.03.1-ce $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 943a18981350 httpd_test:latest "httpd-foreground" 8 minutes ago Up 8 minutes (healthy) 80/tcp httpd_test_httpd_test.2.1oaybpksrkqkc9gx2sutsjygq $ docker run -it --net host --pid host --cap-add audit_control -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST -v /var/lib:/var/lib -v /var/run/docker.sock:/var/run/docker.sock -v /usr/lib/systemd:/usr/lib/systemd -v /etc:/etc --label docker_bench_security docker-bench-security # ------------------------------------------------------------------------------ # Docker Bench for Security v1.3.4 # # Docker, Inc. (c) 2015- # # Checks for dozens of common best-practices around deploying Docker containers in production. # Inspired by the CIS Docker Community Edition Benchmark v1.1.0. # ------------------------------------------------------------------------------ Initializing Thu Jul 12 20:06:37 UTC 2018 [INFO] 1 - Host Configuration [WARN] 1.1 - Ensure a separate partition for containers has been created [NOTE] 1.2 - Ensure the container host has been Hardened [INFO] 1.3 - Ensure Docker is up to date [INFO] * Using 18.03.1, verify is it up to date as deemed necessary [INFO] * Your operating system vendor may provide support and security maintenance for Docker [INFO] 1.4 - Ensure only trusted users are allowed to control Docker daemon [INFO] * docker:x:130:rei [WARN] 1.5 - Ensure auditing is configured for the Docker daemon [WARN] 1.6 - Ensure auditing is configured for Docker files and directories - /var/lib/docker [WARN] 1.7 - Ensure auditing is configured for Docker files and directories - /etc/docker [INFO] 1.8 - Ensure auditing is configured for Docker files and directories - docker.service [INFO] * File not found [INFO] 1.9 - Ensure auditing is configured for Docker files and directories - docker.socket [INFO] * File not found [WARN] 1.10 - Ensure auditing is configured for Docker files and directories - /etc/default/docker [INFO] 1.11 - Ensure auditing is configured for Docker files and directories - /etc/docker/daemon.json [INFO] * File not found [INFO] 1.12 - Ensure auditing is configured for Docker files and directories - /usr/bin/docker-containerd [INFO] * File not found [INFO] 1.13 - Ensure auditing is configured for Docker files and directories - /usr/bin/docker-runc [INFO] * File not found [INFO] 2 - Docker daemon configuration [WARN] 2.1 - Ensure network traffic is restricted between containers on the default bridge [PASS] 2.2 - Ensure the logging level is set to 'info' [PASS] 2.3 - Ensure Docker is allowed to make changes to iptables [PASS] 2.4 - Ensure insecure registries are not used [WARN] 2.5 - Ensure aufs storage driver is not used [INFO] 2.6 - Ensure TLS authentication for Docker daemon is configured [INFO] * Docker daemon not listening on TCP [INFO] 2.7 - Ensure the default ulimit is configured appropriately [INFO] * Default ulimit doesn't appear to be set [WARN] 2.8 - Enable user namespace support [PASS] 2.9 - Ensure the default cgroup usage has been confirmed [PASS] 2.10 - Ensure base device size is not changed until needed [WARN] 2.11 - Ensure that authorization for Docker client commands is enabled [WARN] 2.12 - Ensure centralized and remote logging is configured [INFO] 2.13 - Ensure operations on legacy registry (v1) are Disabled (Deprecated) [PASS] 2.14 - Ensure live restore is Enabled (Incompatible with swarm mode) [WARN] 2.15 - Ensure Userland Proxy is Disabled [PASS] 2.16 - Ensure daemon-wide custom seccomp profile is applied, if needed [PASS] 2.17 - Ensure experimental features are avoided in production [WARN] 2.18 - Ensure containers are restricted from acquiring new privileges [INFO] 3 - Docker daemon configuration files [INFO] 3.1 - Ensure that docker.service file ownership is set to root:root [INFO] * File not found [INFO] 3.2 - Ensure that docker.service file permissions are set to 644 or more restrictive [INFO] * File not found [INFO] 3.3 - Ensure that docker.socket file ownership is set to root:root [INFO] * File not found [INFO] 3.4 - Ensure that docker.socket file permissions are set to 644 or more restrictive [INFO] * File not found [PASS] 3.5 - Ensure that /etc/docker directory ownership is set to root:root [PASS] 3.6 - Ensure that /etc/docker directory permissions are set to 755 or more restrictive [INFO] 3.7 - Ensure that registry certificate file ownership is set to root:root [INFO] * Directory not found [INFO] 3.8 - Ensure that registry certificate file permissions are set to 444 or more restrictive [INFO] * Directory not found [INFO] 3.9 - Ensure that TLS CA certificate file ownership is set to root:root [INFO] * No TLS CA certificate found [INFO] 3.10 - Ensure that TLS CA certificate file permissions are set to 444 or more restrictive [INFO] * No TLS CA certificate found [INFO] 3.11 - Ensure that Docker server certificate file ownership is set to root:root [INFO] * No TLS Server certificate found [INFO] 3.12 - Ensure that Docker server certificate file permissions are set to 444 or more restrictive [INFO] * No TLS Server certificate found [INFO] 3.13 - Ensure that Docker server certificate key file ownership is set to root:root [INFO] * No TLS Key found [INFO] 3.14 - Ensure that Docker server certificate key file permissions are set to 400 [INFO] * No TLS Key found [PASS] 3.15 - Ensure that Docker socket file ownership is set to root:docker [PASS] 3.16 - Ensure that Docker socket file permissions are set to 660 or more restrictive [INFO] 3.17 - Ensure that daemon.json file ownership is set to root:root [INFO] * File not found [INFO] 3.18 - Ensure that daemon.json file permissions are set to 644 or more restrictive [INFO] * File not found [PASS] 3.19 - Ensure that /etc/default/docker file ownership is set to root:root [PASS] 3.20 - Ensure that /etc/default/docker file permissions are set to 644 or more restrictive [INFO] 4 - Container Images and Build File [PASS] 4.1 - Ensure a user for the container has been created [NOTE] 4.2 - Ensure that containers use trusted base images [NOTE] 4.3 - Ensure unnecessary packages are not installed in the container [NOTE] 4.4 - Ensure images are scanned and rebuilt to include security patches [WARN] 4.5 - Ensure Content trust for Docker is Enabled [WARN] 4.6 - Ensure HEALTHCHECK instructions have been added to the container image [WARN] * No Healthcheck found: [httpd:2.4-alpine] [WARN] * No Healthcheck found: [alpine:3.7] [WARN] * No Healthcheck found: [mysql:latest] [WARN] * No Healthcheck found: [k8s.gcr.io/kube-proxy-amd64:v1.10.5] [WARN] * No Healthcheck found: [k8s.gcr.io/kube-scheduler-amd64:v1.10.5] [WARN] * No Healthcheck found: [k8s.gcr.io/kube-apiserver-amd64:v1.10.5] [WARN] * No Healthcheck found: [k8s.gcr.io/kube-controller-manager-amd64:v1.10.5] [WARN] * No Healthcheck found: [postgres:latest] [WARN] * No Healthcheck found: [k8s.gcr.io/kube-proxy-amd64:v1.10.4] [WARN] * No Healthcheck found: [k8s.gcr.io/kube-apiserver-amd64:v1.10.4] [WARN] * No Healthcheck found: [k8s.gcr.io/kube-scheduler-amd64:v1.10.4] [WARN] * No Healthcheck found: [k8s.gcr.io/kube-controller-manager-amd64:v1.10.4] [WARN] * No Healthcheck found: [quay.io/calico/node:v3.1.3] [WARN] * No Healthcheck found: [quay.io/calico/kube-controllers:v3.1.3] [WARN] * No Healthcheck found: [quay.io/calico/cni:v3.1.3] [WARN] * No Healthcheck found: [owncloud:latest] [WARN] * No Healthcheck found: [mongo:latest] [WARN] * No Healthcheck found: [httpd:latest] [WARN] * No Healthcheck found: [centos:7] [WARN] * No Healthcheck found: [k8s.gcr.io/etcd-amd64:3.1.12] [WARN] * No Healthcheck found: [k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3] [WARN] * No Healthcheck found: [quay.io/coreos/flannel:v0.10.0-amd64] [WARN] * No Healthcheck found: [alpine:latest] [WARN] * No Healthcheck found: [k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64:1.14.8] [WARN] * No Healthcheck found: [k8s.gcr.io/k8s-dns-sidecar-amd64:1.14.8] [WARN] * No Healthcheck found: [k8s.gcr.io/k8s-dns-kube-dns-amd64:1.14.8] [WARN] * No Healthcheck found: [k8s.gcr.io/pause-amd64:3.1] [WARN] * No Healthcheck found: [hello-world:latest] [WARN] * No Healthcheck found: [quay.io/coreos/etcd:v3.1.10] [INFO] 4.7 - Ensure update instructions are not use alone in the Dockerfile [INFO] * Update instruction found: [httpd_test:latest] [INFO] * Update instruction found: [mysql:latest] [INFO] * Update instruction found: [postgres:latest] [INFO] * Update instruction found: [owncloud:latest] [INFO] * Update instruction found: [mongo:latest] [INFO] * Update instruction found: [httpd:latest] [NOTE] 4.8 - Ensure setuid and setgid permissions are removed in the images [INFO] 4.9 - Ensure COPY is used instead of ADD in Dockerfile [INFO] * ADD in image history: [docker-bench-security:latest] [INFO] * ADD in image history: [httpd_test:latest] [INFO] * ADD in image history: [httpd:2.4-alpine] [INFO] * ADD in image history: [alpine:3.7] [INFO] * ADD in image history: [mysql:latest] [INFO] * ADD in image history: [k8s.gcr.io/kube-proxy-amd64:v1.10.5] [INFO] * ADD in image history: [k8s.gcr.io/kube-scheduler-amd64:v1.10.5] [INFO] * ADD in image history: [k8s.gcr.io/kube-apiserver-amd64:v1.10.5] [INFO] * ADD in image history: [k8s.gcr.io/kube-controller-manager-amd64:v1.10.5] [INFO] * ADD in image history: [postgres:latest] [INFO] * ADD in image history: [k8s.gcr.io/kube-proxy-amd64:v1.10.4] [INFO] * ADD in image history: [k8s.gcr.io/kube-apiserver-amd64:v1.10.4] [INFO] * ADD in image history: [k8s.gcr.io/kube-scheduler-amd64:v1.10.4] [INFO] * ADD in image history: [k8s.gcr.io/kube-controller-manager-amd64:v1.10.4] [INFO] * ADD in image history: [quay.io/calico/node:v3.1.3] [INFO] * ADD in image history: [quay.io/calico/kube-controllers:v3.1.3] [INFO] * ADD in image history: [quay.io/calico/cni:v3.1.3] [INFO] * ADD in image history: [owncloud:latest] [INFO] * ADD in image history: [mongo:latest] [INFO] * ADD in image history: [httpd:latest] [INFO] * ADD in image history: [centos:7] [INFO] * ADD in image history: [k8s.gcr.io/etcd-amd64:3.1.12] [INFO] * ADD in image history: [k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3] [INFO] * ADD in image history: [quay.io/coreos/flannel:v0.10.0-amd64] [INFO] * ADD in image history: [alpine:latest] [INFO] * ADD in image history: [k8s.gcr.io/k8s-dns-dnsmasq-nanny-amd64:1.14.8] [INFO] * ADD in image history: [k8s.gcr.io/k8s-dns-sidecar-amd64:1.14.8] [INFO] * ADD in image history: [k8s.gcr.io/k8s-dns-kube-dns-amd64:1.14.8] [INFO] * ADD in image history: [k8s.gcr.io/pause-amd64:3.1] [INFO] * ADD in image history: [quay.io/coreos/etcd:v3.1.10] [NOTE] 4.10 - Ensure secrets are not stored in Dockerfiles [NOTE] 4.11 - Ensure verified packages are only Installed [INFO] 5 - Container Runtime [PASS] 5.1 - Ensure AppArmor Profile is Enabled [WARN] 5.2 - Ensure SELinux security options are set, if applicable [WARN] * No SecurityOptions Found: httpd_test_httpd_test.2.1oaybpksrkqkc9gx2sutsjygq [PASS] 5.3 - Ensure Linux Kernel Capabilities are restricted within containers [PASS] 5.4 - Ensure privileged containers are not used [PASS] 5.5 - Ensure sensitive host system directories are not mounted on containers [PASS] 5.6 - Ensure ssh is not run within containers [PASS] 5.7 - Ensure privileged ports are not mapped within containers [NOTE] 5.8 - Ensure only needed ports are open on the container [PASS] 5.9 - Ensure the host's network namespace is not shared [WARN] 5.10 - Ensure memory usage for container is limited [WARN] * Container running without memory restrictions: httpd_test_httpd_test.2.1oaybpksrkqkc9gx2sutsjygq [WARN] 5.11 - Ensure CPU priority is set appropriately on the container [WARN] * Container running without CPU restrictions: httpd_test_httpd_test.2.1oaybpksrkqkc9gx2sutsjygq [WARN] 5.12 - Ensure the container's root filesystem is mounted as read only [WARN] * Container running with root FS mounted R/W: httpd_test_httpd_test.2.1oaybpksrkqkc9gx2sutsjygq [PASS] 5.13 - Ensure incoming container traffic is binded to a specific host interface [WARN] 5.14 - Ensure 'on-failure' container restart policy is set to '5' [WARN] * MaximumRetryCount is not set to 5: httpd_test_httpd_test.2.1oaybpksrkqkc9gx2sutsjygq [PASS] 5.15 - Ensure the host's process namespace is not shared [PASS] 5.16 - Ensure the host's IPC namespace is not shared [PASS] 5.17 - Ensure host devices are not directly exposed to containers [INFO] 5.18 - Ensure the default ulimit is overwritten at runtime, only if needed [INFO] * Container no default ulimit override: httpd_test_httpd_test.2.1oaybpksrkqkc9gx2sutsjygq [PASS] 5.19 - Ensure mount propagation mode is not set to shared [PASS] 5.20 - Ensure the host's UTS namespace is not shared [PASS] 5.21 - Ensure the default seccomp profile is not Disabled [NOTE] 5.22 - Ensure docker exec commands are not used with privileged option [NOTE] 5.23 - Ensure docker exec commands are not used with user option [PASS] 5.24 - Ensure cgroup usage is confirmed [WARN] 5.25 - Ensure the container is restricted from acquiring additional privileges [WARN] * Privileges not restricted: httpd_test_httpd_test.2.1oaybpksrkqkc9gx2sutsjygq [PASS] 5.26 - Ensure container health is checked at runtime [INFO] 5.27 - Ensure docker commands always get the latest version of the image [WARN] 5.28 - Ensure PIDs cgroup limit is used [WARN] * PIDs limit not set: httpd_test_httpd_test.2.1oaybpksrkqkc9gx2sutsjygq [PASS] 5.29 - Ensure Docker's default bridge docker0 is not used [PASS] 5.30 - Ensure the host's user namespaces is not shared [PASS] 5.31 - Ensure the Docker socket is not mounted inside any containers [INFO] 6 - Docker Security Operations [INFO] 6.1 - Avoid image sprawl [INFO] * There are currently: 31 images [INFO] * Only 6 out of 31 are in use [INFO] 6.2 - Avoid container sprawl [INFO] * There are currently a total of 6 containers, with 2 of them currently running [INFO] 7 - Docker Swarm Configuration [WARN] 7.1 - Ensure swarm mode is not Enabled, if not needed [PASS] 7.2 - Ensure the minimum number of manager nodes have been created in a swarm [WARN] 7.3 - Ensure swarm services are binded to a specific host interface [INFO] 7.5 - Ensure Docker's secret management commands are used for managing secrets in a Swarm cluster [WARN] 7.6 - Ensure swarm manager is run in auto-lock mode [NOTE] 7.7 - Ensure swarm manager auto-lock key is rotated periodically [INFO] 7.8 - Ensure node certificates are rotated as appropriate [INFO] 7.9 - Ensure CA certificates are rotated as appropriate [INFO] 7.10 - Ensure management plane traffic has been separated from data plane traffic [INFO] Checks: 104 [INFO] Score: 10 ```
Worker node ```console $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES de2b60a5bd1b httpd_test:latest "httpd-foreground" 10 minutes ago Up 10 minutes (healthy) 80/tcp httpd_test_httpd_test.1.k8ebms2wnnj8mdttuem6r5rxl $ docker run -it --net host --pid host --cap-add audit_control -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST -v /var/lib:/var/lib -v /var/run/docker.sock:/var/run/docker.sock -v /usr/lib/systemd:/usr/lib/systemd -v /etc:/etc --label docker_bench_security docker-bench-security # ------------------------------------------------------------------------------ # Docker Bench for Security v1.3.4 # # Docker, Inc. (c) 2015- # # Checks for dozens of common best-practices around deploying Docker containers in production. # Inspired by the CIS Docker Community Edition Benchmark v1.1.0. # ------------------------------------------------------------------------------ Initializing Thu Jul 12 20:07:58 GMT 2018 [INFO] 1 - Host Configuration [WARN] 1.1 - Ensure a separate partition for containers has been created [NOTE] 1.2 - Ensure the container host has been Hardened [INFO] 1.3 - Ensure Docker is up to date [INFO] * Using 18.03.1, verify is it up to date as deemed necessary [INFO] * Your operating system vendor may provide support and security maintenance for Docker [INFO] 1.4 - Ensure only trusted users are allowed to control Docker daemon [INFO] * docker:x:129:rei,root [WARN] 1.5 - Ensure auditing is configured for the Docker daemon [WARN] 1.6 - Ensure auditing is configured for Docker files and directories - /var/lib/docker [WARN] 1.7 - Ensure auditing is configured for Docker files and directories - /etc/docker [INFO] 1.8 - Ensure auditing is configured for Docker files and directories - docker.service [INFO] * File not found [INFO] 1.9 - Ensure auditing is configured for Docker files and directories - docker.socket [INFO] * File not found [WARN] 1.10 - Ensure auditing is configured for Docker files and directories - /etc/default/docker [WARN] 1.11 - Ensure auditing is configured for Docker files and directories - /etc/docker/daemon.json [INFO] 1.12 - Ensure auditing is configured for Docker files and directories - /usr/bin/docker-containerd [INFO] * File not found [INFO] 1.13 - Ensure auditing is configured for Docker files and directories - /usr/bin/docker-runc [INFO] * File not found [INFO] 2 - Docker daemon configuration [WARN] 2.1 - Ensure network traffic is restricted between containers on the default bridge [PASS] 2.2 - Ensure the logging level is set to 'info' [PASS] 2.3 - Ensure Docker is allowed to make changes to iptables [PASS] 2.4 - Ensure insecure registries are not used [WARN] 2.5 - Ensure aufs storage driver is not used [INFO] 2.6 - Ensure TLS authentication for Docker daemon is configured [INFO] * Docker daemon not listening on TCP [INFO] 2.7 - Ensure the default ulimit is configured appropriately [INFO] * Default ulimit doesn't appear to be set [WARN] 2.8 - Enable user namespace support [PASS] 2.9 - Ensure the default cgroup usage has been confirmed [PASS] 2.10 - Ensure base device size is not changed until needed [WARN] 2.11 - Ensure that authorization for Docker client commands is enabled [WARN] 2.12 - Ensure centralized and remote logging is configured [INFO] 2.13 - Ensure operations on legacy registry (v1) are Disabled (Deprecated) [PASS] 2.14 - Ensure live restore is Enabled (Incompatible with swarm mode) [WARN] 2.15 - Ensure Userland Proxy is Disabled [PASS] 2.16 - Ensure daemon-wide custom seccomp profile is applied, if needed [WARN] 2.17 - Ensure experimental features are avoided in production [WARN] 2.18 - Ensure containers are restricted from acquiring new privileges [INFO] 3 - Docker daemon configuration files [INFO] 3.1 - Ensure that docker.service file ownership is set to root:root [INFO] * File not found [INFO] 3.2 - Ensure that docker.service file permissions are set to 644 or more restrictive [INFO] * File not found [INFO] 3.3 - Ensure that docker.socket file ownership is set to root:root [INFO] * File not found [INFO] 3.4 - Ensure that docker.socket file permissions are set to 644 or more restrictive [INFO] * File not found [PASS] 3.5 - Ensure that /etc/docker directory ownership is set to root:root [PASS] 3.6 - Ensure that /etc/docker directory permissions are set to 755 or more restrictive [INFO] 3.7 - Ensure that registry certificate file ownership is set to root:root [INFO] * Directory not found [INFO] 3.8 - Ensure that registry certificate file permissions are set to 444 or more restrictive [INFO] * Directory not found [INFO] 3.9 - Ensure that TLS CA certificate file ownership is set to root:root [INFO] * No TLS CA certificate found [INFO] 3.10 - Ensure that TLS CA certificate file permissions are set to 444 or more restrictive [INFO] * No TLS CA certificate found [INFO] 3.11 - Ensure that Docker server certificate file ownership is set to root:root [INFO] * No TLS Server certificate found [INFO] 3.12 - Ensure that Docker server certificate file permissions are set to 444 or more restrictive [INFO] * No TLS Server certificate found [INFO] 3.13 - Ensure that Docker server certificate key file ownership is set to root:root [INFO] * No TLS Key found [INFO] 3.14 - Ensure that Docker server certificate key file permissions are set to 400 [INFO] * No TLS Key found [PASS] 3.15 - Ensure that Docker socket file ownership is set to root:docker [PASS] 3.16 - Ensure that Docker socket file permissions are set to 660 or more restrictive [PASS] 3.17 - Ensure that daemon.json file ownership is set to root:root [PASS] 3.18 - Ensure that daemon.json file permissions are set to 644 or more restrictive [PASS] 3.19 - Ensure that /etc/default/docker file ownership is set to root:root [PASS] 3.20 - Ensure that /etc/default/docker file permissions are set to 644 or more restrictive [INFO] 4 - Container Images and Build File [PASS] 4.1 - Ensure a user for the container has been created [NOTE] 4.2 - Ensure that containers use trusted base images [NOTE] 4.3 - Ensure unnecessary packages are not installed in the container [NOTE] 4.4 - Ensure images are scanned and rebuilt to include security patches [WARN] 4.5 - Ensure Content trust for Docker is Enabled [WARN] 4.6 - Ensure HEALTHCHECK instructions have been added to the container image [WARN] * No Healthcheck found: [php_test:latest] [WARN] * No Healthcheck found: [docker:dind] [WARN] * No Healthcheck found: [php:7.0-alpine] [WARN] * No Healthcheck found: [php:7.1-alpine] [WARN] * No Healthcheck found: [php:7.2] [WARN] * No Healthcheck found: [httpd:2.4-alpine] [WARN] * No Healthcheck found: [alpine:edge] [WARN] * No Healthcheck found: [tomcat:8] [WARN] * No Healthcheck found: [postgres:latest] [WARN] * No Healthcheck found: [test_rabbit:latest] [WARN] * No Healthcheck found: [php:7.2.7-fpm-alpine3.7] [WARN] * No Healthcheck found: [rabbitmq:management] [WARN] * No Healthcheck found: [k8s.gcr.io/kube-proxy-amd64:v1.10.5] [WARN] * No Healthcheck found: [alpine_test:latest] [WARN] * No Healthcheck found: [node:8] [WARN] * No Healthcheck found: [postgres:9] [WARN] * No Healthcheck found: [owncloud:latest] [WARN] * No Healthcheck found: [node:alpine] [WARN] * No Healthcheck found: [php:5.6-apache-jessie] [WARN] * No Healthcheck found: [percona:5.6] [WARN] * No Healthcheck found: [k8s.gcr.io/kube-scheduler-amd64:v1.10.4] [WARN] * No Healthcheck found: [k8s.gcr.io/kube-controller-manager-amd64:v1.10.4] [WARN] * No Healthcheck found: [gcc:8] [WARN] * No Healthcheck found: [ubuntu:18.04 ubuntu:latest] [WARN] * No Healthcheck found: [ubuntu:18.04 ubuntu:latest] [WARN] * No Healthcheck found: [centos:latest] [WARN] * No Healthcheck found: [quay.io/calico/node:v3.1.3] [WARN] * No Healthcheck found: [quay.io/calico/cni:v3.1.3] [WARN] * No Healthcheck found: [php:5.6-apache] [WARN] * No Healthcheck found: [busybox:latest] [WARN] * No Healthcheck found: [mysql:latest] [WARN] * No Healthcheck found: [debian:wheezy] [WARN] * No Healthcheck found: [mariadb:5.5.59] [WARN] * No Healthcheck found: [alpine:3.7] [WARN] * No Healthcheck found: [k8s.gcr.io/pause-amd64:3.1] [WARN] * No Healthcheck found: [java:openjdk-9] [INFO] 4.7 - Ensure update instructions are not use alone in the Dockerfile [INFO] * Update instruction found: [httpd_test:latest] [INFO] * Update instruction found: [php:7.2] [INFO] * Update instruction found: [tomcat:8] [INFO] * Update instruction found: [postgres:latest] [INFO] * Update instruction found: [test_rabbit:latest] [INFO] * Update instruction found: [rabbitmq:management] [INFO] * Update instruction found: [node:8] [INFO] * Update instruction found: [postgres:9] [INFO] * Update instruction found: [owncloud:latest] [INFO] * Update instruction found: [php:5.6-apache-jessie] [INFO] * Update instruction found: [percona:5.6] [INFO] * Update instruction found: [gcc:8] [INFO] * Update instruction found: [php:5.6-apache] [INFO] * Update instruction found: [mysql:latest] [INFO] * Update instruction found: [mariadb:5.5.59] [INFO] * Update instruction found: [java:openjdk-9] [NOTE] 4.8 - Ensure setuid and setgid permissions are removed in the images [INFO] 4.9 - Ensure COPY is used instead of ADD in Dockerfile [INFO] * ADD in image history: [docker-bench-security:latest] [INFO] * ADD in image history: [httpd_test:latest] [INFO] * ADD in image history: [php_test:latest] [INFO] * ADD in image history: [docker:dind] [INFO] * ADD in image history: [php:7.0-alpine] [INFO] * ADD in image history: [php:7.1-alpine] [INFO] * ADD in image history: [php:7.2] [INFO] * ADD in image history: [httpd:2.4-alpine] [INFO] * ADD in image history: [alpine:edge] [INFO] * ADD in image history: [tomcat:8] [INFO] * ADD in image history: [postgres:latest] [INFO] * ADD in image history: [test_rabbit:latest] [INFO] * ADD in image history: [php:7.2.7-fpm-alpine3.7] [INFO] * ADD in image history: [rabbitmq:management] [INFO] * ADD in image history: [k8s.gcr.io/kube-proxy-amd64:v1.10.5] [INFO] * ADD in image history: [alpine_test:latest] [INFO] * ADD in image history: [node:8] [INFO] * ADD in image history: [postgres:9] [INFO] * ADD in image history: [owncloud:latest] [INFO] * ADD in image history: [node:alpine] [INFO] * ADD in image history: [php:5.6-apache-jessie] [INFO] * ADD in image history: [percona:5.6] [INFO] * ADD in image history: [k8s.gcr.io/kube-scheduler-amd64:v1.10.4] [INFO] * ADD in image history: [k8s.gcr.io/kube-controller-manager-amd64:v1.10.4] [INFO] * ADD in image history: [gcc:8] [INFO] * ADD in image history: [ubuntu:18.04 ubuntu:latest] [INFO] * ADD in image history: [ubuntu:18.04 ubuntu:latest] [INFO] * ADD in image history: [centos:latest] [INFO] * ADD in image history: [quay.io/calico/node:v3.1.3] [INFO] * ADD in image history: [quay.io/calico/cni:v3.1.3] [INFO] * ADD in image history: [php:5.6-apache] [INFO] * ADD in image history: [busybox:latest] [INFO] * ADD in image history: [mysql:latest] [INFO] * ADD in image history: [debian:wheezy] [INFO] * ADD in image history: [mariadb:5.5.59] [INFO] * ADD in image history: [alpine:3.7] [INFO] * ADD in image history: [k8s.gcr.io/pause-amd64:3.1] [INFO] * ADD in image history: [java:openjdk-9] [NOTE] 4.10 - Ensure secrets are not stored in Dockerfiles [NOTE] 4.11 - Ensure verified packages are only Installed [INFO] 5 - Container Runtime [PASS] 5.1 - Ensure AppArmor Profile is Enabled [WARN] 5.2 - Ensure SELinux security options are set, if applicable [WARN] * No SecurityOptions Found: httpd_test_httpd_test.1.k8ebms2wnnj8mdttuem6r5rxl [PASS] 5.3 - Ensure Linux Kernel Capabilities are restricted within containers [PASS] 5.4 - Ensure privileged containers are not used [PASS] 5.5 - Ensure sensitive host system directories are not mounted on containers [PASS] 5.6 - Ensure ssh is not run within containers [PASS] 5.7 - Ensure privileged ports are not mapped within containers [NOTE] 5.8 - Ensure only needed ports are open on the container [PASS] 5.9 - Ensure the host's network namespace is not shared [WARN] 5.10 - Ensure memory usage for container is limited [WARN] * Container running without memory restrictions: httpd_test_httpd_test.1.k8ebms2wnnj8mdttuem6r5rxl [WARN] 5.11 - Ensure CPU priority is set appropriately on the container [WARN] * Container running without CPU restrictions: httpd_test_httpd_test.1.k8ebms2wnnj8mdttuem6r5rxl [WARN] 5.12 - Ensure the container's root filesystem is mounted as read only [WARN] * Container running with root FS mounted R/W: httpd_test_httpd_test.1.k8ebms2wnnj8mdttuem6r5rxl [PASS] 5.13 - Ensure incoming container traffic is binded to a specific host interface [WARN] 5.14 - Ensure 'on-failure' container restart policy is set to '5' [WARN] * MaximumRetryCount is not set to 5: httpd_test_httpd_test.1.k8ebms2wnnj8mdttuem6r5rxl [PASS] 5.15 - Ensure the host's process namespace is not shared [PASS] 5.16 - Ensure the host's IPC namespace is not shared [PASS] 5.17 - Ensure host devices are not directly exposed to containers [INFO] 5.18 - Ensure the default ulimit is overwritten at runtime, only if needed [INFO] * Container no default ulimit override: httpd_test_httpd_test.1.k8ebms2wnnj8mdttuem6r5rxl [PASS] 5.19 - Ensure mount propagation mode is not set to shared [PASS] 5.20 - Ensure the host's UTS namespace is not shared [PASS] 5.21 - Ensure the default seccomp profile is not Disabled [NOTE] 5.22 - Ensure docker exec commands are not used with privileged option [NOTE] 5.23 - Ensure docker exec commands are not used with user option [PASS] 5.24 - Ensure cgroup usage is confirmed [WARN] 5.25 - Ensure the container is restricted from acquiring additional privileges [WARN] * Privileges not restricted: httpd_test_httpd_test.1.k8ebms2wnnj8mdttuem6r5rxl [PASS] 5.26 - Ensure container health is checked at runtime [INFO] 5.27 - Ensure docker commands always get the latest version of the image [WARN] 5.28 - Ensure PIDs cgroup limit is used [WARN] * PIDs limit not set: httpd_test_httpd_test.1.k8ebms2wnnj8mdttuem6r5rxl [PASS] 5.29 - Ensure Docker's default bridge docker0 is not used [PASS] 5.30 - Ensure the host's user namespaces is not shared [PASS] 5.31 - Ensure the Docker socket is not mounted inside any containers [INFO] 6 - Docker Security Operations [INFO] 6.1 - Avoid image sprawl [INFO] * There are currently: 43 images [INFO] * Only 19 out of 43 are in use [INFO] 6.2 - Avoid container sprawl [INFO] * There are currently a total of 19 containers, with 2 of them currently running [INFO] 7 - Docker Swarm Configuration [WARN] 7.1 - Ensure swarm mode is not Enabled, if not needed Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager. [PASS] 7.2 - Ensure the minimum number of manager nodes have been created in a swarm [PASS] 7.3 - Ensure swarm services are binded to a specific host interface Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager. [INFO] 7.5 - Ensure Docker's secret management commands are used for managing secrets in a Swarm cluster [WARN] 7.6 - Ensure swarm manager is run in auto-lock mode [NOTE] 7.7 - Ensure swarm manager auto-lock key is rotated periodically [INFO] 7.8 - Ensure node certificates are rotated as appropriate [INFO] 7.9 - Ensure CA certificates are rotated as appropriate [INFO] 7.10 - Ensure management plane traffic has been separated from data plane traffic [INFO] Checks: 104 [INFO] Score: 11 ```

Manager node:

[INFO] 4 - Container Images and Build File
[PASS] 4.1  - Ensure a user for the container has been created

Worker node:

[INFO] 4 - Container Images and Build File
[PASS] 4.1  - Ensure a user for the container has been created
Manager node container logs ```console $ docker logs httpd_test_httpd_test.2.1oaybpksrkqkc9gx2sutsjygq AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.0.0.6. Set the 'ServerName' directive globally to suppress this message AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.0.0.6. Set the 'ServerName' directive globally to suppress this message [Thu Jul 12 19:57:53.206264 2018] [mpm_event:notice] [pid 1:tid 140162900888456] AH00489: Apache/2.4.33 (Unix) configured -- resuming normal operations [Thu Jul 12 19:57:53.206318 2018] [core:notice] [pid 1:tid 140162900888456] AH00094: Command line: 'httpd -D FOREGROUND' ```
Worker node container logs ```console $ docker logs httpd_test_httpd_test.1.k8ebms2wnnj8mdttuem6r5rxl AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.0.0.5. Set the 'ServerName' directive globally to suppress this message AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.0.0.5. Set the 'ServerName' directive globally to suppress this message [Thu Jul 12 19:57:29.542919 2018] [mpm_event:notice] [pid 1:tid 139946346732424] AH00489: Apache/2.4.33 (Unix) configured -- resuming normal operations [Thu Jul 12 19:57:29.543028 2018] [core:notice] [pid 1:tid 139946346732424] AH00094: Command line: 'httpd -D FOREGROUND' ```
khba commented 6 years ago

"I'm not able to reproduce any error while deploying a stack to a swarm and testing the nodes." => Yes it is normal that you pass the test 4.1 since "USER www-data" was added to the Dockerfile, therefore the container processes run as non-root. But are your nodes on everlay2 and is apache actually running fine?

Anyway the consequence of adding "User www-data" was that "www-data" user couldn't bind to port 80 and caused apache to fail, which led us to add the setcap instruction. Now the problem is that that new image runs normally if the node has aufs storage driver, but hits again the "Can't bind to port 80" error if you try to run it on a node with overlay2 storage driver.

Yes my initial use case is to deploy it on a swarm (where all the nodes are on everlay2), but to not complicate things, one can simply reproduce this with 2 simple docker hosts, one with aufs and the other with overlay2 like this:

With aufs: => works OK: $ docker run --rm image_name AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message [Wed Jul 11 09:51:33.316839 2018] [mpm_event:notice] [pid 1:tid 140008104651656] AH00489: Apache/2.4.33 (Unix) configured -- resuming normal operations [Wed Jul 11 09:51:33.316997 2018] [core:notice] [pid 1:tid 140008104651656] AH00094: Command line: 'httpd -D FOREGROUND'

With overlay2: works not despite setcap: $ docker run --rm image_name AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message (13)Permission denied: AH00072: make_sock: could not bind to address [::]:80 (13)Permission denied: AH00072: make_sock: could not bind to address 0.0.0.0:80

wglambert commented 6 years ago

I'm using the default AUFS, if you're encountering anomalous behavior on a differing storage driver then you could create an issue on https://github.com/moby/moby as we maintain the official-images and not the underlying components of Docker

Manager node

$ docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS                   PORTS               NAMES
645f15e02290        httpd_test:latest   "httpd-foreground"   5 minutes ago       Up 5 minutes (healthy)   80/tcp              httpd_test_httpd_test.2.trty9eq62w0jo64b2h37w1cch
$ curl 127.0.0.1
<html><body><h1>It works!</h1></body></html>

Worker node

$ docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS                   PORTS               NAMES
8b9061c3725d        httpd_test:latest   "httpd-foreground"   5 minutes ago       Up 5 minutes (healthy)   80/tcp              httpd_test_httpd_test.1.xx14geqpdljybirs8nkj8jhzd
$ curl localhost:80
<html><body><h1>It works!</h1></body></html>

I'm not able to reproduce any issues with the image, if you want further help troubleshooting issues you should try the Docker Community Forums, the Docker Community Slack, or Stack Overflow.

yogig commented 4 years ago

I'm not fully understanding your use case, you mention a node, do you mean you're using swarm and stack deploying to a node, and that this worker node is experiencing an anomaly with permissions of some sort? By my understanding you're primarily concerned with test section 4.1 of the docker-bench-security test which tests for running as normal user in the container. I'm not able to reproduce any error while deploying a stack to a swarm and testing the nodes.

Dockerfile

FROM httpd:2.4-alpine

#Custom changes
RUN apk update && apk upgrade
RUN apk -q add curl vim libcap

#Change access righs to conf, logs, bin from root to www-data
RUN chown -hR www-data:www-data /usr/local/apache2/

#setcap to bind to privileged ports as non-root
RUN setcap 'cap_net_bind_service=+ep' /usr/local/apache2/bin/httpd
RUN getcap /usr/local/apache2/bin/httpd

HEALTHCHECK --interval=60s --timeout=30s CMD nc -zv localhost 80 || exit 1
#Run as a www-data
USER www-data

docker-compose.yml

version: "3"

services:
 httpd_test:
  image: httpd_test
  deploy:
   replicas: 2

Manager node Worker node Manager node:

[INFO] 4 - Container Images and Build File
[PASS] 4.1  - Ensure a user for the container has been created

Worker node:

[INFO] 4 - Container Images and Build File
[PASS] 4.1  - Ensure a user for the container has been created

Manager node container logs Worker node container logs

Helpful!!