Close three paths from an unprivileged session to root
Apply the Omabot patch on Quattro, verify effective SSH hardening, prevent stored provisioning state from restoring the blanket input-group grant, and stop Omarchy from shipping asdcontrol authorization that belongs to the package. Co-authored-by: David Heinemeier Hansson <david@hey.com>
This commit is contained in:
co-authored by
David Heinemeier Hansson
parent
943d2fcbe9
commit
df819a6f98
@@ -677,11 +677,15 @@ user_groups() {
|
|||||||
if [[ -f $PROVISIONING_DIR/groups ]]; then
|
if [[ -f $PROVISIONING_DIR/groups ]]; then
|
||||||
while IFS= read -r group; do
|
while IFS= read -r group; do
|
||||||
[[ -n $group ]] || continue
|
[[ -n $group ]] || continue
|
||||||
# Never grant docker at first boot, even if an older install recorded it
|
# Never replay old privileged group defaults. Docker is always opt-in.
|
||||||
# (or a factory snapshot predating the opt-in default carries it): the
|
# Input is only retained when the factory image has one of the features
|
||||||
# docker group is root-equivalent. It is opt-in via
|
# whose installer deliberately grants access to raw input devices.
|
||||||
# omarchy-setup-security-sudoless-docker.
|
|
||||||
[[ $group == "docker" ]] && continue
|
[[ $group == "docker" ]] && continue
|
||||||
|
if [[ $group == "input" ]] &&
|
||||||
|
! pacman -Qq xpadneo-dkms &>/dev/null &&
|
||||||
|
! pacman -Qq ydotool &>/dev/null; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
getent group "$group" >/dev/null || continue
|
getent group "$group" >/dev/null || continue
|
||||||
[[ ",$groups," == *",$group,"* ]] || groups+=",$group"
|
[[ ",$groups," == *",$group,"* ]] || groups+=",$group"
|
||||||
done <"$PROVISIONING_DIR/groups"
|
done <"$PROVISIONING_DIR/groups"
|
||||||
|
|||||||
@@ -143,6 +143,48 @@ authorize_pasted_key() {
|
|||||||
authorize_key "$key" || exit 1
|
authorize_key "$key" || exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Only called after a key is authorized. Disabling password authentication
|
||||||
|
# before then could lock the owner out of the machine.
|
||||||
|
disable_password_auth() {
|
||||||
|
local config=/etc/ssh/sshd_config.d/10-omarchy-hardening.conf
|
||||||
|
local effective_config
|
||||||
|
|
||||||
|
if [[ ! -s $AUTHORIZED_KEYS ]]; then
|
||||||
|
echo -e "\e[31mCannot disable SSH password authentication without an authorized key.\e[0m" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Disabling SSH password authentication, now that a key is authorized..."
|
||||||
|
sudo install -Dm644 /dev/stdin "$config" <<'CONF'
|
||||||
|
# Written by omarchy-setup-security-sshd once an SSH key was authorized.
|
||||||
|
# Delete this file and reload sshd to allow password logins again.
|
||||||
|
PasswordAuthentication no
|
||||||
|
KbdInteractiveAuthentication no
|
||||||
|
CONF
|
||||||
|
|
||||||
|
# Validate before reloading: a config sshd rejects would otherwise take the
|
||||||
|
# service down on its next restart, potentially stranding a remote owner.
|
||||||
|
if ! sudo sshd -t; then
|
||||||
|
echo -e "\e[31msshd rejected the hardening config; removing it and leaving passwords on.\e[0m" >&2
|
||||||
|
sudo rm -f "$config"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Syntax alone is insufficient because sshd uses the first value it reads for
|
||||||
|
# these settings. An earlier administrator rule could leave passwords enabled.
|
||||||
|
if ! effective_config=$(sudo sshd -T) ||
|
||||||
|
! grep -qxF "passwordauthentication no" <<<"$effective_config" ||
|
||||||
|
! grep -qxF "kbdinteractiveauthentication no" <<<"$effective_config"; then
|
||||||
|
echo -e "\e[31msshd did not apply the password-authentication restrictions; removing the ineffective config.\e[0m" >&2
|
||||||
|
sudo rm -f "$config"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Reload rather than restart so an administrator already connected keeps
|
||||||
|
# their session.
|
||||||
|
sudo systemctl reload sshd.service
|
||||||
|
}
|
||||||
|
|
||||||
echo -e "\e[32mSetting up SSH server access with key-based authentication.\n\e[0m"
|
echo -e "\e[32mSetting up SSH server access with key-based authentication.\n\e[0m"
|
||||||
|
|
||||||
setup_sshd
|
setup_sshd
|
||||||
@@ -161,5 +203,8 @@ else
|
|||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
disable_password_auth
|
||||||
|
|
||||||
echo -e "\e[32m\nPerfect! The SSH server is running and your key is authorized.\e[0m"
|
echo -e "\e[32m\nPerfect! The SSH server is running and your key is authorized.\e[0m"
|
||||||
|
echo "Password logins are off; this machine now accepts authorized keys only."
|
||||||
echo "You can now connect with: ssh $USER@$(hostname)"
|
echo "You can now connect with: ssh $USER@$(hostname)"
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
%wheel ALL=(ALL) NOPASSWD: /usr/bin/asdcontrol
|
|
||||||
@@ -4,7 +4,6 @@ run_logged "$OMARCHY_INSTALL/hardware/dell-xps-touchpad-haptics.sh"
|
|||||||
run_logged "$OMARCHY_INSTALL/hardware/surface.sh"
|
run_logged "$OMARCHY_INSTALL/hardware/surface.sh"
|
||||||
|
|
||||||
run_logged "$OMARCHY_INSTALL/hardware/network.sh"
|
run_logged "$OMARCHY_INSTALL/hardware/network.sh"
|
||||||
run_logged "$OMARCHY_INSTALL/hardware/input-group.sh"
|
|
||||||
run_logged "$OMARCHY_INSTALL/hardware/set-wireless-regdom.sh"
|
run_logged "$OMARCHY_INSTALL/hardware/set-wireless-regdom.sh"
|
||||||
run_logged "$OMARCHY_INSTALL/hardware/fix-fkeys.sh"
|
run_logged "$OMARCHY_INSTALL/hardware/fix-fkeys.sh"
|
||||||
run_logged "$OMARCHY_INSTALL/hardware/fix-synaptic-touchpad.sh"
|
run_logged "$OMARCHY_INSTALL/hardware/fix-synaptic-touchpad.sh"
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
# Give this user privileged input access for dictation tools + xbox controllers to work.
|
|
||||||
# Recorded for provisioning first-boot user creation and factory reset, granted directly
|
|
||||||
# when the install user already exists (deferred-provisioning installs create the user at
|
|
||||||
# first boot instead).
|
|
||||||
provisioning_dir="${OMARCHY_PROVISIONING_DIR:-/var/lib/omarchy/provisioning}"
|
|
||||||
mkdir -p "$provisioning_dir"
|
|
||||||
grep -qxF input "$provisioning_dir/groups" 2>/dev/null || echo input >>"$provisioning_dir/groups"
|
|
||||||
|
|
||||||
if [[ -n ${OMARCHY_INSTALL_USER:-} ]] && getent passwd "$OMARCHY_INSTALL_USER" >/dev/null; then
|
|
||||||
usermod -aG input "$OMARCHY_INSTALL_USER"
|
|
||||||
fi
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
echo "Drop the default input group grant, which allowed unprivileged keylogging"
|
||||||
|
|
||||||
|
# Membership of `input` gives raw read/write access to /dev/input/event*: any
|
||||||
|
# process running as the user can capture keystrokes and synthesize input. The
|
||||||
|
# blanket grant is unnecessary: the Xbox-controller and ydotool installers add
|
||||||
|
# the group themselves when those features are deliberately installed.
|
||||||
|
#
|
||||||
|
# Preserve membership where one of those opt-in features is present; removing
|
||||||
|
# it there would break the feature the user chose to install.
|
||||||
|
if id -nG "$USER" | grep -qw input; then
|
||||||
|
if pacman -Qq xpadneo-dkms &>/dev/null || pacman -Qq ydotool &>/dev/null; then
|
||||||
|
echo "Keeping $USER in the input group: controller or ydotool support is installed."
|
||||||
|
else
|
||||||
|
sudo gpasswd -d "$USER" input >/dev/null
|
||||||
|
echo "Removed $USER from the input group. Log out and back in to apply."
|
||||||
|
omarchy-state set reboot-required
|
||||||
|
fi
|
||||||
|
fi
|
||||||
Executable
+64
@@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
source "$(dirname "$0")/base-test.sh"
|
||||||
|
|
||||||
|
migration="$ROOT/migrations/1787865477.sh"
|
||||||
|
test_dir=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$test_dir"' EXIT
|
||||||
|
|
||||||
|
stub_bin="$test_dir/bin"
|
||||||
|
mkdir -p "$stub_bin"
|
||||||
|
|
||||||
|
cat >"$stub_bin/id" <<'STUB'
|
||||||
|
#!/bin/bash
|
||||||
|
printf '%s\n' "${STUB_GROUPS:-wheel}"
|
||||||
|
STUB
|
||||||
|
cat >"$stub_bin/pacman" <<'STUB'
|
||||||
|
#!/bin/bash
|
||||||
|
[[ $1 == "-Qq" ]] || exit 2
|
||||||
|
[[ " ${STUB_PACKAGES:-} " == *" $2 "* ]]
|
||||||
|
STUB
|
||||||
|
cat >"$stub_bin/sudo" <<'STUB'
|
||||||
|
#!/bin/bash
|
||||||
|
exec "$@"
|
||||||
|
STUB
|
||||||
|
cat >"$stub_bin/gpasswd" <<'STUB'
|
||||||
|
#!/bin/bash
|
||||||
|
printf '%s\n' "$*" >>"${GPASSWD_CALLS:?}"
|
||||||
|
STUB
|
||||||
|
cat >"$stub_bin/omarchy-state" <<'STUB'
|
||||||
|
#!/bin/bash
|
||||||
|
printf '%s\n' "$*" >>"${STATE_CALLS:?}"
|
||||||
|
STUB
|
||||||
|
chmod +x "$stub_bin"/*
|
||||||
|
|
||||||
|
gpasswd_calls="$test_dir/gpasswd-calls"
|
||||||
|
state_calls="$test_dir/state-calls"
|
||||||
|
|
||||||
|
run_migration() {
|
||||||
|
rm -f "$gpasswd_calls" "$state_calls"
|
||||||
|
USER=tester STUB_GROUPS="$1" STUB_PACKAGES="${2:-}" \
|
||||||
|
GPASSWD_CALLS="$gpasswd_calls" STATE_CALLS="$state_calls" \
|
||||||
|
PATH="$stub_bin:$PATH" bash -euo pipefail "$migration"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_migration "wheel input" >/dev/null
|
||||||
|
grep -qxF -- "-d tester input" "$gpasswd_calls" || fail "migration removes default input membership"
|
||||||
|
grep -qxF "set reboot-required" "$state_calls" || fail "migration flags the session change for reboot"
|
||||||
|
pass "migration removes the blanket input grant"
|
||||||
|
|
||||||
|
run_migration "wheel" >/dev/null
|
||||||
|
[[ ! -e $gpasswd_calls ]] || fail "migration does not remove an already-absent group"
|
||||||
|
[[ ! -e $state_calls ]] || fail "migration does not flag a reboot when nothing changed"
|
||||||
|
pass "migration is idempotent after input membership is gone"
|
||||||
|
|
||||||
|
run_migration "wheel input" xpadneo-dkms >/dev/null
|
||||||
|
[[ ! -e $gpasswd_calls ]] || fail "migration preserves input for controller support"
|
||||||
|
[[ ! -e $state_calls ]] || fail "preserved controller support does not flag a reboot"
|
||||||
|
|
||||||
|
run_migration "wheel input" ydotool >/dev/null
|
||||||
|
[[ ! -e $gpasswd_calls ]] || fail "migration preserves input for ydotool"
|
||||||
|
[[ ! -e $state_calls ]] || fail "preserved ydotool support does not flag a reboot"
|
||||||
|
pass "migration preserves deliberate input-group opt-ins"
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# The install scripts that grant group memberships must record them in the provisioning
|
# Privileged groups are never granted by the default install. Docker remains an
|
||||||
# groups file (for first-boot user creation and factory reset) and only call
|
# explicit opt-in, and raw input-device access is granted only by the optional
|
||||||
# usermod when the install user actually exists.
|
# controller and ydotool installers.
|
||||||
#
|
|
||||||
# Docker is deliberately excluded: the docker group is root-equivalent, so it is
|
|
||||||
# no longer granted at install time (opt in with omarchy-setup-security-sudoless-docker).
|
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@@ -16,13 +13,7 @@ trap 'rm -rf "$TMPDIR"' EXIT
|
|||||||
|
|
||||||
export OMARCHY_PROVISIONING_DIR="$TMPDIR/provisioning"
|
export OMARCHY_PROVISIONING_DIR="$TMPDIR/provisioning"
|
||||||
|
|
||||||
# Stub getent/usermod: the fake system knows only the user "existing".
|
|
||||||
mkdir -p "$TMPDIR/bin"
|
mkdir -p "$TMPDIR/bin"
|
||||||
cat >"$TMPDIR/bin/getent" <<'STUB'
|
|
||||||
#!/bin/bash
|
|
||||||
[[ $1 == passwd && $2 == existing ]] && { echo "existing:x:1000:1000::/home/existing:/bin/bash"; exit 0; }
|
|
||||||
exit 2
|
|
||||||
STUB
|
|
||||||
cat >"$TMPDIR/bin/usermod" <<STUB
|
cat >"$TMPDIR/bin/usermod" <<STUB
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
echo "\$@" >>"$TMPDIR/usermod.calls"
|
echo "\$@" >>"$TMPDIR/usermod.calls"
|
||||||
@@ -44,48 +35,31 @@ cat >"$TMPDIR/bin/sudo" <<STUB
|
|||||||
echo "\$@" >>"$TMPDIR/sudo.calls"
|
echo "\$@" >>"$TMPDIR/sudo.calls"
|
||||||
exec "\$@"
|
exec "\$@"
|
||||||
STUB
|
STUB
|
||||||
chmod +x "$TMPDIR/bin"/{getent,usermod,groupadd,install,find,sudo}
|
chmod +x "$TMPDIR/bin"/{usermod,groupadd,install,find,sudo}
|
||||||
export PATH="$TMPDIR/bin:$PATH"
|
export PATH="$TMPDIR/bin:$PATH"
|
||||||
export OMARCHY_PATH="$ROOT"
|
export OMARCHY_PATH="$ROOT"
|
||||||
|
|
||||||
# No install user (deferred-provisioning install): groups recorded, usermod not called.
|
# A deferred-provisioning install records neither privileged group.
|
||||||
OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/config/docker.sh"
|
OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/config/docker.sh"
|
||||||
OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/hardware/input-group.sh"
|
|
||||||
OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/config/browser-policy.sh"
|
OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/config/browser-policy.sh"
|
||||||
|
|
||||||
[[ -f $OMARCHY_PROVISIONING_DIR/groups ]] || fail "groups file written without an install user"
|
[[ ! -f $OMARCHY_PROVISIONING_DIR/groups ]] ||
|
||||||
grep -qxF input "$OMARCHY_PROVISIONING_DIR/groups" || fail "input group recorded"
|
! grep -Eq '^(docker|input)$' "$OMARCHY_PROVISIONING_DIR/groups" ||
|
||||||
! grep -qxF omarchy-browser-policy "$OMARCHY_PROVISIONING_DIR/groups" ||
|
fail "default install must not record docker or input groups"
|
||||||
fail "browser-policy group must not be recorded"
|
|
||||||
[[ ! -f $TMPDIR/usermod.calls ]] || fail "usermod not called without an install user"
|
[[ ! -f $TMPDIR/usermod.calls ]] || fail "usermod not called without an install user"
|
||||||
[[ ! -f $TMPDIR/groupadd.calls ]] || ! grep -F omarchy-browser-policy "$TMPDIR/groupadd.calls" >/dev/null ||
|
[[ ! -f $TMPDIR/groupadd.calls ]] || ! grep -F omarchy-browser-policy "$TMPDIR/groupadd.calls" >/dev/null ||
|
||||||
fail "browser-policy group is not created"
|
fail "browser-policy group is not created"
|
||||||
grep -F -- '-d -m 0755 -o root -g root /etc/chromium/policies/managed' "$TMPDIR/install.calls" >/dev/null ||
|
grep -F -- '-d -m 0755 -o root -g root /etc/chromium/policies/managed' "$TMPDIR/install.calls" >/dev/null ||
|
||||||
fail "browser-policy directory is created root-owned"
|
fail "browser-policy directory is created root-owned"
|
||||||
pass "deferred provisioning records groups without calling usermod"
|
pass "deferred provisioning records no privileged groups"
|
||||||
|
|
||||||
# The docker group is root-equivalent and must never be granted automatically.
|
# The same remains true when an install user already exists.
|
||||||
! grep -qxF docker "$OMARCHY_PROVISIONING_DIR/groups" || fail "docker group must not be recorded"
|
|
||||||
pass "docker group is not recorded at install"
|
|
||||||
|
|
||||||
# Missing user (defensive): no usermod either.
|
|
||||||
OMARCHY_INSTALL_USER=ghost bash -eE "$ROOT/install/hardware/input-group.sh"
|
|
||||||
OMARCHY_INSTALL_USER=ghost bash -eE "$ROOT/install/config/browser-policy.sh"
|
|
||||||
[[ ! -f $TMPDIR/usermod.calls ]] || fail "usermod not called for a missing user"
|
|
||||||
pass "missing install user defers group grants"
|
|
||||||
|
|
||||||
# Re-running never duplicates entries.
|
|
||||||
OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/hardware/input-group.sh"
|
|
||||||
[[ $(grep -cxF input "$OMARCHY_PROVISIONING_DIR/groups") == 1 ]] || fail "input group recorded once"
|
|
||||||
OMARCHY_INSTALL_USER="" bash -eE "$ROOT/install/config/browser-policy.sh"
|
|
||||||
pass "group recording is idempotent"
|
|
||||||
|
|
||||||
# Existing user: usermod applies the recorded groups, and docker is never among them.
|
|
||||||
OMARCHY_INSTALL_USER=existing bash -eE "$ROOT/install/config/docker.sh"
|
OMARCHY_INSTALL_USER=existing bash -eE "$ROOT/install/config/docker.sh"
|
||||||
OMARCHY_INSTALL_USER=existing bash -eE "$ROOT/install/hardware/input-group.sh"
|
|
||||||
OMARCHY_INSTALL_USER=existing bash -eE "$ROOT/install/config/browser-policy.sh"
|
OMARCHY_INSTALL_USER=existing bash -eE "$ROOT/install/config/browser-policy.sh"
|
||||||
grep -qx -- "-aG input existing" "$TMPDIR/usermod.calls" || fail "usermod grants input to the install user"
|
[[ ! -f $TMPDIR/usermod.calls ]] || fail "default install must not grant privileged groups"
|
||||||
! grep -q -- "omarchy-browser-policy" "$TMPDIR/usermod.calls" ||
|
pass "existing install user gets neither docker nor input access"
|
||||||
fail "usermod must not grant browser-policy to the install user"
|
|
||||||
! grep -q -- "docker" "$TMPDIR/usermod.calls" || fail "usermod must not grant docker to the install user"
|
! grep -q 'hardware/input-group.sh' "$ROOT/install/hardware/all.sh" ||
|
||||||
pass "existing install user gets input but never docker or browser-policy"
|
fail "hardware setup must not call the removed input-group grant"
|
||||||
|
[[ ! -e $ROOT/install/hardware/input-group.sh ]] || fail "blanket input-group grant is removed"
|
||||||
|
pass "hardware setup has no blanket input-group grant"
|
||||||
|
|||||||
Executable
+105
@@ -0,0 +1,105 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
source "$(dirname "$0")/base-test.sh"
|
||||||
|
|
||||||
|
test_dir=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$test_dir"' EXIT
|
||||||
|
|
||||||
|
stub_bin="$test_dir/bin"
|
||||||
|
mkdir -p "$stub_bin"
|
||||||
|
|
||||||
|
cat >"$stub_bin/omarchy-pkg-add" <<'STUB'
|
||||||
|
#!/bin/bash
|
||||||
|
printf 'pkg %s\n' "$*" >>"${CALL_LOG:?}"
|
||||||
|
STUB
|
||||||
|
cat >"$stub_bin/omarchy-cmd-missing" <<'STUB'
|
||||||
|
#!/bin/bash
|
||||||
|
exit 0
|
||||||
|
STUB
|
||||||
|
cat >"$stub_bin/systemctl" <<'STUB'
|
||||||
|
#!/bin/bash
|
||||||
|
printf 'systemctl %s\n' "$*" >>"${CALL_LOG:?}"
|
||||||
|
STUB
|
||||||
|
cat >"$stub_bin/sshd" <<'STUB'
|
||||||
|
#!/bin/bash
|
||||||
|
case $1 in
|
||||||
|
-t)
|
||||||
|
[[ ${SSHD_SYNTAX_VALID:-1} == 1 ]]
|
||||||
|
;;
|
||||||
|
-T)
|
||||||
|
printf 'passwordauthentication %s\n' "${SSHD_PASSWORD_AUTH:-no}"
|
||||||
|
printf 'kbdinteractiveauthentication %s\n' "${SSHD_KBD_AUTH:-no}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
STUB
|
||||||
|
cat >"$stub_bin/sudo" <<'STUB'
|
||||||
|
#!/bin/bash
|
||||||
|
case $1 in
|
||||||
|
install)
|
||||||
|
destination="${TEST_ROOT:?}${4:?}"
|
||||||
|
/usr/bin/mkdir -p "${destination%/*}"
|
||||||
|
/usr/bin/install -Dm644 /dev/stdin "$destination"
|
||||||
|
;;
|
||||||
|
rm)
|
||||||
|
/usr/bin/rm -f "${TEST_ROOT:?}${3:?}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
exec "$@"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
STUB
|
||||||
|
chmod +x "$stub_bin"/*
|
||||||
|
|
||||||
|
ssh-keygen -q -t ed25519 -N "" -f "$test_dir/key"
|
||||||
|
public_key=$(<"$test_dir/key.pub")
|
||||||
|
|
||||||
|
run_setup() {
|
||||||
|
local scenario="$1"
|
||||||
|
local home="$test_dir/$scenario/home"
|
||||||
|
local root="$test_dir/$scenario/root"
|
||||||
|
|
||||||
|
mkdir -p "$home" "$root"
|
||||||
|
: >"$test_dir/$scenario.calls"
|
||||||
|
|
||||||
|
HOME="$home" TEST_ROOT="$root" CALL_LOG="$test_dir/$scenario.calls" \
|
||||||
|
SSHD_SYNTAX_VALID="${SSHD_SYNTAX_VALID:-1}" \
|
||||||
|
SSHD_PASSWORD_AUTH="${SSHD_PASSWORD_AUTH:-no}" \
|
||||||
|
SSHD_KBD_AUTH="${SSHD_KBD_AUTH:-no}" \
|
||||||
|
PATH="$stub_bin:$PATH" \
|
||||||
|
bash "$ROOT/bin/omarchy-setup-security-sshd" --key="$public_key"
|
||||||
|
}
|
||||||
|
|
||||||
|
output=$(run_setup success)
|
||||||
|
config="$test_dir/success/root/etc/ssh/sshd_config.d/10-omarchy-hardening.conf"
|
||||||
|
grep -qxF "PasswordAuthentication no" "$config" || fail "SSH setup disables password authentication"
|
||||||
|
grep -qxF "KbdInteractiveAuthentication no" "$config" || fail "SSH setup disables keyboard-interactive authentication"
|
||||||
|
grep -qxF "systemctl reload sshd.service" "$test_dir/success.calls" || fail "SSH setup reloads the validated config"
|
||||||
|
grep -q "Password logins are off" <<<"$output" || fail "SSH setup reports hardening after it succeeds"
|
||||||
|
pass "SSH setup authorizes a key and disables password logins"
|
||||||
|
|
||||||
|
if SSHD_PASSWORD_AUTH=yes run_setup ineffective >"$test_dir/ineffective.output" 2>&1; then
|
||||||
|
fail "SSH setup must fail when password authentication remains effective"
|
||||||
|
fi
|
||||||
|
[[ ! -e $test_dir/ineffective/root/etc/ssh/sshd_config.d/10-omarchy-hardening.conf ]] ||
|
||||||
|
fail "SSH setup removes an ineffective hardening config"
|
||||||
|
! grep -qF "systemctl reload sshd.service" "$test_dir/ineffective.calls" ||
|
||||||
|
fail "SSH setup must not reload ineffective hardening"
|
||||||
|
! grep -q "Password logins are off" "$test_dir/ineffective.output" ||
|
||||||
|
fail "SSH setup must not claim ineffective hardening succeeded"
|
||||||
|
pass "SSH setup verifies the effective daemon settings"
|
||||||
|
|
||||||
|
if SSHD_SYNTAX_VALID=0 run_setup invalid >"$test_dir/invalid.output" 2>&1; then
|
||||||
|
fail "SSH setup must fail when sshd rejects its config"
|
||||||
|
fi
|
||||||
|
[[ ! -e $test_dir/invalid/root/etc/ssh/sshd_config.d/10-omarchy-hardening.conf ]] ||
|
||||||
|
fail "SSH setup removes a rejected hardening config"
|
||||||
|
! grep -qF "systemctl reload sshd.service" "$test_dir/invalid.calls" ||
|
||||||
|
fail "SSH setup must not reload a rejected config"
|
||||||
|
! grep -q "Password logins are off" "$test_dir/invalid.output" ||
|
||||||
|
fail "SSH setup must not claim rejected hardening succeeded"
|
||||||
|
pass "SSH setup fails safely when sshd rejects the config"
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# The docker group is root-equivalent, so no automatic path may grant it. These
|
# Docker is root-equivalent, so no automatic path may grant it. Raw input access
|
||||||
# tests guard the paths that are not exercised by a fresh-install run: first-boot
|
# is likewise excluded unless a feature that explicitly needs it is installed.
|
||||||
# provisioning replaying a recorded (or factory-snapshot) group list, and the
|
|
||||||
# Quattro upgrade. Opting in stays a deliberate, warned step
|
|
||||||
# (omarchy-setup-security-sudoless-docker).
|
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@@ -13,11 +10,15 @@ source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
|||||||
TMPDIR=$(mktemp -d)
|
TMPDIR=$(mktemp -d)
|
||||||
trap 'rm -rf "$TMPDIR"' EXIT
|
trap 'rm -rf "$TMPDIR"' EXIT
|
||||||
|
|
||||||
# First-boot provisioning must never grant docker even when it is recorded (an
|
# First-boot provisioning must not replay old privileged defaults.
|
||||||
# older install, or a factory snapshot predating the opt-in default).
|
|
||||||
mkdir -p "$TMPDIR/bin"
|
mkdir -p "$TMPDIR/bin"
|
||||||
printf '#!/bin/bash\nexit 0\n' >"$TMPDIR/bin/getent" # every group "exists"
|
printf '#!/bin/bash\nexit 0\n' >"$TMPDIR/bin/getent" # every group "exists"
|
||||||
chmod +x "$TMPDIR/bin/getent"
|
cat >"$TMPDIR/bin/pacman" <<'STUB'
|
||||||
|
#!/bin/bash
|
||||||
|
[[ $1 == "-Qq" ]] || exit 2
|
||||||
|
[[ " ${STUB_PACKAGES:-} " == *" $2 "* ]]
|
||||||
|
STUB
|
||||||
|
chmod +x "$TMPDIR/bin/getent" "$TMPDIR/bin/pacman"
|
||||||
export PATH="$TMPDIR/bin:$PATH"
|
export PATH="$TMPDIR/bin:$PATH"
|
||||||
|
|
||||||
PROVISIONING_DIR="$TMPDIR/prov"
|
PROVISIONING_DIR="$TMPDIR/prov"
|
||||||
@@ -29,9 +30,15 @@ eval "$(sed -n '/^user_groups() {/,/^}/p' "$ROOT/bin/omarchy-provision-owner")"
|
|||||||
groups=$(user_groups)
|
groups=$(user_groups)
|
||||||
|
|
||||||
[[ ",$groups," == *",wheel,"* ]] || fail "user_groups always includes wheel"
|
[[ ",$groups," == *",wheel,"* ]] || fail "user_groups always includes wheel"
|
||||||
[[ ",$groups," == *",input,"* ]] || fail "user_groups includes recorded non-docker groups"
|
[[ ",$groups," != *",input,"* ]] || fail "user_groups must not replay the blanket input grant"
|
||||||
[[ ",$groups," == *",docker,"* ]] && fail "user_groups must never grant the docker group"
|
[[ ",$groups," == *",docker,"* ]] && fail "user_groups must never grant the docker group"
|
||||||
pass "first-boot user_groups includes recorded groups but never docker"
|
pass "first-boot user_groups replays neither privileged default"
|
||||||
|
|
||||||
|
groups=$(STUB_PACKAGES=xpadneo-dkms user_groups)
|
||||||
|
[[ ",$groups," == *",input,"* ]] || fail "user_groups keeps input for installed controller support"
|
||||||
|
groups=$(STUB_PACKAGES=ydotool user_groups)
|
||||||
|
[[ ",$groups," == *",input,"* ]] || fail "user_groups keeps input for installed ydotool support"
|
||||||
|
pass "first-boot user_groups keeps deliberate input-group opt-ins"
|
||||||
|
|
||||||
# The Quattro upgrade must not re-add the user to docker.
|
# The Quattro upgrade must not re-add the user to docker.
|
||||||
if rg -q 'usermod -aG docker' "$ROOT/bin/omarchy-upgrade-to-quattro"; then
|
if rg -q 'usermod -aG docker' "$ROOT/bin/omarchy-upgrade-to-quattro"; then
|
||||||
|
|||||||
Reference in New Issue
Block a user