#!/usr/bin/env bash # load-credentials.sh - Load credentials from .secrets file into rdev-api # # Usage: # ./scripts/load-credentials.sh # Load to localhost:8080 # ./scripts/load-credentials.sh https://rdev.example.com # Load to remote # RDEV_ADMIN_KEY=xxx ./scripts/load-credentials.sh # With explicit admin key # # Reads credentials from .secrets file (KEY=VALUE format) and uploads them # to the rdev-api /credentials/batch endpoint. set -euo pipefail # Configuration RDEV_API_URL="${1:-http://localhost:8080}" SECRETS_FILE="${SECRETS_FILE:-.secrets}" ADMIN_KEY="${RDEV_ADMIN_KEY:-}" # Colors for 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"; } # Check for required tools if ! command -v curl &> /dev/null; then log_error "curl is required but not installed" exit 1 fi if ! command -v jq &> /dev/null; then log_error "jq is required but not installed" exit 1 fi # Check secrets file exists if [[ ! -f "$SECRETS_FILE" ]]; then log_error "Secrets file not found: $SECRETS_FILE" log_info "Create a .secrets file with KEY=VALUE pairs, e.g.:" echo " GITEA_TOKEN=your-token-here" echo " CLOUDFLARE_API_TOKEN=your-token-here" exit 1 fi # Get admin key if not provided if [[ -z "$ADMIN_KEY" ]]; then # Try to get from K8s secret if command -v kubectl &> /dev/null; then ADMIN_KEY=$(kubectl get secret rdev-credentials -n rdev -o jsonpath='{.data.RDEV_ADMIN_KEY}' 2>/dev/null | base64 -d 2>/dev/null || true) fi if [[ -z "$ADMIN_KEY" ]]; then log_error "RDEV_ADMIN_KEY not set and could not retrieve from K8s" log_info "Set RDEV_ADMIN_KEY environment variable or ensure kubectl access to rdev namespace" exit 1 fi fi log_info "Loading credentials from $SECRETS_FILE to $RDEV_API_URL" # Map of secret keys to categories and descriptions declare -A CATEGORIES=( ["GITEA_TOKEN"]="gitea" ["GITEA_API_TOKEN"]="gitea" ["GITEA_URL"]="gitea" ["CLOUDFLARE_API_TOKEN"]="cloudflare" ["CLOUDFLARE_ZONE_ID"]="cloudflare" ["WOODPECKER_URL"]="woodpecker" ["WOODPECKER_API_TOKEN"]="woodpecker" ["WOODPECKER_WEBHOOK_SECRET"]="woodpecker" ["REGISTRY_URL"]="registry" ) declare -A DESCRIPTIONS=( ["GITEA_TOKEN"]="Gitea API access token" ["GITEA_API_TOKEN"]="Gitea API access token" ["GITEA_URL"]="Gitea server URL" ["CLOUDFLARE_API_TOKEN"]="Cloudflare API token for DNS management" ["CLOUDFLARE_ZONE_ID"]="Cloudflare zone ID for threesix.ai" ["WOODPECKER_URL"]="Woodpecker CI server URL" ["WOODPECKER_API_TOKEN"]="Woodpecker CI API token for repo activation" ["WOODPECKER_WEBHOOK_SECRET"]="HMAC secret for Woodpecker webhook verification" ["REGISTRY_URL"]="Container registry URL" ) # Build JSON payload from secrets file CREDENTIALS_JSON='{"credentials":[' FIRST=true while IFS='=' read -r key value || [[ -n "$key" ]]; do # Skip empty lines and comments [[ -z "$key" || "$key" =~ ^# ]] && continue # Trim whitespace key=$(echo "$key" | xargs) value=$(echo "$value" | xargs) # Skip if empty value [[ -z "$value" ]] && continue # Normalize key name (GITEA_API_TOKEN -> GITEA_TOKEN) if [[ "$key" == "GITEA_API_TOKEN" ]]; then key="GITEA_TOKEN" fi # Get category and description category="${CATEGORIES[$key]:-other}" description="${DESCRIPTIONS[$key]:-$key credential}" # Add comma if not first if [[ "$FIRST" == "true" ]]; then FIRST=false else CREDENTIALS_JSON+=',' fi # Escape value for JSON escaped_value=$(echo -n "$value" | jq -Rs '.') CREDENTIALS_JSON+="{\"key\":\"$key\",\"value\":$escaped_value,\"category\":\"$category\",\"description\":\"$description\"}" log_info " Prepared: $key ($category)" done < "$SECRETS_FILE" CREDENTIALS_JSON+=']}' # Count credentials CRED_COUNT=$(echo "$CREDENTIALS_JSON" | jq '.credentials | length') if [[ "$CRED_COUNT" == "0" ]]; then log_warn "No credentials found in $SECRETS_FILE" exit 0 fi log_info "Uploading $CRED_COUNT credentials..." # Upload to rdev-api RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$RDEV_API_URL/credentials/batch" \ -H "Content-Type: application/json" \ -H "X-API-Key: $ADMIN_KEY" \ -d "$CREDENTIALS_JSON") HTTP_CODE=$(echo "$RESPONSE" | tail -n1) BODY=$(echo "$RESPONSE" | sed '$d') if [[ "$HTTP_CODE" == "201" ]]; then log_info "Successfully uploaded credentials" echo "$BODY" | jq -r '.keys[]' 2>/dev/null | while read -r k; do echo " - $k" done else log_error "Failed to upload credentials (HTTP $HTTP_CODE)" echo "$BODY" | jq . 2>/dev/null || echo "$BODY" exit 1 fi log_info "Done! Credentials are now stored in rdev database." log_info "Restart rdev-api to reload infrastructure adapters with new credentials."