#!/bin/bash # ============================================ # Woodpecker OAuth Credentials Sync Script # ============================================ # Dieses Script synchronisiert die Woodpecker OAuth-Credentials # zwischen Gitea, Vault und der .env-Datei. # # Verwendung: # ./scripts/sync-woodpecker-credentials.sh [--regenerate] # # Optionen: # --regenerate Erstellt neue OAuth-Credentials # # Das Script: # 1. Liest die aktuellen Credentials aus Vault # 2. Aktualisiert die .env-Datei # 3. Optional: Erstellt neue Credentials in Gitea # ============================================ set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" ENV_FILE="$PROJECT_DIR/.env" # Vault Konfiguration VAULT_ADDR="${VAULT_ADDR:-http://localhost:8200}" VAULT_TOKEN="${VAULT_DEV_TOKEN:-breakpilot-dev-token}" VAULT_SECRET_PATH="secret/cicd/woodpecker" # Gitea Konfiguration GITEA_URL="${GITEA_URL:-http://macmini:3003}" GITEA_API_TOKEN_PATH="secret/cicd/api-tokens" # Farben für Output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color log_info() { echo -e "${GREEN}[INFO]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } # Prüfe ob Docker verfügbar ist check_docker() { if command -v docker &> /dev/null; then DOCKER_CMD="docker" elif [ -x "/usr/local/bin/docker" ]; then DOCKER_CMD="/usr/local/bin/docker" else log_error "Docker nicht gefunden" exit 1 fi } # Hole Credentials aus Vault get_vault_credentials() { log_info "Lade Credentials aus Vault..." VAULT_RESPONSE=$($DOCKER_CMD exec -e VAULT_TOKEN="$VAULT_TOKEN" breakpilot-pwa-vault \ vault kv get -format=json "$VAULT_SECRET_PATH" 2>/dev/null || echo "{}") if echo "$VAULT_RESPONSE" | grep -q "gitea_client_id"; then GITEA_CLIENT_ID=$(echo "$VAULT_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['data']['gitea_client_id'])") GITEA_CLIENT_SECRET=$(echo "$VAULT_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['data']['gitea_client_secret'])") log_info "Credentials aus Vault geladen" return 0 else log_warn "Keine Credentials in Vault gefunden" return 1 fi } # Aktualisiere .env Datei update_env_file() { log_info "Aktualisiere .env Datei..." if [ -z "$GITEA_CLIENT_ID" ] || [ -z "$GITEA_CLIENT_SECRET" ]; then log_error "Credentials nicht verfügbar" return 1 fi # Erstelle Backup cp "$ENV_FILE" "$ENV_FILE.backup" # Aktualisiere oder füge WOODPECKER_GITEA_CLIENT hinzu if grep -q "^WOODPECKER_GITEA_CLIENT=" "$ENV_FILE"; then sed -i.tmp "s|^WOODPECKER_GITEA_CLIENT=.*|WOODPECKER_GITEA_CLIENT=$GITEA_CLIENT_ID|" "$ENV_FILE" else echo "WOODPECKER_GITEA_CLIENT=$GITEA_CLIENT_ID" >> "$ENV_FILE" fi # Aktualisiere oder füge WOODPECKER_GITEA_SECRET hinzu if grep -q "^WOODPECKER_GITEA_SECRET=" "$ENV_FILE"; then sed -i.tmp "s|^WOODPECKER_GITEA_SECRET=.*|WOODPECKER_GITEA_SECRET=$GITEA_CLIENT_SECRET|" "$ENV_FILE" else echo "WOODPECKER_GITEA_SECRET=$GITEA_CLIENT_SECRET" >> "$ENV_FILE" fi rm -f "$ENV_FILE.tmp" log_info ".env aktualisiert" } # Erstelle neue OAuth-Credentials in Gitea regenerate_credentials() { log_info "Erstelle neue OAuth-Credentials..." # Hole Gitea API Token aus Vault API_TOKEN_RESPONSE=$($DOCKER_CMD exec -e VAULT_TOKEN="$VAULT_TOKEN" breakpilot-pwa-vault \ vault kv get -format=json "$GITEA_API_TOKEN_PATH" 2>/dev/null) GITEA_API_TOKEN=$(echo "$API_TOKEN_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['data']['gitea_token'])") # Generiere neue Credentials NEW_CLIENT_ID=$(uuidgen | tr '[:upper:]' '[:lower:]') NEW_CLIENT_SECRET=$(openssl rand -hex 32) # Erstelle bcrypt Hash für das Secret HASHED_SECRET=$($DOCKER_CMD run --rm alpine sh -c "apk add --no-cache apache2-utils >/dev/null 2>&1 && htpasswd -nbBC 10 '' '$NEW_CLIENT_SECRET' | cut -d: -f2 | sed 's/^\$2y/\$2a/'") HASHED_SECRET_B64=$(echo -n "$HASHED_SECRET" | base64) # Lösche alte OAuth Apps $DOCKER_CMD exec breakpilot-pwa-postgres psql -U breakpilot -d gitea -c \ "DELETE FROM oauth2_application WHERE name = 'Woodpecker CI';" >/dev/null # Erstelle neue OAuth App TIMESTAMP=$(date +%s) $DOCKER_CMD exec breakpilot-pwa-postgres psql -U breakpilot -d gitea -c \ "INSERT INTO oauth2_application (uid, name, client_id, confidential_client, redirect_uris, created_unix, updated_unix) VALUES (1, 'Woodpecker CI', '$NEW_CLIENT_ID', true, '[\"http://macmini:8090/authorize\"]', $TIMESTAMP, $TIMESTAMP);" >/dev/null # Setze das gehashte Secret (via base64 decode um Shell-Escaping zu vermeiden) DECODED_HASH=$(echo "$HASHED_SECRET_B64" | base64 -d) $DOCKER_CMD exec breakpilot-pwa-postgres psql -U breakpilot -d gitea -c \ "UPDATE oauth2_application SET client_secret = '$DECODED_HASH' WHERE client_id = '$NEW_CLIENT_ID';" >/dev/null # Speichere in Vault $DOCKER_CMD exec -e VAULT_TOKEN="$VAULT_TOKEN" breakpilot-pwa-vault vault kv put "$VAULT_SECRET_PATH" \ gitea_client_id="$NEW_CLIENT_ID" \ gitea_client_secret="$NEW_CLIENT_SECRET" >/dev/null GITEA_CLIENT_ID="$NEW_CLIENT_ID" GITEA_CLIENT_SECRET="$NEW_CLIENT_SECRET" log_info "Neue Credentials erstellt und in Vault gespeichert" } # Hauptlogik main() { check_docker if [ "$1" == "--regenerate" ]; then regenerate_credentials else get_vault_credentials || regenerate_credentials fi update_env_file log_info "Credentials synchronisiert!" echo "" echo "Nächste Schritte:" echo "1. Sync .env zu macmini: rsync -av .env macmini:~/Projekte/breakpilot-pwa/" echo "2. Woodpecker neu starten: docker compose restart woodpecker-server" echo "3. Login testen: http://macmini:8090" } main "$@"