GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — Detect rootless mode by themr0c · Pull Request #1484 · pre-commit/pre-commit Conversation
Contributor
fix #1243 - the -u option is not necessary on podman
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Contributor
Author
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
Contributor
Author
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
asottile
reviewed
Uh oh!
There was an error while loading. Please reload this page.
webknjaz
reviewed
Uh oh!
There was an error while loading. Please reload this page.
Contributor
Author
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
webknjaz
reviewed
Uh oh!
There was an error while loading. Please reload this page.
|
There was an error while loading. Please reload this page.
|
I spent some time trying to understand how to write a test to make the build pass. I just don't understand how to get it. Too much to learn in one go. May I request some help (again)? So far I understand that it should probably take the for of a block like that in Then I assume we have to mock the content of Then I got lost in the pytest documentation. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
@themr0c you can use a built-in fixture called The simple one case test would be _ROOTLESS_DOCKER_OUTPUT = """ some garbage rootless: true even more garbage """ def test_rootless_docker(monkeypatch): """Verify that only rootless docker/podman doesn't add args.""" monkeypatch.setattr('subprocess.check_output', lambda cmd, text: _ROOTLESS_DOCKER_OUTPUT) assert docker.get_docker_user() == () |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
And going further this would create tests for 4 test cases (rootless docker, rootless podman, non-rootless docker and non-rootless podman): import os import pytest _CURRENT_UID = os.getuid() _CURRENT_GID = os.getgid() @pytest.mark.parametrize( ('docker_sys_info', 'expected_args'), ( pytest.param( """ some garbage rootless: true even more garbage """, (), id='rootless podman', ), pytest.param( """ some garbage rootless: false even more garbage """, (_CURRENT_UID, _CURRENT_GID), id='non-rootless podman', ), pytest.param( """ some garbage rootless even more garbage """, (), id='rootless docker', ), pytest.param( """ some garbage nothing good even more garbage """, (_CURRENT_UID, _CURRENT_GID), id='non-rootless docker', ), ), ) def test_rootless_docker(docker_sys_info, expected_args, monkeypatch): """Verify that only rootless docker/podman doesn't add args.""" monkeypatch.setattr('subprocess.check_output', lambda cmd, text: docker_sys_info) assert docker.get_docker_user() == expected_args |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
before going further please address my comments here in particular:
additionally:
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I am completely illiterate in writing python code, it seems I chose a task too complex for me as first attempt to contribute :/.
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@themr0c you literally can just |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
in-process cache is fine -- there's currently no precedent for across-process caching in pre-commit, though I plan to do that eventually for virtualenv invalidation |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
you're doing great! we'll help you through it :)
in this case it would just be importing
the helper is
taking the test above, you'd use with mock.patch.object(docker, 'cmd_output', return_value=(0, ..., '')): ... instead of the |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Side note: We have a videocall scheduled with @themr0c for early next week (this week it didn't work out) and we'll go trough the requested changes together. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
| # rootless docker has "rootless" | ||
| # rootless podman has "rootless: true" | ||
| if line.strip().startswith('rootless'): | ||
| if 'false' not in line: |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Note: Technically, the case where false is present is not tested. However in practice, we haven't found a case like this, this check is present as precaution.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This would be useful as a code comment
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Is that what is causing the coverage error?
Name Stmts Miss Branch BrPart Cover Missing
----------------------------------------------------------------------------
pre_commit/languages/docker.py 72 2 10 2 95% 89->91, 91, 101->102, 102
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This is weird. If tests include example outputs containing rootless, they should also hit this condition check.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
@asottile any ideas about this?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
there's no test for rootless: false so line 91 is never hit -- perhaps simpler would be if line.strip() == 'rootless: true': ...
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
That would probably not catch docker's behavior. Better to just improve the test matrix
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@themr0c I think this PR's title/description should be updated. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| Insecure Registries: | ||
| 127.0.0.0/8 | ||
| Live Restore Enabled: true | ||
| ''' # noqa |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
it's usually better to specify specific violation codes instead of ignoring everything
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
let me know if you'd like me to finish this one, I've finally gotten around to setting up podman to reproduce this |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Depends on @themr0c. I am available to meet again and address the review comments, but if they prefer you to handle it, I don't mind. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I may be able to take a look at this as I use CentOS and have both docker and podman installed. Are the review comments still current? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
looks like |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
The user option is not necessary, podman does the correct mapping. On the contrary, specifying user and userns can lead to trouble: One of the main advantages of podman is to get rid of the -u option that you need when you run docker if you don't want to see your workspaces filled by files owned by root... So why insist on keeping some unnecessary complexity? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
the default mapping gives too much permission and can create undeletable files outside: $ podman run --rm -ti -v $PWD:/z:rw ubuntu:focal bash -c 'mkdir -p /z/1/2/3 && chown -R nobody /z/1' $ rm -rf 1 rm: cannot remove '1/2/3': Permission denied |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Now I undertand better. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
good for issue
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Came here from #2173 and would be interested in taking this over. Would it be sufficient to return |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
@PhilipTrauner please take it over. I am happy if this pull request gets closed, even unresolved. I apologize for having started something that I am not able to finish. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
run-in-node-container is used for javascript "rollup", so the tools running in the container produce files which must be owned by the user on the host. To achieve this, the docker run --user option is used to ensure that the tools in the container are run as host user. However, with rootless mode - apparently in both docker and podman, but I'm using podman - a user namespace is used and users in the container are mapped to a range of users on the host. This means that if we run a command as root in the container, this corresponds to the host user. When we specify --user, this results in a different host user being used. There are apparently two ways of achieving what we want - not using --user so that the commands run as root in the container, which is mapped to the desired host user. Or we can use --userns keep-id which means a 1:1 user mapping is used, and the user specified by --user corresponds to the same user on the host. The former seems more like how you'd typically use this mode. And so we detect rootless mode using "docker system info", and avoid the --user flag in this case. Podman reports "rootless: (true|false)", whereas docker just includes a "rootless" keyword. For more on this, see: https://www.redhat.com/sysadmin/user-flag-rootless-containers https://docs.docker.com/engine/security/rootless pre-commit/pre-commit#1243 pre-commit/pre-commit#1484 (Note: all of the above applies even without SELinux and was tested with "setenforce 0")
| returncode, stdout, stderr = cmd_output( | ||
| 'docker', 'system', 'info', | ||
| ) |
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
It would be even faster and simplify both the logic below and the mock output used in testing to only query Docker/Podman for the field we care about. From the rootless-docker GitHub Action's README, docker info --format "{{ .ClientInfo.Context }}" outputs rootless in Docker when in rootless mode, and other strings (most commonly default, I believe) otherwise. I suspect, based on Podman's documentation, that podman info --format "{{ .host.security.rootless }}" outputs true when in rootless mode and false otherwise. Go templates are quite powerful, so we can say: docker info --format '{{ if .ClientInfo.Context }} {{ eq .ClientInfo.Context "rootless" }} {{ else }} {{ .host.security.rootless }} {{ end }}'. This command outputs true when running in rootless mode and false otherwise in both Docker and Podman, although I have only tested it on Docker. I don't have Podman installed, so hopefully someone who does can straighten me out if I'm mistaken. Disclosure: I am the author of the rootless-docker GitHub Action.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Here on my machine (Linux Mint 19.3, Docker version 20.10.16, build aa7e414) your suggestion returns default for rootless docker, as rootless seems to be part of the Security Options under Server.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Thanks for letting me know. Bummer that the behavior isn't consistent across our machines even on the exact same build of Docker. I am on Ubuntu 22.04, but I wonder whether the difference has more to do with how we installed rootless Docker? It's possible to detect rootless mode under SecurityOptions too (e.g., docker info --format '{{ range .SecurityOptions }}{{ if eq . "name=rootless" }}true{{ end }}{{ end }}'), FWIW.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
IIRC I followed the official instructions for Ubuntu. Maybe you chose to set the client context explicitly where I went for the DOCKER_HOST environment variable? Both options are listed in the instructions: https://docs.docker.com/engine/security/rootless/#client
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are correct. I suppose one could check the DOCKER_HOST environment variable before running docker info.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Closing, as this pull request implements the feature: kubernetes/test-infra#25841 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
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 <[email protected]> Co-authored-by: Fabrice Flore-Thébault <[email protected]>
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 <[email protected]> Co-authored-by: Fabrice Flore-Thébault <[email protected]>
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 <[email protected]> Co-authored-by: Fabrice Flore-Thébault <[email protected]>
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 <[email protected]> Co-authored-by: Fabrice Flore-Thébault <[email protected]>
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
Permission issue with rootless containers
There was an error while loading. Please reload this page.