Experimento 2: Seguridad - AndersenCastanedaUniAndes/proyecto-1 GitHub Wiki



| Título del experimento | Validación operativa de la ruta de acceso stateless (JWT + RBAC + Revocación + Rotación de claves) bajo carga ligera y fallas de soporte |
|---|---|
| Propósito del experimento | No validamos el estándar JWT. Validamos nuestra integración operativa (middleware, política de roles, revocación por jti, rotación de claves por kid, observabilidad) frente a atributos de calidad: disponibilidad, latencia y continuidad ante fallas (p. ej., Redis caído). |
| Fuera de alcance | No se valida la criptografía de JWT como estándar. |
| No se evalúan amenazas L7 avanzadas (CSRF, SSRF, etc.). | |
| No se prueba escalado horizontal ni caos de red (se deja como trabajo futuro). | |
| Recursos requeridos | Python + FastAPI, Uvicorn |
| PyJWT (o equivalente) RS256, bcrypt | |
| Redis (para blacklist) o tabla SQL de respaldo | |
| pytest + httpx (tests), Postman/Swagger (demo) | |
| Docker (opcional para reproducibilidad) | |
| Elementos de arquitectura involucrados | Autenticación (emisión de tokens), Autorización (RBAC por roles/scopes), Middleware de validación, Auditoría mínima. |
| Puntos de sensibilidad a probar | Impacto de la rotación de claves RS256 con kid en latencia y disponibilidad |
| Tolerancia del sistema a desincronización de relojes ±60s | |
| Disponibilidad del mecanismo de revocación (Redis caído, fallback activo | |
| Eficiencia de la aplicación de RBAC en middleware bajo carga | |
| Latencia del middleware | |
| Esfuerzo estimado | 24 horas. |
| Hipótesis de diseño | Descripción | Criterio de aceptación |
|---|---|---|
| Continuidad ante rotación: | Con tráfico sostenido, la rotación de claves no interrumpe el servicio. Los tokens emitidos antes de la rotación siguen siendo válidos. | Disponibilidad ≥ 99.5 % durante la ventana de rotación y errores espurios ≤ 0.5 %. |
| Resiliencia sin Redis | Si Redis (blacklist) falla, el sistema deniega o aplica fallback SQLite sin accesos indebidos. | Accesos indebidos = 0 con tokens revocados; redis_connection_status = 0 reflejado en métricas. |
| Desempeño del middleware | La validación (JWT + RBAC + revocación) mantiene latencia aceptable en dev con carga ligera. | p95 ≤ 1.0 s, p99 ≤ 2.0 s (medido con Runner de Postman y /metrics). |
| Historia de arquitectura asociada | MED-220 — HU Seguridad: Acceso administrativo | |
| MED-198 — HU Seguridad: Validación de token en operaciones sensibles | ||
| MED-197 — HU Seguridad: Emisión de token JWT | ||
| Nivel de incertidumbre : Medio | RBAC por claims (MED-220): riesgo de omisiones al mapear path → permisos. Mitigación: “policy-as-data” JSON + tests contractuales rol × acción. | |
| Revocación/refresh (MED-197/198): concurrencia y replay al refrescar. Mitigación: uso único por jti y marca de consumo. |
ASR (Seguridad): Solo accesos con tokens válidos, no revocados y con rol adecuado; 0 fugas de secretos.
| Patrones de arquitectura asociadas al experimento | Descripción |
|---|---|
| Chain of Responsibility (pipeline de middleware) | Middleware JWT + RBAC - pasos encadenados y desacoplados: Extracción → Decodificación/RS256(kid) → Revocación(jti) → Guard de rol/scope → Continuar. Cada eslabón falla temprano (401/403) sin tocar la lógica de negocio. |
| Strategy (algoritmo de firma y validaciones) | Encapsula el algoritmo (RS256 hoy, ES256 mañana) y la política de claims (qué iss/aud/nbf/exp exigir) |
| Builder (o Factory) de JWT | Construye el payload de forma segura y consistente (sub, role, exp, iat, iss, aud, jti) y firma con la clave apuntada por kid |
| Policy/Guard (RBAC) | Evita if role == "admin" dispersos. Define políticas por ruta/acción (can(DeleteUser), can(ReadUser)). |
| Repository + Hashing (bcrypt) | Protege credenciales y desacopla acceso a datos; jamás persistes contraseñas en claro. |
| DTO / Schema Validation (Pydantic) | Reduce superficies de ataque y normaliza qué expones. |
| Patrones de arquitectura asociadas al experimento | Descripción |
|---|---|
| Stateless access path | Para endpoints protegidos NO consultas BD; validas solo criptografía + claims + RBAC sobre el access token. |
| Claves en memoria del proceso: | Cargas al arranque las públicas/privadas por kid (archivo/env). No hace falta Redis ni disco en cada request. |
| Microservicio | Propósito y comportamiento esperado | Tecnología asociada |
|---|---|---|
| Experimento Seguridad (Auth Service) | Generar token del usuario | Python - jwt -RBAC |
| Conector | Comportamiento deseado en el experimento | Tecnología Asociada |
|---|---|---|
| API REST | Autenticación y autorización de usuarios mediante JWT | FastAPI, python-jose |
| Base de datos | Almacenamiento seguro de credenciales y registros | Postgresql |
| Cliente HTTP | Consumo de endpoints para pruebas y validación | Postman, requests |
| Contenedor | Despliegue aislado y reproducible del servicio | Docker |
| Tecnología asociada con el experimento (Desarrollo, infraestructura, almacenamiento) | Justificación |
|---|---|
| Lenguajes de programación | Python |
| Plataforma de despliegue | Docker, Kubernetes |
| Bases de datos | PostgreSQL |
| Herramientas de análisis | Postman, pytest |
| Librerías | FastAPI, SQLAlchemy, python-jose, passlib, bcrypt |
| Frameworks de desarrollo | FastAPI |
| Integrante | Tareas a realizar | Esfuerzo Estimado |
|---|---|---|
| Margarita Forero | Implementar emisión de JWT RS256 con kid estático | 2 horas |
| Margarita Forero | Crear endpoint de login con generación de access token | 1 hora |
| Margarita Forero | Middleware de validación JWT con roles (admin, user) | 2 horas |
| Margarita Forero | Endpoint sensible protegido (DELETE /users/{id} solo admin) | 1.5 horas |
| Margarita Forero | Endpoint protegido simple (GET /users/{id} cualquier autenticado) | 1 horas |
| Margarita Forero | Tests básicos: token válido, expirado, firma inválida, rol insuficiente | 2 horas |
| Margarita Forero | Diagramas simples (C4 nivel contenedor + secuencia login/validación) | 2 horas |
| Margarita Forero | Configurar Prometheus middleware en FastAPI para latencia JWT | 2 horas |
| Margarita Forero | Dashboard básico en Grafana con p95/p99 de validación | 1.5 horas |
| Publio | Redacción de informe breve (hipótesis → resultados → conclusiones) | 2 horas |
| Publio | Crear tabla users con rol y hash bcrypt | 1 hora |
| Publio | Docker Compose con app + Prometheus + Grafana | 2.5 horas |
| Publio | Semilla de usuarios (admin y user) | 1 hora |
(Se usan solo para validar el correcto funcionamiento básico de JWT + RBAC, no forman parte del experimento arquitectónico)
| Caso | Descripción |
|---|---|
| Login OK | /auth/login → access_token (exp=15m), refresh_token. |
| Acceso con rol | GET /users/{id} con role=admin → 200. |
| Rol insuficiente | role=user → 403. |
| Token expirado | 401 |
| Token firma inválida | (clave equivocada) → 401. |
| Token revocado (jti en blacklist) | 401 |
| Refresh OK | /auth/refresh → nuevo acceso válido. |
| Refresh inválido/expirado | 400/401. |
| Clock skew ±60 s | tolerancia configurable. |
(Estos son los que evalúan atributos de calidad bajo condiciones adversas)
| Caso | Descripción | Métrica clave |
|---|---|---|
| Carga concurrente | 200–500 req/s sobre /users/{id} | Latencia p95/p99, % errores |
| Rotación de clave RS256 | Cambio de kid en JWKS con tráfico en curso | % errores espurios, continuidad |
| Redis caído | Inaccesibilidad de blacklist jti | Accesos indebidos (=0), tiempo de recuperación |
| Desfase de reloj | Cliente con ±60 s de diferencia | % falsos 401 |
| JWKS no disponible | Endpoint de claves inaccesible temporalmente | Continuidad con claves cacheadas |
















| Caso | Descripción |
|---|---|
| RBAC fail-closed | Las rutas protegidas exigen Bearer; con rol insuficiente devuelven 403, con rol correcto 200. No hay “bypass” por ruta. |
| Revocación efectiva por jti | El flujo POST /auth/revoke (con Authorization: Bearer y body { "token": "<token_a_revocar>" }) invalida el token y los usos posteriores responden 401. |
| Observabilidad útil y segura. | /metrics expone latencias y errores del middleware sin PII/secretos. Prometheus y Grafana levantan y consumen métricas. |
| Despliegue reproducible | docker compose levanta app + Postgres + Redis + Prometheus + Grafana + Nginx. El acceso vía http://localhost: es correcto porque los puertos de los contenedores están mapeados al host. |
| Caso | Descripción |
|---|---|
| Resiliencia con Redis caído (fallback SQLite) | validar 0 accesos indebidos y revocación operativa sin Redis. |
| Revocación efectiva por jti | El flujo POST /auth/revoke (con Authorization: Bearer y body { "token": "<token_a_revocar>" }) invalida el token y los usos posteriores responden 401. |
| Rotación de claves bajo tráfico | continuidad de servicio y errores espurios ≤ 0.5%. |
| Rendimiento | Medir p95 < 8 ms / p99 < 12 ms en 200–500 rps. |
| Clock skew ±60 s | sin falsos 401 dentro de la tolerancia. |