#!/bin/bash # Validação completa do deploy # Uso: ./scripts/validate.sh [sha8] # Ex: ./scripts/validate.sh imobiliaria.matheussouza.com.br 849789d set -euo pipefail DOMAIN="${1:?Informe o domínio: ./validate.sh [sha8]}" EXPECTED_TAG="${2:-}" PASS=0 FAIL=0 GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' NC='\033[0m' ok() { echo -e "${GREEN}✅ PASS${NC} — $1"; ((PASS++)); } fail() { echo -e "${RED}❌ FAIL${NC} — $1"; ((FAIL++)); } info() { echo -e "${YELLOW}ℹ️ $1${NC}"; } echo "" info "Validando https://$DOMAIN" echo "────────────────────────────────────────────" # 1. Frontend HTTPS STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 15 "https://$DOMAIN" || echo "000") [ "$STATUS" = "200" ] && ok "Frontend HTTPS (200)" || fail "Frontend HTTPS retornou $STATUS" # 2. HTTP → HTTPS redirect LOCATION=$(curl -s -o /dev/null -w "%{redirect_url}" --max-time 10 "http://$DOMAIN" || echo "") echo "$LOCATION" | grep -q "https://" \ && ok "HTTP → HTTPS redirect ($LOCATION)" \ || fail "Redirect HTTP→HTTPS ausente (got: '$LOCATION')" # 3. Backend /health HEALTH=$(curl -s --max-time 15 "https://$DOMAIN/api/health" || echo "{}") STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 15 "https://$DOMAIN/api/health" || echo "000") [ "$STATUS" = "200" ] && ok "Backend /api/health (200) → $HEALTH" || fail "Backend /api/health retornou $STATUS" # 4. DB conectado (campo db no health) echo "$HEALTH" | grep -q '"db": "ok"' \ && ok "Banco de dados conectado" \ || fail "Banco de dados não conectado — response: $HEALTH" # 5. /api/version VERSION_RESP=$(curl -s --max-time 10 "https://$DOMAIN/api/version" || echo "{}") STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "https://$DOMAIN/api/version" || echo "000") [ "$STATUS" = "200" ] && ok "/api/version (200) → $VERSION_RESP" || fail "/api/version retornou $STATUS" # 6. Validar tag se fornecida if [ -n "$EXPECTED_TAG" ]; then echo "$VERSION_RESP" | grep -q "$EXPECTED_TAG" \ && ok "Image tag confere ($EXPECTED_TAG)" \ || fail "Image tag não confere — esperado '$EXPECTED_TAG', got: $VERSION_RESP" fi # 7. Properties API STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 15 "https://$DOMAIN/api/properties?limit=1" || echo "000") [ "$STATUS" = "200" ] && ok "GET /api/properties (200)" || fail "GET /api/properties retornou $STATUS" # 8. Auth endpoint existe STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 \ -X POST "https://$DOMAIN/api/v1/auth/login" \ -H "Content-Type: application/json" \ -d '{"email":"x","password":"x"}' || echo "000") # Esperamos 400 ou 401 (endpoint existe mas credenciais inválidas) [[ "$STATUS" =~ ^(400|401|422)$ ]] \ && ok "POST /api/v1/auth/login existe ($STATUS)" \ || fail "POST /api/v1/auth/login retornou inesperado $STATUS" # 9. TLS — validade do certificado EXPIRY=$(echo | openssl s_client -connect "$DOMAIN:443" -servername "$DOMAIN" 2>/dev/null \ | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2 || echo "") if [ -n "$EXPIRY" ]; then EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s 2>/dev/null || echo 0) NOW_EPOCH=$(date +%s) DAYS_LEFT=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 )) [ "$DAYS_LEFT" -gt 7 ] \ && ok "Certificado TLS válido por $DAYS_LEFT dias (expira: $EXPIRY)" \ || fail "Certificado expira em $DAYS_LEFT dias!" else fail "Não foi possível verificar o certificado TLS" fi # 10. TLS — versão mínima TLS 1.2 TLS_VERSION=$(echo | openssl s_client -connect "$DOMAIN:443" -servername "$DOMAIN" \ -tls1_1 2>&1 | grep -c "handshake failure" || true) [ "$TLS_VERSION" -gt 0 ] \ && ok "TLS 1.1 bloqueado (mínimo TLS 1.2)" \ || info "TLS 1.1 pode estar habilitado — verifique configuração do Traefik" # ── Resumo ──────────────────────────────────────────────────────────────────── echo "" echo "────────────────────────────────────────────" echo -e "Resultado: ${GREEN}$PASS passou(aram)${NC} / ${RED}$FAIL falhou(aram)${NC}" echo "" [ "$FAIL" -eq 0 ] && echo -e "${GREEN}🚀 Deploy validado com sucesso!${NC}" && exit 0 echo -e "${RED}💥 $FAIL verificação(ões) falharam.${NC}" && exit 1