Includes: - `bootstrap-debian13.yml` for system setup and user configuration - `firewall-iptables.yml` for IPv4 firewall management - `run-playbook.sh` and `check.sh` scripts for playbook execution and validation - `inventory.ini` for host definitions - Template for iptables rules at `templates/iptables/rules.v4.j2` - `README.md` with usage instructions
138 lines
4.1 KiB
Bash
Executable File
138 lines
4.1 KiB
Bash
Executable File
#!/bin/bash
|
||
# check.sh
|
||
# Usage:
|
||
# ./check.sh <playbook.yml> [inventory.ini] [limit]
|
||
# Examples:
|
||
# ./check.sh bootstrap-debian13.yml
|
||
# ./check.sh bootstrap-debian13.yml inventory.ini finlog_dev
|
||
# ./check.sh bootstrap-debian13.yml inventory.ini localdev.host.getfinlog.app
|
||
#
|
||
# Behavior:
|
||
# - Attempt 1: Dry-run with key auth as user ${SSH_KEY_USER:-bummsa}
|
||
# - If SSH/unreachable: Attempt 2 with --ask-pass as root and -e ansible_become=false
|
||
# - If still unreachable: exit 0 (treated as “validated”); otherwise propagate error
|
||
|
||
set -euo pipefail
|
||
|
||
PLAYBOOK="${1:-}"
|
||
INVENTORY="${2:-inventory.ini}"
|
||
LIMIT_ARG="${3:-}"
|
||
|
||
# default SSH key user (can override: SSH_KEY_USER=admin ./check.sh ...)
|
||
SSH_KEY_USER="${SSH_KEY_USER:-bummsa}"
|
||
|
||
if [ -z "$PLAYBOOK" ]; then
|
||
echo "Usage: $0 <playbook.yml> [inventory.ini] [limit]"
|
||
exit 1
|
||
fi
|
||
[ -f "$PLAYBOOK" ] || { echo "❌ Playbook not found: $PLAYBOOK"; exit 1; }
|
||
[ -f "$INVENTORY" ] || { echo "❌ Inventory not found: $INVENTORY"; exit 1; }
|
||
|
||
echo "🔍 Playbook: $PLAYBOOK"
|
||
echo "📂 Inventory: $INVENTORY"
|
||
[ -n "$LIMIT_ARG" ] && echo "🎯 Limit: $LIMIT_ARG"
|
||
echo "👤 Dry-run key user: $SSH_KEY_USER"
|
||
echo
|
||
|
||
# --- helpers ---
|
||
is_unreachable_output() {
|
||
grep -Eq 'UNREACHABLE!|Failed to connect to the host via ssh|Permission denied \(publickey,password\)|Permission denied, please try again|No route to host|Could not resolve hostname|Name or service not known|Host key verification failed' "$1"
|
||
}
|
||
|
||
PLAY_HAS_BECOME=false
|
||
if grep -Eq '^\s*become:\s*true\b' "$PLAYBOOK"; then
|
||
PLAY_HAS_BECOME=true
|
||
fi
|
||
|
||
ANSIBLE_LIMIT_OPTS=()
|
||
[ -n "$LIMIT_ARG" ] && ANSIBLE_LIMIT_OPTS=(--limit "$LIMIT_ARG")
|
||
|
||
# 1) YAML lint (soft)
|
||
if command -v yamllint >/dev/null 2>&1; then
|
||
echo "=== YAML Lint ==="
|
||
yamllint "$PLAYBOOK"
|
||
echo
|
||
else
|
||
echo "⚠️ yamllint not installed, skipping…"
|
||
echo
|
||
fi
|
||
|
||
# 2) ansible-lint (soft)
|
||
if command -v ansible-lint >/dev/null 2>&1; then
|
||
echo "=== Ansible Lint ==="
|
||
ansible-lint "$PLAYBOOK"
|
||
echo
|
||
else
|
||
echo "⚠️ ansible-lint not installed, skipping…"
|
||
echo
|
||
fi
|
||
|
||
# 3) Inventory check (hard)
|
||
echo "=== Inventory Validation ==="
|
||
ansible-inventory -i "$INVENTORY" --list >/dev/null
|
||
echo "✅ Inventory OK"
|
||
echo
|
||
|
||
# 4) Syntax check (hard)
|
||
echo "=== Ansible Syntax Check ==="
|
||
ansible-playbook -i "$INVENTORY" "${ANSIBLE_LIMIT_OPTS[@]}" -u "$SSH_KEY_USER" "$PLAYBOOK" --syntax-check
|
||
echo "✅ Syntax OK"
|
||
echo
|
||
|
||
# 5) Targets info (soft)
|
||
echo "=== Target Hosts (per play) ==="
|
||
ansible-playbook -i "$INVENTORY" "${ANSIBLE_LIMIT_OPTS[@]}" -u "$SSH_KEY_USER" "$PLAYBOOK" --list-hosts || true
|
||
echo
|
||
|
||
# 6) Dry run – Attempt 1 (Key as $SSH_KEY_USER)
|
||
echo "=== Dry Run (Check Mode) — Attempt 1 (Key as $SSH_KEY_USER) ==="
|
||
TMP1="$(mktemp)"
|
||
set +e
|
||
ansible-playbook -i "$INVENTORY" "${ANSIBLE_LIMIT_OPTS[@]}" -u "$SSH_KEY_USER" "$PLAYBOOK" --check --diff 2>&1 | tee "$TMP1"
|
||
RC1=${PIPESTATUS[0]}
|
||
set -e
|
||
|
||
if [ $RC1 -eq 0 ]; then
|
||
echo
|
||
echo "✅ Dry Run erfolgreich (Key as $SSH_KEY_USER)"
|
||
exit 0
|
||
fi
|
||
|
||
# 7) Fallback — Attempt 2 (Password as root, no become)
|
||
if is_unreachable_output "$TMP1"; then
|
||
echo
|
||
echo "⚠️ Host unreachable/SSH failed im ersten Versuch."
|
||
if [ -t 0 ]; then
|
||
echo "🔁 Starte zweiten Versuch mit Passwort-Login (als root, ohne become)…"
|
||
TMP2="$(mktemp)"
|
||
set +e
|
||
ansible-playbook -i "$INVENTORY" "${ANSIBLE_LIMIT_OPTS[@]}" "$PLAYBOOK" --check --diff --ask-pass -u root -e ansible_become=false 2>&1 | tee "$TMP2"
|
||
RC2=${PIPESTATUS[0]}
|
||
set -e
|
||
|
||
if [ $RC2 -eq 0 ]; then
|
||
echo
|
||
echo "✅ Dry Run erfolgreich (Password-Fallback als root)"
|
||
exit 0
|
||
fi
|
||
|
||
if is_unreachable_output "$TMP2"; then
|
||
echo
|
||
echo "⚠️ Auch mit Passwort-Fallback unreachable. Ignoriere für Dry-Run (Exit 0)."
|
||
echo " Tipp: Key verteilen (ssh-copy-id) oder Zugang prüfen."
|
||
exit 0
|
||
else
|
||
echo
|
||
echo "❌ Dry Run fehlgeschlagen (kein reiner SSH/Unreachable-Fehler)."
|
||
exit $RC2
|
||
fi
|
||
else
|
||
echo "ℹ️ Keine TTY verfügbar → kann kein Passwort abfragen. Ignoriere Unreachable für Dry-Run (Exit 0)."
|
||
exit 0
|
||
fi
|
||
else
|
||
echo
|
||
echo "❌ Dry Run fehlgeschlagen (kein SSH/Unreachable-Thema)."
|
||
exit $RC1
|
||
fi
|