Files
omarchy/test/shell.d/fixtures/passwordless-sudo-test.sh
T
David Heinemeier Hansson d9b970dd62 Let users choose passwordless sudo duration (#14435)
* Let users choose passwordless sudo duration

* Warn in the menu bar when passwordless sudo is active

* Fix sudo indicator hover behavior and repeated authentication

* Disable passwordless sudo from the bar without a terminal

* Shorten passwordless sudo indicator tooltip

* Recover interrupted passwordless sudo duration switches

* Allow sudo grant changes when listings require authentication

* Start passwordless sudo setup with the duration question
2026-10-07 14:41:27 +02:00

143 lines
5.2 KiB
Bash

#!/bin/bash
# Exercise complete production functions with private paths and harmless
# command stand-ins. Never install sudo policy or start a host timer.
test_tmp=$(mktemp -d)
children=()
cleanup_grant_fixture() {
local status=$?
trap - EXIT
if (( ${#children[@]} )); then
kill "${children[@]}" 2>/dev/null || true
wait "${children[@]}" 2>/dev/null || true
fi
rm -rf "$test_tmp"
exit "$status"
}
trap cleanup_grant_fixture EXIT
export TEST_GRANT_ROOT=$test_tmp
mkdir -p "$test_tmp/bin" "$test_tmp/etc/sudoers.d" "$test_tmp/etc/tmpfiles.d" "$test_tmp/run/lock" "$test_tmp/var/lib" "$test_tmp/hooks"
cat >"$test_tmp/bin/mock" <<'STUB'
#!/bin/bash
set -euo pipefail
name=${0##*/}
printf '%s %s\n' "$name" "$*" >>"$TEST_GRANT_ROOT/commands"
case "$name" in
stat)
path=${@: -1}
owner=0
mode=$(/usr/bin/stat -Lc '%a' -- "$path")
[[ $path != /tmp ]] || mode=755
[[ $path != "${TEST_BAD_PATH:-}" ]] || owner=1000
case $2 in
'%u') echo "$owner" ;;
'%a') echo "$mode" ;;
'%u %a') echo "$owner $mode" ;;
*) exec /usr/bin/stat "$@" ;;
esac
;;
chown) exit 0 ;;
install)
args=()
while (($#)); do
case $1 in -o|-g) shift 2 ;; *) args+=("$1"); shift ;; esac
done
exec /usr/bin/install "${args[@]}"
;;
rm)
for path in "$@"; do
if [[ ${TEST_DELETE_FAIL:-0} == 1 && $path == "$TEST_GRANT_ROOT/etc/sudoers.d/99-omarchy-nopasswd-1000" ]]; then exit 1; fi
done
exec /usr/bin/rm "$@"
;;
mv)
[[ ${TEST_PUBLISH_FAIL:-0} != 1 ]] || exit 1
[[ ${TEST_REQUIRE_EXISTING_TARGET:-0} != 1 || -f ${@: -1} ]] || exit 1
/usr/bin/mv "$@"
[[ ${TEST_KILL_AFTER_PUBLISH:-0} != 1 ]] || /usr/bin/kill -KILL "$PPID"
[[ ${TEST_POST_PUBLISH_FAIL:-0} != 1 ]] || : >"$TEST_GRANT_ROOT/run/omarchy-sudo-passwordless-package-removing"
;;
systemd-run)
[[ ${TEST_TIMER_FAIL:-0} != 1 ]] || exit 1
if [[ ${TEST_CANCEL_ENABLE:-0} == 1 ]]; then kill -TERM "$PPID"; fi
;;
systemctl)
[[ $1 != "is-active" || ${TEST_INACTIVE_TIMER:-0} != 1 ]]
;;
date)
if [[ ${TEST_EXPIRED:-0} == 1 && $* == '-u +%Y%m%d%H%M%SZ' ]]; then echo 99991231235959Z; else /usr/bin/date "$@"; fi
;;
getent) printf '%s:x:1000:1000:Test:/nonexistent:/bin/bash\n' "${TEST_ACCOUNT:-audituser}" ;;
sudo)
if [[ ${1:-} == -h ]]; then echo 'usage: sudo [-N] command'; exit 0; fi
if [[ ${1:-} == -k ]]; then exit 0; fi
if [[ ${1:-} == -n && ${3:-} == -l ]]; then
[[ ${TEST_POLICY_FAILURE:-0} != 1 ]] || exit 1
default_policy=' Options: authenticate'
[[ ${TEST_STATUS:-3} == 3 ]] || default_policy=' Options: !authenticate'
printf '%s\n' "${TEST_POLICY:-$default_policy}"
exit 0
fi
if [[ ${1:-} == -n ]]; then shift; fi
if [[ ${1:-} == -N || ${1:-} == -kn ]]; then shift; fi
if [[ ${1:-} == -- ]]; then shift; fi
if [[ ${TEST_MIGRATION:-0} == 1 ]]; then
[[ ${TEST_NO_SUDO:-0} != 1 ]] || exit 1
TEST_EUID=0 /usr/bin/bash -p "$@"
else
[[ ${2:-} != __status ]] || exit "${TEST_STATUS:-3}"
fi
;;
gum)
if [[ $1 == choose ]]; then
[[ ${TEST_CHOICE_CANCEL:-0} != 1 ]] || exit 130
printf '%s\n' "${TEST_CHOICE:-15 minutes}"
else
exit "${TEST_CONFIRM_STATUS:-1}"
fi
;;
*) exit 99 ;;
esac
STUB
chmod +x "$test_tmp/bin/mock"
for name in stat chown install rm mv systemd-run systemctl date getent sudo gum; do
ln -s mock "$test_tmp/bin/$name"
done
python3 - "$ROOT" "$test_tmp" <<'PY'
from pathlib import Path
import sys
root, temp = map(Path, sys.argv[1:])
for name in ('omarchy-sudo-passwordless', 'omarchy-security-functions'):
text = (root/'bin'/name).read_text()
for path in ('/etc/', '/var/lib', '/run/', '/usr/share/libalpm/hooks'):
target = str(temp/'hooks') if path == '/usr/share/libalpm/hooks' else str(temp) + path
text = text.replace(path, target)
text = text.replace('((EUID == 0))', '((${TEST_EUID:-1} == 0))')
for command in ('stat', 'chown', 'install', 'rm', 'mv', 'systemd-run', 'systemctl', 'date', 'getent', 'sudo', 'gum'):
text = text.replace('/usr/bin/' + command, str(temp/'bin'/command))
(temp/name).write_text(text)
(temp/name).chmod(0o755)
PY
library="$test_tmp/functions.sh"
{
printf 'source %q\n' "$test_tmp/omarchy-security-functions"
awk '/^set -euo pipefail$/ { functions=1 } /^case "\$\{1:-\}" in$/ { exit } functions { print }' "$test_tmp/omarchy-sudo-passwordless"
} >"$library"
cp "$ROOT/default/libalpm/hooks/05-omarchy-passwordless-revoke.hook" "$test_tmp/hooks/"
sed "s|/etc/|$test_tmp/etc/|g" "$ROOT/etc/tmpfiles.d/omarchy-nopasswd-sudo.conf" >"$test_tmp/etc/tmpfiles.d/omarchy-nopasswd-sudo.conf"
: >"$test_tmp/commands"
# New subshell per case prevents one test's overrides and readonly constants
# from affecting the next. External commands log enough to verify ordering.
assert_status() {
local expected=$1 actual=0
shift
"$@" || actual=$?
(( actual == expected )) || fail "expected status $expected, got $actual from $*"
}
reset_grant() {
rm -f "$test_tmp/etc/sudoers.d/99-omarchy-permanent-nopasswd-1000" "$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-1000" "$test_tmp/run/omarchy-sudo-passwordless-package-removing"
: >"$test_tmp/commands"
}