Docker – SELinux with docker and traefik

dockerfedoraselinux

I have a SELinux security problem on /run/docker.sock using traefik in docker.
docker ps works correctly, it's only a problem with traefik needing to map volume /var/run/docker.sock

Here is what I tried:

 git clone https://github.com/jamct/traefik-example.git
 cd traefik-example/04_config_files
 sudo setenforce 0
 docker-compose up
 #it works
 sudo setenforce 1
 docker-compose up
 # it fails

$ ls  -lsZ /run/docker.sock
0 srw-rw-rw-. 1 root docker system_u:object_r:container_file_t:s0:c134,c237 0  4 mars  11:38 /run/docker.sock

I have got this error log

traefik_1  | time="2020-03-04T15:46:16Z" level=error msg="Provider connection error Got permission    denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.24/version: dial unix /var/run/docker.sock: connect: permission denied, retrying in 4.506218855s" providerName=docker

and the log in permissive mod in /var/log/audit/audit.log:

type=AVC msg=audit(1583336776.607:1931): avc:  denied  { connectto } for  pid=16969 comm="traefik" path="/run/docker.sock" scontext=system_u:system_r:container_t:s0:c134,c237 tcontext=system_u:system_r:container_runtime_t:s0 tclass=unix_stream_socket permissive=0

the docker-compose.yml

version: "3.7"
services:
  traefik:
    image: traefik:v2.0
    command: --providers.docker
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:rw
      - ./traefik.yml:/etc/traefik/traefik.yml
      - ./dynamic.yml:/etc/traefik/dynamic/traefik.yml
  web1:
    image: nginx:alpine
    labels:
      - traefik.http.routers.web1.rule=Host(`web1.localhost`)
  web2:
    image: containous/whoami
    labels:
      - traefik.http.routers.web2.rule=Host(`web2.localhost`) || ( Host(`localhost`) && PathPrefix(`/web2`) )
      - traefik.http.routers.web2.middlewares=demo-whitelist@file

Is there a clean way to make traefik work with selinux enabled? Is there a "chcon" CLI that I can use on /run/docker.sock file?

Best Answer

Edit and Disclaimer: this solution is not the recommended one since it breaks security rules on docker, The solutions are here: https://stackoverflow.com/questions/29089023/var-run-docker-sock-unaccessible-in-container-running-on-centos-7/30368817#30368817

Thanks to the bug report of redhat given by @Bert I could get a solution:

Why SELinux prevent access to /run/docker.sock in redhat configuration (fedora, centos)

Bug 1495053 - SELinux is preventing traefik from 'connectto' This bug report is classed as "not a bug" for the folowing reason:

You are trying to connect a confined domain to the docker socket. There is no sense in doing this, since the ability to talk to the docker socket allows you full control over the host. Either this is a very serious breakout of your container, or you should be running a privileged container. SELinux is doing exactly what it should do in blocking access to the docker socket.

So i shouldn't change access to docker.sock as it would be the same as disabling selinux. Instead, I could run in a "privileged" container.

Solution

I just changed the docker-compose.yml file to run in provilieged mode (the same mode can be obtained in other docker launchers).

Here is the working docker-compose.yml file

version: "3.7"
services:
  traefik:
    image: traefik:v2.1.6
    command: --providers.docker
    ports:
      - "80:80"
      - "8080:8080"
    privileged: true
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:rw
      - ./traefik.yml:/etc/traefik/traefik.yml
      - ./dynamic.yml:/etc/traefik/dynamic/traefik.yml
  web1:
    image: nginx:alpine
    labels:
      - traefik.http.routers.web1.rule=Host(`web1.localhost`)  ||  PathPrefix(`/web1`) 
  web2:
    image: containous/whoami
    labels:
      - traefik.http.routers.web2.rule=Host(`web2.localhost`) || ( Host(`localhost`) && PathPrefix(`/web2`) )
      - traefik.http.routers.web2.middlewares=demo-whitelist@file

The important line is privileged: true in the traefik container.

With privileged: true and selinux enabled, it works, if i change back to privileged: false, I get back the error log, what is expected.