Skip to content

Commit b1ecc0b

Browse files
authored
verify_exercises_in_docker: allow using podman (#2142)
Podman is a container runtime with several advantages over docker: - It's fully open-source. Beyond the ethics, that comes with practical benefts. For example, more Linux distributions carry Podman in their official package repositories. The installation of Docker, on the other hand, can be a pain. - It's designed to run in rootless mode. That means "sudo" is not required to run this test script. Actually, the test script doesn't use sudo, because it assumes that people add themselves to the docker group, allowing themselves to use the docker command without sudo. This is a privilege escalation vulnerability: An attacker who gains RCE with that user can easily upgrade to root privileges via docker. Exercism contributors should not be required to lower their system's security to contribute. There are slight incompatibilities, which are addressed: - The bind mounts require the "Z" option to permit the container access to these directories on systems using SELinux, like Fedora. - Podman maps user IDs to a separate namespace per container. In order to keep the mounted directories owned and writable by the normal local user, this mapping is suppressed with the `--userns=keep-id` option.
1 parent 334c0b2 commit b1ecc0b

1 file changed

Lines changed: 18 additions & 4 deletions

File tree

bin/verify_exercises_in_docker.sh

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,20 @@ required_tool() {
2020
die "${1} is required but not installed. Please install it and make sure it's in your PATH."
2121
}
2222

23-
required_tool docker
23+
# prefer podman over docker if it's installed
24+
if which podman &> /dev/null ; then
25+
docker() {
26+
podman "$@"
27+
}
28+
# for SELinux systems, permit container access to mounted directories
29+
podman_mount_opt=",Z"
30+
# use same user ID for container, avoids file ownership problems
31+
podman_run_opt="--userns=keep-id"
32+
else
33+
required_tool docker
34+
podman_mount_opt=""
35+
podman_run_opt=""
36+
fi
2437

2538
copy_example_or_examplar_to_solution() {
2639
jq -c '[.files.solution, .files.exemplar // .files.example] | transpose | map(select(.[0] and .[1]) | {src: .[1], dst: .[0]}) | .[]' .meta/config.json \
@@ -45,9 +58,10 @@ run_tests() {
4558
-u "$(id -u):$(id -g)" \
4659
--rm \
4760
--network none \
48-
--mount type=bind,src="${PWD}",dst=/solution \
49-
--mount type=bind,src="${PWD}",dst=/output \
61+
--mount type=bind,src="${PWD}",dst=/solution${podman_mount_opt} \
62+
--mount type=bind,src="${PWD}",dst=/output${podman_mount_opt} \
5063
--mount type=tmpfs,dst=/tmp \
64+
${podman_run_opt} \
5165
"${image}" "${slug}" /solution /output
5266
jq -e '.status == "pass"' "${PWD}/results.json" >/dev/null 2>&1
5367
}
@@ -99,7 +113,7 @@ done
99113
shift "$((OPTIND - 1))"
100114

101115
if [[ -z "${image}" ]]; then
102-
image="exercism/rust-test-runner"
116+
image="docker.io/exercism/rust-test-runner"
103117
pull_docker_image
104118
fi
105119

0 commit comments

Comments
 (0)