Quarantine unrecognized policy under the generated sudoers prefix
Matching a legacy grant by its filename and rule relationship is not a complete fingerprint: the legacy writer took the filename from $USER but produced the rule with echo, and under BASH_ENV with xpg_echo a name such as ali\0143e yields an alice rule in a mismatched file. Preserving that as administrator policy let the migration certify success with an unrestricted grant still live until the next boot. The prefix is reserved anyway: boot cleanup and the package hook remove everything under it. Move any file the classifier does not recognize into a fresh root-only directory under /var/lib/omarchy/sudoers-quarantine/ as `policy`, with the original name stored beside it, so nothing there stays live, the administrator keeps the content, and a legacy filename already close to NAME_MAX still fits. An untrusted quarantine directory keeps the migration pending. Cover the mismatched and maximum-length legacy files in the unit cleanup and through the real migration runner. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
3eb3142313
commit
ea617b9126
3 files changed
+54
-9
No files matched your search
@@ -4,6 +4,19 @@ set -euo pipefail
|
||||
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
||||
source "$SHELL_TEST_DIR/fixtures/passwordless-sudo-test.sh"
|
||||
|
||||
quarantine="$test_tmp/var/lib/omarchy/sudoers-quarantine"
|
||||
quarantined_policy() {
|
||||
local entry
|
||||
for entry in "$quarantine"/*/; do
|
||||
if [[ $(cat "$entry/name") == "$1" ]]; then
|
||||
cat "$entry/policy"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
# The old writer accepted any $USER, so a basename can sit just under NAME_MAX.
|
||||
long_suffix=$(printf 'l%.0s' {1..223})
|
||||
(
|
||||
source "$library"
|
||||
printf 'deleteduser ALL=(ALL) NOPASSWD: ALL\n' >"$(rule_file 1000)"
|
||||
@@ -11,17 +24,23 @@ source "$SHELL_TEST_DIR/fixtures/passwordless-sudo-test.sh"
|
||||
# The legacy command never validated the account name, so a manual or NSS
|
||||
# account outside the current policy still has its exact old grant removed.
|
||||
printf 'Alice ALL=(ALL) NOPASSWD: ALL\n' >"$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-Alice"
|
||||
# The legacy writer produced the body with echo. Under BASH_ENV with
|
||||
# xpg_echo, USER='ali\0143e' yields this filename with an 'alice' rule, so
|
||||
# a suffix/body mismatch does not prove administrator authorship.
|
||||
printf 'alice ALL=(ALL) NOPASSWD: ALL\n' >"$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-ali\\0143e"
|
||||
printf 'alice ALL=(ALL) NOPASSWD: ALL\n' >"$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-$long_suffix"
|
||||
printf 'admin ALL=(ALL) NOPASSWD: /usr/bin/true\n' >"$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-custom"
|
||||
printf 'Alice ALL=(ALL) NOPASSWD: ALL\n' >"$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-handwritten"
|
||||
TEST_DELETE_FAIL=1 assert_status 1 cleanup_all_locked
|
||||
[[ -e $(rule_file 1000) ]]
|
||||
cleanup_all_locked
|
||||
[[ ! -e $(rule_file 1000) && ! -e $test_tmp/etc/sudoers.d/99-omarchy-nopasswd-Alice ]]
|
||||
[[ -e $test_tmp/etc/sudoers.d/99-omarchy-nopasswd-custom && -e $test_tmp/etc/sudoers.d/99-omarchy-nopasswd-handwritten ]]
|
||||
! compgen -G "$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-buildbot*"
|
||||
rm "$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-custom" "$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-handwritten"
|
||||
! compgen -G "$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-*"
|
||||
[[ $(stat -c '%a' "$quarantine") == 700 ]]
|
||||
[[ $(quarantined_policy '99-omarchy-nopasswd-ali\0143e') == 'alice ALL=(ALL) NOPASSWD: ALL' ]]
|
||||
[[ $(quarantined_policy "99-omarchy-nopasswd-$long_suffix") == 'alice ALL=(ALL) NOPASSWD: ALL' ]]
|
||||
[[ $(quarantined_policy 99-omarchy-nopasswd-custom) == 'admin ALL=(ALL) NOPASSWD: /usr/bin/true' ]]
|
||||
(( $(ls -A "$quarantine" | wc -l) == 3 ))
|
||||
)
|
||||
pass "legacy cleanup removes generated orphan rules for any account and preserves custom policy"
|
||||
pass "legacy cleanup removes generated rules for any account and quarantines everything else in the prefix"
|
||||
|
||||
# Run the actual migration queue for separate temporary homes. Sudo only calls
|
||||
# the mapped helper and can be refused without requesting host authorization.
|
||||
@@ -36,13 +55,18 @@ run_migrations() {
|
||||
marker="$test_tmp/var/lib/omarchy/migrations/1788163635"
|
||||
(
|
||||
source "$library"
|
||||
# A quarantine that cannot be trusted keeps the migration pending.
|
||||
printf 'alice ALL=(ALL) NOPASSWD: ALL\n' >"$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-mismatch"
|
||||
TEST_BAD_PATH="$test_tmp/var/lib/omarchy" assert_status 1 run_migrations first
|
||||
[[ ! -e $marker && -e $test_tmp/etc/sudoers.d/99-omarchy-nopasswd-mismatch ]]
|
||||
printf 'audituser ALL=(ALL) NOPASSWD: ALL\n' >"$(rule_file 1000)"
|
||||
printf 'Alice ALL=(ALL) NOPASSWD: ALL\n' >"$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-Alice"
|
||||
TEST_DELETE_FAIL=1 assert_status 1 run_migrations first
|
||||
[[ ! -e $marker && ! -e $test_tmp/first/1788163636.sh ]]
|
||||
run_migrations first
|
||||
[[ -f $marker && -f $test_tmp/first/1788163636.sh ]]
|
||||
[[ ! -e $test_tmp/etc/sudoers.d/99-omarchy-nopasswd-Alice ]]
|
||||
! compgen -G "$test_tmp/etc/sudoers.d/99-omarchy-nopasswd-*"
|
||||
[[ $(quarantined_policy 99-omarchy-nopasswd-mismatch) == 'alice ALL=(ALL) NOPASSWD: ALL' ]]
|
||||
enable_locked 1000 15
|
||||
cp "$(rule_file 1000)" "$test_tmp/renewed"
|
||||
: >"$test_tmp/commands"
|
||||
|
||||
Reference in new issue
Block a user