K-114: Input-Validierung in build.func + Mini-CI #5

Merged
l.kirchner merged 5 commits from k114/input-validierung-mini-ci into main 2026-06-12 16:40:38 +02:00
8 changed files with 95 additions and 5 deletions
Showing only changes of commit aa3ad2f716 - Show all commits
+1
View File
@@ -29,6 +29,7 @@ CRED_FILE="/root/authentik.credentials"
# ── base packages + Docker ────────────────────────────────────────────────────
setup_base_apt ca-certificates curl
configure_ssh_root_login
if ! command -v docker >/dev/null 2>&1; then
msg_info "Installing Docker (get.docker.com)..."
curl -fsSL https://get.docker.com | sh >/dev/null
+1
View File
@@ -19,6 +19,7 @@ DEVPI_PORT="3141"
# ── packages + user + dirs ───────────────────────────────────────────────────
setup_base_apt python3 python3-venv python3-pip
configure_ssh_root_login
create_system_user "$DEVPI_USER" "$DEVPI_HOME"
mkdir -p "$DEVPI_DATA"
+1
View File
@@ -36,6 +36,7 @@ CRED_FILE="/root/nexus-db.credentials"
# ── packages: PGDG repo + PostgreSQL 16 + pgvector ────────────────────────────
setup_base_apt curl ca-certificates gnupg lsb-release
configure_ssh_root_login
if [[ ! -f /etc/apt/sources.list.d/pgdg.sources ]] && [[ ! -f /etc/apt/sources.list.d/pgdg.list ]]; then
msg_info "Adding PGDG apt repo..."
+1
View File
@@ -46,6 +46,7 @@ run_user() { runuser -u "$APP_USER" -- env HOME="$APP_HOME" "$@"; }
# ── packages: git + rsync + sudo ; Node.js via NodeSource ─────────────────────
setup_base_apt git rsync sudo
configure_ssh_root_login
NODE_HAVE="$(command -v node >/dev/null 2>&1 && node -v | sed -E 's/^v([0-9]+).*/\1/' || echo 0)"
if [[ "$NODE_HAVE" != "$NODE_MAJOR" ]]; then
+1
View File
@@ -44,6 +44,7 @@ run_user() { runuser -u "$APP_USER" -- env HOME="$APP_HOME" "$@"; }
# ── packages: git + rsync + sudo ; Node.js via NodeSource ────────────────────
setup_base_apt git rsync sudo
configure_ssh_root_login
NODE_HAVE="$(command -v node >/dev/null 2>&1 && node -v | sed -E 's/^v([0-9]+).*/\1/' || echo 0)"
if [[ "$NODE_HAVE" != "$NODE_MAJOR" ]]; then
+24 -1
View File
@@ -147,6 +147,16 @@ is_cidr() {
is_ipcfg() { [[ "$1" == "dhcp" ]] || is_cidr "$1"; }
# Ja/Nein-Antworten (Prompts wie "… erlauben? [Y/n]"). Akzeptiert
# deutsch/englisch, normalize_yesno macht daraus kanonisch yes|no.
is_yesno() { is_clean_ascii "$1" && [[ "${1,,}" =~ ^(y|yes|j|ja|n|no|nein)$ ]]; }
normalize_yesno() {
case "${1,,}" in
y|yes|j|ja) printf 'yes' ;;
*) printf 'no' ;;
esac
}
# Space/comma-separated list of IPv4s (DNS prompt). Gesamtstring zuerst
# prüfen — die Wort-Splittung würde eingebettete Newlines sonst verstecken.
is_ipv4_list() {
@@ -311,6 +321,17 @@ prompt_lxc_config() {
else
msg_warn "No network profile for VLAN ${VLAN_TAG:-none}; DHCP DNS will be inherited."
fi
# SSH-Root-Login (Default: ja, Homelab-Komfort). Umgesetzt wird das im
# Install-Pfad per sshd-Drop-in (configure_ssh_root_login, lib/install.func);
# bootstrap_install_script reicht den normalisierten Wert in den Container.
if [[ -z "${SSH_ROOT_LOGIN:-}" ]]; then
prompt_validated SSH_ROOT_LOGIN "SSH-Root-Login erlauben? [Y/n]: " is_yesno "y"
else
require_valid SSH_ROOT_LOGIN is_yesno "SSH root login (y/n)"
fi
SSH_ROOT_LOGIN="$(normalize_yesno "$SSH_ROOT_LOGIN")"
echo " → SSH root login: $SSH_ROOT_LOGIN"
}
# ── template ─────────────────────────────────────────────────────────────────
@@ -408,7 +429,9 @@ bootstrap_install_script() {
pct exec "$CTID" -- bash -c "apt-get update -qq && apt-get install -y -qq curl ca-certificates >/dev/null"
msg_info "Running installer ($url)..."
pct exec "$CTID" -- bash -c "curl -fsSL '$url' -o /root/${APP}-install.sh && bash /root/${APP}-install.sh"
# SSH_ROOT_LOGIN ist durch normalize_yesno kanonisch yes|no — als Env in
# den Container durchreichen (configure_ssh_root_login wertet es aus).
pct exec "$CTID" -- bash -c "curl -fsSL '$url' -o /root/${APP}-install.sh && SSH_ROOT_LOGIN='${SSH_ROOT_LOGIN:-yes}' bash /root/${APP}-install.sh"
}
# ── summary ──────────────────────────────────────────────────────────────────
+30
View File
@@ -38,6 +38,36 @@ apt_cleanup() {
apt-get autoclean -qq >/dev/null || true
}
# ── ssh ──────────────────────────────────────────────────────────────────────
# SSH-Root-Login gemäß Host-Prompt (prompt_lxc_config setzt SSH_ROOT_LOGIN,
# bootstrap_install_script reicht es als Env durch; Default: yes).
# yes → PermitRootLogin yes (Passwort-Login mit dem generierten Root-Passwort)
# no → PermitRootLogin prohibit-password (Debian-Default, nur SSH-Key)
# Umsetzung als Drop-in, damit Paket-Updates von sshd_config nicht kollidieren.
configure_ssh_root_login() {
local choice="${SSH_ROOT_LOGIN:-yes}" value
case "$choice" in
yes) value="yes" ;;
no) value="prohibit-password" ;;
*) msg_err "SSH_ROOT_LOGIN must be yes|no, got: '$choice'"; return 1 ;;
esac
if [[ ! -d /etc/ssh/sshd_config.d ]]; then
if [[ "$choice" == "no" ]]; then
msg_warn "openssh-server not installed — nothing to configure (root login stays off)"
return 0
fi
msg_info "Installing openssh-server..."
apt-get install -y -qq openssh-server >/dev/null
fi
msg_info "Configuring SSH root login: PermitRootLogin $value"
printf 'PermitRootLogin %s\n' "$value" >/etc/ssh/sshd_config.d/zz-root-login.conf
systemctl reload ssh 2>/dev/null || systemctl restart ssh 2>/dev/null \
|| msg_warn "ssh.service not active yet — config applies on first start"
msg_ok "SSH root login: $choice"
}
# ── users / dirs ─────────────────────────────────────────────────────────────
create_system_user() {
local user="$1" home="$2"
+36 -4
View File
@@ -77,6 +77,38 @@ assert_false "is_hostname lehnt 'a b' ab" is_hostname "a b"
assert_true "is_token akzeptiert local-lvm" is_token "local-lvm"
assert_false "is_token lehnt 'a;b' ab" is_token "a;b"
# ── Ja/Nein (SSH-Root-Login-Prompt) ──────────────────────────────────────────
assert_true "is_yesno akzeptiert y" is_yesno "y"
assert_true "is_yesno akzeptiert Ja" is_yesno "Ja"
assert_true "is_yesno akzeptiert NO" is_yesno "NO"
assert_true "is_yesno akzeptiert nein" is_yesno "nein"
assert_false "is_yesno lehnt 'maybe' ab" is_yesno "maybe"
assert_false "is_yesno lehnt leeren Wert ab" is_yesno ""
[[ "$(normalize_yesno "J")" == "yes" && "$(normalize_yesno "nein")" == "no" ]] \
&& ok "normalize_yesno kanonisiert J→yes, nein→no" \
|| nok "normalize_yesno kanonisiert J→yes, nein→no"
# SSH-Root-Login-Prompt: leere Eingabe = Default Y → normalisiert yes;
# explizites 'n' → no.
ssh_default="$(
printf '\n' | {
SSH_ROOT_LOGIN=""
prompt_validated SSH_ROOT_LOGIN "SSH-Root-Login erlauben? [Y/n]: " is_yesno "y" >/dev/null 2>&1
normalize_yesno "$SSH_ROOT_LOGIN"
}
)"
[[ "$ssh_default" == "yes" ]] && ok "SSH-Root-Login: leere Eingabe → Default yes" \
|| nok "SSH-Root-Login Default (got: '$ssh_default')"
ssh_no="$(
printf 'n\n' | {
SSH_ROOT_LOGIN=""
prompt_validated SSH_ROOT_LOGIN "SSH-Root-Login erlauben? [Y/n]: " is_yesno "y" >/dev/null 2>&1
normalize_yesno "$SSH_ROOT_LOGIN"
}
)"
[[ "$ssh_no" == "no" ]] && ok "SSH-Root-Login: 'n' → no" \
|| nok "SSH-Root-Login 'n' (got: '$ssh_no')"
# ── require_valid: env-Werte werden sanitisiert + geprüft ────────────────────
CHECKVAL=$' 7\r'
require_valid CHECKVAL is_uint "Testwert" && [[ "$CHECKVAL" == "7" ]] \
@@ -145,12 +177,12 @@ ctid_out="$(
smoke_out="$(
env CTID=999 CT_HOSTNAME=smoke DISK_SIZE=8 CORES=2 RAM=1024 BRIDGE=vmbr0 \
VLAN_TAG=20 TEMPLATE_STORAGE=local ROOTFS_STORAGE=local-lvm \
IPCFG=10.11.20.99/24 GATEWAY=10.11.20.1 NAMESERVER="" \
IPCFG=10.11.20.99/24 GATEWAY=10.11.20.1 NAMESERVER="" SSH_ROOT_LOGIN=J \
NET_PROFILES_FILE="$REPO_ROOT/lib/networks.conf" \
bash -c "source '$REPO_ROOT/lib/build.func' && prompt_lxc_config >/dev/null && echo SMOKE-OK"
bash -c "source '$REPO_ROOT/lib/build.func' && prompt_lxc_config >/dev/null && echo SMOKE-OK:\$SSH_ROOT_LOGIN"
)" || true
[[ "$smoke_out" == *SMOKE-OK* ]] \
&& ok "prompt_lxc_config Dry-Run mit validen env-Werten läuft durch" \
[[ "$smoke_out" == *SMOKE-OK:yes* ]] \
&& ok "prompt_lxc_config Dry-Run mit validen env-Werten läuft durch (SSH_ROOT_LOGIN J→yes)" \
|| nok "prompt_lxc_config Dry-Run (got: '$smoke_out')"
smoke_bad="$(