164 lines
5 KiB
Bash
164 lines
5 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
# =============================================================================
|
||
|
|
# ssh_context.sh
|
||
|
|
# Wird von den Deploy-Skripten gesourced.
|
||
|
|
# Stellt Target-Aufloesung und SSH-Setup bereit.
|
||
|
|
#
|
||
|
|
# Targets werden NICHT mehr hartkodiert, sondern aus Konfigurationsdateien unter
|
||
|
|
# targets/<target>.env geladen. Neue Targets legt man interaktiv mit ./init.sh an.
|
||
|
|
#
|
||
|
|
# Der SSH-Key (id_ed25519_forgejo) ist mit einer Passphrase verschluesselt.
|
||
|
|
# setup_ssh() laedt ihn in einen temporaeren ssh-agent; dabei wird die
|
||
|
|
# Passphrase einmalig abgefragt (Quelle: VaultWarden). Eine falsche Passphrase
|
||
|
|
# kann den Key nicht entschluesseln -> Abbruch, keine SSH/SFTP-Verbindung.
|
||
|
|
# Ein separates Passwort-Secret ist dadurch nicht mehr noetig.
|
||
|
|
# =============================================================================
|
||
|
|
|
||
|
|
# --- Pfade ---
|
||
|
|
CONTEXT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
|
TARGETS_DIR="${CONTEXT_DIR}/targets"
|
||
|
|
|
||
|
|
# --- Hilfsfunktion: verfuegbare Targets auflisten ---
|
||
|
|
# Eine einzige Quelle fuer die Target-Liste (keine duplizierten Strings mehr).
|
||
|
|
list_targets() {
|
||
|
|
local found=""
|
||
|
|
local f name
|
||
|
|
if [ -d "${TARGETS_DIR}" ]; then
|
||
|
|
for f in "${TARGETS_DIR}"/*.env; do
|
||
|
|
[ -e "$f" ] || continue
|
||
|
|
name="$(basename "$f" .env)"
|
||
|
|
# 'example' ist nur eine Vorlage und kein echtes Target.
|
||
|
|
[ "$name" = "example" ] && continue
|
||
|
|
found="${found:+${found}, }${name}"
|
||
|
|
done
|
||
|
|
fi
|
||
|
|
if [ -n "$found" ]; then
|
||
|
|
echo "Verfuegbare Targets: ${found}"
|
||
|
|
else
|
||
|
|
echo "Keine Targets konfiguriert. Lege eines mit ./init.sh an."
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# --- Target-Validierung ---
|
||
|
|
TARGET="${1:-}"
|
||
|
|
|
||
|
|
if [ -z "$TARGET" ]; then
|
||
|
|
echo "FEHLER: Target ist erforderlich."
|
||
|
|
echo "Verwendung: $0 <target>"
|
||
|
|
list_targets
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Target-Name auf sichere Zeichen beschraenken, bevor daraus ein Pfad gebaut
|
||
|
|
# wird (verhindert Path-Traversal wie '../' und das Laden beliebiger Dateien).
|
||
|
|
if ! printf '%s' "$TARGET" | grep -Eq '^[A-Za-z0-9._-]+$'; then
|
||
|
|
echo "FEHLER: Ungueltiger Target-Name '${TARGET}'."
|
||
|
|
echo "Erlaubt sind nur Buchstaben, Zahlen sowie '.', '_' und '-'."
|
||
|
|
list_targets
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# --- Target-Aufloesung (Config aus targets/<target>.env laden) ---
|
||
|
|
TARGET_FILE="${TARGETS_DIR}/${TARGET}.env"
|
||
|
|
|
||
|
|
if [ ! -f "${TARGET_FILE}" ]; then
|
||
|
|
echo "FEHLER: Unbekanntes Target '${TARGET}'."
|
||
|
|
list_targets
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# shellcheck disable=SC1090
|
||
|
|
source "${TARGET_FILE}"
|
||
|
|
|
||
|
|
# Pflichtfelder pruefen, damit kaputte Configs frueh auffallen.
|
||
|
|
for _var in SSH_HOST SFTP_HOST DB_NAME GIT_REMOTE DOMAIN; do
|
||
|
|
if [ -z "${!_var:-}" ]; then
|
||
|
|
echo "FEHLER: '${_var}' fehlt oder ist leer in ${TARGET_FILE}."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
unset _var
|
||
|
|
|
||
|
|
export TARGET SSH_HOST SFTP_HOST DB_NAME GIT_REMOTE DOMAIN
|
||
|
|
|
||
|
|
echo "Target: ${TARGET} (${DOMAIN})"
|
||
|
|
|
||
|
|
# --- SSH-Setup ---
|
||
|
|
setup_ssh() {
|
||
|
|
WORKSPACE_SSH_DIR="/home/runner/workspace/.ssh"
|
||
|
|
KEY_PATH="${WORKSPACE_SSH_DIR}/id_ed25519_forgejo"
|
||
|
|
local FORGEJO_SSH_PORT="2222"
|
||
|
|
SFTP_PORT="2022"
|
||
|
|
|
||
|
|
mkdir -p "${WORKSPACE_SSH_DIR}"
|
||
|
|
|
||
|
|
# SSH-Config fuer den aktuellen Host erstellen/aktualisieren
|
||
|
|
local TEMP_CONFIG
|
||
|
|
TEMP_CONFIG=$(mktemp)
|
||
|
|
|
||
|
|
if [ -f "${WORKSPACE_SSH_DIR}/config" ]; then
|
||
|
|
# Bestehende Eintraege fuer diesen Host entfernen
|
||
|
|
awk -v host="${SSH_HOST}" '
|
||
|
|
/^Host / { skip = ($2 == host); }
|
||
|
|
!skip { print; }
|
||
|
|
' "${WORKSPACE_SSH_DIR}/config" > "${TEMP_CONFIG}"
|
||
|
|
else
|
||
|
|
touch "${TEMP_CONFIG}"
|
||
|
|
fi
|
||
|
|
|
||
|
|
cat >> "${TEMP_CONFIG}" <<EOF
|
||
|
|
Host ${SSH_HOST}
|
||
|
|
HostName ${SSH_HOST}
|
||
|
|
Port ${FORGEJO_SSH_PORT}
|
||
|
|
User git
|
||
|
|
IdentityFile ${KEY_PATH}
|
||
|
|
StrictHostKeyChecking no
|
||
|
|
EOF
|
||
|
|
|
||
|
|
mv "${TEMP_CONFIG}" "${WORKSPACE_SSH_DIR}/config"
|
||
|
|
# Git speichert keine 0600-Rechte -> nach Checkout/Reset liegt der Key auf 0644,
|
||
|
|
# was ssh-add ablehnt. Rechte hier korrigieren und Fehler sichtbar machen.
|
||
|
|
if ! chmod 600 "${KEY_PATH}"; then
|
||
|
|
echo "FEHLER: Konnte Rechte auf ${KEY_PATH} nicht auf 600 setzen."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
chmod 644 "${WORKSPACE_SSH_DIR}/config"
|
||
|
|
|
||
|
|
# Symlinks ins Home-Verzeichnis
|
||
|
|
mkdir -p ~/.ssh
|
||
|
|
ln -sf "${WORKSPACE_SSH_DIR}/config" ~/.ssh/config
|
||
|
|
ln -sf "${KEY_PATH}" ~/.ssh/id_ed25519_forgejo
|
||
|
|
ln -sf "${KEY_PATH}.pub" ~/.ssh/id_ed25519_forgejo.pub
|
||
|
|
|
||
|
|
# --- Verschluesselten Key in ssh-agent laden (Passphrase-Abfrage) ---
|
||
|
|
if [ ! -f "${KEY_PATH}" ]; then
|
||
|
|
echo "FEHLER: SSH-Key nicht gefunden: ${KEY_PATH}"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# ssh-add fragt die Passphrase ueber das Terminal ab.
|
||
|
|
if [ ! -t 0 ]; then
|
||
|
|
echo "FEHLER: Kein interaktives Terminal. Skript muss manuell ausgefuehrt werden."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Frischen ssh-agent starten und beim Script-Ende automatisch beenden,
|
||
|
|
# damit der entschluesselte Key nur waehrend der Laufzeit im Speicher liegt.
|
||
|
|
eval "$(ssh-agent -s)" >/dev/null
|
||
|
|
trap 'ssh-agent -k >/dev/null 2>&1 || true' EXIT
|
||
|
|
|
||
|
|
echo "Lade SSH-Key in den Agent (Passphrase erforderlich; siehe VaultWarden)..."
|
||
|
|
if ! ssh-add "${KEY_PATH}"; then
|
||
|
|
echo "FEHLER: SSH-Key konnte nicht geladen werden (falsche Passphrase?)."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
echo "SSH-Key geladen."
|
||
|
|
|
||
|
|
echo "SSH-Setup fuer ${SSH_HOST} abgeschlossen."
|
||
|
|
|
||
|
|
# Exportiere Pfade fuer andere Skripte
|
||
|
|
export WORKSPACE_SSH_DIR KEY_PATH SFTP_PORT
|
||
|
|
}
|