#!/bin/bash
#
# Credential Rotation Script
# 
# Per DoD/MilSpec requirements (NIST SP 800-53: SC-12, IA-5)
# This script assists with rotating credentials across the system
#
# Usage:
#   ./scripts/rotate-credentials.sh [credential-type]
#
# Credential types:
#   - jwt: JWT signing secret
#   - db: Database password
#   - keycloak: Keycloak client secret
#   - proxmox: Proxmox API tokens
#   - all: Rotate all credentials
#

set -euo pipefail

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Logging functions
log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# Generate a secure random secret
generate_secret() {
    local length=${1:-64}
    openssl rand -base64 $length | tr -d '\n' | head -c $length
}

# Rotate JWT secret
rotate_jwt_secret() {
    log_info "Rotating JWT secret..."
    
    local new_secret=$(generate_secret 64)
    
    # Update in environment or secret management system
    if [ -f .env ]; then
        if grep -q "^JWT_SECRET=" .env; then
            sed -i.bak "s/^JWT_SECRET=.*/JWT_SECRET=${new_secret}/" .env
            log_info "Updated JWT_SECRET in .env (backup created: .env.bak)"
        else
            echo "JWT_SECRET=${new_secret}" >> .env
            log_info "Added JWT_SECRET to .env"
        fi
    else
        log_warn ".env file not found. Please set JWT_SECRET=${new_secret} manually"
    fi
    
    # If using Kubernetes secrets
    if command -v kubectl &> /dev/null; then
        log_info "Updating Kubernetes secret..."
        kubectl create secret generic jwt-secret \
            --from-literal=secret="${new_secret}" \
            --dry-run=client -o yaml | kubectl apply -f -
    fi
    
    log_warn "IMPORTANT: Restart all services using JWT_SECRET after rotation"
    log_warn "All existing JWT tokens will be invalidated"
}

# Rotate database password
rotate_db_password() {
    log_info "Rotating database password..."
    
    local new_password=$(generate_secret 32)
    
    # Update in environment
    if [ -f .env ]; then
        if grep -q "^DB_PASSWORD=" .env; then
            sed -i.bak "s/^DB_PASSWORD=.*/DB_PASSWORD=${new_password}/" .env
            log_info "Updated DB_PASSWORD in .env (backup created: .env.bak)"
        else
            echo "DB_PASSWORD=${new_password}" >> .env
            log_info "Added DB_PASSWORD to .env"
        fi
    else
        log_warn ".env file not found. Please set DB_PASSWORD=${new_password} manually"
    fi
    
    # Update database password
    log_warn "IMPORTANT: You must update the database password manually:"
    log_warn "  ALTER USER postgres WITH PASSWORD '${new_password}';"
    
    # If using Kubernetes secrets
    if command -v kubectl &> /dev/null; then
        log_info "Updating Kubernetes secret..."
        kubectl create secret generic db-credentials \
            --from-literal=password="${new_password}" \
            --dry-run=client -o yaml | kubectl apply -f -
    fi
}

# Rotate Keycloak client secret
rotate_keycloak_secret() {
    log_info "Rotating Keycloak client secret..."
    
    local new_secret=$(generate_secret 32)
    
    if [ -f .env ]; then
        if grep -q "^KEYCLOAK_CLIENT_SECRET=" .env; then
            sed -i.bak "s/^KEYCLOAK_CLIENT_SECRET=.*/KEYCLOAK_CLIENT_SECRET=${new_secret}/" .env
            log_info "Updated KEYCLOAK_CLIENT_SECRET in .env (backup created: .env.bak)"
        else
            echo "KEYCLOAK_CLIENT_SECRET=${new_secret}" >> .env
            log_info "Added KEYCLOAK_CLIENT_SECRET to .env"
        fi
    else
        log_warn ".env file not found. Please set KEYCLOAK_CLIENT_SECRET=${new_secret} manually"
    fi
    
    log_warn "IMPORTANT: Update Keycloak client secret in Keycloak admin console"
    log_warn "All existing Keycloak sessions will be invalidated"
}

# Rotate Proxmox API tokens
rotate_proxmox_tokens() {
    log_info "Rotating Proxmox API tokens..."
    
    log_warn "Proxmox API tokens must be rotated manually:"
    log_warn "1. Log into Proxmox web interface"
    log_warn "2. Go to Datacenter -> Permissions -> API Tokens"
    log_warn "3. Revoke old tokens and create new ones"
    log_warn "4. Update tokens in Kubernetes secrets or configuration"
    
    # If using Kubernetes secrets
    if command -v kubectl &> /dev/null; then
        log_info "To update Kubernetes secret after creating new token:"
        log_info "  kubectl create secret generic proxmox-credentials \\"
        log_info "    --from-literal=credentials.json='{\"username\":\"root@pam\",\"token\":\"NEW_TOKEN\"}' \\"
        log_info "    --dry-run=client -o yaml | kubectl apply -f -"
    fi
}

# Main function
main() {
    local credential_type=${1:-all}
    
    log_info "Starting credential rotation (DoD/MilSpec compliance)"
    log_info "Credential type: ${credential_type}"
    
    case "${credential_type}" in
        jwt)
            rotate_jwt_secret
            ;;
        db|database)
            rotate_db_password
            ;;
        keycloak)
            rotate_keycloak_secret
            ;;
        proxmox)
            rotate_proxmox_tokens
            ;;
        all)
            log_info "Rotating all credentials..."
            rotate_jwt_secret
            echo ""
            rotate_db_password
            echo ""
            rotate_keycloak_secret
            echo ""
            rotate_proxmox_tokens
            ;;
        *)
            log_error "Unknown credential type: ${credential_type}"
            echo "Usage: $0 [jwt|db|keycloak|proxmox|all]"
            exit 1
            ;;
    esac
    
    log_info "Credential rotation complete"
    log_warn "Remember to:"
    log_warn "  1. Restart all affected services"
    log_warn "  2. Verify services are working correctly"
    log_warn "  3. Update any documentation with new rotation date"
    log_warn "  4. Archive old credentials securely (if required by policy)"
}

# Run main function
main "$@"

