Con una cuenta desbloqueas el cuestionario, el foro de dudas y el tutor con IA de esta lección, además del registro de progreso y el certificado verificable al terminar «Sistemas Distribuidos para Misiones Espaciales».
Ninguna arista del clúster es anónima: cada llamada entre apps se autentica con una clave de API asociada a un rango de privilegio. El clúster define tres rangos, de menor a mayor poder: viewer (solo lectura de datos públicos o agregados), service (lectura y escritura del tráfico normal de una integración: publicar eventos, consultar el catálogo, recibir artefactos) y admin (gestión del propio registro: crear o revocar claves de otras apps, cambiar manifiestos). El principio rector es mínimo privilegio: la clave que usa el clasificador de señales para publicar sus resultados es de rango service, y no puede administrar el hub — aunque el mismo proceso que la usa esté comprometido, el daño posible queda acotado a lo que una clave service permite hacer, nunca a lo que permite una admin.
Las claves se guardan como hash, nunca en claro
El hub nunca almacena las claves de API en texto plano: guarda su hash SHA-256. Cuando una app se autentica, el hub calcula el hash de la clave recibida y lo compara contra el hash guardado — nunca compara la clave original contra nada, porque nunca la tiene. La consecuencia de seguridad es directa: si la base de datos del hub se filtrara (una copia de seguridad mal protegida, un acceso no autorizado), nadie podría recuperar las claves reales a partir de los hashes guardados, y todas las claves de todas las apps seguirían siendo válidas y no comprometidas de forma inmediata — el diseño limita el daño de una fuga en el peor de los casos.
Por qué importa la comparación en tiempo constante
Comparar dos strings con el operador == habitual (que se detiene en el primer carácter distinto) parece inofensivo, pero filtra información por temporización: un atacante que mide con precisión cuánto tarda la comparación puede inferir, carácter a carácter, cuántos caracteres iniciales acertó — y usar esa señal para adivinar el hash correcto byte a byte, muchísimo más rápido que probando al azar. Un ataque de temporización (timing attack) explota exactamente esa diferencia de microsegundos. La defensa es comparar siempre en tiempo constante: una función que recorre todos los caracteres sin importar en cuál difieren (como hmac.compare_digest en Python), de modo que el tiempo de comparación no revela ninguna información sobre dónde está el error.
Firma HMAC de webhooks: verificar que el mensaje es genuino
Cuando el hub entrega un evento por webhook (lección 3), el receptor necesita verificar dos cosas: que el mensaje realmente viene del hub, y que no ha sido alterado ni reproducido después de capturarlo. El clúster usa el estilo popularizado por Stripe: se firma con HMAC-SHA256 la concatenación de un timestamp y el cuerpo del mensaje (timestamp + "." + cuerpo), usando una clave secreta compartida solo por el hub y el receptor. El receptor recalcula la firma con la misma fórmula y clave, y la compara (¡en tiempo constante!) contra la firma recibida en la cabecera. Firmar el timestamp junto con el cuerpo — y no solo el cuerpo — es lo que permite que el receptor rechace una firma válida pero vieja: si el timestamp está fuera de una ventana de unos pocos minutos, el mensaje se rechaza aunque la firma sea matemáticamente correcta, cerrando la puerta a un ataque de repetición (replay) donde alguien capturó una llamada legítima y la reenvía más tarde. (El estilo de GitHub firma solo el cuerpo, sin ventana temporal — más simple, pero sin esta protección anti-replay por sí solo.)
Fail-open vs. fail-closed: una decisión explícita por operación
Cuando un chequeo de seguridad o de disponibilidad no puede completarse (un servicio de verificación está caído, una respuesta tarda demasiado), hay dos posturas posibles: fail-open (dejar pasar la operación de todas formas, priorizando disponibilidad) o fail-closed (bloquearla, priorizando seguridad). Ninguna de las dos es "la correcta" en abstracto — la decisión depende de la operación concreta, y debe documentarse explícitamente, no dejarse a la implementación por defecto de una librería. Una sonda de telemetría de solo lectura (por ejemplo, reportar el estado de salud de un servicio) puede razonablemente degradar en fail-open: si el chequeo de autenticación de la sonda falla, es preferible perder un dato de monitoreo que bloquear la observabilidad completa. Pero una acción de mando — programar un pase de rastreo, escribir en el catálogo científico, revocar una clave — jamás debe fail-open: si no se puede verificar con certeza que quien la pide tiene permiso, se bloquea, sin excepción.
Rotación de claves con periodo de gracia
Rotar una clave comprometida o simplemente vencida no puede exigir coordinar el despliegue simultáneo de dos apps (eso sería, de nuevo, el acoplamiento A5 de la lección 1). El clúster rota claves con un periodo de gracia: se emite la clave nueva y se activa de inmediato, pero la clave vieja sigue siendo válida durante una ventana acordada (por ejemplo, 24–72 horas) mientras el consumidor actualiza su configuración a su propio ritmo. Pasado ese periodo, la clave vieja se revoca definitivamente. Esto permite rotar claves de forma rutinaria y segura, sin que un despliegue mal sincronizado deje a una app sin poder autenticarse.
Comprueba tu comprensión de estos conceptos:
¿Por qué el hub guarda el hash SHA-256 de cada clave de API en vez de la clave en texto plano?
Verifica una firma HMAC-SHA256 paso a paso, tal como lo haría el receptor de un webhook del hub:
Playground · python
8. Custodia de datos: un backup no probado no es backup