-
-
Notifications
You must be signed in to change notification settings - Fork 874
Fix permission errors for mounts in rootless docker #3446
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix permission errors for mounts in rootless docker #3446
Conversation
26b203c
to
399f2f0
Compare
tests/languages/docker_test.py
Outdated
), | ||
) | ||
def test_docker_user_rootless_docker(info_ret, expect_root): | ||
docker._is_rootless_docker.cache_clear() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 maybe we should clear this before and after the test run: otherwise we risk polluting following tests with whatever value we last injected (and not the real value it reads from docker
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
usually a better approach is something like this:
@pytest.fixture(autouse=True)
def _avoid_cache():
with mock.patch.object(docker, '_is_rootless_docker', docker._is_rootless_docker.__wrapped__):
yield
this bypasses the cache for the duration of the test
pre_commit/languages/docker.py
Outdated
retcode, out, _ = cmd_output_b( | ||
'docker', 'system', 'info', '--format', '{{ json .SecurityOptions }}', | ||
) | ||
# some failures are to be expected, e.g. for 'podman' aliased as 'docker' | ||
if retcode != 0: | ||
return False | ||
|
||
info = json.loads(out) | ||
return any(opt == 'name=rootless' for opt in info) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesn't seem to work for podman :(
$ readlink -f $(which docker)
/usr/bin/podman
$ docker system info --format '{{ json .SecurityOptions }}'
Error: template: info:1:8: executing "info" at <.SecurityOptions>: can't evaluate field SecurityOptions in type *define.Info
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesn't seem to work for podman :(
$ readlink -f $(which docker) /usr/bin/podman $ docker system info --format '{{ json .SecurityOptions }}' Error: template: info:1:8: executing "info" at <.SecurityOptions>: can't evaluate field SecurityOptions in type *define.Info
It looks like the invocation we need for podman
is: podman system info --format '{{ json .Host.Security.Rootless }}'
, I guess we could either:
- Run the docker command and on failure try the podman one, or
- Run a separate command to figure out if
docker
invokes docker or podman and then run the corresponding command (ignoring any other container engines for now)
Trying to find a suitable command:
- Naively I just want to run
docker --version
and search the output for"podman"
- Or use the entire JSON output from
docker system info
- If
.host
exists: check["host"]["Security"]["Rootless"]
, else - Check in
["SecurityOptions"]
- If
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parsing the entire info response seemed the most robust: 9bc412d
tests/languages/docker_test.py
Outdated
if expect_root: | ||
assert docker.get_docker_user() == () | ||
else: | ||
assert docker.get_docker_user() != () |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't write logic in tests -- these are two separate disparate behaviours and should be tested separately
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't write logic in tests -- these are two separate disparate behaviours and should be tested separately
909c165 also included your cache suggestion from above
3b3d042
to
026db3a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By running containers in a rootless docker context as root. This is because user and group IDs are remapped in the user namespaces uses by rootless docker, and it's unlikely that the current user ID will map to the same ID under this remap (see docs[1] for some more details). Specifically, it means ownership of mounted volumes will not be for the current user and trying to write can result in permission errors. This change borrows heavily from an existing PR[2]. The output format of `docker system info` I don't think is documented/guaranteed anywhere, but it should corresponding to the format of a `/info` API request to Docker[3] The added test _hopes_ to avoid regressions in this behaviour, but since tests aren't run in a rootless docker context on the PR checks (and I couldn't find an easy way to make it the case) there's still a risk of regressions sneaking in. Link: https://docs.docker.com/engine/security/rootless/ [1] Link: pre-commit#1484 [2] Link: https://docs.docker.com/reference/api/engine/version/v1.48/#tag/System/operation/SystemAuth [3] Co-authored-by: Kurt von Laven <Kurt-von-Laven@users.noreply.github.com> Co-authored-by: Fabrice Flore-Thébault <ffloreth@redhat.com>
026db3a
to
466f6c4
Compare
By running containers in a rootless docker context as root. This is because user and group IDs are remapped in the user namespaces uses by rootless docker, and it's unlikely that the current user ID will map to the same ID under this remap (see docs[1] for some more details). Specifically, it means ownership of mounted volumes will not be for the current user and trying to write can result in permission errors.
This change borrows heavily from an existing PR[2].
The output format of
docker system info
I don't think is documented/guaranteed anywhere, but it should corresponding to the format of a/info
API request to Docker[3]The added test hopes to avoid regressions in this behaviour, but since tests aren't run in a rootless docker context on the PR checks (and I couldn't find an easy way to make it the case) there's still a risk of regressions sneaking in.
Link: https://docs.docker.com/engine/security/rootless/ [1]
Link: #1484 [2]
Link: https://docs.docker.com/reference/api/engine/version/v1.48/#tag/System/operation/SystemAuth [3]
resolves #1243