Pruebas y Validación End-to-End
Introducción
Antes de declarar un despliegue "en producción", es esencial validar que todos los componentes funcionen correctamente en conjunto. Esta sección presenta una metodología de pruebas completa.
Metodología de Pruebas
┌─────────────────────────────────────────────────────────────┐
│ PIRÁMIDE DE PRUEBAS DE INFRAESTRUCTURA │
├─────────────────────────────────────────────────────────────┤
│ │
│ ▲ │
│ ╱ ╲ │
│ ╱ ╲ │
│ ╱ E2E ╲ Pruebas End-to-End │
│ ╱───────╲ (usuario real) │
│ ╱ ╲ │
│ ╱Integración╲ Pruebas de Integración │
│ ╱─────────────╲ (componentes juntos) │
│ ╱ ╲ │
│ ╱ Componentes ╲ Pruebas Unitarias │
│ ╱───────────────────╲ (cada servicio) │
│ ╱ ╲ │
│ ╱ Infraestructura ╲ Validación Config │
│ ╱─────────────────────────╲(CloudFormation,etc) │
│ │
│ Comenzar desde abajo, subir progresivamente │
│ │
└─────────────────────────────────────────────────────────────┘
Pruebas de Validación de Infraestructura
1. Validación VPC y Red
# Test 1: VPC existe y está disponible
aws ec2 describe-vpcs --vpc-ids vpc-xxx \
--query 'Vpcs[0].State'
# Esperado: "available"
# Test 2: Todos los subnets creados
aws ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-xxx" \
--query 'Subnets[*].[SubnetId,CidrBlock,AvailabilityZone]'
# Esperado: 6 subnets listados
# Test 3: Internet Gateway adjunto
aws ec2 describe-internet-gateways \
--filters "Name=attachment.vpc-id,Values=vpc-xxx" \
--query 'InternetGateways[0].Attachments[0].State'
# Esperado: "available"
# Test 4: Rutas correctas
aws ec2 describe-route-tables \
--filters "Name=vpc-id,Values=vpc-xxx" \
--query 'RouteTables[*].Routes'
# Esperado: ruta 0.0.0.0/0 hacia igw para subnets públicos
2. Validación de Security Groups
# Test 5: SG ALB permite HTTPS
aws ec2 describe-security-groups --group-ids sg-alb \
--query 'SecurityGroups[0].IpPermissions[?ToPort==`443`]'
# Esperado: regla con 0.0.0.0/0
# Test 6: SG App permite solo desde ALB
aws ec2 describe-security-groups --group-ids sg-app \
--query 'SecurityGroups[0].IpPermissions[*].UserIdGroupPairs[*].GroupId'
# Esperado: contiene sg-alb
# Test 7: SG DB permite solo desde App
aws ec2 describe-security-groups --group-ids sg-db \
--query 'SecurityGroups[0].IpPermissions[*].UserIdGroupPairs[*].GroupId'
# Esperado: contiene sg-app
3. Validación de Instancias EC2
# Test 8: Instancias en ejecución
aws ec2 describe-instance-status \
--instance-ids i-app1 i-app2 \
--query 'InstanceStatuses[*].[InstanceId,InstanceState.Name,SystemStatus.Status,InstanceStatus.Status]'
# Esperado: todos "running", "ok", "ok"
# Test 9: Instancias en los subnets correctos
aws ec2 describe-instances --instance-ids i-app1 i-app2 \
--query 'Reservations[*].Instances[*].[InstanceId,SubnetId]'
# Esperado: subnets privados (10.0.11.0/24, 10.0.12.0/24)
Pruebas de Conectividad
Matriz de Pruebas
┌─────────────────────────────────────────────────────────────┐
│ MATRIZ DE CONECTIVIDAD │
├─────────────────────────────────────────────────────────────┤
│ │
│ DE / HACIA │ Internet │ ALB │ App │ DB │ S3 │
│ ────────────┼──────────┼─────┼─────┼─────┼─────────── │
│ Internet │ - │ ✅ │ ❌ │ ❌ │ ✅(public) │
│ ALB │ ✅ │ - │ ✅ │ ❌ │ ❌ │
│ App │ ✅(NAT) │ ❌ │ ✅ │ ✅ │ ✅(endpoint) │
│ DB │ ❌ │ ❌ │ ❌ │ - │ ❌ │
│ │
│ ✅ = Debe funcionar │
│ ❌ = Debe estar bloqueado │
│ │
└─────────────────────────────────────────────────────────────┘
Scripts de Prueba de Conectividad
#!/bin/bash
# test-connectivity.sh
echo "=== Pruebas de Conectividad BlogPro ==="
# Test Internet → ALB (HTTPS)
echo -n "Test 1: Internet → ALB (HTTPS)... "
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://blog.example.com)
if [ "$HTTP_CODE" = "200" ]; then
echo "✅ PASS ($HTTP_CODE)"
else
echo "❌ FAIL ($HTTP_CODE)"
fi
# Test Internet → ALB (HTTP redirect)
echo -n "Test 2: HTTP → HTTPS redirect... "
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://blog.example.com)
if [ "$HTTP_CODE" = "301" ] || [ "$HTTP_CODE" = "302" ]; then
echo "✅ PASS (redirect $HTTP_CODE)"
else
echo "❌ FAIL ($HTTP_CODE)"
fi
# Test Health Check endpoint
echo -n "Test 3: Health Check... "
HEALTH=$(curl -s https://blog.example.com/health | jq -r '.status')
if [ "$HEALTH" = "healthy" ]; then
echo "✅ PASS"
else
echo "❌ FAIL ($HEALTH)"
fi
# Test Direct IP access (should fail - no public IP)
echo -n "Test 4: Direct IP access (should timeout)... "
timeout 5 curl -s http://10.0.11.20 > /dev/null 2>&1
if [ $? -eq 124 ]; then
echo "✅ PASS (correctly blocked)"
else
echo "❌ FAIL (should not be accessible)"
fi
echo "=== Pruebas finalizadas ==="
Pruebas de Load Balancing
Verificar la Distribución
#!/bin/bash
# test-load-balancing.sh
echo "=== Prueba de Distribución Load Balancer ==="
# Realizar 20 solicitudes y contar las respuestas de cada servidor
declare -A SERVER_COUNT
for i in {1..20}; do
SERVER=$(curl -s https://blog.example.com/api/server-id)
((SERVER_COUNT[$SERVER]++))
done
echo "Distribución de las solicitudes:"
for server in "${!SERVER_COUNT[@]}"; do
echo " $server: ${SERVER_COUNT[$server]} solicitudes"
done
# Verificar que ambos servidores recibieron solicitudes
if [ ${#SERVER_COUNT[@]} -ge 2 ]; then
echo "✅ Load balancing funcional"
else
echo "❌ Load balancing defectuoso"
fi
Prueba de Failover
┌─────────────────────────────────────────────────────────────┐
│ PROCEDIMIENTO PRUEBA FAILOVER │
├─────────────────────────────────────────────────────────────┤
│ │
│ Paso 1 : Verificar estado inicial │
│ ──────────────────────────────── │
│ $ aws elbv2 describe-target-health \ │
│ --target-group-arn arn:aws:...:tg-app │
│ → Los 2 targets deben estar "healthy" │
│ │
│ Paso 2 : Simular falla de un servidor │
│ ───────────────────────────────────── │
│ $ aws ec2 stop-instances --instance-ids i-app1 │
│ │
│ Paso 3 : Esperar el health check (30-60s) │
│ ────────────────────────────────────────── │
│ $ watch -n 5 'curl -s https://blog.example.com/health' │
│ → El sitio debe permanecer accesible │
│ │
│ Paso 4 : Verificar que el tráfico va a App2 │
│ ──────────────────────────────────────────── │
│ $ for i in {1..10}; do curl -s https://blog.example.com/ │
│ api/server-id; done │
│ → Todas las respuestas provienen de App2 │
│ │
│ Paso 5 : Restaurar App1 │
│ ──────────────────────────── │
│ $ aws ec2 start-instances --instance-ids i-app1 │
│ → Después de unos minutos, tráfico distribuido nuevamente │
│ │
└─────────────────────────────────────────────────────────────┘
Pruebas de Rendimiento
Prueba de Carga Básica
# Usar Apache Benchmark (ab)
# 1000 solicitudes, 50 concurrentes
ab -n 1000 -c 50 https://blog.example.com/
# Resultados esperados:
# - Requests per second > 100
# - Time per request < 500ms (mean)
# - Failed requests: 0
Métricas a Monitorear
| Métrica | Umbral Aceptable | Acción si se Supera |
|---|---|---|
| Latencia P50 | < 200ms | Optimizar código/cache |
| Latencia P95 | < 500ms | Verificar consultas DB |
| Latencia P99 | < 1000ms | Investigar outliers |
| Error rate | < 0.1% | Verificar logs |
| CPU (EC2) | < 70% | Agregar instancias |
| Memoria (EC2) | < 80% | Aumentar tamaño |
Pruebas de Seguridad
Checklist de Seguridad
┌─────────────────────────────────────────────────────────────┐
│ CHECKLIST DE SEGURIDAD │
├─────────────────────────────────────────────────────────────┤
│ │
│ RED │
│ ☐ Ningún puerto innecesario abierto a Internet │
│ ☐ SSH accesible solo vía bastion/VPN │
│ ☐ Base de datos no accesible desde Internet │
│ ☐ HTTPS forzado (redirect HTTP→HTTPS) │
│ │
│ CERTIFICADO SSL │
│ ☐ Certificado válido (no expirado) │
│ ☐ Cadena de certificados completa │
│ ☐ Solo TLS 1.2+ │
│ ☐ Sin vulnerabilidades SSL (prueba SSL Labs) │
│ │
│ INSTANCIAS │
│ ☐ Sin credenciales en el código/user-data │
│ ☐ Uso de roles IAM (sin claves) │
│ ☐ OS actualizado │
│ ☐ Firewall local configurado │
│ │
│ BASE DE DATOS │
│ ☐ Encryption at rest activado │
│ ☐ Encryption in transit (SSL) │
│ ☐ Sin credenciales por defecto │
│ ☐ Backups automáticos activados │
│ │
└─────────────────────────────────────────────────────────────┘
Prueba SSL con SSL Labs
# Usar la prueba en línea SSL Labs
# https://www.ssllabs.com/ssltest/
# O con testssl.sh
docker run --rm -ti drwetter/testssl.sh https://blog.example.com
# Puntuación esperada: A o A+
Informe de Validación
Plantilla de Informe
# Informe de Validación - BlogPro
## Resumen Ejecutivo
- Fecha: YYYY-MM-DD
- Versión: 1.0
- Estado: ✅ VALIDADO / ❌ NO VALIDADO
## Pruebas de Infraestructura
| Prueba | Resultado | Notas |
|--------|-----------|-------|
| VPC creada | ✅ | vpc-xxx |
| Subnets (6) | ✅ | |
| IGW adjunto | ✅ | |
| Rutas correctas | ✅ | |
## Pruebas de Seguridad
| Prueba | Resultado | Notas |
|--------|-----------|-------|
| SG ALB | ✅ | Solo HTTPS |
| SG App | ✅ | Solo ALB |
| SG DB | ✅ | Solo App |
| SSL Grade | A | SSL Labs |
## Pruebas Funcionales
| Prueba | Resultado | Notas |
|--------|-----------|-------|
| Sitio accesible | ✅ | 200 OK |
| Health check | ✅ | healthy |
| Load balancing | ✅ | 50/50 |
| Failover | ✅ | < 60s |
## Pruebas de Rendimiento
| Métrica | Valor | Umbral | Estado |
|---------|-------|--------|--------|
| Latencia P50 | 150ms | < 200ms | ✅ |
| Latencia P95 | 380ms | < 500ms | ✅ |
| Throughput | 250 rps | > 100 rps | ✅ |
## Problemas Identificados
1. Ninguno
## Recomendaciones
1. Activar los VPC Flow Logs para monitoreo
2. Configurar alertas CloudWatch
## Aprobación
- [ ] Tech Lead
- [ ] Security Review
- [ ] Ops Team
Automatización de Pruebas
Script de Validación Completo
#!/bin/bash
# validate-deployment.sh
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
DOMAIN="blog.example.com"
PASS=0
FAIL=0
function test_result() {
if [ $1 -eq 0 ]; then
echo -e "${GREEN}✅ PASS${NC}: $2"
((PASS++))
else
echo -e "${RED}❌ FAIL${NC}: $2"
((FAIL++))
fi
}
echo "========================================"
echo " VALIDACIÓN DESPLIEGUE BLOGPRO"
echo "========================================"
echo ""
# Test 1: Sitio accesible
echo "Test 1: Accesibilidad HTTPS"
curl -sf "https://${DOMAIN}" > /dev/null
test_result $? "Sitio accesible vía HTTPS"
# Test 2: Health check
echo "Test 2: Health Check"
HEALTH=$(curl -sf "https://${DOMAIN}/health" | jq -r '.status' 2>/dev/null)
[ "$HEALTH" = "healthy" ]
test_result $? "Health check endpoint"
# Test 3: HTTP redirect
echo "Test 3: HTTP → HTTPS redirect"
CODE=$(curl -sf -o /dev/null -w "%{http_code}" "http://${DOMAIN}")
[ "$CODE" = "301" ] || [ "$CODE" = "302" ]
test_result $? "HTTP redirect to HTTPS"
# Test 4: Certificado SSL
echo "Test 4: Certificado SSL válido"
curl -sf --cert-status "https://${DOMAIN}" > /dev/null
test_result $? "Certificado SSL válido"
# Test 5: Tiempo de respuesta
echo "Test 5: Tiempo de respuesta < 500ms"
TIME=$(curl -sf -o /dev/null -w "%{time_total}" "https://${DOMAIN}")
[ $(echo "$TIME < 0.5" | bc) -eq 1 ]
test_result $? "Tiempo de respuesta (${TIME}s)"
echo ""
echo "========================================"
echo " RESULTADO: $PASS PASS, $FAIL FAIL"
echo "========================================"
if [ $FAIL -gt 0 ]; then
exit 1
fi
Resumen
| Fase | Pruebas | Herramientas |
|---|---|---|
| Infraestructura | VPC, SG, Rutas | AWS CLI |
| Conectividad | Matriz de acceso | curl, nc, telnet |
| Funcional | E2E, Health | curl, scripts |
| Rendimiento | Carga, latencia | ab, hey, k6 |
| Seguridad | SSL, acceso | testssl, nmap |
Volver: Resumen MÓDULO 7