#!/bin/bash # scripts/repair-bot/repair-bot-110.sh # 修復機器人白名單腳本 — 110 主機 (DevOps 金庫) # 2026-04-05 Claude Code: Sprint 3 Host Auto-Repair # # 安全設計: # - SSH authorized_keys 的 command= 指向此腳本 # - 只允許執行 COMPOSE_DIRS 中定義的修復指令 # - 格式: repair: # - SSH key 洩漏也只能執行白名單內的 docker compose up -d # # 部署位置: /home/wooo/bin/repair-bot-110.sh (on 192.168.0.110) # 使用者: wooo LOG="${HOME}/.repair-bot.log" log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG"; } # 白名單: component → compose dir declare -A COMPOSE_DIRS=( ["sentry"]="/opt/sentry" ["harbor"]="/home/wooo/harbor/harbor" ["gitea"]="/home/wooo/gitea" ["gitea-runner"]="/home/wooo/act-runner" ["langfuse"]="/home/wooo/langfuse" ["alertmanager"]="/home/wooo/monitoring" ["signoz"]="/home/wooo/signoz/deploy/docker" ) CMD="${SSH_ORIGINAL_COMMAND:-}" log "repair-bot-110 invoked: CMD=$CMD" if [[ "$CMD" =~ ^repair:([a-z0-9][a-z0-9-]{0,30})$ ]]; then # M3: 統一 Python 端 regex,禁止底線 COMPONENT="${BASH_REMATCH[1]}" DIR="${COMPOSE_DIRS[$COMPONENT]}" if [ -z "$DIR" ]; then log "DENIED: unknown component '$COMPONENT'" echo "REPAIR_DENIED:unknown_component:$COMPONENT" exit 1 fi if [ ! -d "$DIR" ]; then log "DENIED: directory not found '$DIR'" echo "REPAIR_DENIED:dir_not_found:$DIR" exit 1 fi log "EXECUTING: cd $DIR && docker compose up -d" cd "$DIR" && docker compose up -d 2>&1 | tail -5 EXIT_CODE=$? if [ $EXIT_CODE -eq 0 ]; then log "REPAIR_OK: $COMPONENT" echo "REPAIR_OK:$COMPONENT" else log "REPAIR_FAIL: $COMPONENT (exit $EXIT_CODE)" echo "REPAIR_FAIL:$COMPONENT:exit_$EXIT_CODE" exit 1 fi elif [ "$CMD" = "health" ]; then # 健康檢查 — 允許連線測試 echo "REPAIR_BOT_HEALTHY:110" else log "DENIED: invalid command '$CMD'" echo "REPAIR_DENIED:invalid_command" exit 1 fi