Classic confinement request for cot

Hi,

cot is a tool I’ve been working on for some time now. The goal is to make it easier to run every day commands such as npm install (it can run any command that can run in a Podman/Docker container) in a more secure way. The tool uses Podman and Docker and therefore it cannot run in confined mode.

https://snapcraft.io/cot

Source code and snapcraft.yaml are available on GitHub.

Best regards

Have you looked at using the docker snap, and plugging docker-executables and docker from your snap, and connecting these interfaces to the slots from the docker snap? Other snaps have been able to do this and gotten store approval for this as well.

I’m just starting to get familiar with Snap but as far as I understand it wouldn’t work because:

  • People might use the non-Snap version of Docker and in this case it wouldn’t be compatible, right? (In fact I don’t know anyone who does use the Docker Snap.) (There are also cases where you can’t use the Snap such as Docker EE.)
  • There is no security benefit: with access to the Docker socket - even if it’s the Snap version of Docker - it’s very easy to escape the sandbox. Just run docker run --rm -it -v /:/host alpine sh and you’ll have access to everything on the host.
  • It wouldn’t work together with Podman. While Podman can’t do everything Docker does, it can do many things without root privileges. Podman support gives users the ability to work without root privileges (as said, access to the Docker socket effectively means root). Users would have to use Docker, even in cases where it’s not required, effectively weakening security. Also there is no working Snap version of Podman so far.
  • Access to the Docker socket is limited to the docker group by default. cot will use sudo docker if Docker is used and the current user is not in the docker group. The additional password prompt can increase security, but this wouldn’t work in confined mode.

Another thing that I’m not sure about is environment variables: cot’s behavior can be changed using environment variables. AFAIK those wouldn’t be forwarded to cot in confined mode.

There has been some discussion on lifting this restriction and allowing the docker interface to be provided by the system snap (i.e. core or snapd snaps), which would allow using non-snap versions of docker. See Request for "classic" confinement for package Wilfred - #27 by jdstrand

Does podman also listen on the docker socket at the normal location? If so, then changing the docker interface to be implicit would satisfy this use case.

A potential solution for this to be able to work with strict confinement would be to just fail if the user is not in the docker group and print a message saying they should add themselves to the group or they should run cot with sudo.

This isn’t true, environment variables are still forwarded to snap apps.

There is no socket, Podman doesn’t run as a daemon:

Podman can be easily run as a normal user, without requiring a setuid binary. When run without root, Podman containers use user namespaces to set root in the container to the user running Podman. Rootless Podman runs locked-down containers with no privileges that the user running the container does not have. Some of these restrictions can be lifted (via --privileged , for example), but rootless containers will never have more privileges than the user that launched them. If you run Podman as your user and mount in /etc/passwd from the host, you still won’t be able to change it, since your user doesn’t have permission to do so. Source

That wouldn’t be a solution, the feature would just not be available in the Snap. :confused:

Good to know, thanks! :smiley:

There are plans to adjust the docker interface to work with a non-snap docker.

Yes, the docker socket is very powerful and we require a similar process for using it as for granting classic (where we typically do not allow auto-connection). Do note that the docker socket is typically protected with traditional unix permissions where you either need to be root to connect to it or be in a specific group (eg, docker). It is also typically easier to maintain a strict mode snap and a strict mode snap can be installed on Ubuntu Core.

Furthermore, the rational that classic is ok since plugging a superprivileged interface like docker, docker-support, lxd, kernel-module-control, etc is not a justification for classic. Classic grants instant full admin access to the snap. Plugging an interface means that auto-connection can be regulated and maintains the user’s voice

It sounds like you would likely need to also plugs the docker-support interface (which would also require a request to use it) to have access to this functionality.

This is correct, but lack of a sudo prompt is not a reason for classic confinement. Instead of having cot use sudo, you can check if you have access to the socket and then ask the user to rerun the command under sudo.

Based on the information in this request so far, classic does not seem to be required.

Hi @jdstrand,

thanks for your response!

I can live with losing the sudo feature but losing Podman support would be kind of a deal breaker for me. Can you please elaborate on how this should work? Would I include Podman in the Snap? If yes, how?

Oh, I thought you were saying you already were using podman, hence my recommendation to use ‘docker-support’ to allow podman to work.

How does your snap communicate with podman? Over a socket like docker? Over DBus? Some other means?

There is no daemon to talk to, you just run podman run, the tool creates a new user namespace, network namespace etc. and then launches the container in a subprocess.

Ok, then, yes, you would need to ship podman in your snap. I suggest for now going with strict mode for docker (and we’ll make using with the non-snap docker work) and feel free to release to beta, candidate or stable.

Then create a devmode snap (feel free to plugs docker-support for the time being) that includes podman, release it to edge and report back with instructions on how to use it and all the the functionality your snap supports in working with podman as non-root. Since docker runs as root and podman does not, we can perhaps create a podman-support interface that isn’t quite as wide open as docker-support. Assuming that happens soon enough, I can take a look at the accesses for as part of the above docker interface work, hopefully ready for the snapd 2.45 release.

I got this:

parts:
  podman:
    plugin: go
    source: https://github.com/containers/libpod/archive/v1.8.2.tar.gz
    go-importpath: github.com/containers/libpod

How can I tell snapcraft which application to build? It seems to run cd /root/parts/podman/build && go build -o /root/parts/podman/install/bin ./... and fails because the cmd/podmanV2 application cannot be built. I only need cmd/podman. I tried setting go-packages but it did not work.

I suggest splitting this part of the conversation out and creating a new topic in the ‘snapcraft’ category so the right people can see this and help you.