microsoft / vscode-dev-containers

NOTE: Most of the contents of this repository have been migrated to the new devcontainers GitHub org (https://github.com/devcontainers). See https://github.com/devcontainers/template-starter and https://github.com/devcontainers/feature-starter for information on creating your own!
https://aka.ms/vscode-remote
MIT License
4.72k stars 1.4k forks source link

Use suid so the container does not need to be started as root or have sudo configured #488

Open felipecrs opened 4 years ago

felipecrs commented 4 years ago

The docker-debian.sh relies on the container being started as root or to have sudo properly configured.

To get rid of this requirement, we can use the suid bit so the script has permission to as root by itself. I made a small project to prove that it works, by using shc, the Shell Script Compiler, to make such thing work with shell scripts. See fixdockergid.

At the end, we could have a very less intrusive docker run call to start the container:

docker run -u "$(id -u):$(id -g)" -v /var/run/docker.sock:/var/run/docker.sock ubuntu-with-fixdockergid

And the Dockerfile can still have the USER vscode as its last statement.

PavelSosin-320 commented 4 years ago

I vote for it with another use-case: "Native docker running inside WSL2 distro (CentOS) listening standard /var/run/docker.sock:/var/run/docker.sock." Docker itself is much more stable and secure than Docker-for-Windows due to pure enterprise origin and docker CLI and docker-compose come as platform packages.

felipecrs commented 4 years ago

I vote for it with another use-case: "Native docker running inside WSL2 distro (CentOS) listening standard /var/run/docker.sock:/var/run/docker.sock." Docker itself is much more stable and secure than Docker-for-Windows due to pure enterprise origin and docker CLI and docker-compose come as platform packages.

I didn't quite understand... can you elaborate?

Chuxel commented 4 years ago

@felipecassiors The script that is referenced is a bit smarter than the simplistic description in the README... which is intended to "just work" on all platforms. If it detects the group on the socket is not "0", it creates a group and adds the user to it. The socat version is a final fallback since I'm finding that on Windows and macOS, the group is zero in some cases but not others (e.g. WSL it might not be, but hyper-v and macOS it is). That isn't really needed on Linux in most cases, but I don't want to just chown the socket for macOS/Windows since on Linux that would update the host.

Basically, the script should do the right thing when possible and then fall back to the socat approach as a final fallback.

Check out https://github.com/microsoft/vscode-dev-containers/blob/master/script-library/docker-debian.sh the "docker-init.sh" script is embedded in it just to have a single file to do the work.

Is that what you are getting at?

felipecrs commented 4 years ago

@Chuxel you're right. The script already performs the necessary changes to the docker group in the container or even creates it.

The disadvantage of it against the fixdockergid approach is that it relies on either:

  1. The container being started as root
  2. sudo installed and configured (SUDOERS)

You can get rid of those requirements by setting the suid bit. The fixdockergid is one example of how it can be used on shell scripts, with the shc compiler.

Chuxel commented 4 years ago

Yeah, the the issue is extensions like "Docker" access the socket directly rather than through the CLI, so I'm not sure setting that bit on the docker CLI resolves the problem. The specific problem here is that the socket itself.. and thus the underlying GID and UID on the host, is "root" -- intentionally.

That said, we could probably drop the use of sudo if we set the suid bit on the shell scripts - that's a good idea.

There's code that updates the UID/GID if the remoteUser is set in the core of the extension, but this doesn't try to scan the whole filesystem to make updates given the potential perf implications of that. Not sure if @chrmarti looked at using fixuid for that functionality already.

felipecrs commented 4 years ago

That said, we could probably drop the use of sudo if we set the suid bit on the shell scripts - that's a good idea.

Exactly, that's the point.

There's code that updates the UID/GID if the remoteUser is set in the core of the extension, but this doesn't try to scan the whole filesystem to make updates given the potential perf implications of that. Not sure if @chrmarti looked at using fixuid for that functionality already.

I don't think there are significant performance implications, but need to evaluate.

felipecrs commented 4 years ago

I rewrote this Issue to point the real proposal.

PavelSosin-320 commented 4 years ago

The standard way to enable access to the docker by any user is documented in every "native" docker installation guide: docker installation creates a docker user group and every user who belongs to this group has access to docker. For example, I run native docker in CentOS 7 distro that has my user, created and assigned to the docker user group and I can use docker without any sudo or wsl -u root just because my login user belongs to the docker group. The assignment is done once because users and groups are persistent in the Linux distro. Indeed, I disabled SELINUX in my distro because I don't see such a security level is relevant for WSL. It means some security compromise. When docker or podman are installed on SELINUX distro as a platform package from the corresponding repository the installation takes MAC security into account and such docker installation can pass the most rigorous security check.

felipecrs commented 4 years ago

Another problem which would be solved by using fixuid or at least it's approach is that we would not need to know the UID and GID of the host machine in the build time, but only in the run time.

This would enable people to build and push their non-root dev containers and be able to use anywhere else. I'm personally facing a problem trying to run some automated tests against my dotfiles using a pre-built Remote - Containers image (https://github.com/felipecrs/dotfiles/pull/16).

Because the user of GitHub Actions Runner has the UID 1001 and GID 116, I'm not able to start the container as a non-root user since the UID (1000) and GID (1000) of the vscode user in the container does not get properly adjusted at the run time.