Offer to reboot when toggling sudoless Docker; show only the relevant menu entry (#8098)
* Offer to reboot when toggling sudoless Docker; show only the relevant menu entry Group membership only takes effect on a fresh session, and in practice a logout or newgrp isn't enough — only a reboot reliably applies it. So the setup/remove commands now flag the reboot and offer to do it now with a gum confirm (like the GPU toggle), and the notices say "after a reboot" instead of pointing at logout or newgrp. The existing-user migration passes OMARCHY_DEFER_REBOOT so it does not prompt mid-update — omarchy-update-restart still handles the reboot once the whole update finishes. The Setup > Security menu also showed Sudoless Docker under both Setup and Remove. Condition the Setup entry on the group being absent (Remove already conditions on it being present), so only the applicable one appears. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gb7x6poap4hGCndPx5qt5T * Ask omarchy-sudo-docker whether Docker needs sudo Every place that chooses between talking to Docker directly and elevating was testing group membership by hand, and the menu guards tested the wrong thing: they read the running session's groups, which do not change until the reboot, so after enabling sudoless Docker the menu still offered Setup — the one action that could no longer do anything — while Remove stayed hidden. Add omarchy-sudo-docker as the single answer, with the two questions that actually differ in that window. By default it asks whether this session can reach the socket, which is what decides if a command must elevate: lazydocker and the Windows VM keep prompting until the reboot lands. With --configured it asks whether the account is set up for sudoless Docker, which is what the menu and the toggles need, so the menu switches to the action that can change state as soon as the group is written. Also correct a comment: nothing surfaces reboot-required in the bar; it is omarchy-update-restart that reads it during a later update. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> 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
Claude Opus 4.8
David Heinemeier Hansson
parent
5d3299fb94
commit
06a3dbca42
@@ -9,10 +9,12 @@
|
||||
# no prompt. lazydocker needs the root-owned Docker socket, so when the group is
|
||||
# absent, gate that access behind a polkit prompt. If the user has opted into
|
||||
# sudoless Docker (omarchy-setup-security-sudoless-docker), the socket is already
|
||||
# reachable, so run lazydocker directly. pkexec sanitizes the environment, so
|
||||
# carry TERM through for the TUI to render and run lazydocker from root's PATH.
|
||||
if id -nG 2>/dev/null | grep -qw docker; then
|
||||
exec lazydocker
|
||||
else
|
||||
# reachable, so run lazydocker directly — omarchy-sudo-docker answers that for
|
||||
# this session, so the prompt stays until the reboot that grants the group.
|
||||
# pkexec sanitizes the environment, so carry TERM through for the TUI to render
|
||||
# and run lazydocker from root's PATH.
|
||||
if omarchy-sudo-docker; then
|
||||
exec pkexec /usr/bin/env TERM="${TERM:-xterm-256color}" lazydocker
|
||||
else
|
||||
exec lazydocker
|
||||
fi
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
|
||||
set -e
|
||||
|
||||
if ! id -nG "$USER" 2>/dev/null | grep -qw docker; then
|
||||
# Ask about the configured groups, not this session's: right after enabling,
|
||||
# sudoless Docker is on for the account even though the running session still
|
||||
# needs a prompt, and this command is what turns it back off.
|
||||
if omarchy-sudo-docker --configured; then
|
||||
echo "Sudoless Docker is not enabled: $USER is not in the docker group."
|
||||
exit 0
|
||||
fi
|
||||
@@ -13,13 +16,19 @@ fi
|
||||
echo "Removing $USER from the docker group..."
|
||||
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.
|
||||
# Group membership is only re-read by a fresh session, and in practice logging
|
||||
# out or newgrp isn't enough — only a reboot reliably applies it. Record it so a
|
||||
# later `omarchy update` still prompts (omarchy-update-restart reads this), then
|
||||
# offer to do it now.
|
||||
omarchy-state set reboot-required
|
||||
|
||||
echo ""
|
||||
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 "(Super + Shift + D) and the Windows VM will ask when they need it, and the"
|
||||
echo "plain 'docker' CLI runs under sudo."
|
||||
echo "Sudoless Docker DISABLED. Docker access goes through a polkit/sudo prompt"
|
||||
echo "again: the Docker TUI (Super + Shift + D) and the Windows VM ask when they"
|
||||
echo "need it, and the plain 'docker' CLI runs under sudo. It takes effect after a reboot."
|
||||
echo ""
|
||||
# The migration reuses this command during 'omarchy update' and defers the
|
||||
# reboot to omarchy-update-restart, so it doesn't cut the update short.
|
||||
if [[ -z ${OMARCHY_DEFER_REBOOT:-} ]] && gum confirm "Reboot now to apply?"; then
|
||||
omarchy-system-reboot
|
||||
fi
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
|
||||
set -e
|
||||
|
||||
if id -nG "$USER" 2>/dev/null | grep -qw docker; then
|
||||
# Ask about the configured groups, not this session's: once enabled it stays
|
||||
# enabled for the account even before the reboot that lets this session use it.
|
||||
if ! omarchy-sudo-docker --configured; then
|
||||
echo "Sudoless Docker is already enabled: $USER is in the docker group."
|
||||
echo "To disable it again, run: omarchy-remove-security-sudoless-docker"
|
||||
exit 0
|
||||
@@ -28,14 +30,20 @@ echo ""
|
||||
|
||||
if gum confirm "Enable sudoless Docker? This gives anything running as you passwordless root."; then
|
||||
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).
|
||||
# A new docker group membership is only picked up by a fresh session, and in
|
||||
# practice logging out or newgrp isn't enough — only a reboot reliably applies
|
||||
# it. Record it so a later `omarchy update` still prompts
|
||||
# (omarchy-update-restart reads this), then offer to do it now.
|
||||
omarchy-state set reboot-required
|
||||
echo ""
|
||||
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 "To disable it again, run: omarchy-remove-security-sudoless-docker"
|
||||
echo "Sudoless Docker ENABLED. It takes effect after a reboot."
|
||||
echo "To disable it again: Setup > Security > Sudoless Docker."
|
||||
echo ""
|
||||
# The migration reuses this command during 'omarchy update' and defers the
|
||||
# reboot to omarchy-update-restart, so it doesn't cut the update short.
|
||||
if [[ -z ${OMARCHY_DEFER_REBOOT:-} ]] && gum confirm "Reboot now to apply?"; then
|
||||
omarchy-system-reboot
|
||||
fi
|
||||
else
|
||||
echo "Aborted. No changes made. Docker access still goes through a prompt."
|
||||
fi
|
||||
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Succeed when Docker needs sudo, fail when it can be used directly
|
||||
# omarchy:args=[--configured]
|
||||
# omarchy:examples=omarchy-sudo-docker && echo "needs sudo" | omarchy-sudo-docker --configured
|
||||
# omarchy:hidden=true
|
||||
|
||||
# The docker group is root-equivalent, so Omarchy leaves users out of it by
|
||||
# default and reaches the daemon through a prompt instead. Everything that has
|
||||
# to make that choice asks here rather than testing group membership itself.
|
||||
#
|
||||
# Two questions, because they have different answers between toggling sudoless
|
||||
# Docker and the reboot that applies it (group membership is fixed when the
|
||||
# session is created):
|
||||
#
|
||||
# (default) Does Docker need sudo *right now*? Answered by whether this
|
||||
# process can actually reach the socket, which is what decides
|
||||
# if a command must elevate. Still true in the window after
|
||||
# sudoless Docker is enabled but before the reboot.
|
||||
# --configured Will it need sudo once the account's groups take effect?
|
||||
# Answered from the account's configured groups, so the menu
|
||||
# offers the toggle that can actually change state.
|
||||
#
|
||||
# Succeeds (exit 0) when sudo is needed, so it reads as `if omarchy-sudo-docker`.
|
||||
|
||||
DOCKER_SOCKET="${OMARCHY_DOCKER_SOCKET:-/var/run/docker.sock}"
|
||||
|
||||
case "${1:-}" in
|
||||
--configured)
|
||||
# An account in the docker group will not need sudo after the next login.
|
||||
id -nG "$USER" 2>/dev/null | grep -qw docker && exit 1
|
||||
exit 0
|
||||
;;
|
||||
"")
|
||||
# A socket we can write is a daemon we can drive without elevating. A missing
|
||||
# socket counts as needing sudo: reaching it means starting it as root anyway.
|
||||
[[ -w $DOCKER_SOCKET ]] && exit 1
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Usage: omarchy-sudo-docker [--configured]" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
@@ -31,8 +31,11 @@ CONTAINER="omarchy-windows"
|
||||
|
||||
# --- privilege helpers -------------------------------------------------------
|
||||
|
||||
# True when the user can reach the Docker socket directly (sudoless Docker on).
|
||||
in_docker_group() { id -nG 2>/dev/null | grep -qw docker; }
|
||||
# True when this session can reach the Docker socket directly (sudoless Docker
|
||||
# on and in effect). Asking about the socket rather than the configured groups
|
||||
# keeps the prompt in place through the window where sudoless Docker is enabled
|
||||
# but the reboot that grants the group has not happened yet.
|
||||
docker_needs_sudo() { omarchy-sudo-docker; }
|
||||
|
||||
# The command to hand pkexec for the privileged re-exec. pkexec runs whatever
|
||||
# executable it is given (after authorization) and only shows the path in the
|
||||
@@ -64,7 +67,7 @@ priv_target() {
|
||||
priv() {
|
||||
local action="$1"
|
||||
shift
|
||||
if [[ $action != write_compose ]] && in_docker_group; then
|
||||
if [[ $action != write_compose ]] && ! docker_needs_sudo; then
|
||||
"__priv_$action" "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
@@ -179,7 +179,7 @@
|
||||
"setup.security.fido2": {"icon":"","label":"Fido2","action":"omarchy-launch-floating-terminal-with-presentation omarchy-setup-security-fido2"},
|
||||
"setup.security.sshd": {"icon":"","label":"SSHD","action":"omarchy-launch-floating-terminal-with-presentation omarchy-setup-security-sshd"},
|
||||
"setup.security.passwordless-sudo": {"icon":"","label":"Passwordless Sudo","action":"omarchy-launch-floating-terminal-with-presentation omarchy-sudo-passwordless"},
|
||||
"setup.security.sudoless-docker": {"icon":"","label":"Sudoless Docker","action":"omarchy-launch-floating-terminal-with-presentation omarchy-setup-security-sudoless-docker"},
|
||||
"setup.security.sudoless-docker": {"icon":"","label":"Sudoless Docker","when":"omarchy-sudo-docker --configured","action":"omarchy-launch-floating-terminal-with-presentation omarchy-setup-security-sudoless-docker"},
|
||||
"setup.config.hyprland": {"icon":"","label":"Hyprland","action":"omarchy-launch-config-editor \"$HOME/.config/hypr/hyprland.lua\""},
|
||||
"setup.config.hyprsunset": {"icon":"","label":"Hyprsunset","action":"omarchy-launch-config-editor ~/.config/hypr/hyprsunset.conf && omarchy-restart-hyprsunset"},
|
||||
"setup.config.xcompose": {"icon":"","label":"XCompose","action":"omarchy-launch-config-editor ~/.XCompose && omarchy-restart-xcompose"},
|
||||
@@ -291,7 +291,7 @@
|
||||
"remove.security.fingerprint": {"icon":"","label":"Fingerprint","when":"omarchy-pkg-present fprintd","action":"omarchy-launch-floating-terminal-with-presentation omarchy-remove-security-fingerprint"},
|
||||
"remove.security.fido2": {"icon":"","label":"Fido2","when":"omarchy-pkg-present pam-u2f","action":"omarchy-launch-floating-terminal-with-presentation omarchy-remove-security-fido2"},
|
||||
"remove.security.sshd": {"icon":"","label":"SSHD","when":"systemctl is-enabled --quiet sshd","action":"omarchy-launch-floating-terminal-with-presentation omarchy-remove-security-sshd"},
|
||||
"remove.security.sudoless-docker": {"icon":"","label":"Sudoless Docker","when":"id -nG | grep -qw docker","action":"omarchy-launch-floating-terminal-with-presentation omarchy-remove-security-sudoless-docker"},
|
||||
"remove.security.sudoless-docker": {"icon":"","label":"Sudoless Docker","when":"! omarchy-sudo-docker --configured","action":"omarchy-launch-floating-terminal-with-presentation omarchy-remove-security-sudoless-docker"},
|
||||
"remove.browser.chrome": {"icon":"","label":"Chrome","when":"omarchy-pkg-present google-chrome","action":"omarchy-launch-floating-terminal-with-presentation 'omarchy-remove-browser chrome'"},
|
||||
"remove.browser.edge": {"icon":"","label":"Edge","when":"omarchy-pkg-present microsoft-edge-stable-bin","action":"omarchy-launch-floating-terminal-with-presentation 'omarchy-remove-browser edge'"},
|
||||
"remove.browser.brave": {"icon":"","label":"Brave","when":"omarchy-pkg-present brave-bin","action":"omarchy-launch-floating-terminal-with-presentation 'omarchy-remove-browser brave'"},
|
||||
|
||||
@@ -2,13 +2,15 @@ echo "Move this install to the opt-in docker group default (the group is root-eq
|
||||
|
||||
# The docker group grants passwordless root (a container can bind-mount / and
|
||||
# rewrite the host), so Omarchy no longer puts users in it by default. Bring
|
||||
# existing installs in line: remove this user from the group if present. It takes
|
||||
# effect at next login, and the current session keeps working until then. Anyone
|
||||
# who wants passwordless docker back can opt in, behind a warning, with
|
||||
# existing installs in line: remove this user from the group if present. The
|
||||
# change applies after a reboot, so it stays reachable until then. Anyone who
|
||||
# wants passwordless docker back can opt in, behind a warning, with
|
||||
# Setup > Security > Sudoless Docker. Reuses the removal command so there is one
|
||||
# source of truth for the privileged change and its notice.
|
||||
# source of truth for the privileged change and its notice; DEFER_REBOOT keeps
|
||||
# it from prompting mid-update — omarchy-update-restart handles the reboot once
|
||||
# the whole update has finished.
|
||||
if id -nG "$USER" | grep -qw docker; then
|
||||
omarchy-remove-security-sudoless-docker
|
||||
OMARCHY_DEFER_REBOOT=1 omarchy-remove-security-sudoless-docker
|
||||
fi
|
||||
|
||||
# The Docker app entry copied into ~/.local/share/applications used to run
|
||||
|
||||
@@ -39,16 +39,30 @@ cat >"$stub_bin/gpasswd" <<'STUB'
|
||||
#!/bin/bash
|
||||
echo "$@" >>"${GPASSWD_CALLS:?}"
|
||||
STUB
|
||||
chmod +x "$stub_bin/id" "$stub_bin/sudo" "$stub_bin/gpasswd"
|
||||
# gum confirm always says yes, and reboot records that it fired: the migration
|
||||
# must still NOT reboot (it defers to omarchy-update-restart), so neither should
|
||||
# be reached.
|
||||
cat >"$stub_bin/gum" <<'STUB'
|
||||
#!/bin/bash
|
||||
[[ $1 == confirm ]] && exit 0
|
||||
exit 0
|
||||
STUB
|
||||
cat >"$stub_bin/omarchy-system-reboot" <<'STUB'
|
||||
#!/bin/bash
|
||||
touch "${REBOOT_CALLED:?}"
|
||||
STUB
|
||||
chmod +x "$stub_bin/id" "$stub_bin/sudo" "$stub_bin/gpasswd" "$stub_bin/gum" "$stub_bin/omarchy-system-reboot"
|
||||
|
||||
reboot_flag="$home/.local/state/omarchy/reboot-required"
|
||||
gpasswd_calls="$test_dir/gpasswd-calls"
|
||||
reboot_called="$test_dir/reboot-called"
|
||||
launcher="$home/.local/share/applications/Docker.desktop"
|
||||
|
||||
run_migration() {
|
||||
rm -f "$gpasswd_calls" "$reboot_flag"
|
||||
rm -f "$gpasswd_calls" "$reboot_flag" "$reboot_called"
|
||||
HOME="$home" OMARCHY_PATH="$omarchy_path" USER="tester" STUB_GROUPS="$1" \
|
||||
GPASSWD_CALLS="$gpasswd_calls" PATH="$stub_bin:$ROOT/bin:$PATH" \
|
||||
GPASSWD_CALLS="$gpasswd_calls" REBOOT_CALLED="$reboot_called" \
|
||||
PATH="$stub_bin:$ROOT/bin:$PATH" \
|
||||
bash -euo pipefail "$migration" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
@@ -56,6 +70,7 @@ run_migration() {
|
||||
run_migration "wheel input docker" || fail "migration runs when the user is in the docker group"
|
||||
grep -q -- "-d tester docker" "$gpasswd_calls" || fail "migration removes the user from the docker group"
|
||||
[[ -f $reboot_flag ]] || fail "migration flags a reboot so the group change takes effect"
|
||||
[[ ! -f $reboot_called ]] || fail "migration must defer the reboot (not reboot mid-update)"
|
||||
[[ $(cat "$launcher") == "NEW-LAUNCHER" ]] || fail "migration refreshes the stale Docker launcher entry"
|
||||
pass "migration removes the group, flags a reboot, and refreshes the launcher"
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# omarchy-sudo-docker is the single answer to "does Docker need sudo", and it
|
||||
# answers two different questions on purpose. The default asks whether this
|
||||
# session can reach the socket, which is what decides if a command must elevate.
|
||||
# --configured asks whether the account is set up for sudoless Docker, which is
|
||||
# what the menu needs so it offers the toggle that can change state. Between
|
||||
# enabling sudoless Docker and the reboot that grants the group, those disagree.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
||||
|
||||
TMPDIR=$(mktemp -d)
|
||||
trap 'rm -rf "$TMPDIR"' EXIT
|
||||
|
||||
command="$ROOT/bin/omarchy-sudo-docker"
|
||||
|
||||
# Stub id so the configured groups are controllable.
|
||||
mkdir -p "$TMPDIR/bin"
|
||||
cat >"$TMPDIR/bin/id" <<'STUB'
|
||||
#!/bin/bash
|
||||
printf '%s\n' "${STUB_GROUPS:-wheel input}"
|
||||
STUB
|
||||
chmod +x "$TMPDIR/bin/id"
|
||||
|
||||
# A writable stand-in means the socket is reachable; an unwritable one means it
|
||||
# is not. Test the file mode rather than a live daemon.
|
||||
reachable_socket="$TMPDIR/reachable.sock"
|
||||
blocked_socket="$TMPDIR/blocked.sock"
|
||||
touch "$reachable_socket" "$blocked_socket"
|
||||
chmod 600 "$reachable_socket"
|
||||
chmod 400 "$blocked_socket"
|
||||
|
||||
run() { # SOCKET GROUPS [--configured]
|
||||
env PATH="$TMPDIR/bin:$PATH" OMARCHY_DOCKER_SOCKET="$1" STUB_GROUPS="$2" USER=tester \
|
||||
bash "$command" ${3:+"$3"}
|
||||
}
|
||||
|
||||
# Default mode follows the socket, not the group list.
|
||||
run "$blocked_socket" "wheel input" || fail "an unreachable socket means Docker needs sudo"
|
||||
run "$reachable_socket" "wheel input" && fail "a reachable socket means Docker does not need sudo"
|
||||
pass "default mode answers from the socket this session can reach"
|
||||
|
||||
# A socket that isn't there at all still needs elevation (starting it is root work).
|
||||
run "$TMPDIR/absent.sock" "wheel input docker" || fail "a missing socket means Docker needs sudo"
|
||||
pass "a missing socket counts as needing sudo"
|
||||
|
||||
# --configured follows the account's groups, not the socket.
|
||||
run "$blocked_socket" "wheel input docker" --configured && fail "a configured docker group means no sudo is needed"
|
||||
run "$reachable_socket" "wheel input" --configured || fail "no docker group means sudo is needed"
|
||||
pass "--configured answers from the account's groups"
|
||||
|
||||
# The window this split exists for: sudoless Docker has just been enabled, so the
|
||||
# account carries the group while the running session still cannot use it. The
|
||||
# menu must offer Remove (--configured says no sudo) while lazydocker and the
|
||||
# Windows VM must still prompt (default says sudo).
|
||||
run "$blocked_socket" "wheel input docker" || fail "the session still needs sudo before the reboot"
|
||||
run "$blocked_socket" "wheel input docker" --configured && fail "the account is already configured for sudoless Docker"
|
||||
pass "the two modes disagree between enabling sudoless Docker and the reboot"
|
||||
|
||||
# An unknown argument is a usage error, not a silent answer either way.
|
||||
run "$reachable_socket" "wheel input" --bogus 2>/dev/null && fail "an unknown flag exits non-zero"
|
||||
status=0
|
||||
run "$reachable_socket" "wheel input" --bogus >/dev/null 2>&1 || status=$?
|
||||
(( status == 2 )) || fail "an unknown flag exits 2, not the boolean 1"
|
||||
pass "an unknown flag is a usage error"
|
||||
@@ -0,0 +1,93 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Toggling sudoless Docker changes the docker group, which only takes effect on a
|
||||
# reboot. The setup/remove commands must flag the reboot and offer to do it now
|
||||
# (gum confirm), but defer it when OMARCHY_DEFER_REBOOT is set (the migration
|
||||
# reuses them inside `omarchy update`, where omarchy-update-restart handles it).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
||||
|
||||
test_dir=$(mktemp -d)
|
||||
trap 'rm -rf "$test_dir"' EXIT
|
||||
home="$test_dir/home"
|
||||
stub_bin="$test_dir/bin"
|
||||
mkdir -p "$home" "$stub_bin"
|
||||
|
||||
cat >"$stub_bin/id" <<'STUB'
|
||||
#!/bin/bash
|
||||
printf '%s\n' "${STUB_GROUPS:-wheel input}"
|
||||
STUB
|
||||
cat >"$stub_bin/sudo" <<'STUB'
|
||||
#!/bin/bash
|
||||
exec "$@"
|
||||
STUB
|
||||
cat >"$stub_bin/usermod" <<'STUB'
|
||||
#!/bin/bash
|
||||
echo "$@" >>"${USERMOD_CALLS:?}"
|
||||
STUB
|
||||
cat >"$stub_bin/gpasswd" <<'STUB'
|
||||
#!/bin/bash
|
||||
echo "$@" >>"${GPASSWD_CALLS:?}"
|
||||
STUB
|
||||
cat >"$stub_bin/gum" <<'STUB'
|
||||
#!/bin/bash
|
||||
touch "${GUM_CALLED:?}"
|
||||
exit "${GUM_ANSWER:-0}"
|
||||
STUB
|
||||
cat >"$stub_bin/omarchy-system-reboot" <<'STUB'
|
||||
#!/bin/bash
|
||||
touch "${REBOOT_CALLED:?}"
|
||||
STUB
|
||||
chmod +x "$stub_bin"/*
|
||||
|
||||
reboot_flag="$home/.local/state/omarchy/reboot-required"
|
||||
gum_called="$test_dir/gum-called"
|
||||
reboot_called="$test_dir/reboot-called"
|
||||
gpasswd_calls="$test_dir/gpasswd-calls"
|
||||
usermod_calls="$test_dir/usermod-calls"
|
||||
|
||||
run() { # command STUB_GROUPS GUM_ANSWER DEFER(0|1)
|
||||
rm -f "$reboot_flag" "$gum_called" "$reboot_called" "$gpasswd_calls" "$usermod_calls"
|
||||
local defer_env=()
|
||||
[[ ${4:-0} == 1 ]] && defer_env=(OMARCHY_DEFER_REBOOT=1)
|
||||
env HOME="$home" USER="tester" STUB_GROUPS="$2" GUM_ANSWER="$3" \
|
||||
GUM_CALLED="$gum_called" REBOOT_CALLED="$reboot_called" \
|
||||
GPASSWD_CALLS="$gpasswd_calls" USERMOD_CALLS="$usermod_calls" \
|
||||
PATH="$stub_bin:$ROOT/bin:$PATH" "${defer_env[@]}" \
|
||||
bash "$ROOT/bin/$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Remove, interactive, reboot confirmed -> group removed, flag set, reboot fired.
|
||||
run omarchy-remove-security-sudoless-docker "wheel input docker" 0 0
|
||||
grep -q -- "-d tester docker" "$gpasswd_calls" || fail "remove drops the user from the docker group"
|
||||
[[ -f $reboot_flag ]] || fail "remove flags a reboot"
|
||||
[[ -f $reboot_called ]] || fail "remove reboots when the prompt is confirmed"
|
||||
pass "remove drops the group, flags a reboot, and reboots on confirm"
|
||||
|
||||
# Remove, interactive, reboot declined -> flag set, but no reboot.
|
||||
run omarchy-remove-security-sudoless-docker "wheel input docker" 1 0
|
||||
[[ -f $reboot_flag ]] || fail "remove still flags a reboot when the prompt is declined"
|
||||
[[ ! -f $reboot_called ]] || fail "remove does not reboot when the prompt is declined"
|
||||
pass "remove leaves the reboot to the user when declined"
|
||||
|
||||
# Remove, deferred (migration/update) -> flag set, prompt never shown.
|
||||
run omarchy-remove-security-sudoless-docker "wheel input docker" 0 1
|
||||
[[ -f $reboot_flag ]] || fail "deferred remove still flags a reboot"
|
||||
[[ ! -f $gum_called ]] || fail "deferred remove must not prompt to reboot"
|
||||
[[ ! -f $reboot_called ]] || fail "deferred remove must not reboot"
|
||||
pass "deferred remove flags the reboot without prompting"
|
||||
|
||||
# Remove, already out of the group -> no-op, nothing flagged.
|
||||
run omarchy-remove-security-sudoless-docker "wheel input" 0 0
|
||||
[[ ! -f $gpasswd_calls ]] || fail "remove is a no-op when the user is not in the docker group"
|
||||
[[ ! -f $reboot_flag ]] || fail "remove does not flag a reboot when nothing changed"
|
||||
pass "remove is a no-op when sudoless Docker is already off"
|
||||
|
||||
# Setup, enable confirmed then reboot confirmed -> group added, flag set, reboot.
|
||||
run omarchy-setup-security-sudoless-docker "wheel input" 0 0
|
||||
grep -q -- "-aG docker tester" "$usermod_calls" || fail "setup adds the user to the docker group"
|
||||
[[ -f $reboot_flag ]] || fail "setup flags a reboot"
|
||||
[[ -f $reboot_called ]] || fail "setup reboots when the prompt is confirmed"
|
||||
pass "setup adds the group, flags a reboot, and reboots on confirm"
|
||||
Reference in New Issue
Block a user