mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-15 17:11:30 +00:00
fix: unblock the Ubuntu 26.04 installer (qemu-kvm, sudo-rs) (#665)
setup.sh aborts twice on resolute. qemu-kvm is a virtual package with two providers there, so apt refuses to resolve it; the token was redundant anyway since $QEMU_PACKAGES already installs qemu-system-x86/arm and spinifex execs the qemu-system-* binaries directly. sudo-rs, Ubuntu's default sudo since 25.10, then rejects the sudoers file: it implements no pam_session Defaults setting, and forbids a wildcard inside a command argument. pam_session is now emitted only for classic sudo, and the sysctl grant names a fixed-verb helper instead of a wildcard. The helper is narrower than the rule it replaces: it accepts one interface, a key restricted to rp_filter or accept_local, and a value restricted to 0 or 1, where the old grant permitted any net.ipv4.conf key at any value. Granting sysctl with an unconstrained argument was rejected as root-equivalent. Adds scripts/lint-apt-packages.sh and an Apt Packages workflow so the runtime package list is resolved against each supported suite's real indices in CI.
This commit is contained in:
+93
-12
@@ -24,6 +24,9 @@ set -e
|
||||
INSTALL_SPINIFEX_CHANNEL="${INSTALL_SPINIFEX_CHANNEL:-latest}"
|
||||
INSTALL_BASE_URL="${INSTALL_BASE_URL:-https://install.mulgadc.com}"
|
||||
|
||||
# Referenced by both the sudoers grant and the daemon, so the path is fixed here.
|
||||
ENDPOINT_SYSCTL_HELPER="/usr/local/lib/spinifex/spinifex-set-endpoint-sysctl"
|
||||
|
||||
# --- Colors ---
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
@@ -181,15 +184,76 @@ create_service_users() {
|
||||
}
|
||||
|
||||
# --- Install scoped sudoers rules ---
|
||||
# sudo-rs (Ubuntu's default sudo since 25.10) implements only a subset of
|
||||
# Defaults and rejects an unknown one outright, so pam_session must be omitted
|
||||
# there rather than emitted and ignored.
|
||||
sudo_is_sudo_rs() {
|
||||
sudo --version 2>/dev/null | head -1 | grep -qi 'sudo-rs'
|
||||
}
|
||||
|
||||
# The daemon only ever sets rp_filter and accept_local on an endpoint it just
|
||||
# created. A fixed-verb helper keeps that grant expressible without a wildcard,
|
||||
# which sudo-rs forbids inside command arguments.
|
||||
install_endpoint_sysctl_helper() {
|
||||
$SUDO install -d -m 0755 /usr/local/lib/spinifex
|
||||
$SUDO tee "${ENDPOINT_SYSCTL_HELPER}" > /dev/null << 'HELPER'
|
||||
#!/bin/sh
|
||||
# Sets one of two per-endpoint sysctls for the asymmetric IMDS reply path.
|
||||
# Interface, key and value are all constrained: this runs as root under a
|
||||
# NOPASSWD grant, so it must never pass an arbitrary key through to sysctl.
|
||||
set -eu
|
||||
|
||||
if [ "$#" -ne 3 ]; then
|
||||
echo "usage: $0 <interface> <rp_filter|accept_local> <0|1>" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
iface=$1
|
||||
key=$2
|
||||
value=$3
|
||||
|
||||
# Reject anything that is not a plain interface name, so the key cannot be
|
||||
# steered elsewhere in the sysctl tree with a "." or a "/".
|
||||
case "${iface}" in
|
||||
''|*[!A-Za-z0-9_-]*) echo "invalid interface: ${iface}" >&2; exit 2 ;;
|
||||
esac
|
||||
|
||||
case "${key}" in
|
||||
rp_filter|accept_local) ;;
|
||||
*) echo "key not permitted: ${key}" >&2; exit 2 ;;
|
||||
esac
|
||||
|
||||
case "${value}" in
|
||||
0|1) ;;
|
||||
*) echo "value not permitted: ${value}" >&2; exit 2 ;;
|
||||
esac
|
||||
|
||||
exec sysctl -qw "net.ipv4.conf.${iface}.${key}=${value}"
|
||||
HELPER
|
||||
$SUDO chown root:root "${ENDPOINT_SYSCTL_HELPER}"
|
||||
$SUDO chmod 0755 "${ENDPOINT_SYSCTL_HELPER}"
|
||||
}
|
||||
|
||||
install_sudoers() {
|
||||
stage "installing scoped sudoers rules"
|
||||
$SUDO tee /etc/sudoers.d/spinifex-network > /dev/null << 'SUDOERS'
|
||||
install_endpoint_sysctl_helper
|
||||
|
||||
if sudo_is_sudo_rs; then
|
||||
$SUDO tee /etc/sudoers.d/spinifex-network > /dev/null << 'SUDOERS'
|
||||
# pam_session is omitted: this host runs sudo-rs, which does not implement it.
|
||||
SUDOERS
|
||||
else
|
||||
$SUDO tee /etc/sudoers.d/spinifex-network > /dev/null << 'SUDOERS'
|
||||
# No PAM session for the service users. Every sudo call otherwise logs
|
||||
# "pam_limits: Could not set limit for 'core'": the units set LimitCORE=0 and
|
||||
# their CapabilityBoundingSet omits CAP_SYS_RESOURCE, so pam_limits cannot apply
|
||||
# the limits.conf default and warns. It also means sudo children inherit the
|
||||
# unit's rlimits rather than the system defaults, which is the RG-9 intent.
|
||||
Defaults:spinifex-daemon !pam_session
|
||||
SUDOERS
|
||||
fi
|
||||
|
||||
$SUDO tee -a /etc/sudoers.d/spinifex-network > /dev/null << 'SUDOERS'
|
||||
|
||||
# The OVS/OVN client tools are deliberately absent. They do all their work over
|
||||
# control sockets that setup-ovn.sh group-owns to `spinifex`, so they run as the
|
||||
@@ -208,11 +272,16 @@ Defaults:spinifex-daemon !pam_session
|
||||
|
||||
# Spinifex daemon: tap devices and OpenFlow rules. Its unit holds no
|
||||
# CAP_NET_ADMIN, so unlike vpcd it cannot drop these. ovs-ofctl installs the
|
||||
# per-tap IMDS datapath flows on br-imds; sysctl sets the per-endpoint
|
||||
# rp_filter/accept_local the asymmetric reply path needs.
|
||||
# per-tap IMDS datapath flows on br-imds; the sysctl helper sets the
|
||||
# per-endpoint rp_filter/accept_local the asymmetric reply path needs.
|
||||
spinifex-daemon ALL=(root) NOPASSWD: /sbin/ip, /usr/sbin/ip
|
||||
spinifex-daemon ALL=(root) NOPASSWD: /usr/bin/ovs-ofctl
|
||||
spinifex-daemon ALL=(root) NOPASSWD: /usr/sbin/sysctl -qw net.ipv4.conf.*
|
||||
SUDOERS
|
||||
|
||||
# Separate append so the prose above can stay in a quoted heredoc: it carries
|
||||
# backticks that an expanding one would run as command substitution.
|
||||
$SUDO tee -a /etc/sudoers.d/spinifex-network > /dev/null << SUDOERS
|
||||
spinifex-daemon ALL=(root) NOPASSWD: ${ENDPOINT_SYSCTL_HELPER}
|
||||
SUDOERS
|
||||
$SUDO chmod 0440 /etc/sudoers.d/spinifex-network
|
||||
$SUDO visudo -cf /etc/sudoers.d/spinifex-network || fatal "Invalid sudoers syntax in spinifex-network"
|
||||
@@ -224,6 +293,18 @@ SUDOERS
|
||||
# scripts/iso-builder/build/packages.list in the mulga repo. When you add,
|
||||
# remove, or change a runtime package here, review that file too — drift means
|
||||
# the ISO and `curl | bash` paths install different software.
|
||||
#
|
||||
# Hoisted out of the apt-get call so scripts/lint-apt-packages.sh can resolve the
|
||||
# same list against each supported suite. The arch-specific qemu package is
|
||||
# added by install_apt_deps from detect_arch.
|
||||
APT_RUNTIME_PACKAGES="nbdkit
|
||||
qemu-utils gdisk ovmf qemu-efi-aarch64 less
|
||||
libvirt-daemon-system libvirt-clients
|
||||
pciutils
|
||||
jq curl iproute2 netcat-openbsd wget unzip xz-utils file
|
||||
ovn-central ovn-host openvswitch-switch openvswitch-ipsec strongswan-charon dhcpcd-base
|
||||
chrony"
|
||||
|
||||
install_apt_deps() {
|
||||
stage "installing apt dependencies"
|
||||
if [ "${INSTALL_SPINIFEX_SKIP_APT}" = "1" ]; then
|
||||
@@ -232,14 +313,10 @@ install_apt_deps() {
|
||||
info "Installing system dependencies..."
|
||||
$SUDO apt-get update -qq
|
||||
|
||||
# Unquoted on purpose: both variables are whitespace-separated package lists.
|
||||
# shellcheck disable=SC2086
|
||||
DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq \
|
||||
nbdkit \
|
||||
$QEMU_PACKAGES qemu-utils gdisk qemu-kvm ovmf qemu-efi-aarch64 less \
|
||||
libvirt-daemon-system libvirt-clients \
|
||||
pciutils \
|
||||
jq curl iproute2 netcat-openbsd wget unzip xz-utils file \
|
||||
ovn-central ovn-host openvswitch-switch openvswitch-ipsec strongswan-charon dhcpcd-base \
|
||||
chrony \
|
||||
$QEMU_PACKAGES $APT_RUNTIME_PACKAGES \
|
||||
> /dev/null
|
||||
|
||||
info "System dependencies installed"
|
||||
@@ -879,4 +956,8 @@ main() {
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
# Guarded so the package lint can source this file for APT_RUNTIME_PACKAGES
|
||||
# without running the installer.
|
||||
if [ "${INSTALL_SPINIFEX_LIB_ONLY:-0}" != "1" ]; then
|
||||
main "$@"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user