Flag a reboot when the docker group changes (#8080)
Group membership is fixed at login, so removing (or adding) the docker group does not take effect in the running session. The existing-user migration and the Setup > Security toggles now call `omarchy-state set reboot-required`, so omarchy-update-restart prompts for the reboot that actually applies the change (and the bar shows it pending). A plain log out and back in still works. The migration test now exercises the real removal command and omarchy-state rather than a stub, asserting the reboot flag is set on removal and left alone when the user is already out of the group. Claude-Session: https://claude.ai/code/session_01Gb7x6poap4hGCndPx5qt5T Co-authored-by: David Heinemeier Hansson <david@hey.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
David Heinemeier Hansson
Claude Opus 4.8
parent
b5ded31e2f
commit
1565919c87
@@ -13,8 +13,13 @@ fi
|
|||||||
echo "Removing $USER from the docker group..."
|
echo "Removing $USER from the docker group..."
|
||||||
sudo gpasswd -d "$USER" docker >/dev/null
|
sudo gpasswd -d "$USER" docker >/dev/null
|
||||||
|
|
||||||
|
# Group membership is fixed at login, so the running session keeps its docker
|
||||||
|
# access until it ends. Flag a reboot so omarchy-update-restart prompts for one
|
||||||
|
# (and the bar shows it pending); a plain log out and back in works too.
|
||||||
|
omarchy-state set reboot-required
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Sudoless Docker DISABLED. Log out and back in for the change to take effect."
|
echo "Sudoless Docker DISABLED. Reboot (or log out and back in) for the change to take effect."
|
||||||
echo "Docker access now goes through a polkit/sudo prompt again: the Docker TUI"
|
echo "Docker access now goes through a polkit/sudo prompt again: the Docker TUI"
|
||||||
echo "(Super + Shift + D) and the Windows VM will ask when they need it, and the"
|
echo "(Super + Shift + D) and the Windows VM will ask when they need it, and the"
|
||||||
echo "plain 'docker' CLI runs under sudo."
|
echo "plain 'docker' CLI runs under sudo."
|
||||||
|
|||||||
@@ -28,8 +28,12 @@ echo ""
|
|||||||
|
|
||||||
if gum confirm "Enable sudoless Docker? This gives anything running as you passwordless root."; then
|
if gum confirm "Enable sudoless Docker? This gives anything running as you passwordless root."; then
|
||||||
sudo usermod -aG docker "$USER"
|
sudo usermod -aG docker "$USER"
|
||||||
|
# Group membership is fixed at login, so docker won't be reachable without a
|
||||||
|
# prompt until the session restarts. Flag a reboot so omarchy-update-restart
|
||||||
|
# prompts for one (and the bar shows it pending).
|
||||||
|
omarchy-state set reboot-required
|
||||||
echo ""
|
echo ""
|
||||||
echo "Sudoless Docker ENABLED. Log out and back in (or run 'newgrp docker')"
|
echo "Sudoless Docker ENABLED. Reboot, or log out and back in (or run 'newgrp docker'),"
|
||||||
echo "for the new group membership to take effect."
|
echo "for the new group membership to take effect."
|
||||||
echo "To disable it again, run: omarchy-remove-security-sudoless-docker"
|
echo "To disable it again, run: omarchy-remove-security-sudoless-docker"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# The docker-group opt-in migration must remove an existing install's user from
|
# The docker-group opt-in migration must remove an existing install's user from
|
||||||
# the root-equivalent docker group (only when they are in it), refresh the stale
|
# the root-equivalent docker group (only when they are in it), flag a reboot so
|
||||||
# Docker launcher entry, and stay idempotent on reruns.
|
# the group change actually takes effect (group membership is fixed at login),
|
||||||
|
# refresh the stale Docker launcher entry, and stay idempotent on reruns.
|
||||||
|
#
|
||||||
|
# The real omarchy-remove-security-sudoless-docker and omarchy-state run here
|
||||||
|
# (from the repo bin); only the privileged/system calls are stubbed, so the whole
|
||||||
|
# chain — including the reboot flag — is exercised.
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@@ -17,49 +22,53 @@ omarchy_path="$test_dir/omarchy"
|
|||||||
stub_bin="$test_dir/bin"
|
stub_bin="$test_dir/bin"
|
||||||
mkdir -p "$home/.local/share/applications" "$omarchy_path/applications" "$stub_bin"
|
mkdir -p "$home/.local/share/applications" "$omarchy_path/applications" "$stub_bin"
|
||||||
|
|
||||||
# The packaged (new) launcher entry the migration should copy over the stale one.
|
|
||||||
printf 'NEW-LAUNCHER\n' >"$omarchy_path/applications/Docker.desktop"
|
printf 'NEW-LAUNCHER\n' >"$omarchy_path/applications/Docker.desktop"
|
||||||
printf 'OLD-LAUNCHER\n' >"$home/.local/share/applications/Docker.desktop"
|
printf 'OLD-LAUNCHER\n' >"$home/.local/share/applications/Docker.desktop"
|
||||||
|
|
||||||
# Stub id to report a controllable group set, and the removal command to record
|
# id reports a controllable group set; sudo just drops the prefix; gpasswd
|
||||||
# that it was called instead of touching the real system.
|
# records its call instead of touching the real system.
|
||||||
cat >"$stub_bin/id" <<'STUB'
|
cat >"$stub_bin/id" <<'STUB'
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Only the migration's `id -nG "$USER"` needs answering here.
|
|
||||||
printf '%s\n' "${STUB_GROUPS:-wheel input}"
|
printf '%s\n' "${STUB_GROUPS:-wheel input}"
|
||||||
STUB
|
STUB
|
||||||
cat >"$stub_bin/omarchy-remove-security-sudoless-docker" <<'STUB'
|
cat >"$stub_bin/sudo" <<'STUB'
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
touch "${REMOVE_CALLED:?}"
|
exec "$@"
|
||||||
STUB
|
STUB
|
||||||
chmod +x "$stub_bin/id" "$stub_bin/omarchy-remove-security-sudoless-docker"
|
cat >"$stub_bin/gpasswd" <<'STUB'
|
||||||
|
#!/bin/bash
|
||||||
|
echo "$@" >>"${GPASSWD_CALLS:?}"
|
||||||
|
STUB
|
||||||
|
chmod +x "$stub_bin/id" "$stub_bin/sudo" "$stub_bin/gpasswd"
|
||||||
|
|
||||||
|
reboot_flag="$home/.local/state/omarchy/reboot-required"
|
||||||
|
gpasswd_calls="$test_dir/gpasswd-calls"
|
||||||
|
launcher="$home/.local/share/applications/Docker.desktop"
|
||||||
|
|
||||||
remove_called="$test_dir/remove-called"
|
|
||||||
run_migration() {
|
run_migration() {
|
||||||
rm -f "$remove_called"
|
rm -f "$gpasswd_calls" "$reboot_flag"
|
||||||
HOME="$home" OMARCHY_PATH="$omarchy_path" USER="tester" \
|
HOME="$home" OMARCHY_PATH="$omarchy_path" USER="tester" STUB_GROUPS="$1" \
|
||||||
STUB_GROUPS="$1" REMOVE_CALLED="$remove_called" \
|
GPASSWD_CALLS="$gpasswd_calls" PATH="$stub_bin:$ROOT/bin:$PATH" \
|
||||||
PATH="$stub_bin:$PATH" bash -euo pipefail "$migration" >/dev/null 2>&1
|
bash -euo pipefail "$migration" >/dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
# In the docker group: the user is removed and the launcher is refreshed.
|
# In the docker group: user removed, reboot flagged, launcher refreshed.
|
||||||
run_migration "wheel input docker" || fail "migration runs when the user is in the docker group"
|
run_migration "wheel input docker" || fail "migration runs when the user is in the docker group"
|
||||||
[[ -e $remove_called ]] || fail "migration removes a user who is in the docker group"
|
grep -q -- "-d tester docker" "$gpasswd_calls" || fail "migration removes the user from the docker group"
|
||||||
[[ $(cat "$home/.local/share/applications/Docker.desktop") == "NEW-LAUNCHER" ]] ||
|
[[ -f $reboot_flag ]] || fail "migration flags a reboot so the group change takes effect"
|
||||||
fail "migration refreshes the stale Docker launcher entry"
|
[[ $(cat "$launcher") == "NEW-LAUNCHER" ]] || fail "migration refreshes the stale Docker launcher entry"
|
||||||
pass "migration removes the docker group and refreshes the launcher"
|
pass "migration removes the group, flags a reboot, and refreshes the launcher"
|
||||||
|
|
||||||
# Not in the docker group (fresh install, or already migrated): no removal.
|
# Not in the docker group (fresh install, or already migrated): nothing changes.
|
||||||
printf 'OLD-LAUNCHER\n' >"$home/.local/share/applications/Docker.desktop"
|
printf 'OLD-LAUNCHER\n' >"$launcher"
|
||||||
run_migration "wheel input" || fail "migration runs when the user is not in the docker group"
|
run_migration "wheel input" || fail "migration runs when the user is not in the docker group"
|
||||||
[[ ! -e $remove_called ]] || fail "migration must not call the removal when the user is not in the docker group"
|
[[ ! -f $gpasswd_calls ]] || fail "migration must not touch the group when the user is not in it"
|
||||||
[[ $(cat "$home/.local/share/applications/Docker.desktop") == "NEW-LAUNCHER" ]] ||
|
[[ ! -f $reboot_flag ]] || fail "migration must not flag a reboot when nothing changed"
|
||||||
fail "migration still refreshes the launcher when the group is already absent"
|
[[ $(cat "$launcher") == "NEW-LAUNCHER" ]] || fail "migration still refreshes the launcher when the group is already absent"
|
||||||
pass "migration is a no-op on the group when it is already absent"
|
pass "migration is a no-op on the group and reboot when already out"
|
||||||
|
|
||||||
# No launcher entry present: the refresh is skipped without error.
|
# No launcher entry present: the refresh is skipped without error.
|
||||||
rm -f "$home/.local/share/applications/Docker.desktop"
|
rm -f "$launcher"
|
||||||
run_migration "wheel input" || fail "migration tolerates a missing launcher entry"
|
run_migration "wheel input" || fail "migration tolerates a missing launcher entry"
|
||||||
[[ ! -e $home/.local/share/applications/Docker.desktop ]] ||
|
[[ ! -e $launcher ]] || fail "migration does not create a launcher entry that was not there"
|
||||||
fail "migration does not create a launcher entry that was not there"
|
|
||||||
pass "migration skips the launcher refresh when no entry exists"
|
pass "migration skips the launcher refresh when no entry exists"
|
||||||
|
|||||||
Reference in New Issue
Block a user