#!/bin/bash # ============================================================================= # SACC v4 - Script de Destruccion de Entorno TEST # ============================================================================= # Destruye de forma SEGURA el entorno de pruebas en cuenta 668889063715 # # Este script: # 1. Pide confirmacion multiple # 2. Realiza backup de datos RDS # 3. Destruye recursos Terraform # 4. Limpia S3 (opcional) # 5. Muestra resumen de lo destruido # # USO: # export AWS_ACCESS_KEY_ID=... # export AWS_SECRET_ACCESS_KEY=... # export AWS_SESSION_TOKEN=... # export AWS_DEFAULT_REGION=mx-central-1 # ./destroy-test-environment.sh [opciones] # # OPCIONES: # --force Omitir confirmaciones (USAR CON PRECAUCION) # --skip-rds-backup Omitir backup de RDS # --delete-s3 Eliminar contenido de S3 antes de destruir # --keep-state No eliminar bucket de estado Terraform # ============================================================================= set -euo pipefail # Colores RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' BOLD='\033[1m' NC='\033[0m' # ============================================================================= # CONFIGURACION # ============================================================================= SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" TERRAFORM_DIR="$PROJECT_ROOT/terraform/environments/test" BACKUP_DIR="$PROJECT_ROOT/backups/rds-$(date +%Y%m%d-%H%M%S)" LOG_FILE="$PROJECT_ROOT/logs/destroy-$(date +%Y%m%d-%H%M%S).log" ACCOUNT_ID="668889063715" REGION="mx-central-1" mkdir -p "$(dirname "$LOG_FILE")" # Flags FORCE=false SKIP_RDS_BACKUP=false DELETE_S3=false KEEP_STATE=false # ============================================================================= # FUNCIONES # ============================================================================= log() { echo -e "${GREEN}[$(date '+%H:%M:%S')] OK:${NC} $1" | tee -a "$LOG_FILE" } warn() { echo -e "${YELLOW}[$(date '+%H:%M:%S')] WARN:${NC} $1" | tee -a "$LOG_FILE" } error() { echo -e "${RED}[$(date '+%H:%M:%S')] ERROR:${NC} $1" | tee -a "$LOG_FILE" } info() { echo -e "${BLUE}[$(date '+%H:%M:%S')] INFO:${NC} $1" | tee -a "$LOG_FILE" } fatal() { echo -e "${RED}${BOLD}[$(date '+%H:%M:%S')] FATAL:${NC} $1" | tee -a "$LOG_FILE" exit 1 } # ============================================================================= # PARSEAR ARGUMENTOS # ============================================================================= parse_args() { while [ $# -gt 0 ]; do case "$1" in --force) FORCE=true warn "Modo FORZADO activado - Se omitiran confirmaciones" ;; --skip-rds-backup) SKIP_RDS_BACKUP=true warn "Se omitira backup de RDS" ;; --delete-s3) DELETE_S3=true info "Se eliminara contenido de S3" ;; --keep-state) KEEP_STATE=true info "Se conservara bucket de estado Terraform" ;; --help) echo "Uso: $0 [opciones]" echo "" echo "Opciones:" echo " --force Omitir confirmaciones (USAR CON PRECAUCION)" echo " --skip-rds-backup Omitir backup de RDS" echo " --delete-s3 Eliminar contenido de S3 antes de destruir" echo " --keep-state No eliminar bucket de estado Terraform" echo " --help Mostrar esta ayuda" exit 0 ;; *) echo "Opcion desconocida: $1" exit 1 ;; esac shift done } # ============================================================================= # VALIDAR PREREQUISITOS # ============================================================================= validate() { info "========================================" info "Validando prerequisitos" info "========================================" if ! command -v aws &> /dev/null; then fatal "AWS CLI no esta instalado" fi if ! command -v terraform &> /dev/null; then fatal "Terraform no esta instalado" fi # Verificar credenciales local current_account current_account=$(aws sts get-caller-identity --query 'Account' --output text) if [ "$current_account" != "$ACCOUNT_ID" ]; then fatal "Cuenta AWS incorrecta. Esperada: $ACCOUNT_ID, Actual: $current_account" fi log "Cuenta AWS validada: $current_account" # Verificar estado de Terraform if [ ! -f "$TERRAFORM_DIR/terraform.tfstate" ] && [ ! -d "$TERRAFORM_DIR/.terraform" ]; then fatal "No existe estado de Terraform en $TERRAFORM_DIR" fi } # ============================================================================= # MOSTRAR RECURSOS A DESTRUIR # ============================================================================= show_resources() { info "========================================" info "Recursos que seran destruidos" info "========================================" cd "$TERRAFORM_DIR" info "Ejecutando terraform plan -destroy..." terraform plan -destroy -var-file=terraform.tfvars -out=destroy.plan info "" info "Revisa el plan de destruccion mostrado arriba." info "" } # ============================================================================= # CONFIRMACIONES # ============================================================================= confirm_destruction() { if [ "$FORCE" == "true" ]; then warn "Modo forzado: Omitiendo confirmaciones" return 0 fi echo "" echo -e "${RED}${BOLD}ATENCION: ESTA ACCION ES IRREVERSIBLE${NC}" echo -e "${RED}Se destruiran todos los recursos del entorno TEST${NC}" echo "" echo "Recursos afectados:" echo " - Instancia EC2 (con Elastic IP)" echo " - Base de datos RDS (con backups automaticos)" echo " - Bucket S3 (frontend)" echo " - Distribucion CloudFront" echo " - Funciones Lambda y EventBridge" echo " - Security Groups, VPC, Subnets" echo " - Registros Route53" echo "" read -p "Escribe 'DESTRUIR' para confirmar: " confirm1 if [ "$confirm1" != "DESTRUIR" ]; then fatal "Confirmacion incorrecta. Abortando." fi read -p "Estas ABSOLUTAMENTE SEGURO? Escribe 'SI': " confirm2 if [ "$confirm2" != "SI" ]; then fatal "Confirmacion incorrecta. Abortando." fi log "Confirmacion recibida. Procediendo con la destruccion." } # ============================================================================= # BACKUP DE RDS # ============================================================================= backup_rds() { if [ "$SKIP_RDS_BACKUP" == "true" ]; then warn "Omitiendo backup de RDS (--skip-rds-backup)" return 0 fi info "========================================" info "Realizando backup de RDS" info "========================================" cd "$TERRAFORM_DIR" local rds_endpoint rds_endpoint=$(terraform output -raw rds_endpoint 2>/dev/null || echo "") local db_name db_name=$(terraform output -raw rds_db_name 2>/dev/null || echo "") if [ -z "$rds_endpoint" ]; then warn "No se pudo obtener endpoint RDS. Omitiendo backup." return 1 fi mkdir -p "$BACKUP_DIR" log "RDS Endpoint: $rds_endpoint" log "Base de datos: $db_name" log "Directorio de backup: $BACKUP_DIR" # Crear snapshot final local snapshot_id="sacc4-test-final-$(date +%Y%m%d-%H%M%S)" local rds_instance_id="sacc4-test-db-prod" log "Creando snapshot final: $snapshot_id" aws rds create-db-snapshot \ --db-instance-identifier "$rds_instance_id" \ --db-snapshot-identifier "$snapshot_id" \ --region "$REGION" log "Esperando que el snapshot se complete..." aws rds wait db-snapshot-available \ --db-snapshot-identifier "$snapshot_id" \ --region "$REGION" log "Snapshot creado exitosamente: $snapshot_id" echo "$snapshot_id" > "$BACKUP_DIR/snapshot-id.txt" # Intentar dump SQL (si tenemos acceso) local ec2_ip ec2_ip=$(terraform output -raw ec2_public_ip 2>/dev/null || echo "") local ssh_key="$HOME/.ssh/sacc4-test-key.pem" if [ -n "$ec2_ip" ] && [ -f "$ssh_key" ]; then log "Intentando crear dump SQL desde EC2..." if ssh -i "$ssh_key" -o StrictHostKeyChecking=no ubuntu@"$ec2_ip" "mysqldump -h $rds_endpoint -u sacc_app_user -p'$db_name' --all-databases > /tmp/sacc4-test-backup.sql 2>/dev/null" 2>/dev/null; then scp -i "$ssh_key" -o StrictHostKeyChecking=no "ubuntu@$ec2_ip:/tmp/sacc4-test-backup.sql" "$BACKUP_DIR/" log "Dump SQL guardado en: $BACKUP_DIR/sacc4-test-backup.sql" else warn "No se pudo crear dump SQL (credenciales no disponibles)" fi fi log "Backup completado en: $BACKUP_DIR" } # ============================================================================= # LIMPIAR S3 # ============================================================================= cleanup_s3() { if [ "$DELETE_S3" != "true" ]; then info "Omitiendo limpieza de S3 (usar --delete-s3 para eliminar)" return 0 fi info "========================================" info "Limpiando bucket S3" info "========================================" cd "$TERRAFORM_DIR" local bucket_name bucket_name=$(terraform output -raw frontend_bucket_name 2>/dev/null || echo "") if [ -z "$bucket_name" ]; then warn "No se pudo obtener nombre del bucket S3" return 1 fi log "Bucket a limpiar: $bucket_name" # Verificar si tiene versionamiento local versioning versioning=$(aws s3api get-bucket-versioning --bucket "$bucket_name" --query 'Status' --output text 2>/dev/null || echo "Disabled") if [ "$versioning" == "Enabled" ]; then warn "Bucket tiene versionamiento habilitado. Eliminando todas las versiones..." # Eliminar todas las versiones (incluyendo delete markers) aws s3api list-object-versions --bucket "$bucket_name" --query 'Versions[].{Key:Key,VersionId:VersionId}' --output json | \ jq -c '.[]' | while read -r obj; do key=$(echo "$obj" | jq -r '.Key') version=$(echo "$obj" | jq -r '.VersionId') aws s3api delete-object --bucket "$bucket_name" --key "$key" --version-id "$version" > /dev/null done fi # Vaciar bucket log "Vaciando bucket..." aws s3 rm "s3://$bucket_name" --recursive log "Bucket $bucket_name vaciado" } # ============================================================================= # DESTRUIR CON TERRAFORM # ============================================================================= destroy_terraform() { info "========================================" info "Destruyendo recursos con Terraform" info "========================================" cd "$TERRAFORM_DIR" if [ "$FORCE" == "true" ]; then terraform destroy -auto-approve -var-file=terraform.tfvars else terraform destroy -var-file=terraform.tfvars fi log "Terraform destroy completado" } # ============================================================================= # LIMPIAR ESTADO TERRAFORM # ============================================================================= cleanup_terraform_state() { if [ "$KEEP_STATE" == "true" ]; then info "Conservando bucket de estado Terraform (--keep-state)" return 0 fi info "========================================" info "Limpiando recursos de estado Terraform" info "========================================" local state_bucket="sacc4-terraform-state-test-668889063715" local dynamo_table="sacc4-terraform-locks-test-668889063715" # Preguntar antes de eliminar if [ "$FORCE" != "true" ]; then read -p "Eliminar bucket de estado S3 y tabla DynamoDB? (yes/no): " confirm if [ "$confirm" != "yes" ]; then warn "Conservando recursos de estado" return 0 fi fi # Eliminar contenido del bucket primero log "Vaciando bucket de estado: $state_bucket" aws s3 rm "s3://$state_bucket" --recursive 2>/dev/null || true # Eliminar bucket log "Eliminando bucket: $state_bucket" aws s3api delete-bucket --bucket "$state_bucket" --region "$REGION" 2>/dev/null || warn "No se pudo eliminar bucket" # Eliminar tabla DynamoDB log "Eliminando tabla DynamoDB: $dynamo_table" aws dynamodb delete-table --table-name "$dynamo_table" --region "$REGION" 2>/dev/null || warn "No se pudo eliminar tabla" log "Recursos de estado eliminados" } # ============================================================================= # VERIFICAR DESTRUCCION # ============================================================================= verify_destruction() { info "========================================" info "Verificando destruccion" info "========================================" cd "$TERRAFORM_DIR" local vpc_id vpc_id=$(terraform output -raw vpc_id 2>/dev/null || echo "") if [ -n "$vpc_id" ]; then if aws ec2 describe-vpcs --vpc-ids "$vpc_id" >/dev/null 2>&1; then warn "VPC $vpc_id aun existe" else log "VPC eliminada correctamente" fi fi # Verificar EC2 local ec2_ip ec2_ip=$(terraform output -raw ec2_public_ip 2>/dev/null || echo "") if [ -n "$ec2_ip" ]; then if ping -c 1 -W 2 "$ec2_ip" >/dev/null 2>&1; then warn "EC2 $ec2_ip aun responde a ping" else log "EC2 no responde (esperado)" fi fi } # ============================================================================= # RESUMEN # ============================================================================= show_summary() { info "========================================" info "RESUMEN DE DESTRUCCION" info "========================================" log "Entorno TEST destruido exitosamente" info "" info "Acciones realizadas:" if [ "$SKIP_RDS_BACKUP" != "true" ]; then info " [OK] Backup de RDS guardado en: $BACKUP_DIR" fi if [ "$DELETE_S3" == "true" ]; then info " [OK] Contenido de S3 eliminado" fi info " [OK] Recursos de infraestructura destruidos" if [ "$KEEP_STATE" != "true" ]; then info " [OK] Estado Terraform eliminado" fi info "" info "Costos: La destruccion de recursos detiene la generacion de cargos." info "Nota: Los snapshots de RDS y logs de CloudWatch pueden generar costos menores." info "" info "Log completo: $LOG_FILE" } # ============================================================================= # MAIN # ============================================================================= main() { parse_args "$@" echo -e "${RED}${BOLD}" echo "========================================" echo "SACC v4 - Destruccion de Entorno TEST" echo "========================================" echo -e "${NC}" echo "Cuenta: $ACCOUNT_ID" echo "Region: $REGION" echo "" echo -e "${RED}ADVERTENCIA: Esta accion destruira todos los recursos${NC}" validate show_resources confirm_destruction backup_rds cleanup_s3 destroy_terraform cleanup_terraform_state verify_destruction show_summary } main "$@"