Keep USB approvals portable and preserve approval prompts
This commit is contained in:
1 parent
60d6b255da
commit
c3cdcb1e82
15 files changed
+535
-52
No files matched your search
@@ -1,20 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Ask before new USB devices can access the system
|
||||
# omarchy:args=[--boot] [--yes]
|
||||
# omarchy:args=[--boot] [--yes] [--review-existing]
|
||||
# omarchy:requires-sudo=true
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
assume_yes=0
|
||||
from_boot=0
|
||||
review_existing=0
|
||||
|
||||
while (( $# > 0 )); do
|
||||
case "$1" in
|
||||
--yes) assume_yes=1 ;;
|
||||
--boot) from_boot=1 ;;
|
||||
--review-existing) review_existing=1 ;;
|
||||
-h | --help)
|
||||
echo "Usage: omarchy-setup-security-usb-authorization [--boot] [--yes]"
|
||||
echo "Usage: omarchy-setup-security-usb-authorization [--boot] [--yes] [--review-existing]"
|
||||
echo
|
||||
echo "Trusts USB devices that are connected now, then blocks new devices"
|
||||
echo "until you approve them from an Omarchy notification."
|
||||
@@ -25,6 +27,9 @@ while (( $# > 0 )); do
|
||||
echo "Older snapshots without USBGuard keep all USB disabled after startup,"
|
||||
echo "including keyboards, network adapters, and storage. Use --boot only if"
|
||||
echo "disk unlock and recovery work without any USB devices."
|
||||
echo
|
||||
echo "--review-existing reviews connected devices with older port-bound approvals."
|
||||
echo "Each portable approval requires confirmation; existing rules are preserved."
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
@@ -43,6 +48,58 @@ daemon_config=/etc/usbguard/usbguard-daemon.conf
|
||||
|
||||
source "$OMARCHY_PATH/install/helpers/usb-authorization.sh"
|
||||
|
||||
if (( review_existing )); then
|
||||
# Older Omarchy rules have no per-rule ownership marker. They cannot safely
|
||||
# be distinguished from intentionally restricted administrator rules.
|
||||
(( ! assume_yes && ! from_boot )) || { echo "Review requires individual confirmation; do not combine it with --yes or --boot." >&2; exit 2; }
|
||||
policy=$(usbguard list-rules)
|
||||
declare -A reviewed=()
|
||||
# Keep stdin attached to the terminal for gum (and any sudo prompt).
|
||||
mapfile -t policy_lines <<<"$policy"
|
||||
for line in "${policy_lines[@]}"; do
|
||||
if [[ $line =~ ^[0-9]+:[[:space:]] ]]; then
|
||||
rule=${line#*: }
|
||||
[[ $rule == allow\ * ]] || continue
|
||||
portable=$(usb_authorization_portable_rule "$rule") || continue
|
||||
[[ ${portable% label *} != "$rule" ]] || continue
|
||||
devices=$(usbguard list-devices "$rule")
|
||||
mapfile -t candidates <<<"$devices"
|
||||
for device in "${candidates[@]}"; do
|
||||
[[ $device =~ ^([0-9]+):[[:space:]](allow[[:space:]].*)$ ]] || continue
|
||||
id=${BASH_REMATCH[1]} current=${BASH_REMATCH[2]}
|
||||
[[ ! -v reviewed[$id] ]] || continue
|
||||
reviewed[$id]=1
|
||||
echo
|
||||
printf '%s\n' "$current" | LC_ALL=C tr -c '\11\12\15\40-\176' '?'
|
||||
echo "This device has a location-bound approval. Details are supplied by the device."
|
||||
if gum confirm "Trust this device on any USB port or hub?"; then
|
||||
sudo /usr/bin/omarchy-usb-authorization-approve "$id" "$current"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
echo "Review complete. Disconnected devices can be approved when reconnected."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# The watcher runs in the session's environment, which may differ from a
|
||||
# command invoked in a checkout. Fail before enabling blocking on mismatched
|
||||
# or incomplete installations, including dangling dev-link unit symlinks.
|
||||
session_environment=$(systemctl --user show-environment)
|
||||
grep -Fqx -- "OMARCHY_PATH=$OMARCHY_PATH" <<<"$session_environment" || {
|
||||
echo "The session and this command use different Omarchy installations. Update the session before enabling USB protection." >&2
|
||||
exit 1
|
||||
}
|
||||
for required in "$unit_source" /usr/share/omarchy/install/helpers/usb-authorization-policy.sh; do
|
||||
[[ -r $required ]] || { echo "USB authorization installation is incomplete: $required" >&2; exit 1; }
|
||||
done
|
||||
for required in "$OMARCHY_PATH/bin/omarchy-usb-authorization-watch" \
|
||||
"$OMARCHY_PATH/bin/omarchy-usb-authorization-event" \
|
||||
"$OMARCHY_PATH/bin/omarchy-usb-authorization-review" \
|
||||
/usr/bin/omarchy-usb-authorization-approve; do
|
||||
[[ -r $required && -x $required ]] || { echo "USB authorization command is unavailable: $required" >&2; exit 1; }
|
||||
done
|
||||
|
||||
if (( ! assume_yes )); then
|
||||
if (( from_boot )); then
|
||||
gum style --foreground 212 --bold "USB authorization from boot"
|
||||
@@ -93,19 +150,27 @@ sudo usbguard add-user "$USER" \
|
||||
--policy=list \
|
||||
--exceptions=listen
|
||||
|
||||
sudo install -Dm644 "$OMARCHY_PATH/default/polkit/org.omarchy.usb.policy" /usr/share/polkit-1/actions/org.omarchy.usb.policy
|
||||
|
||||
# Install a real file: a link into a checkout can become dangling on a branch
|
||||
# switch. Start the waiting watcher before USBGuard can block new devices.
|
||||
unit_temporary=$(mktemp "${unit}.XXXXXXXXXX")
|
||||
install -m644 "$unit_source" "$unit_temporary"
|
||||
mv -fT "$unit_temporary" "$unit"
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable omarchy-usb-authorization.service
|
||||
systemctl --user restart omarchy-usb-authorization.service
|
||||
systemctl --user is-active --quiet omarchy-usb-authorization.service
|
||||
|
||||
sudo systemctl enable usbguard.service
|
||||
# add-user ACL changes are loaded only when the daemon starts, so restart an
|
||||
# existing service as well as starting a fresh one.
|
||||
sudo systemctl restart usbguard.service
|
||||
|
||||
ln -sfn "$unit_source" "$unit"
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable --now omarchy-usb-authorization.service
|
||||
systemctl is-active --quiet usbguard.service
|
||||
systemctl --user is-active --quiet omarchy-usb-authorization.service
|
||||
|
||||
if (( from_boot )); then
|
||||
# Take the trust snapshot only after USBGuard is enforcing the policy. Every
|
||||
# ID is resolved by the daemon, and no device-controlled descriptor text is
|
||||
# passed to a privileged command.
|
||||
# The fixed helper independently verifies each full live device snapshot.
|
||||
usb_authorization_trust_present_devices
|
||||
sudo omarchy-usb-authorization-boot enable
|
||||
fi
|
||||
@@ -113,6 +178,7 @@ fi
|
||||
echo
|
||||
echo "USB device authorization is enabled."
|
||||
echo "Devices connected during setup remain trusted; new devices require approval."
|
||||
echo "To review older port-bound approvals, run: omarchy-setup-security-usb-authorization --review-existing"
|
||||
if (( from_boot )); then
|
||||
echo "Boot-time authorization is enabled and takes effect after reboot."
|
||||
fi
|
||||
Reference in new issue
Block a user