Archived
fix(docker): run hostexec as container user
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@jmfederico/pi-web": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Run Docker host command bridge commands as the PI WEB container user by default, with `hostexec --root` for administrative commands.
|
||||||
+6
-6
@@ -16,7 +16,7 @@ By design, the runtime containers get deliberate host access so PI WEB agents ca
|
|||||||
- `/var/run/docker.sock` is mounted into the containers. The Docker socket is root-equivalent on the host.
|
- `/var/run/docker.sock` is mounted into the containers. The Docker socket is root-equivalent on the host.
|
||||||
- `/srv`, `/opt`, and `/home` are mounted read/write.
|
- `/srv`, `/opt`, and `/home` are mounted read/write.
|
||||||
- `/` is mounted read-only at `/host` for inspection.
|
- `/` is mounted read-only at `/host` for inspection.
|
||||||
- `hostexec` can start a temporary privileged helper container and run explicit commands in the host namespaces.
|
- `hostexec` can start a temporary privileged helper container and run explicit commands in the host namespaces. Commands run as the container user by default, and `hostexec --root` can still run explicit administrative commands as root.
|
||||||
|
|
||||||
Only install this on machines where the PI WEB user, the selected workspaces, and the browser/API clients are trusted. Review scripts before piping them to `sh` if you do not already trust this repository.
|
Only install this on machines where the PI WEB user, the selected workspaces, and the browser/API clients are trusted. Review scripts before piping them to `sh` if you do not already trust this repository.
|
||||||
|
|
||||||
@@ -150,16 +150,16 @@ If you use a reverse proxy, keep the container bound to localhost or a private a
|
|||||||
|
|
||||||
## `hostexec` examples
|
## `hostexec` examples
|
||||||
|
|
||||||
`hostexec <command...>` is the only host command bridge provided by this Docker setup. It intentionally does not abstract package managers or detect distributions.
|
`hostexec [--root] <command...>` is the only host command bridge provided by this Docker setup. It intentionally does not abstract package managers or detect distributions. By default, commands run as the same numeric user/group as the PI WEB container. Use `--root` only for administrative host commands.
|
||||||
|
|
||||||
Run it from a PI WEB session, a PI WEB terminal, or by execing into the runtime container:
|
Run it from a PI WEB session, a PI WEB terminal, or by execing into the runtime container:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
hostexec uname -a
|
hostexec uname -a
|
||||||
hostexec systemctl status docker
|
hostexec systemctl status docker
|
||||||
hostexec zypper refresh
|
hostexec --root zypper refresh
|
||||||
hostexec sh -lc 'zypper refresh && zypper dup -y'
|
hostexec --root sh -lc 'zypper refresh && zypper dup -y'
|
||||||
hostexec apt-get update
|
hostexec --root apt-get update
|
||||||
```
|
```
|
||||||
|
|
||||||
From the host shell, for a quick smoke test:
|
From the host shell, for a quick smoke test:
|
||||||
@@ -169,7 +169,7 @@ cd ~/.local/share/pi-web-docker
|
|||||||
docker compose exec web hostexec uname -a
|
docker compose exec web hostexec uname -a
|
||||||
```
|
```
|
||||||
|
|
||||||
`hostexec` starts a temporary privileged helper container through the mounted Docker socket, enters the host namespaces with `nsenter`, and runs exactly the command you passed. Treat it like running a privileged host command.
|
`hostexec` starts a temporary privileged helper container through the mounted Docker socket, enters the host namespaces with `nsenter`, and runs exactly the command you passed. Treat it like privileged host access even when the final command drops back to the container user.
|
||||||
|
|
||||||
## Development Docker setup
|
## Development Docker setup
|
||||||
|
|
||||||
|
|||||||
+84
-9
@@ -3,13 +3,36 @@ set -euo pipefail
|
|||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat >&2 <<'EOF'
|
cat >&2 <<'EOF'
|
||||||
Usage: hostexec <command...>
|
Usage: hostexec [--root] [--] <command...>
|
||||||
|
|
||||||
Run a command on the Docker host by starting a temporary privileged helper
|
Run a command on the Docker host by starting a temporary privileged helper
|
||||||
container through the mounted Docker socket and entering the host namespaces.
|
container through the mounted Docker socket and entering the host namespaces.
|
||||||
|
Commands run as the current container UID/GID by default. Use --root to keep
|
||||||
|
root privileges for administrative host commands.
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
run_as_root=false
|
||||||
|
while [ "$#" -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--root)
|
||||||
|
run_as_root=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--help|-h)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
if [ "$#" -eq 0 ]; then
|
if [ "$#" -eq 0 ]; then
|
||||||
usage
|
usage
|
||||||
exit 64
|
exit 64
|
||||||
@@ -30,19 +53,71 @@ if [[ "$docker_host" == unix://* ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
helper_image="${HOSTEXEC_IMAGE:-alpine:3.22}"
|
helper_image="${HOSTEXEC_IMAGE:-alpine:3.22}"
|
||||||
|
target_uid="$(id -u)"
|
||||||
|
target_gid="$(id -g)"
|
||||||
tty_args=(--interactive)
|
tty_args=(--interactive)
|
||||||
if [ -t 0 ] && [ -t 1 ]; then
|
if [ -t 0 ] && [ -t 1 ]; then
|
||||||
tty_args+=(--tty)
|
tty_args+=(--tty)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
docker_args=(
|
||||||
|
--rm
|
||||||
|
"${tty_args[@]}"
|
||||||
|
--pull=missing
|
||||||
|
--privileged
|
||||||
|
--security-opt label=disable
|
||||||
|
--pid=host
|
||||||
|
--network=host
|
||||||
|
--volume /:/host:rw
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ "$run_as_root" = true ] || { [ "$target_uid" = 0 ] && [ "$target_gid" = 0 ]; }; then
|
||||||
exec docker run \
|
exec docker run \
|
||||||
--rm \
|
"${docker_args[@]}" \
|
||||||
"${tty_args[@]}" \
|
|
||||||
--pull=missing \
|
|
||||||
--privileged \
|
|
||||||
--security-opt label=disable \
|
|
||||||
--pid=host \
|
|
||||||
--network=host \
|
|
||||||
--volume /:/host:rw \
|
|
||||||
"$helper_image" \
|
"$helper_image" \
|
||||||
nsenter -t 1 -m -u -i -n -p -- "$@"
|
nsenter -t 1 -m -u -i -n -p -- "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
run_as_container_user='target_uid="${HOSTEXEC_TARGET_UID:?}"
|
||||||
|
target_gid="${HOSTEXEC_TARGET_GID:?}"
|
||||||
|
|
||||||
|
target_user=""
|
||||||
|
if command -v getent >/dev/null 2>&1; then
|
||||||
|
passwd_entry="$(getent passwd "$target_uid" || true)"
|
||||||
|
if [ -n "$passwd_entry" ]; then
|
||||||
|
target_user="${passwd_entry%%:*}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$target_user" ]; then
|
||||||
|
if command -v runuser >/dev/null 2>&1; then
|
||||||
|
exec runuser -u "$target_user" -- "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v su >/dev/null 2>&1; then
|
||||||
|
exec su -s /bin/sh -c '\''exec "$@"'\'' -- "$target_user" hostexec-su "$@"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v setpriv >/dev/null 2>&1; then
|
||||||
|
if [ -n "$target_user" ]; then
|
||||||
|
exec setpriv --reuid "$target_uid" --regid "$target_gid" --init-groups -- "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec setpriv --reuid "$target_uid" --regid "$target_gid" --clear-groups -- "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v nsenter >/dev/null 2>&1; then
|
||||||
|
exec nsenter -t 1 -m -u -i -n -p -S "$target_uid" -G "$target_gid" -- "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "hostexec: unable to switch to host uid:gid $target_uid:$target_gid" >&2
|
||||||
|
exit 69
|
||||||
|
'
|
||||||
|
|
||||||
|
exec docker run \
|
||||||
|
"${docker_args[@]}" \
|
||||||
|
--env HOSTEXEC_TARGET_UID="$target_uid" \
|
||||||
|
--env HOSTEXEC_TARGET_GID="$target_gid" \
|
||||||
|
"$helper_image" \
|
||||||
|
nsenter -t 1 -m -u -i -n -p -- /bin/sh -c "$run_as_container_user" hostexec-user "$@"
|
||||||
|
|||||||
Reference in New Issue
Block a user