Report enrollment failures with stage and exit status

This commit is contained in:
2026-10-04 13:07:13 +02:00
parent 4bdc2c366d
commit 13efdb2ad4
+29 -10
View File
@@ -283,6 +283,8 @@ DIR=$1; MANAGER=$2; AGENT_VERSION=$3; LOGIN=$4; CT_HOSTNAME=$5; WANT_TS=$6; WANT
SSH_ENABLED=$8; SSH_USER=$9; SSH_SUDO=${10}; SSH_NOPASSWD=${11}
TS_ACCEPT_DNS=${12}
RESUME_TS=${13}
STEP='Vorbereitung'
trap 'rc=$?; printf "FEHLER: %s (Status %s, Worker-Zeile %s).\n" "$STEP" "$rc" "$LINENO" >&2; exit "$rc"' ERR
case "$TS_ACCEPT_DNS" in 1) DNS_FLAG=true;; 0) DNS_FLAG=false;; *) exit 1;; esac
trap 'rm -f -- "$DIR/headscale.key" "$DIR/enrollment.pass" "$DIR/sudo.pass"' EXIT
export DEBIAN_FRONTEND=noninteractive
@@ -309,11 +311,13 @@ if [[ $WANT_TS == 0 && $RESUME_TS == 1 ]]; then
fi
[[ $JOIN_TS == 1 || $WANT_WZ == 1 || $SSH_ENABLED == 1 ]] || { echo 'Komponenten inzwischen vorhanden; nichts geaendert.'; exit 0; }
STEP='APT-Grundpakete'
apt-get -o DPkg::Lock::Timeout=120 update
apt-get -o DPkg::Lock::Timeout=120 install -y --no-install-recommends ca-certificates curl gnupg
install -d -m 755 /usr/share/keyrings /etc/apt/sources.list.d
if [[ $WANT_TS == 1 ]]; then
STEP='Tailscale-Installation'
# Isolate distribution variables: os-release also defines NAME and VERSION.
os_details=$( . /etc/os-release; printf '%s|%s' "$ID" "$VERSION_CODENAME")
IFS='|' read -r DISTRO_ID DISTRO_CODENAME <<<"$os_details"
@@ -329,6 +333,7 @@ if [[ $WANT_TS == 1 ]]; then
systemctl enable --now tailscaled
fi
if [[ $JOIN_TS == 1 ]]; then
STEP='Headscale-Anmeldung'
[[ -c /dev/net/tun && -s $DIR/headscale.key ]] || { echo 'TUN oder Headscale-Schluessel fehlt.' >&2; exit 1; }
# File reference keeps the key out of command arguments/history.
timeout 90 tailscale up --login-server="$LOGIN" --auth-key="file:$DIR/headscale.key" --hostname="$CT_HOSTNAME" --accept-dns="$DNS_FLAG" --timeout=60s
@@ -339,9 +344,11 @@ fi
# Explicitly accepted DNS settings may also enable MagicDNS on an existing client.
# Do not disable or reauthenticate an existing client when this option is declined.
STEP='Headscale-DNS'
if [[ $TS_ACCEPT_DNS == 1 && $WANT_TS == 0 ]]; then tailscale set --accept-dns=true; fi
if [[ $WANT_WZ == 1 ]]; then
STEP='Wazuh-Installation und Verbindung'
# A Headscale manager IP only becomes reachable after the new client joins.
for port in 1514 1515; do
timeout 5 bash -c 'exec 7<>/dev/tcp/$1/$2' -- "$MANAGER" "$port" || {
@@ -383,6 +390,7 @@ if [[ $WANT_WZ == 1 ]]; then
fi
if [[ $SSH_ENABLED == 1 ]]; then
STEP='Tailscale-SSH und Nutzer'
if [[ $SSH_SUDO == 1 ]]; then apt-get -o DPkg::Lock::Timeout=120 install -y --no-install-recommends sudo; fi
new_user=0
if id "$SSH_USER" >/dev/null 2>&1; then
@@ -415,29 +423,40 @@ fi
WORKER
}
deploy_step() {
local id=$1 step=$2 rc
shift 2
if "$@"; then return 0
else
rc=$?
say "LXC $id: $step fehlgeschlagen (Status $rc)." >&2
return 1
fi
}
deploy_one() {
local id=$1 dir ts wz
[[ $(pct status "$id") == 'status: running' ]] || return 1
[[ $(pct status "$id") == 'status: running' ]] || { say "LXC $id: Container nicht mehr laufend." >&2; return 1; }
if pct config "$id" | grep -q '^lock:'; then say "LXC $id inzwischen gesperrt."; return 1; fi
ts=$((1-${TS[$id]})); wz=$((1-${WZ[$id]}))
if [[ ( $ts == 1 || $RESUME_TS == 1 ) && ${TUN[$id]} == 0 ]]; then ensure_tun "$id" || return 1; fi
dir=$(pct exec "$id" -- mktemp -d /run/lxc-enroll.XXXXXXXX) || return 1
[[ $dir =~ ^/run/lxc-enroll\.[A-Za-z0-9]+$ ]] || return 1
if [[ ( $ts == 1 || $RESUME_TS == 1 ) && ${TUN[$id]} == 0 ]]; then deploy_step "$id" 'TUN-Einrichtung/Neustart' ensure_tun "$id" || return 1; fi
dir=$(deploy_step "$id" 'Temporäres Verzeichnis' pct exec "$id" -- mktemp -d /run/lxc-enroll.XXXXXXXX) || return 1
[[ $dir =~ ^/run/lxc-enroll\.[A-Za-z0-9]+$ ]] || { say "LXC $id: Unerwarteter temporaerer Pfad." >&2; return 1; }
REMOTE_DIRS[$id]=$dir
pct push "$id" "$TMP/worker.sh" "$dir/worker.sh" --user 0 --group 0 --perms 600 || return 1
if [[ $ts == 1 || $RESUME_TS == 1 ]]; then pct push "$id" "$TMP/headscale.key" "$dir/headscale.key" --user 0 --group 0 --perms 600 || return 1; fi
if [[ $wz == 1 && -s $TMP/enrollment.pass ]]; then pct push "$id" "$TMP/enrollment.pass" "$dir/enrollment.pass" --user 0 --group 0 --perms 600 || return 1; fi
deploy_step "$id" 'Worker-Datei kopieren' pct push "$id" "$TMP/worker.sh" "$dir/worker.sh" --user 0 --group 0 --perms 600 || return 1
if [[ $ts == 1 || $RESUME_TS == 1 ]]; then deploy_step "$id" 'Headscale-Schluessel kopieren' pct push "$id" "$TMP/headscale.key" "$dir/headscale.key" --user 0 --group 0 --perms 600 || return 1; fi
if [[ $wz == 1 && -s $TMP/enrollment.pass ]]; then deploy_step "$id" 'Enrollment-Passwort kopieren' pct push "$id" "$TMP/enrollment.pass" "$dir/enrollment.pass" --user 0 --group 0 --perms 600 || return 1; fi
if [[ $SSH_ENABLED == 1 ]]; then
if [[ -s $TMP/sudo.pass ]]; then pct push "$id" "$TMP/sudo.pass" "$dir/sudo.pass" --user 0 --group 0 --perms 600 || return 1; fi
if [[ -s $TMP/sudo.pass ]]; then deploy_step "$id" 'Sudo-Passwort kopieren' pct push "$id" "$TMP/sudo.pass" "$dir/sudo.pass" --user 0 --group 0 --perms 600 || return 1; fi
fi
# Credentials are files, never pct arguments. bash receives only non-secret settings.
pct exec "$id" -- bash "$dir/worker.sh" "$dir" "$MANAGER" "$VERSION" "$LOGIN_SERVER" "${NAMES[$id]}" "$ts" "$wz" "$SSH_ENABLED" "$SSH_USER" "$SSH_SUDO" "$SSH_NOPASSWD" "$TS_ACCEPT_DNS" "$RESUME_TS" || return 1
deploy_step "$id" 'Einrichtung im Container' pct exec "$id" -- bash "$dir/worker.sh" "$dir" "$MANAGER" "$VERSION" "$LOGIN_SERVER" "${NAMES[$id]}" "$ts" "$wz" "$SSH_ENABLED" "$SSH_USER" "$SSH_SUDO" "$SSH_NOPASSWD" "$TS_ACCEPT_DNS" "$RESUME_TS" || return 1
if [[ $ts == 1 || $RESUME_TS == 1 ]]; then
pct exec "$id" -- tailscale status --json | python3 -c 'import json,sys; d=json.load(sys.stdin); sys.exit(0 if d.get("BackendState")=="Running" and d.get("Self",{}).get("Online") is True else 1)' || {
say "LXC $id: Headscale-Verbindung nicht als online bestaetigt."; return 1;
}
fi
pct exec "$id" -- rm -rf -- "$dir" || return 1
deploy_step "$id" 'Temporaere Dateien entfernen' pct exec "$id" -- rm -rf -- "$dir" || return 1
REMOTE_DIRS[$id]=''
}