Autorización de Grano Fino: Zanzibar, OpenFGA y afines
Cómo el artículo de Google sobre Zanzibar convirtió la autorización en un problema de alcanzabilidad en un grafo, por qué eso resuelve el acceso con forma de relaciones (grupos anidados, carpetas compartidas, permisos delegados) que los motores de políticas planos llevan mal, y cómo OpenFGA, SpiceDB y Ory Keto sacaron el modelo fuera de Google, incluido el problema de coherencia del 'nuevo enemigo' y cómo lo resuelven los zookies.
Una regla que no para de crecer
A Daniel le piden añadir la opción de compartir a la herramienta interna de operaciones, donde los equipos guardan informes en carpetas. El primer requisito suena sencillo: si una carpeta se comparte con un equipo, todos los del equipo pueden ver los informes que hay dentro. Lo escribe como una regla Rego y funciona. Luego las carpetas tienen subcarpetas y la regla tiene que mirar un nivel hacia arriba, luego dos. Luego los equipos tienen subequipos y la regla también tiene que mirar dentro de grupos anidados. En la cuarta reunión la regla es una búsqueda recursiva por todos los grupos a los que Sara podría pertenecer y todas las carpetas por encima de cada documento, y Daniel se da cuenta de que ya no está escribiendo una regla. Está escribiendo a mano una búsqueda en un grafo, dentro de un lenguaje que no se diseñó para eso.
El artículo anterior terminaba justo con esta pregunta: ¿puede Sara ver este documento porque está en un grupo con el que se compartió una carpeta que lo contiene? Rego, Cedar y Casbin pueden comprobar un salto, “¿está Sara en este grupo?” o “¿está este documento en esta carpeta?”. Lo que les cuesta es la cadena: la pertenencia a grupos, anidada a cualquier profundidad, alimentando la contención de carpetas, anidada a cualquier profundidad, y todo ello desembocando en un sí o un no que depende de recorrer un camino por unos datos cuya forma no conoces de antemano. Esa cadena no es una regla plana. Es un grafo, y “¿puede Sara llegar a este documento?” es una pregunta de alcanzabilidad en un grafo.
Este artículo trata de la familia de sistemas construidos para responder a esa pregunta a escala de producción: Google Zanzibar, el artículo de 2019 y el sistema interno que formalizaron el enfoque, y sus principales descendientes de código abierto, OpenFGA, SpiceDB y Ory Keto. La técnica de modelado que comparten es el ReBAC, el control de acceso basado en relaciones, que conociste entre los modelos de decisión. Aquí el ReBAC deja de ser una idea de modelado y se convierte en una arquitectura que puedes poner en marcha.
Por qué una regla plana no escala a relaciones
Concreta la cadena. Sara es miembro del grupo finance-team. finance-team es lector de la carpeta Q3-Reports. Q3-Reports contiene un documento llamado board-summary. Sara debería poder ver board-summary, no porque alguna regla nombre a Sara o a ese documento, sino porque el camino entre ellos, a través de la pertenencia y la contención, se resuelve como “lector”.
Ahora intenta expresar “lector de un documento” como una sola condición plana, como quieren los motores del artículo anterior. Tendrías que enumerar todos los grupos a los que Sara podría pertenecer, todas las carpetas a las que podría llegar cada grupo y todos los documentos que podría contener cada carpeta, y en cuanto alguien crea una subcarpeta dentro de Q3-Reports o mete un grupo dentro de otro, tu regla está mal. Es lo que vivió Daniel. El problema no es que Rego, Cedar o Casbin sean malos lenguajes; es que la pregunta no es “evalúa esta condición”, sino “¿existe un camino?”, y eso es recorrer un grafo, no evaluar una regla. Un sistema basado en relaciones guarda las aristas, los hechos en bruto, Sara miembro-de finance-team, finance-team lector-de Q3-Reports, Q3-Reports padre-de board-summary, y responde a cada pregunta de acceso recorriéndolas, por profundo que sea el grafo en el momento de la consulta.
No es un modelo de decisión nuevo. Es el mismo ReBAC de los artículos de modelos, con el mismo espíritu. Lo nuevo es la arquitectura que hace funcionar el ReBAC cuando el grafo tiene millones de nodos y aristas y necesita una respuesta en pocos milisegundos: un motor de almacenamiento y consulta hecho para esta forma de problema en lugar de un lenguaje de políticas general forzado a un trabajo para el que no se pensó.
Google Zanzibar
Google necesitaba un único sistema de autorización para Drive, Calendar, YouTube, Photos, Cloud y decenas de productos más, cada uno con su propio modelo de compartir, y todos con comprobaciones de acceso correctas y rápidas sobre billones de relaciones guardadas y millones de consultas por segundo. El artículo de 2019 Zanzibar: Google’s Consistent, Global Authorization System describe cómo lo construyeron, y su modelo de datos se convirtió en la plantilla que han seguido casi todos los sistemas ReBAC desde entonces.
En Zanzibar todo es una tupla de relación, escrita objeto#relación@sujeto, “este objeto tiene esta relación con este sujeto”. doc:board-summary#viewer@user:sara significa que Sara es lectora directa del documento board-summary. Lo clave es que el sujeto de una tupla puede ser a su vez la relación de otro objeto, un userset, y así la pertenencia a grupos y la jerarquía salen de la misma pieza en lugar de necesitar un tratamiento aparte: doc:board-summary#viewer@group:finance-team#member significa que todos los miembros de finance-team son lectores, no un usuario concreto. Encadena unas cuantas y tienes el caso de Sara: tuplas de pertenencia, tuplas de contención y una regla de reescritura que las une en un único grafo.
Una tupla en bruto solo afirma un hecho directo. El comportamiento interesante, “los editores también son lectores”, “ver una carpeta es ver todo lo que hay dentro”, sale de una configuración de espacio de nombres que define, para cada tipo de objeto, cómo se calcula cada relación a partir de otras. Importan sobre todo dos operaciones de reescritura. Una unión dice que la relación A incluye a todos los que tienen la relación B; una relación de editor suele incluir la de lector, así que todo editor es lector sin una segunda tupla. El tuple-to-userset dice que la relación A sobre este objeto se calcula siguiendo una tupla hasta otro objeto y leyendo allí una relación; así “lector de la carpeta” se convierte en “lector de todos los documentos que contiene”, reescribiendo la relación de lector de un documento para que incluya a los lectores de su carpeta a través de la tupla de contención.
flowchart LR accTitle: Cómo se combinan las tuplas directas y una reescritura de userset en un grafo de relaciones recorrible accDescr: El diagrama muestra tres tuplas de relación directas como nodos unidos por aristas con etiqueta. Sara se une al grupo Equipo de Finanzas por una arista miembro. El grupo Equipo de Finanzas se une a la carpeta Reportes Q3 por una arista lector. La carpeta Reportes Q3 se une al documento Resumen Directivo por una arista padre. Una nota aparte explica la regla de reescritura: la relación lector de un documento se calcula como la unión de cualquier tupla de lector directa más la relación lector de su carpeta padre, siguiendo la arista padre. Esa regla es lo que permite que la pertenencia de Sara y la concesión de lectura de la carpeta se resuelvan, a través de la arista padre, en que Sara sea lectora del documento. Sara((Sara)) -- miembro --> Team[Equipo de Finanzas<br/>grupo] Team -- lector --> Folder[Reportes Q3<br/>carpeta] Folder -- padre --> Doc[Resumen Directivo<br/>documento] Rule["Regla en document.viewer:<br/>lector directo O<br/>lector de la carpeta padre"] Rule -.-> Doc
En la sintaxis interna de Zanzibar, simplificada a partir del formato basado en protobuf del artículo, la configuración de esa regla de documento se parece a esto:
name: "document"
relation { name: "parent" }
relation {
name: "viewer"
userset_rewrite {
union {
child { _this {} }
child { tuple_to_userset {
tupleset { relation: "parent" }
computed_userset { relation: "viewer" }
} }
}
}
}Es el tipo de configuración que escriben y mantienen los productos de Google, y es justo lo que el lenguaje de modelado de OpenFGA, que vemos más abajo, existe para hacer legible: la misma unión de lectores directos y heredados, el mismo salto tuple-to-userset a través de parent, con una sintaxis que nadie querría escribir a mano a gran escala. Entender una vez la forma en bruto hace que cualquier notación más amable se lea al instante, porque nunca aprendes un modelo nuevo, solo una notación nueva para las mismas piezas de unión y tuple-to-userset.
Todos los sistemas de la familia Zanzibar exponen la misma operación central: Check(objeto, relación, sujeto). ¿Está este sujeto relacionado con este objeto por esta relación, directamente o a través de alguna cadena de tuplas y reglas de reescritura? Responder supone recorrer el grafo hacia fuera desde el objeto de forma recursiva: leer su regla de reescritura, seguir cada rama de unión y de tuple-to-userset y bajar a las relaciones de cada objeto al que se hace referencia, hasta encontrar un camino al sujeto o agotar todas las ramas. Para Sara, Check(doc:board-summary, viewer, user:sara) sigue la regla de reescritura hasta la carpeta padre, mira los lectores de la carpeta (sin coincidencia directa), expande finance-team#member y encuentra a Sara. Existe un camino, así que la respuesta es verdadero.
sequenceDiagram accTitle: Una llamada Check que recorre de forma recursiva el grafo de relaciones accDescr: El diagrama muestra los pasos para evaluar Check sobre el documento Resumen Directivo, relación lector, para la usuaria Sara. El cliente llama a Check. El motor lee la regla de reescritura del documento y la sigue hasta la relación lector de la carpeta padre. El motor lee la tupla de lector de la carpeta, que nombra un userset, la relación miembro del grupo Equipo de Finanzas, y no un usuario directo. El motor expande ese userset leyendo las tuplas de miembro de Equipo de Finanzas y encuentra a Sara como miembro directo. Como ha encontrado un camino, el motor devuelve Allow al cliente. Client->>Engine: Check(doc:board-summary, viewer, user:sara) Engine->>Engine: aplica la regla (directo O lector del padre) Engine->>Engine: lee el lector de la carpeta (apunta a los miembros del equipo) Engine->>Engine: expande los miembros del equipo Engine->>Engine: Sara es miembro directo de Equipo de Finanzas Engine-->>Client: Allow (hay camino)
El problema del nuevo enemigo
Recorrer el grafo no basta para ser seguro. La otra aportación que define a Zanzibar es una garantía de coherencia, motivada por una forma de ataque que el artículo llama el problema del nuevo enemigo. Supón que a Sara la sacan de finance-team en el momento T porque se cambia de equipo, una revocación deliberada. Si, un instante después de T, una comprobación de su acceso la atiende una réplica de la base de datos que todavía no ha recibido la retirada, puede seguir devolviendo Allow. El “enemigo” no es un atacante aprovechando un fallo; es la coherencia eventual de siempre, aplicada al único tipo de lectura en el que un dato viejo es un agujero de seguridad y no una pequeña molestia.
sequenceDiagram accTitle: El problema del nuevo enemigo y cómo lo arregla un token de coherencia accDescr: El diagrama compara dos líneas de tiempo. En la primera, un administrador saca a Sara de Equipo de Finanzas en el momento T, escribiendo en la base de datos principal. Poco después, una llamada Check sobre el acceso de Sara a Resumen Directivo la atiende una réplica desactualizada que aún no ha recibido la retirada, y devuelve Allow por error, que es el problema del nuevo enemigo. En la segunda, la misma llamada Check lleva un token de coherencia zookie atado a una instantánea igual o posterior a T. El motor tiene que leer datos al menos así de recientes, ve la retirada y devuelve Deny, que es lo correcto. Admin->>DB: saca a Sara de Equipo de Finanzas (momento T) DB->>DB: aplicado en la principal, aún sin replicar Client->>Engine: Check(sara, viewer, doc), sin zookie Engine->>DB: lee de una réplica desactualizada DB-->>Engine: Sara sigue siendo miembro (dato viejo) Engine-->>Client: Allow (ERROR, el nuevo enemigo) Client->>Engine: Check(sara, viewer, doc), zookie atado a T Engine->>DB: lee en una instantánea >= T DB-->>Engine: Sara ya no es miembro (dato fresco) Engine-->>Client: Deny (correcto)
La solución de Zanzibar es el zookie, un token de coherencia opaco derivado de las marcas de tiempo ordenadas globalmente de Google Spanner y sus relojes TrueTime, que un cliente adjunta a un Check para decir “responde con datos al menos tan recientes como este punto”. Una escritura devuelve un zookie que marca cuándo surtió efecto, y el cliente que acaba de hacer una escritura sensible, como una revocación, puede pasarlo en su siguiente Check y tener garantizado que verá la revocación en lugar de competir con una caché de coherencia eventual. Zanzibar hace que cada Check sea por defecto “al menos tan reciente como la última escritura que le importa a este cliente”, así que el comportamiento seguro es el de serie y no algo que cada llamada tenga que recordar.
Es tentador ver el recorrido del grafo como el problema interesante y la coherencia como un detalle operativo. Es al revés. Recorrer el grafo para un Check es un problema bien conocido; hacerlo correctamente a escala global, con carga, sin dejar nunca que un permiso revocado siga valiendo un rato, es lo que hizo falta que resolviera el artículo de Google y con lo que tiene que lidiar cualquier implementación seria de la familia Zanzibar. Un motor ReBAC con el modelo de grafo bien y el modelo de coherencia mal no es un Zanzibar más pequeño; le falta la mitad del diseño que lo hace fiable para decisiones de seguridad.
OpenFGA: Zanzibar para todos los demás
OpenFGA es un motor de autorización de código abierto, nacido en Auth0 y hoy proyecto de la CNCF, que implementa el modelo de tuplas y Check de Zanzibar sin infraestructura a escala de Google por debajo. Es la forma más extendida de llevar hoy un ReBAC al estilo Zanzibar a producción.
Donde la configuración de espacio de nombres de Zanzibar es un formato interno, OpenFGA define tipos y relaciones con un lenguaje de modelado compacto y legible:
type user
type group
relations
define member: [user]
type folder
relations
define viewer: [user, group#member]
type document
relations
define parent: [folder]
define viewer: [user, group#member] or viewer from parentLee la última línea como leíste la regla de reescritura de Zanzibar. La relación viewer de un documento es la unión de las concesiones directas, [user, group#member], que encajan con usuarios sueltos o con miembros de grupos, o de la relación viewer heredada de su carpeta parent, justo la reescritura tuple-to-userset que dejaba que el acceso de Sara a la carpeta bajara hasta el documento. Los hechos se guardan como tuplas, con la misma estructura que en Zanzibar:
{"user": "user:sara", "relation": "member", "object": "group:finance-team"}
{"user": "group:finance-team#member", "relation": "viewer", "object": "folder:q3-reports"}
{"user": "folder:q3-reports", "relation": "parent", "object": "document:board-summary"}Y la consulta es la misma operación Check con los nombres de OpenFGA:
POST /stores/{store_id}/check
{
"tuple_key": {
"user": "user:sara",
"relation": "viewer",
"object": "document:board-summary"
}
}Check responde si un sujeto puede hacer una cosa. Las aplicaciones reales también necesitan las preguntas inversas, qué documentos puede ver Sara, para pintar una lista de ficheros, y quién puede ver este documento, para pintar un diálogo de compartir, y responder a cualquiera de las dos lanzando Check contra cada objeto o usuario candidato no escala. OpenFGA tiene APIs específicas, ListObjects y ListUsers, apoyadas en índices optimizados para lectura y algoritmos de expansión inversa, porque listar todo lo alcanzable es una consulta distinta y más difícil que comprobar si una cosa lo es. Cuando evalúes un sistema de autorización de grano fino, pregunta no solo lo rápido que es Check, sino cómo resuelve List.
OpenFGA funciona como un servicio independiente por gRPC o HTTP, normalmente con la forma de servicio central del artículo de XACML, un servicio de autorización al que llama cada aplicación que necesita una decisión, con SDK para los lenguajes de servidor habituales. También se ofrece como servicio gestionado, Auth0 FGA. La coherencia se puede ajustar en cada petición: quien llama puede pedir la mínima latencia, aceptando una pequeña ventana de datos viejos, o más coherencia, pagando más latencia a cambio de una garantía de frescura al estilo Zanzibar, según lo sensible que sea esa comprobación. Es la misma lección de “un equilibrio, no una respuesta fija” que daba el artículo de XACML sobre dónde poner el PDP, aplicada a la coherencia.
Otros miembros de la familia
OpenFGA es la implementación de código abierto más extendida, pero no la única. SpiceDB, de AuthZed, es otra implementación de Zanzibar de código abierto y lista para producción, con su propio lenguaje de esquemas, mucho énfasis en almacenamiento intercambiable y fuertemente coherente (PostgreSQL, CockroachDB, Spanner) y una herramienta de línea de comandos para pruebas, zed. Su API de coherencia es especialmente explícita: quien llama elige en cada petición minimize_latency, at_least_as_fresh, la garantía al estilo zookie, o fully_consistent, de modo que el equilibrio entre latencia y frescura es un parámetro visible y no un valor oculto. Ory Keto es un servidor de permisos de código abierto más ligero, también inspirado en Zanzibar, que prioriza la sencillez y encaja de forma natural con el resto del ecosistema de Ory, Kratos para la identidad e Hydra para OAuth y OIDC, una buena opción para equipos que ya trabajan con Ory. Permify es un recién llegado que busca una experiencia de modelado accesible como la de OpenFGA, con filtrado por atributos junto a las relaciones y un validador de esquemas que detecta errores de modelado antes de producción.
Los cuatro comparten el mismo ADN, tuplas, un grafo de relaciones movido por reglas de reescritura y una API Check de alcanzabilidad, porque son implementaciones fieles del modelo que describía el artículo. Elegir entre ellos hoy depende sobre todo del almacenamiento que prefieras, del modo de alojamiento (gestionado por ti o como servicio), de lo fino que puedas ajustar la coherencia y del encaje con tu ecosistema, no de semánticas de autorización distintas. Ninguno necesita Spanner ni TrueTime como el Zanzibar de Google, y ese es el logro de ingeniería de cada uno: las garantías de coherencia de Zanzibar sobre bases de datos corrientes y al alcance de cualquiera.
Cómo se compara con lo demás
Es fácil confundir los motores ReBAC con “otro lenguaje de políticas más”, cuando resuelven un problema de estructura distinta.
| OPA / Cedar / Casbin | Zanzibar / OpenFGA y afines | |
|---|---|---|
| La pregunta que responden | ¿Cumple esta petición esta regla, evaluada sobre atributos? | ¿Hay un camino entre este sujeto y este objeto en un grafo de relaciones? |
| Lo que se guarda | Reglas (políticas Rego o Cedar, un modelo y una política de Casbin) | Tuplas de relación (hechos en bruto) más reglas de reescritura sobre cómo se combinan las relaciones |
| Encaja con | Condiciones sobre atributos, comprobaciones de rol, un nivel de pertenencia a grupos | Compartir, anidar y delegar a cualquier profundidad: carpetas en carpetas, grupos en grupos |
| El problema de ingeniería difícil | Expresividad frente a capacidad de análisis (Cedar), o configurabilidad (Casbin) | La coherencia a escala, el problema del nuevo enemigo, más consultas de alcanzabilidad rápidas |
| Consultas inversas (“¿qué puede ver este usuario?”) | No son una prioridad | Una API de primera clase (ListObjects, ListUsers), porque aquí son difíciles por estructura |
Las dos familias no compiten tanto como sirven a formas de pregunta distintas, y los sistemas en producción a menudo usan las dos: OPA o Cedar deciden si una llamada a la API está permitida en absoluto, y OpenFGA responde qué documentos concretos puede incluir la respuesta.
Los informes de Sara, de principio a fin
Vuelve a la herramienta de operaciones de Daniel, ahora con cada pieza nombrada. Sara entra en finance-team cuando se incorpora, una tupla: group:finance-team#member@user:sara. Su responsable comparte la carpeta Q3-Reports con todo el equipo, una tupla: folder:q3-reports#viewer@group:finance-team#member. Alguien sube board-summary a la carpeta, una tupla: document:board-summary#parent@folder:q3-reports. Nadie le da nunca acceso explícito a Sara a board-summary y, aun así, cuando abre la herramienta, Check(document:board-summary, viewer, user:sara) recorre el camino del diagrama y devuelve Allow. La regla Rego recursiva de Daniel se sustituye por tres hechos y una línea de modelo.
Ahora Sara se cambia de equipo. El sistema de RR. HH. borra la tupla group:finance-team#member@user:sara, un solo borrado y nada más. Cada documento de cada carpeta compartida con finance-team, a cualquier profundidad, deja de ser alcanzable para Sara al instante, porque el camino que lo hacía alcanzable ya no existe. No hay limpieza documento a documento ni concesiones olvidadas que perseguir. Ese único borrado, reflejado de forma correcta e inmediata gracias a las garantías de coherencia que hemos visto, es toda la recompensa de modelar el acceso como un grafo y no como un montón de permisos sueltos: la forma del grafo es el modelo de acceso, así que cambiar una relación cambia todo lo que dependía de ella.
Probar y operar un modelo de relaciones
Un grafo de relaciones sigue siendo política, y la disciplina de las políticas como código sigue valiendo; solo que pruebas alcanzabilidad en lugar de condiciones de reglas. OpenFGA admite ficheros de prueba, normalmente .fga.yaml, que juntan un modelo y un conjunto de tuplas con aserciones explícitas: con estas tuplas, Check(document:board-summary, viewer, user:sara) tiene que dar verdadero; sin la tupla de pertenencia, falso. Se ejecutan en CI igual que opa test ejecuta aserciones de Rego. La herramienta zed de SpiceDB ofrece un flujo equivalente para probar y validar en local un esquema y un conjunto de relaciones. Un grafo de autorización roto debería hacer fallar una pull request, no descubrirse en producción.
Operarlo en producción añade una preocupación que los motores de políticas planos no tienen: la profundidad del grafo. Una revocación es barata, una tupla borrada, pero un Check sobre un grafo muy anidado, grupos dentro de grupos dentro de grupos, carpetas a muchos niveles, hace más trabajo de recorrido del que haría nunca una regla plana. Por eso todas las implementaciones de este artículo invierten tanto en caché, en profundidad de recorrido acotada y en índices optimizados para las consultas List. Diseñar un modelo de relaciones es un ejercicio de esquema y, sin remedio, también de rendimiento.
Resumen
La autorización basada en relaciones resuelve el problema hacia el que venían estos artículos, el acceso que depende de un grafo y no de una regla plana. Cambió la pregunta, no solo el lenguaje: “¿puede Sara llegar a este documento?” es alcanzabilidad, y por eso OPA, Cedar y Casbin sufren con el compartir y el anidar a cualquier profundidad, por buenos que sean sus lenguajes. El modelo de Zanzibar son tuplas más reglas de reescritura: hechos directos, objeto#relación@sujeto, que se combinan mediante uniones y reescrituras tuple-to-userset en un grafo que responde una única operación Check que lo recorre. El problema del nuevo enemigo es la parte más difícil: una revocación tiene que verse de inmediato, no con el tiempo, y los zookies lo resuelven atando un Check a una instantánea no más antigua que una escritura concreta. OpenFGA, SpiceDB, Ory Keto y Permify sacan el modelo fuera de Google, con lenguajes de modelado más amables sobre las mismas piezas y APIs List de primera clase para las consultas inversas que los motores planos rara vez llevan bien. Y es otra herramienta para otra pregunta, no un sustituto de OPA, Cedar o Casbin; los sistemas reales a menudo usan ambas.
Tres preguntas para ponerte a prueba
- Con el ejemplo de Sara, finance-team, Q3-Reports y board-summary, explica por qué “¿puede Sara ver este documento?” no se puede escribir como una única regla plana como lo haría un
permitde Cedar o un matcher de Casbin. ¿Qué la convierte exactamente en una pregunta de alcanzabilidad? - Describe con tus palabras el problema del nuevo enemigo: ¿qué tiene que salir mal, y en qué orden, para que cause un incidente de seguridad? Después explica qué cambia un zookie en esa secuencia.
- Un equipo está construyendo “compartir este documento con un grupo” y duda entre una política Cedar con una lista fija de grupos permitidos y una tupla de relación en OpenFGA. ¿Qué encaja mejor cuando la funcionalidad crezca para admitir carpetas anidadas y grupos anidados, y por qué?
Ejercicios prácticos
- Modela el caso de Sara. Escribe un modelo de OpenFGA, o la configuración de espacio de nombres equivalente al estilo Zanzibar, con los tipos
user,group,folderydocumenty las relaciones de pertenencia, lectura y carpeta padre de este artículo. Añade las tres tuplas del caso de Sara y comprueba que el Check de(document:board-summary, viewer, user:sara)devuelve verdadero; luego quita la tupla de pertenencia y comprueba que devuelve falso. - Sigue un grafo más profundo sobre el papel. Amplía el ejemplo con una segunda carpeta dentro de
q3-reportsy un segundo grupo dentro definance-team, si tu motor admite grupos dentro de grupos. Escribe paso a paso cómo cruzaría un Check las capas extra y señala dónde podría encarecerse el recorrido si el anidamiento fuera mucho más profundo. - Diseña una batería de pruebas para un modelo de relaciones. Con el formato
.fga.yamlde OpenFGA o uno equivalente, escribe al menos cuatro aserciones para el caso de Sara: acceso concedido a través del grupo, acceso denegado tras quitar la tupla de pertenencia, acceso denegado a un usuario sin relación y acceso concedido a un segundo documento añadido a la misma carpeta sin ninguna concesión directa nueva.
Preguntas frecuentes
¿Qué es la autorización de grano fino y en qué se diferencia del ReBAC?
La autorización de grano fino son decisiones de acceso tomadas al nivel de cada recurso y cada relación concretos y no de roles amplios: '¿puede Sara ver este documento en concreto?' y no '¿pueden los agentes de soporte ver cuentas?'. El ReBAC (control de acceso basado en relaciones) es la técnica de modelado que trata este artículo para conseguirlo: expresar los permisos como un grafo de relaciones entre sujetos y objetos y responder a las preguntas de acceso comprobando la alcanzabilidad en ese grafo. Los dos términos van juntos tan a menudo porque el ReBAC es hoy la forma dominante en que los sistemas en producción implementan una autorización de grano fino de verdad a gran escala.
¿Qué es Google Zanzibar?
Zanzibar es el sistema de autorización que Google construyó para resolver desde un único servicio global las comprobaciones de acceso de Drive, Calendar, YouTube, Photos y decenas de productos más, descrito en un artículo de USENIX de 2019. Modela cada permiso como una tupla de relación (objeto, relación, sujeto), responde a '¿puede este sujeto hacer esto sobre este objeto?' comprobando la alcanzabilidad en ese grafo y garantiza que una comprobación nunca use datos de autorización más antiguos que la última escritura relevante, la garantía de coherencia del 'nuevo enemigo'. Zanzibar es interno de Google, pero su modelo de datos y su enfoque de la coherencia se convirtieron en el plano de OpenFGA, SpiceDB y Ory Keto.
¿Es OpenFGA lo mismo que Zanzibar?
OpenFGA es un motor de autorización de código abierto que implementa las ideas centrales de Zanzibar, tuplas de relación, una API Check sobre el grafo de relaciones y reescrituras de usersets para la herencia de grupos y jerarquías, con un lenguaje de modelado más accesible y sin necesitar debajo una infraestructura a escala de Google como Spanner. No es el Zanzibar de Google, sino una reimplementación fiel y lista para producción del modelo que describía el artículo, hoy proyecto de la CNCF con sus propios equilibrios de coherencia y consultas.
¿Qué es el 'problema del nuevo enemigo' y por qué importa?
Es el fallo de seguridad en el que retirar el acceso a alguien no surte efecto lo bastante rápido: una persona sacada de un grupo en el momento T podría seguir superando una comprobación de autorización justo después de T si esa comprobación lee de una réplica desactualizada de los datos de permisos, una carrera entre una revocación y una lectura. La respuesta de Zanzibar es el 'zookie', un token de coherencia que ata una comprobación a una instantánea no más antigua que una escritura concreta, de modo que la revocación se respeta de inmediato y no 'con el tiempo'. Importa porque la mayoría de los sistemas distribuidos usan por defecto coherencia eventual para leer rápido, lo que vale para casi todo salvo para la consulta en la que un dato viejo significa una puerta que debería estar cerrada y sigue abierta.
¿Cuándo conviene un ReBAC al estilo Zanzibar en lugar de OPA, Cedar o Casbin?
Cuando la pregunta de acceso trata en el fondo de un grafo de relaciones y no de una regla plana sobre atributos: compartir (alguien comparte una carpeta con un grupo y todos los del grupo deberían ver todo lo de dentro, a cualquier profundidad), delegar o permisos con forma de organigrama donde no se conocen de antemano la profundidad ni la forma del grafo. OPA, Cedar y Casbin pueden expresar un nivel de pertenencia a grupos, pero modelar grafos de relaciones de cualquier profundidad y forma como reglas planas se vuelve muy penoso enseguida. Si tu modelo de acceso es un grafo por naturaleza, usa un motor hecho para grafos.
¿No se vuelve lento comprobar un grafo en cada petición?
Puede, y por eso todos los sistemas de la familia Zanzibar invierten mucho en que Check sea rápido: profundidad de recorrido acotada, caché agresiva de resultados intermedios e índices optimizados para lectura en las dos consultas caras, '¿puede este sujeto hacer esto?' (Check) y '¿a qué objetos puede acceder este sujeto?' (List). Además, en la mayoría de las implementaciones se puede ajustar el equilibrio entre coherencia y latencia, pidiendo más coherencia en las comprobaciones sensibles y menos en las baratas y masivas en lugar de pagar la garantía más estricta en cada consulta.