#!/usr/bin/env bash set -euo pipefail # === METADATA === SCRIPT_NAME="$(basename "$0")" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SKILL_ROOT="$(dirname "$SCRIPT_DIR")" CHECKS_DIR="$SKILL_ROOT/checks" # === CONFIGURATION === : "${NODE_NAME:=node-a}" : "${OPERATOR_EMAIL:=}" : "${GITOPS_ROOT:=$HOME/infrastructure}" : "${TUNNEL_NAME:=$NODE_NAME-tunnel}" : "${OUTPUT_DIR:=$SKILL_ROOT/outputs}" # === FUNCTIONS === log_info() { echo "[INFO] $(date -Iseconds) $*"; } log_warn() { echo "[WARN] $(date -Iseconds) $*" >&2; } log_error() { echo "[ERROR] $(date -Iseconds) $*" >&2; } preflight() { GITOPS_ROOT="${GITOPS_ROOT/#\~/$HOME}" [[ -d "$OUTPUT_DIR" ]] || mkdir -p "$OUTPUT_DIR" } check_gpg() { if [[ -n "$OPERATOR_EMAIL" ]] && gpg --list-keys "$OPERATOR_EMAIL" &>/dev/null 2>&1; then echo "true" else echo "false" fi } check_ssh() { if [[ -f "$HOME/.ssh/id_ed25519_${NODE_NAME}" ]]; then echo "true" else echo "false" fi } check_pass() { if [[ -d "$HOME/.password-store" ]] && [[ -f "$HOME/.password-store/.gpg-id" ]]; then echo "true" else echo "false" fi } check_tunnel() { if [[ -f "$HOME/.cloudflared/${TUNNEL_NAME}.json" ]]; then echo "true" else echo "false" fi } check_gitops() { if [[ -d "$GITOPS_ROOT/config.git" ]] && \ [[ -d "$GITOPS_ROOT/secrets.git" ]] && \ [[ -d "$GITOPS_ROOT/manifests.git" ]]; then echo "true" else echo "false" fi } run_external_check() { local check_script="$1" if [[ -x "$CHECKS_DIR/$check_script" ]]; then if "$CHECKS_DIR/$check_script" &>/dev/null; then echo "true" else echo "false" fi else echo "skip" fi } generate_status_matrix() { local status_file="$OUTPUT_DIR/status_matrix.json" local gpg_ok=$(check_gpg) local ssh_ok=$(check_ssh) local pass_ok=$(check_pass) local tunnel_ok=$(check_tunnel) local gitops_ok=$(check_gitops) # Build arrays for JSON local blockers="" local warnings="" local next_steps="" if [[ "$gpg_ok" == "false" ]]; then blockers="${blockers}\"GPG key not found for $OPERATOR_EMAIL\"," fi if [[ "$ssh_ok" == "false" ]]; then blockers="${blockers}\"SSH keys not found at ~/.ssh/id_ed25519_${NODE_NAME}\"," fi if [[ "$pass_ok" == "false" ]]; then warnings="${warnings}\"Pass store not initialized\"," fi if [[ "$tunnel_ok" == "false" ]]; then warnings="${warnings}\"Cloudflare tunnel not configured\"," fi if [[ "$gitops_ok" == "false" ]]; then warnings="${warnings}\"GitOps repositories not created\"," fi if [[ "$tunnel_ok" == "true" ]]; then next_steps="${next_steps}\"Test tunnel: cloudflared tunnel --config ~/.cloudflared/config-${TUNNEL_NAME}.yml run\"," fi if [[ "$gitops_ok" == "true" ]]; then next_steps="${next_steps}\"Clone repos: git clone $GITOPS_ROOT/config.git ~/config\"," fi if [[ "$gpg_ok" == "true" ]] && [[ "$ssh_ok" == "true" ]]; then next_steps="${next_steps}\"Proceed to node-hardening skill\"," fi # Remove trailing commas and wrap in arrays blockers="[${blockers%,}]" warnings="[${warnings%,}]" next_steps="[${next_steps%,}]" cat > "$status_file" <