#!/usr/bin/env bash set -euo pipefail # === METADATA === SCRIPT_NAME="$(basename "$0")" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SKILL_ROOT="$(dirname "$SCRIPT_DIR")" # === CONFIGURATION === : "${NODE_NAME:=node-a}" : "${OPERATOR_NAME:=Unknown Operator}" : "${OPERATOR_EMAIL:=unknown@example.com}" : "${DOMAIN:=example.com}" : "${GITOPS_ROOT:=$HOME/infrastructure}" : "${TUNNEL_NAME:=$NODE_NAME-tunnel}" : "${OUTPUT_DIR:=$SKILL_ROOT/outputs}" # === FUNCTIONS === log_info() { echo "[INFO] $(date -Iseconds) $*"; } preflight() { GITOPS_ROOT="${GITOPS_ROOT/#\~/$HOME}" [[ -d "$OUTPUT_DIR" ]] || mkdir -p "$OUTPUT_DIR" } get_gpg_fingerprint() { gpg --list-keys --with-colons "$OPERATOR_EMAIL" 2>/dev/null | \ grep fpr | head -1 | cut -d: -f10 || echo "Not configured" } get_ssh_key_count() { ls -1 "$HOME/.ssh/id_"*"_${NODE_NAME}" 2>/dev/null | wc -l || echo "0" } get_pass_status() { if [[ -d "$HOME/.password-store" ]]; then echo "Initialized ($(cat "$HOME/.password-store/.gpg-id" 2>/dev/null || echo "unknown GPG ID"))" else echo "Not initialized" fi } get_tunnel_status() { if [[ -f "$HOME/.cloudflared/config-${TUNNEL_NAME}.yml" ]]; then echo "Configured" else echo "Not configured" fi } get_gitops_status() { local count=0 [[ -d "$GITOPS_ROOT/config.git" ]] && ((count++)) [[ -d "$GITOPS_ROOT/secrets.git" ]] && ((count++)) [[ -d "$GITOPS_ROOT/manifests.git" ]] && ((count++)) echo "$count/3 repositories" } main() { preflight log_info "Starting $SCRIPT_NAME..." local report="$OUTPUT_DIR/audit_report.md" local status_file="$OUTPUT_DIR/status_matrix.json" cat > "$report" < **Skill Version:** 1.0.0 --- ## Executive Summary This report documents the bootstrap operations performed on **$NODE_NAME** for sovereign EU infrastructure deployment. --- ## Components Status ### 1. Identity | Component | Status | |-----------|--------| | GPG Key | $(get_gpg_fingerprint) | | SSH Keys | $(get_ssh_key_count) key pair(s) | | SSH Config | $(grep -q "Host $NODE_NAME" "$HOME/.ssh/config" 2>/dev/null && echo "Updated" || echo "Not updated") | ### 2. Secrets Management | Component | Status | |-----------|--------| | Pass Store | $(get_pass_status) | | Location | ~/.password-store | ### 3. Cloudflare Tunnel | Component | Status | |-----------|--------| | Tunnel Name | $TUNNEL_NAME | | Configuration | $(get_tunnel_status) | | SSH Endpoint | ssh.$DOMAIN | ### 4. GitOps Repositories | Component | Status | |-----------|--------| | Repository Count | $(get_gitops_status) | | Root Directory | $GITOPS_ROOT | --- ## Verification Results $(if [[ -f "$status_file" ]]; then echo '```json' cat "$status_file" echo '```' else echo "Status matrix not found. Run 90_verify.sh first." fi) --- ## EU Compliance Declaration | Aspect | Value | |--------|-------| | Data Residency | EU (Ireland - Dublin) | | GDPR Applicable | Yes | | Jurisdiction | Irish Law | | Encryption | GPG (local keys only) | --- ## Rollback Procedures If any component needs to be reverted, use these scripts in order: 1. **Tunnel:** \`./scripts/rollback/undo_tunnel.sh\` 2. **GitOps:** \`./scripts/rollback/undo_gitops.sh\` 3. **SSH Config:** \`./scripts/rollback/undo_ssh_config.sh\` 4. **Identity:** \`./scripts/rollback/undo_identity.sh\` --- ## Next Steps 1. Test tunnel connectivity: \`\`\`bash cloudflared tunnel --config ~/.cloudflared/config-${TUNNEL_NAME}.yml run \`\`\` 2. Clone GitOps repositories: \`\`\`bash git clone $GITOPS_ROOT/config.git ~/config git clone $GITOPS_ROOT/secrets.git ~/secrets git clone $GITOPS_ROOT/manifests.git ~/manifests \`\`\` 3. Proceed to **node-hardening** skill for security configuration 4. Document this bootstrap in LAWCHAIN (if applicable) --- ## Artifact Locations | Artifact | Path | |----------|------| | Identity Manifest | $OUTPUT_DIR/identity_manifest.json | | Secrets Manifest | $OUTPUT_DIR/secrets_manifest.json | | Tunnel Config | $OUTPUT_DIR/tunnel_config.json | | GitOps Manifest | $OUTPUT_DIR/gitops_manifest.json | | Status Matrix | $OUTPUT_DIR/status_matrix.json | | This Report | $OUTPUT_DIR/audit_report.md | --- *Report generated by operator-bootstrap skill v1.0.0* *$(date -Iseconds)* EOF log_info "Audit report written to $report" # Display the report echo "" cat "$report" log_info "Completed $SCRIPT_NAME" } [[ "${BASH_SOURCE[0]}" == "$0" ]] && main "$@"