#!/bin/bash # deploy-argocd-secret.sh # ArgoCD-specific script to generate and deploy Django SECRET_KEY to vorgabenui namespace set -euo pipefail # ArgoCD-specific configuration (hardcoded for consistency) NAMESPACE="vorgabenui" SECRET_NAME="vorgabenui-secrets" SECRET_KEY_NAME="vorgabenui_secret" SCRIPT_DIR="$(dirname "$0")" ARGOCD_DIR="$SCRIPT_DIR/../argocd" TEMPLATES_DIR="$SCRIPT_DIR/../templates" SECRET_TEMPLATE="$TEMPLATES_DIR/secret.yaml" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' 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" } log_step() { echo -e "${BLUE}[STEP]${NC} $1" } # Function to generate a secure Django SECRET_KEY generate_secret_key() { # Generate a 50-character secret key using Python (same as Django's default) python3 -c " import secrets import string # Django-style secret key generation chars = string.ascii_letters + string.digits + '!@#$%^&*(-_=+)' print(''.join(secrets.choice(chars) for _ in range(50))) " } # Function to check if kubectl is available check_kubectl() { if ! command -v kubectl &> /dev/null; then log_error "kubectl is not installed or not in PATH" exit 1 fi } # Function to check if Python3 is available check_python() { if ! command -v python3 &> /dev/null; then log_error "python3 is not installed or not in PATH" exit 1 fi } # Function to check if secret template exists check_template() { if [ ! -f "$SECRET_TEMPLATE" ]; then # Fallback to argocd directory if templates directory doesn't exist FALLBACK_TEMPLATE="$ARGOCD_DIR/secret.yaml" if [ -f "$FALLBACK_TEMPLATE" ]; then SECRET_TEMPLATE="$FALLBACK_TEMPLATE" log_warn "Using fallback template: $SECRET_TEMPLATE" else log_error "Secret template not found at either:" log_error " Primary: $TEMPLATES_DIR/secret.yaml" log_error " Fallback: $FALLBACK_TEMPLATE" exit 1 fi fi } # Function to create the secret create_secret() { local secret_key="$1" log_step "Creating Kubernetes secret '$SECRET_NAME' in namespace '$NAMESPACE'..." # Create the secret directly with kubectl (this will create or update) kubectl create secret generic "$SECRET_NAME" \ --from-literal="$SECRET_KEY_NAME=$secret_key" \ --namespace="$NAMESPACE" \ --dry-run=client -o yaml | kubectl apply -f - if [ $? -eq 0 ]; then log_info "Successfully created/updated secret '$SECRET_NAME'" return 0 else log_error "Failed to create/update secret '$SECRET_NAME'" return 1 fi } # Function to verify the secret verify_secret() { log_step "Verifying secret deployment..." if kubectl get secret "$SECRET_NAME" --namespace="$NAMESPACE" &> /dev/null; then log_info "✅ Secret '$SECRET_NAME' exists in namespace '$NAMESPACE'" # Show secret metadata (without revealing the actual key) echo "" log_info "Secret details:" kubectl describe secret "$SECRET_NAME" --namespace="$NAMESPACE" | grep -E "^(Name|Namespace|Type|Data)" # Verify the key exists in the secret if kubectl get secret "$SECRET_NAME" --namespace="$NAMESPACE" -o jsonpath="{.data.$SECRET_KEY_NAME}" &> /dev/null; then log_info "✅ Secret key '$SECRET_KEY_NAME' is present in the secret" return 0 else log_error "❌ Secret key '$SECRET_KEY_NAME' not found in secret" return 1 fi else log_error "❌ Secret '$SECRET_NAME' not found in namespace '$NAMESPACE'" return 1 fi } # Function to test secret in pod (if deployment exists) test_secret_in_pod() { log_step "Testing secret accessibility in Django deployment..." # Check if Django deployment exists if kubectl get deployment django --namespace="$NAMESPACE" &> /dev/null; then log_info "Django deployment found, testing secret access..." # Try to get the secret value from a pod (this will fail if env var not configured) local pod_name pod_name=$(kubectl get pods -l app=django --namespace="$NAMESPACE" -o jsonpath="{.items[0].metadata.name}" 2>/dev/null) if [ -n "$pod_name" ] && [ "$pod_name" != "" ]; then log_info "Testing secret in pod: $pod_name" if kubectl exec "$pod_name" --namespace="$NAMESPACE" -- printenv VORGABENUI_SECRET &> /dev/null; then log_info "✅ VORGABENUI_SECRET environment variable is accessible in pod" else log_warn "⚠️ VORGABENUI_SECRET environment variable not found in pod" log_warn " This is expected if the deployment hasn't been updated yet" fi else log_warn "⚠️ No running Django pods found" fi else log_info "Django deployment not found - secret will be available when deployment is updated" fi } # Function to show usage show_usage() { echo "ArgoCD Secret Deployment Script for VorgabenUI" echo "" echo "Usage: $0 [OPTIONS]" echo "" echo "This script deploys Django SECRET_KEY to the vorgabenui namespace for ArgoCD." echo "" echo "Options:" echo " -h, --help Show this help message" echo " --verify-only Only verify existing secret, don't create new one" echo " --dry-run Show what would be done without making changes" echo "" echo "Configuration (hardcoded for ArgoCD):" echo " Namespace: $NAMESPACE" echo " Secret Name: $SECRET_NAME" echo " Secret Key: $SECRET_KEY_NAME" echo " Template: $SECRET_TEMPLATE" echo "" echo "Examples:" echo " $0 # Generate and deploy new secret" echo " $0 --verify-only # Verify existing secret" echo " $0 --dry-run # Preview changes" echo "" echo "After running this script, update argocd/deployment.yaml to reference the secret." } # Parse command line arguments VERIFY_ONLY=false DRY_RUN=false while [[ $# -gt 0 ]]; do case $1 in --verify-only) VERIFY_ONLY=true shift ;; --dry-run) DRY_RUN=true shift ;; -h|--help) show_usage exit 0 ;; *) log_error "Unknown option: $1" show_usage exit 1 ;; esac done # Main execution main() { echo "" log_info "🚀 ArgoCD Django SECRET_KEY Deployment Script" log_info "=============================================" echo "" log_info "Target Configuration:" log_info " Namespace: $NAMESPACE" log_info " Secret Name: $SECRET_NAME" log_info " Secret Key Name: $SECRET_KEY_NAME" echo "" # Perform checks log_step "Performing pre-flight checks..." check_kubectl check_python check_template log_info "✅ All pre-flight checks passed" echo "" # Verify-only mode if [ "$VERIFY_ONLY" = true ]; then log_info "🔍 Verify-only mode - checking existing secret" verify_secret test_secret_in_pod exit $? fi # Generate new secret key log_step "Generating new Django SECRET_KEY..." SECRET_KEY=$(generate_secret_key) if [ -z "$SECRET_KEY" ]; then log_error "Failed to generate secret key" exit 1 fi log_info "✅ Generated secret key (first 10 chars): ${SECRET_KEY:0:10}..." echo "" # Dry-run mode if [ "$DRY_RUN" = true ]; then log_info "🔍 Dry-run mode - showing what would be done:" echo "" log_info "Would create secret with the following command:" echo " kubectl create secret generic $SECRET_NAME \\" echo " --from-literal=$SECRET_KEY_NAME='[GENERATED_KEY]' \\" echo " --namespace=$NAMESPACE \\" echo " --dry-run=client -o yaml | kubectl apply -f -" echo "" log_info "Secret key would be: ${SECRET_KEY:0:10}...${SECRET_KEY: -5}" echo "" log_info "Run without --dry-run to execute the deployment" exit 0 fi # Create namespace if it doesn't exist if ! kubectl get namespace "$NAMESPACE" &> /dev/null; then log_warn "Namespace '$NAMESPACE' does not exist, creating..." kubectl create namespace "$NAMESPACE" log_info "✅ Created namespace '$NAMESPACE'" fi # Create the secret if create_secret "$SECRET_KEY"; then echo "" # Verify deployment verify_secret echo "" test_secret_in_pod echo "" log_info "🎉 Secret deployment completed successfully!" echo "" log_info "📋 Next steps:" log_info "1. Update argocd/deployment.yaml to include environment variable:" echo "" echo " env:" echo " - name: VORGABENUI_SECRET" echo " valueFrom:" echo " secretKeyRef:" echo " name: $SECRET_NAME" echo " key: $SECRET_KEY_NAME" echo "" log_info "2. Apply the updated deployment:" echo " kubectl apply -f argocd/deployment.yaml" echo "" log_info "3. Verify Django pods restart and pick up the new secret" echo "" else log_error "Secret deployment failed" exit 1 fi } # Run main function main