harden(desudo): funnel firewall/ssh/socket/systemd system ops through runSystem
firewall_initial_setup + firewall_clear_rules (ufw/ufw-docker), host_access.sh (sshd/-T/-t, /etc/ssh, authorized_keys, systemctl reload), set_socket_permissions (docker socket test/chmod), and webui_install_systemd (systemd unit tee + systemctl) -> runSystem. These stay real-root in both modes and define part of the eventual scoped allowlist. Left the 'sudo -u <manager> crontab' run-as-manager lines for a dedicated pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
parent
8532aecb3f
commit
d7c0d12314
@ -16,8 +16,8 @@ dockerSwitcherSetSocketPermissions()
|
|||||||
if [[ $CFG_DOCKER_INSTALL_TYPE == "rooted" ]]; then
|
if [[ $CFG_DOCKER_INSTALL_TYPE == "rooted" ]]; then
|
||||||
if [[ $docker_rootless_exist == "false" ]]; then
|
if [[ $docker_rootless_exist == "false" ]]; then
|
||||||
# if File exists
|
# if File exists
|
||||||
if sudo test -e "$docker_rootless_socket"; then
|
if runSystem test -e "$docker_rootless_socket"; then
|
||||||
local result=$(sudo chmod o-r "$docker_rootless_socket")
|
local result=$(runSystem chmod o-r "$docker_rootless_socket")
|
||||||
checkSuccess "Removing read permissions from Rootless docker socket."
|
checkSuccess "Removing read permissions from Rootless docker socket."
|
||||||
docker_rootless_found="true"
|
docker_rootless_found="true"
|
||||||
else
|
else
|
||||||
@ -27,8 +27,8 @@ dockerSwitcherSetSocketPermissions()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# if File exists
|
# if File exists
|
||||||
if sudo test -e "$docker_rooted_socket"; then
|
if runSystem test -e "$docker_rooted_socket"; then
|
||||||
local result=$(sudo chmod +r "$docker_rooted_socket")
|
local result=$(runSystem chmod +r "$docker_rooted_socket")
|
||||||
checkSuccess "Adding read permissions to Rooted docker socket."
|
checkSuccess "Adding read permissions to Rooted docker socket."
|
||||||
docker_rooted_found="true"
|
docker_rooted_found="true"
|
||||||
else
|
else
|
||||||
@ -39,8 +39,8 @@ dockerSwitcherSetSocketPermissions()
|
|||||||
|
|
||||||
if [[ $CFG_DOCKER_INSTALL_TYPE == "rootless" ]]; then
|
if [[ $CFG_DOCKER_INSTALL_TYPE == "rootless" ]]; then
|
||||||
# if File exists
|
# if File exists
|
||||||
if sudo test -e "$docker_rooted_socket"; then
|
if runSystem test -e "$docker_rooted_socket"; then
|
||||||
local result=$(sudo chmod o-r "$docker_rooted_socket")
|
local result=$(runSystem chmod o-r "$docker_rooted_socket")
|
||||||
checkSuccess "Removing read permissions from Rooted docker socket."
|
checkSuccess "Removing read permissions from Rooted docker socket."
|
||||||
docker_rooted_found="true"
|
docker_rooted_found="true"
|
||||||
else
|
else
|
||||||
@ -49,8 +49,8 @@ dockerSwitcherSetSocketPermissions()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# if File exists
|
# if File exists
|
||||||
if sudo test -e "$docker_rootless_socket"; then
|
if runSystem test -e "$docker_rootless_socket"; then
|
||||||
local result=$(sudo chmod +r "$docker_rootless_socket")
|
local result=$(runSystem chmod +r "$docker_rootless_socket")
|
||||||
checkSuccess "Adding read permissions to Rootless docker socket."
|
checkSuccess "Adding read permissions to Rootless docker socket."
|
||||||
docker_rootless_found="true"
|
docker_rootless_found="true"
|
||||||
else
|
else
|
||||||
|
|||||||
@ -15,7 +15,7 @@ firewallInitialSetup()
|
|||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
if [[ "$firewallallowport_port" =~ ^[0-9]+$ && $firewallallowport_port -ge 1 && $firewallallowport_port -le 65535 ]]; then
|
if [[ "$firewallallowport_port" =~ ^[0-9]+$ && $firewallallowport_port -ge 1 && $firewallallowport_port -le 65535 ]]; then
|
||||||
local result=$(sudo ufw allow "$firewallallowport_port")
|
local result=$(runSystem ufw allow "$firewallallowport_port")
|
||||||
checkSuccess "Opening port $firewallallowport_port in the UFW Firewall"
|
checkSuccess "Opening port $firewallallowport_port in the UFW Firewall"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
@ -36,7 +36,7 @@ firewallInitialSetup()
|
|||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
if [[ "$firewallblockport_port" =~ ^[0-9]+$ && $firewallblockport_port -ge 1 && $firewallblockport_port -le 65535 ]]; then
|
if [[ "$firewallblockport_port" =~ ^[0-9]+$ && $firewallblockport_port -ge 1 && $firewallblockport_port -le 65535 ]]; then
|
||||||
local result=$(sudo ufw deny "$firewallblockport_port")
|
local result=$(runSystem ufw deny "$firewallblockport_port")
|
||||||
checkSuccess "Blocking port $firewallblockport_port in the UFW Firewall"
|
checkSuccess "Blocking port $firewallblockport_port in the UFW Firewall"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
@ -49,9 +49,9 @@ firewallInitialSetup()
|
|||||||
echo ""
|
echo ""
|
||||||
echo "---- Block port 22 (SSH) :"
|
echo "---- Block port 22 (SSH) :"
|
||||||
echo ""
|
echo ""
|
||||||
local result=$(sudo ufw deny 22)
|
local result=$(runSystem ufw deny 22)
|
||||||
checkSuccess "Disabling Port 22 through the firewall"
|
checkSuccess "Disabling Port 22 through the firewall"
|
||||||
local result=$(sudo ufw deny ssh)
|
local result=$(runSystem ufw deny ssh)
|
||||||
checkSuccess "Disabling SSH through the firewall"
|
checkSuccess "Disabling SSH through the firewall"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -60,9 +60,9 @@ firewallInitialSetup()
|
|||||||
echo ""
|
echo ""
|
||||||
echo "---- Allow port 22 (SSH) :"
|
echo "---- Allow port 22 (SSH) :"
|
||||||
echo ""
|
echo ""
|
||||||
local result=$(sudo ufw allow 22)
|
local result=$(runSystem ufw allow 22)
|
||||||
checkSuccess "Allowing Port 22 through the firewall"
|
checkSuccess "Allowing Port 22 through the firewall"
|
||||||
local result=$(sudo ufw allow ssh)
|
local result=$(runSystem ufw allow ssh)
|
||||||
checkSuccess "Allowing SSH through the firewall"
|
checkSuccess "Allowing SSH through the firewall"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ firewallInitialSetup()
|
|||||||
case "$CFG_UFW_LOGGING" in
|
case "$CFG_UFW_LOGGING" in
|
||||||
on|off|low|medium|high|full)
|
on|off|low|medium|high|full)
|
||||||
# Valid logging type
|
# Valid logging type
|
||||||
local result=$(yes | sudo ufw logging $CFG_UFW_LOGGING)
|
local result=$(yes | runSystem ufw logging $CFG_UFW_LOGGING)
|
||||||
checkSuccess "Updating UFW Firewall Logging to $CFG_UFW_LOGGING"
|
checkSuccess "Updating UFW Firewall Logging to $CFG_UFW_LOGGING"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|||||||
@ -6,7 +6,7 @@ firewallClearLibrePortalRules()
|
|||||||
local total_cleared=0
|
local total_cleared=0
|
||||||
|
|
||||||
if [[ $EUID -eq 0 ]] && command -v ufw-docker &> /dev/null; then
|
if [[ $EUID -eq 0 ]] && command -v ufw-docker &> /dev/null; then
|
||||||
local libreportal_rules=$(sudo ufw-docker list 2>/dev/null | grep -E "(allow|deny)" || echo "")
|
local libreportal_rules=$(runSystem ufw-docker list 2>/dev/null | grep -E "(allow|deny)" || echo "")
|
||||||
if [[ -n "$libreportal_rules" ]]; then
|
if [[ -n "$libreportal_rules" ]]; then
|
||||||
echo "$libreportal_rules" | while read -r rule_line; do
|
echo "$libreportal_rules" | while read -r rule_line; do
|
||||||
if [[ $rule_line =~ (allow|deny)\ ([^[:space:]]+)\ ([^[:space:]]+) ]]; then
|
if [[ $rule_line =~ (allow|deny)\ ([^[:space:]]+)\ ([^[:space:]]+) ]]; then
|
||||||
@ -16,7 +16,7 @@ firewallClearLibrePortalRules()
|
|||||||
|
|
||||||
# Only clear LibrePortal app rules (not system rules)
|
# Only clear LibrePortal app rules (not system rules)
|
||||||
if [[ -d "$containers_dir/$container" ]]; then
|
if [[ -d "$containers_dir/$container" ]]; then
|
||||||
local result=$(sudo ufw-docker delete "$action" "$container" "$port_spec" 2>&1)
|
local result=$(runSystem ufw-docker delete "$action" "$container" "$port_spec" 2>&1)
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
((total_cleared++))
|
((total_cleared++))
|
||||||
isSuccessful "Cleared: $action $container $port_spec"
|
isSuccessful "Cleared: $action $container $port_spec"
|
||||||
@ -31,7 +31,7 @@ firewallClearLibrePortalRules()
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
elif command -v ufw &> /dev/null; then
|
elif command -v ufw &> /dev/null; then
|
||||||
local libreportal_rules=$(sudo ufw status numbered 2>/dev/null | grep -E "ALLOW.*LibrePortal" || echo "")
|
local libreportal_rules=$(runSystem ufw status numbered 2>/dev/null | grep -E "ALLOW.*LibrePortal" || echo "")
|
||||||
|
|
||||||
if [[ -n "$libreportal_rules" ]]; then
|
if [[ -n "$libreportal_rules" ]]; then
|
||||||
echo "$libreportal_rules" | while read -r rule_line; do
|
echo "$libreportal_rules" | while read -r rule_line; do
|
||||||
@ -40,7 +40,7 @@ firewallClearLibrePortalRules()
|
|||||||
local action="${BASH_REMATCH[2]}"
|
local action="${BASH_REMATCH[2]}"
|
||||||
local port_spec="${BASH_REMATCH[3]}"
|
local port_spec="${BASH_REMATCH[3]}"
|
||||||
|
|
||||||
local result=$(sudo ufw --force delete "$rule_num" 2>&1)
|
local result=$(runSystem ufw --force delete "$rule_num" 2>&1)
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
((total_cleared++))
|
((total_cleared++))
|
||||||
isNotice "Cleared rule #$rule_num: $action $port_spec"
|
isNotice "Cleared rule #$rule_num: $action $port_spec"
|
||||||
|
|||||||
@ -37,26 +37,26 @@ hostSshEnsureDir()
|
|||||||
u=$(hostSshUser)
|
u=$(hostSshUser)
|
||||||
sshdir="$(hostSshHome)/.ssh"
|
sshdir="$(hostSshHome)/.ssh"
|
||||||
akf=$(hostSshAuthKeysFile)
|
akf=$(hostSshAuthKeysFile)
|
||||||
sudo mkdir -p "$sshdir"
|
runSystem mkdir -p "$sshdir"
|
||||||
sudo touch "$akf"
|
runSystem touch "$akf"
|
||||||
sudo chmod 700 "$sshdir"
|
runSystem chmod 700 "$sshdir"
|
||||||
sudo chmod 600 "$akf"
|
runSystem chmod 600 "$akf"
|
||||||
sudo chown -R "$u":"$u" "$sshdir"
|
runSystem chown -R "$u":"$u" "$sshdir"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Count valid authorized public keys.
|
# Count valid authorized public keys.
|
||||||
hostSshKeyCount()
|
hostSshKeyCount()
|
||||||
{
|
{
|
||||||
local akf; akf=$(hostSshAuthKeysFile)
|
local akf; akf=$(hostSshAuthKeysFile)
|
||||||
sudo test -f "$akf" || { echo 0; return; }
|
runSystem test -f "$akf" || { echo 0; return; }
|
||||||
sudo grep -cvE '^[[:space:]]*($|#)' "$akf" 2>/dev/null || echo 0
|
runSystem grep -cvE '^[[:space:]]*($|#)' "$akf" 2>/dev/null || echo 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# True when sshd currently allows password authentication.
|
# True when sshd currently allows password authentication.
|
||||||
hostSshPasswordAuthEnabled()
|
hostSshPasswordAuthEnabled()
|
||||||
{
|
{
|
||||||
local v
|
local v
|
||||||
v=$(sudo sshd -T 2>/dev/null | awk '/^passwordauthentication/ {print $2}')
|
v=$(runSystem sshd -T 2>/dev/null | awk '/^passwordauthentication/ {print $2}')
|
||||||
[[ -z "$v" ]] && v=$(grep -iE '^[[:space:]]*PasswordAuthentication' "$sshd_config" 2>/dev/null | tail -1 | awk '{print tolower($2)}')
|
[[ -z "$v" ]] && v=$(grep -iE '^[[:space:]]*PasswordAuthentication' "$sshd_config" 2>/dev/null | tail -1 | awk '{print tolower($2)}')
|
||||||
[[ "$v" == "no" ]] && return 1
|
[[ "$v" == "no" ]] && return 1
|
||||||
return 0 # default-on when unspecified
|
return 0 # default-on when unspecified
|
||||||
@ -81,14 +81,14 @@ hostSshKeyAdd()
|
|||||||
local akf body
|
local akf body
|
||||||
akf=$(hostSshAuthKeysFile)
|
akf=$(hostSshAuthKeysFile)
|
||||||
body=$(awk '{print $2}' <<< "$pub")
|
body=$(awk '{print $2}' <<< "$pub")
|
||||||
if sudo grep -qF "$body" "$akf" 2>/dev/null; then
|
if runSystem grep -qF "$body" "$akf" 2>/dev/null; then
|
||||||
isNotice "That key is already authorized."
|
isNotice "That key is already authorized."
|
||||||
else
|
else
|
||||||
printf '%s\n' "$pub" | sudo tee -a "$akf" >/dev/null
|
printf '%s\n' "$pub" | runSystem tee -a "$akf" >/dev/null
|
||||||
isSuccessful "SSH key authorized for $(hostSshUser)"
|
isSuccessful "SSH key authorized for $(hostSshUser)"
|
||||||
fi
|
fi
|
||||||
sudo chown "$(hostSshUser)":"$(hostSshUser)" "$akf"
|
runSystem chown "$(hostSshUser)":"$(hostSshUser)" "$akf"
|
||||||
sudo chmod 600 "$akf"
|
runSystem chmod 600 "$akf"
|
||||||
hostSshRefreshUi
|
hostSshRefreshUi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ hostSshKeyRemove()
|
|||||||
local fp="$1"
|
local fp="$1"
|
||||||
[[ -z "$fp" ]] && { isError "hostSshKeyRemove requires <fingerprint>"; return 1; }
|
[[ -z "$fp" ]] && { isError "hostSshKeyRemove requires <fingerprint>"; return 1; }
|
||||||
local akf; akf=$(hostSshAuthKeysFile)
|
local akf; akf=$(hostSshAuthKeysFile)
|
||||||
sudo test -f "$akf" || { isError "No authorized_keys file"; return 1; }
|
runSystem test -f "$akf" || { isError "No authorized_keys file"; return 1; }
|
||||||
|
|
||||||
if ! hostSshPasswordAuthEnabled && [[ "$(hostSshKeyCount)" -le 1 ]]; then
|
if ! hostSshPasswordAuthEnabled && [[ "$(hostSshKeyCount)" -le 1 ]]; then
|
||||||
isError "Refusing to remove the last key while password login is disabled — you'd be locked out. Re-enable password login first."
|
isError "Refusing to remove the last key while password login is disabled — you'd be locked out. Re-enable password login first."
|
||||||
@ -117,12 +117,12 @@ hostSshKeyRemove()
|
|||||||
removed=1; continue
|
removed=1; continue
|
||||||
fi
|
fi
|
||||||
printf '%s\n' "$line" >> "$tmp"
|
printf '%s\n' "$line" >> "$tmp"
|
||||||
done < <(sudo cat "$akf")
|
done < <(runSystem cat "$akf")
|
||||||
|
|
||||||
if [[ "$removed" -eq 1 ]]; then
|
if [[ "$removed" -eq 1 ]]; then
|
||||||
sudo cp "$tmp" "$akf"
|
runSystem cp "$tmp" "$akf"
|
||||||
sudo chown "$(hostSshUser)":"$(hostSshUser)" "$akf"
|
runSystem chown "$(hostSshUser)":"$(hostSshUser)" "$akf"
|
||||||
sudo chmod 600 "$akf"
|
runSystem chmod 600 "$akf"
|
||||||
isSuccessful "Removed SSH key $fp"
|
isSuccessful "Removed SSH key $fp"
|
||||||
else
|
else
|
||||||
isNotice "No key matched fingerprint $fp"
|
isNotice "No key matched fingerprint $fp"
|
||||||
@ -148,16 +148,16 @@ hostSshSetPasswordAuth()
|
|||||||
|
|
||||||
local value="yes"; [[ "$want" == "off" ]] && value="no"
|
local value="yes"; [[ "$want" == "off" ]] && value="no"
|
||||||
local backup="${sshd_config}.libreportal.$(date +%s)"
|
local backup="${sshd_config}.libreportal.$(date +%s)"
|
||||||
sudo cp "$sshd_config" "$backup"
|
runSystem cp "$sshd_config" "$backup"
|
||||||
sudo sed -i '/^[[:space:]]*#\?[[:space:]]*PasswordAuthentication\b/d' "$sshd_config"
|
runSystem sed -i '/^[[:space:]]*#\?[[:space:]]*PasswordAuthentication\b/d' "$sshd_config"
|
||||||
echo "PasswordAuthentication $value" | sudo tee -a "$sshd_config" >/dev/null
|
echo "PasswordAuthentication $value" | runSystem tee -a "$sshd_config" >/dev/null
|
||||||
|
|
||||||
if ! sudo sshd -t 2>/dev/null; then
|
if ! runSystem sshd -t 2>/dev/null; then
|
||||||
isError "sshd config test failed — restoring backup, no change made."
|
isError "sshd config test failed — restoring backup, no change made."
|
||||||
sudo cp "$backup" "$sshd_config"
|
runSystem cp "$backup" "$sshd_config"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
sudo systemctl reload ssh 2>/dev/null || sudo systemctl reload sshd 2>/dev/null
|
runSystem systemctl reload ssh 2>/dev/null || runSystem systemctl reload sshd 2>/dev/null
|
||||||
isSuccessful "Password login ${want} (sshd reloaded; backup at $backup)"
|
isSuccessful "Password login ${want} (sshd reloaded; backup at $backup)"
|
||||||
hostSshRefreshUi
|
hostSshRefreshUi
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,7 @@ Environment=XDG_RUNTIME_DIR=/run/user/${libreportal_uid}"
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Create systemd service file
|
# Create systemd service file
|
||||||
sudo tee "$service_file" > /dev/null <<EOF
|
runSystem tee "$service_file" > /dev/null <<EOF
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=LibrePortal Task Processor
|
Description=LibrePortal Task Processor
|
||||||
After=network.target
|
After=network.target
|
||||||
@ -64,9 +64,9 @@ EOF
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Reload systemd and enable service
|
# Reload systemd and enable service
|
||||||
sudo systemctl daemon-reload
|
runSystem systemctl daemon-reload
|
||||||
sudo systemctl enable libreportal.service >/dev/null 2>&1
|
runSystem systemctl enable libreportal.service >/dev/null 2>&1
|
||||||
sudo systemctl start libreportal.service
|
runSystem systemctl start libreportal.service
|
||||||
|
|
||||||
isSuccessful "LibrePortal task processor service setup."
|
isSuccessful "LibrePortal task processor service setup."
|
||||||
fi
|
fi
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user