La arquitectura se centra en un servicio de autorización distribuido inspirado en Zanzibar, compuesto por tres niveles: nodos de evaluación del motor de verificación sin estado, una base de datos de instantáneas de gráficos globalmente distribuida y un pipeline de vigilancia impulsado por eventos para la invalidación de caché. Este diseño separa las verificaciones de autorización, que son intensivas en lectura, de las actualizaciones de permisos, que son intensivas en escritura, lo que permite una escalabilidad independiente de la capacidad de evaluación mientras se mantienen fuertes garantías de consistencia para las mutaciones de relaciones. El sistema emplea el patrón de zookie de Google para limitar la obsolescencia sin sacrificar los beneficios de rendimiento del almacenamiento en caché en el borde.
Los nodos del motor de verificación desplegados en ubicaciones periféricas evalúan las consultas de autorización utilizando cachés locales en memoria y mapas de bits de permisos compactos. Estos nodos cargan configuraciones de espacio de nombres desde un clúster de etcd replicado y resuelven tuplas de relaciones desde una instancia de CockroachDB o Spanner geo-particionada, que proporciona consistencia externa a través de TrueTime o relojes lógicos híbridos. Cada nodo mantiene filtros de Bloom para prevenir que fallos de caché afecten a la base de datos cuando las relaciones definitivamente no existen.
Para manejar el "problema del nuevo enemigo", donde las revocaciones recientes pueden ser invisibles para las cachés en el borde, el sistema implementa tokens de zookie: marcas de tiempo opacas que codifican la consistencia de la instantánea, que obligan a los fallos de caché para operaciones sensibles dentro de una ventana de incertidumbre configurable. Los clientes reciben estos tokens con las verificaciones iniciales y deben repetirlos al acceder a recursos de alto valor, asegurando que los permisos recientemente revocados sean visibles de inmediato sin requerir una invalidación global de caché. Este mecanismo equilibra la necesidad de baja latencia con el requisito de seguridad de la visibilidad inmediata de la revocación.
La invalidación de caché aprovecha un pipeline de vigilancia respaldado por Apache Kafka que propaga cambios de tupla a todos los motores de verificación en el borde utilizando hash consistente, asegurando que las tormentas de revocación desencadenen refrescos de caché escalonados en lugar de bombardeos sincronizados a la base de datos. El pipeline emplea retroceso exponencial alterado para evitar estampidas de rebaños cuando los objetos ampliamente compartidos experimentan cambios de permisos. Esta arquitectura asegura que el sistema mantenga una latencia de menos de 10 ms para aciertos de caché mientras garantiza la consistencia causal para las actualizaciones de permisos a través de nodos distribuidos geográficamente.
Una plataforma global de colaboración de documentos que sirve a 50 millones de usuarios empresariales experimentó picos de latencia catastróficos durante las horas pico al evaluar jerarquías de compartición complejas. Cada acceso a un documento requería cruzar miembros de grupos anidados y permisos heredados almacenados en un clúster monolítico de PostgreSQL, lo que resultaba en tiempos de consulta de más de 500 ms y frecuentes tiempos de espera durante las actualizaciones masivas de permisos cuando los empleados cambiaban de departamentos o proyectos. El equipo de ingeniería requería una solución capaz de ofrecer una latencia de menos de 10 ms mientras mantenía estrictas garantías de seguridad durante revocaciones en cascada a través de estructuras de carpetas anidadas.
El primer enfoque evaluó mantener un clúster centralizado de PostgreSQL con vistas materializadas en Redis que almacenaban en caché los caminos de permisos. Los pros incluían sólidas garantías ACID que aseguraban visibilidad inmediata de las revocaciones y una semántica de transacción sencilla para actualizaciones complejas de múltiples tablas. Los contras involucraban graves cuellos de botella de escritura durante cambios masivos de permisos, riesgos inevitables de estampida de caché cuando se actualizaban documentos populares, y la incapacidad fundamental de escalar el rendimiento de lectura geográficamente sin réplicas de lectura complejas que introdujeran un retraso inaceptable de replicación para decisiones críticas de seguridad.
El segundo enfoque sugería un despliegue completamente desnormalizado de Apache Cassandra con resolución de permisos del lado de la aplicación y expiración de caché basada en TTL. Los pros incluían un excelente rendimiento de escritura para mutaciones de relaciones y disponibilidad inherente multi-región sin puntos de falla únicos. Los contras revelaban compromisos de consistencia eventual inaceptables donde los permisos revocados permanecían visibles durante minutos debido a retrasos en el protocolo de gossip, y la falta de eliminaciones en cascada atómicas creaba agujeros de seguridad donde los usuarios mantenían acceso a recursos después de ser eliminados de grupos padres, violando el principio de menor privilegio.
El equipo finalmente seleccionó una arquitectura estilo Zanzibar utilizando CockroachDB para el almacenamiento de tuplas de relaciones, sidecars de Envoy como Puntos de Aplicación de Políticas, y nodos del Motor de Verificación escalados horizontalmente con cachés de Menos Recientemente Usados precedidos por filtros de Bloom. Esta elección equilibró la necesidad de una fuerte consistencia en escrituras de permisos a través de aislamiento serializable por defecto con requerimientos de rendimiento en el borde a través de cachés de evaluación locales y flujos de invalidación impulsados por Apache Kafka. El resultado redujo la latencia de autorización p99 de 500 ms a 4 ms, soportó 15 millones de verificaciones por segundo globalmente, y aseguró que las revocaciones de permisos se propagaran a todos los nodos en el borde dentro de los 150 milisegundos mientras mantenía un 99.99% de disponibilidad.
¿Cómo evitas que las verificaciones de autorización devuelvan decisiones "permitir" obsoletas inmediatamente después de una revocación de permisos sin sacrificar los beneficios de rendimiento del almacenamiento en caché distribuido?
Los candidatos a menudo pasan por alto el patrón de zookie o vectores de versión, en su lugar proponen la invalidación global de caché o lecturas de base de datos para cada verificación. La solución requiere que el servicio de autorización devuelva un token de consistencia con cada decisión que codifica la marca de tiempo de la instantánea de los datos utilizados. Para operaciones sensibles o después de eventos recientes de revocación, el cliente debe presentar este token, obligando al Motor de Verificación a verificar contra el almacén central si su caché local es anterior a la marca de tiempo del token. Esto asegura consistencia causal sin requerir invalidación global de caché o sacrificar el rendimiento de lectura para la mayoría de las solicitudes.
¿Cómo arquitectarías el mecanismo de invalidación de caché para evitar efectos de estampida de rebaños cuando un objeto ampliamente compartido tiene sus permisos modificados, potencialmente desencadenando millones de refrescos de caché simultáneos?
La técnica clave implica el hash consistente de claves de caché combinado con retroceso exponencial alterado y coalescencia de solicitudes en los nodos de borde. Cuando el Pipeline de Vigilancia transmite un cambio de tupla, los nodos en el borde no invalidan inmediatamente sino que programan la invalidación utilizando un hash de la ID del objeto para dispersar los refrescos a lo largo de una ventana de tiempo. Además, cada Motor de Verificación mantiene un grupo de vuelo para verificaciones en progreso, asegurando que solicitudes concurrentes para el mismo objeto compartan un solo resultado de consulta de backend, evitando la sobrecarga de la base de datos durante actualizaciones de objetos populares.
¿Por qué usar una simple traversa de gráfico dirigido es insuficiente para modelar políticas de ReBAC, y cómo manejas las restricciones de intersección y exclusión en un entorno de evaluación distribuido?
La simple traversa de gráfico no captura las operaciones de conjuntos requeridas para políticas sofisticadas como "permitir solo si el usuario está en el grupo A Y NO en el grupo B". La solución implementa un sistema de reescritura donde las configuraciones de espacio de nombres se compilan en árboles de decisión evaluados a través de búsquedas de índice inverso, almacenando explícitamente tanto tuplas de relación positivas como negativas. Para las restricciones de intersección, el sistema consulta ambos conjuntos y computa la intersección en el Motor de Verificación, mientras que las exclusiones emplean evaluación corta con terminación anticipada. Este enfoque asegura que la lógica booleana compleja se evalúe de manera eficiente sin requerir múltiples viajes de ida y vuelta a la base de datos.