Diseño de Política RBAC + ABAC para una App de Cashback

Un caso de estudio completo: llevar una aplicación de cashback concreta desde una lista de funcionalidades hasta una autorización real y desplegada. Clasificar cada funcionalidad en el espectro de granularidad, diseñar sus roles RBAC y sus atributos ABAC, escribir la política real en Cedar, Casbin y OpenFGA para cada una, decidir dónde se ejecuta cada comprobación y probarlo todo en CI. Todos los marcos de este módulo aplicados a un sistema, de principio a fin.

Una pizarra y siete funcionalidades

Daniel tiene una pizarra, un rotulador y una lista de siete funcionalidades que la app de cashback tiene que soportar antes de que acabe el trimestre. La última vez que alguien diseñó la autorización aquí fue con una comprobación de rol por pantalla, y de ahí salió el incidente de la consola de soporte del artículo de granularidad. Esta vez quiere que cada decisión sea deliberada y poder explicarle cada una a la auditora que hizo aquella pregunta incómoda.


Cada artículo de este módulo te dio una pieza. El artículo de XACML, los cuatro componentes con los que se construye cualquier sistema de autorización. Políticas como código, tres lenguajes para escribir reglas reales. Autorización de grano fino, el modelo de grafo de relaciones para lo compartido que no cabe en una regla plana. El artículo de granularidad, una forma de decidir cuánta precisión necesita una decisión, y autorización descentralizada, una forma de decidir dónde se ejecuta. Este artículo hace lo que ninguno podía hacer por separado: tomar una aplicación real y usar todas las piezas para diseñar su autorización, desde la lista de funcionalidades hasta una política desplegada y probada.


La aplicación es CashBack Rewards, la plataforma de fidelización de comercios que este dominio ha usado en sus ejemplos. Los clientes ganan cashback con sus compras, los comercios gestionan sus propios registros de transacciones, los agentes de soporte ayudan a los clientes con problemas de cuenta y el personal de cada comercio comparte informes internos de ahorro con su equipo. Es corriente a propósito. Nada en ella necesita tecnología exótica, y de eso se trata: casi todo lo que construyas se parecerá más a esto que al grafo de compartición de Google Drive, y la habilidad aquí es reconocer qué partes, si es que hay alguna, necesitan esa maquinaria.


La lista de funcionalidades

Siete funcionalidades cubren la parte de la autorización de la app que merece diseñarse a propósito:


  1. Abrir el panel de recompensas. Cualquier cliente con una cuenta activa ve su propio resumen de cashback.
  2. Ver tu historial de transacciones. Un cliente ve las compras que le dieron cashback.
  3. Un agente de soporte ve la cuenta de un cliente, para atender un ticket.
  4. Un comercio edita una transacción en borrador, para corregir un error antes de que se liquide.
  5. Ver un informe de ahorro compartido con tu equipo, dentro del personal de un comercio.
  6. Abrir el panel de administración, para el personal interno de operaciones que gestiona la plataforma.
  7. Una administradora global revisa la cuenta de un comercio en cualquiera de las dos regiones, ahora que la empresa opera en Estados Unidos y en la UE.

No hay nada raro en esa lista. Es el tipo de funcionalidades que acumula en su primer año casi cualquier app que da servicio a la vez a empresas y a consumidores. Por eso sirve como cierre: el objetivo no es lucir maquinaria de autorización, sino mostrar que casi todo el control de acceso de una app es sencillo cuando se clasifica bien, y que solo una parte pequeña necesita peso de verdad.


Paso 1: clasifica cada funcionalidad

Antes de elegir una sola herramienta, pasa cada funcionalidad por la pregunta del artículo de granularidad: ¿la respuesta correcta depende de qué recurso o relación concretos están en juego, para este llamador concreto?


#Funcionalidad¿Solo el rol?¿Atributos de este recurso?¿Un grafo de relaciones?Capa
1Abrir el panelSí (cuenta activa)NoNoMódulo/rol
2Ver tus transaccionesNoSí (propiedad)NoRecurso
3El agente ve una cuentaEn parte (rol)Sí (ticket, horario)NoRecurso
4El comercio edita una transacción en borradorNoSí (propiedad, estado)NoRecurso
5Ver un informe compartidoNoNoSí (pertenencia al equipo, compartición)Relación
6Abrir el panel de administraciónSí (rol)NoNoMódulo/rol
7Administración global, cualquier regiónSí (rol)NoSí (alcance entre regiones)Módulo + relación

Una tabla, y la forma de todo el diseño ya está ahí antes de que exista una sola línea de política. Dos funcionalidades son barreras de rol puras. Tres son decisiones sobre atributos del recurso de distinta complejidad. Una es un grafo de relaciones de verdad. Y otra combina una barrera de rol con una cuestión entre regiones que tiene que responder el artículo de ubicación, no el de granularidad. Por eso la clasificación va primero: las herramientas del resto del artículo salen de esta tabla en lugar de elegirse funcionalidad a funcionalidad.


Paso 2: los roles RBAC

Daniel diseña el conjunto de roles más pequeño que cubre la parte de cada funcionalidad que depende del rol, y se resiste a crear un rol por cada puesto del organigrama, que es la clásica explosión de roles de la que avisaba el artículo de RBAC. Acaba con cinco.


customer es cualquiera con una cuenta activa: abre el panel y ve sus propias transacciones. merchant es el personal de un comercio que gestiona sus propios registros; tiene todo lo de un cliente, más editar sus transacciones en borrador y ver los informes compartidos con su equipo. support-agent es el personal interno de soporte, que puede ver cuentas de clientes con las condiciones de recurso del paso siguiente. admin es el personal interno de operaciones, que abre el panel de administración y gestiona la configuración de la plataforma. global-admin son unos pocos operadores entre regiones, con todo lo de admin en cualquiera de las dos.


Cinco roles, no quince. El modelo de roles responde “¿está este tipo de acción sobre la mesa para este tipo de llamador?” y, a propósito, no dice nada de qué recurso concreto. Esa pregunta es de los dos pasos siguientes, y mantenerla aparte importa. Mezclar “¿pueden los agentes de soporte ver cuentas?” (rol) con “¿puede este agente ver esta cuenta?” (recurso) en una regla enorme es como los sistemas RBAC acaban con cientos de roles casi idénticos, cada uno intentando codificar una excepción de un recurso concreto que nunca fue trabajo del rol.


Paso 3: los atributos ABAC

Tres de las siete funcionalidades necesitan algo más que un rol. Daniel apunta los atributos que esas decisiones leen de verdad, separados a la manera de XACML en sujeto, recurso y entorno, porque esa separación es lo que mantiene legibles las políticas del paso siguiente.


Del sujeto salen role, que usan todas las funcionalidades; user_id, para las comprobaciones de propiedad de las funcionalidades 2 y 4; assigned_ticket_customer_ids, los clientes con los que el agente tiene tickets abiertos, para la funcionalidad 3, y team_id, que la funcionalidad 5 usa a través de una relación y no como condición directa. Del recurso salen owner_id, para las funcionalidades 2 y 4; status, borrador o liquidada, para la 4, y customer_id, para la 3. Del entorno salen current_time, para el horario laboral de la funcionalidad 3, y region, para la 7.


Nueve atributos, casi todos usados por más de una funcionalidad, forman una superficie de Policy Information Point que un equipo puede gestionar. Cada uno se puede nombrar, tiene una fuente conocida y se puede mantener al día, que es la cuestión operativa que planteaba el artículo de XACML sobre los PIP y el de grano fino sobre los datos de relaciones: un atributo o una tupla solo es tan fiable como el sistema que lo mantiene actualizado.


CashBack Rewards — una superficie de autorización, cuatro capas Cuatro capas de autorización para la app CashBack Rewards — perímetro, módulo/rol, recurso, relación — con cada una de las siete funcionalidades de la app ubicada en su carril. CashBack Rewards — una superficie de autorización, cuatro capas PERÍMETRO Comprobación de validez de token MÓDULO / ROL customer merchant support-agent admin global-admin → panel → panel, editar txn, informe → vista agente (carril recurso) → panel admin → panel admin + entre regiones Abrir panel Abrir panel de administración RECURSO Ver transacciones propias atributos: owner_id herramienta: Cedar Agente ve cuenta atributos: assigned_ticket_ids, horario laboral herramienta: Cedar Comercio edita transacción en borrador atributos: owner_id, status herramienta: Casbin RELACIÓN Ver informe compartido herramienta: OpenFGA depende de: membresía de equipo + tuplas de compartición entre regiones — almacén consciente de la región cada funcionalidad cae en exactamente un carril (o dos, para el caso del administrador entre regiones).
Toda la superficie de autorización de la app, un carril por capa de granularidad. Cada una de las siete funcionalidades cae en un carril, o en dos en el caso de la administración entre regiones. Es la clasificación del paso 1 dibujada como la arquitectura en la que se convierte.

Paso 4: escribe la política, funcionalidad a funcionalidad

Funcionalidades 1 y 6: barreras de rol puras

Abrir el panel y abrir el panel de administración no necesitan más que una comprobación de rol: ni una ida y vuelta al PDP ni una consulta de atributos, solo un claim que ya está en el token de sesión de quien llama. En un servicio con Casbin embebido es casi el matcher más simple que permite el lenguaje:


[request_definition]
r = sub, act
 
[policy_definition]
p = sub, act
 
[matchers]
m = r.sub == p.sub && r.act == p.act

p, customer, open_dashboard
p, merchant, open_dashboard
p, admin, open_admin_panel
p, global-admin, open_admin_panel

No hay columna obj. Estas dos funcionalidades no tienen ningún recurso sobre el que razonar, y eso es justo lo que las sitúa en la capa de módulo y no en la de recurso. Traer aquí un motor más pesado sería modelar de más, como advertía el artículo de granularidad.


Funcionalidad 2: ver tus transacciones

La primera decisión sobre atributos del recurso: quien llama tiene que ser el dueño de la transacción que pide. La forma de permit y forbid de Cedar, limitada a propósito para que siga siendo analizable, expresa una condición de propiedad con limpieza:


permit (
  principal,
  action == Action::"viewTransaction",
  resource
) when {
  resource.owner_id == principal.user_id
};

Funcionalidad 3: un agente de soporte ve una cuenta

Es la consola de soporte del artículo de granularidad, por fin escrita como una política real. El rol support-agent permite el tipo de acción, pero esta consulta concreta exige un ticket abierto asignado al agente y horario laboral:


permit (
  principal in Role::"support-agent",
  action == Action::"viewAccount",
  resource
) when {
  resource.customer_id in principal.assigned_ticket_customer_ids &&
  context.current_time.hour >= 9 &&
  context.current_time.hour < 18
};

Aquí la capa de recurso se gana lo que cuesta. El rol del paso 2 es necesario pero no suficiente, y las dos condiciones extra son toda la diferencia entre “cualquier agente, cualquier cuenta, a cualquier hora” y el mínimo privilegio que el negocio necesita de verdad. Si es fuera de horario, o la cuenta no tiene ningún ticket asignado, la misma política deniega, sin una segunda regla que mantener. Y si vuelve el equipo dedicado del socio comercial del artículo de granularidad, es una condición más en la misma política, no un rol nuevo.


Funcionalidad 4: un comercio edita una transacción en borrador

Otra vez propiedad, más una condición: una transacción liquidada no debe poder editarse nunca, sea de quien sea. Es lo bastante pequeña para quedarse en el modelo embebido de Casbin en lugar de ir a Cedar, porque la comprobación no tiene ningún motivo para salir del servicio que es dueño de los datos de transacciones:


[request_definition]
r = sub, obj_owner, obj_status, act
 
[policy_definition]
p = act, allowed_status
 
[matchers]
m = r.sub == r.obj_owner && r.act == p.act && r.obj_status == p.allowed_status

p, edit_transaction, draft

El matcher compara directamente a quien llama con el dueño del recurso (r.sub == r.obj_owner, que pasa el servicio que llama en lugar de buscarlo Casbin) y fija el estado permitido en draft. Una transacción liquidada no tiene ninguna fila de política que encaje, así que cae en la denegación por defecto. Es la misma idea de propiedad que en la funcionalidad 2 con otra herramienta, porque esta decisión vive entera dentro de un servicio y no hay razón para pagar un salto de red hasta un PDP aparte.


Funcionalidad 5: ver un informe de ahorro compartido con tu equipo

Es la única funcionalidad de la lista que de verdad es una relación y no un atributo. Un informe compartido con un equipo lo ve todo el equipo, se organice como se organice su pertenencia, y esa es la forma para la que se construyó OpenFGA:


type user
 
type team
  relations
    define member: [user]
 
type report
  relations
    define viewer: [user, team#member]

{"user": "user:sara", "relation": "member", "object": "team:merchant-42-staff"}
{"user": "team:merchant-42-staff#member", "relation": "viewer", "object": "report:q3-savings"}

sequenceDiagram
  accTitle: Comprobación de la vista de un informe compartido a través de la pertenencia al equipo
  accDescr: El diagrama muestra a un cliente que pide a OpenFGA comprobar si Sara puede ver el informe de ahorro del tercer trimestre. OpenFGA lee la tupla viewer del informe, que nombra como userset la relación member del equipo de personal del comercio y no a un usuario directo. OpenFGA expande ese userset leyendo las tuplas member del equipo y encuentra a Sara como miembro directo. Como ha encontrado un camino a través de un nivel de pertenencia al equipo, OpenFGA devuelve Allow al cliente.
  Client->>OpenFGA: Check(report:q3-savings, viewer, sara)
  OpenFGA->>OpenFGA: lee la tupla viewer
  OpenFGA->>OpenFGA: expande las tuplas member del equipo
  OpenFGA->>OpenFGA: Sara es miembro directo
  OpenFGA-->>Client: Allow (hay camino)
El Check del informe compartido, seguido para una empleada de un comercio. Sara es miembro del equipo de personal de su comercio, el equipo recibió el permiso viewer sobre el informe y el Check de OpenFGA recorre ese camino de un salto y devuelve Allow. Es el modelo de alcanzabilidad del artículo de grano fino aplicado a la función real de compartir de esta app.

Todo lo demás de la lista se podía resolver sin un motor de relaciones, y así se hizo. Esto no, porque la pertenencia a equipos y la compartición se anidan de formas que las reglas planas no expresan con limpieza. Es la disciplina que defendía el artículo de granularidad: traer la herramienta pesada solo donde la pregunta es de verdad un grafo.


Funcionalidad 7: una administradora global entre regiones

Esta es una barrera de rol, global-admin, con una consecuencia de ubicación y no una forma de política nueva. La decisión interesante no es qué comprobar, sino dónde viven los datos que lee la comprobación, que es el paso siguiente.


Paso 5: dónde se ejecuta cada comprobación

Cada funcionalidad tiene ya su política. Ubicarlas sigue directamente el artículo de autorización descentralizada.


Las comprobaciones de rol de las funcionalidades 1 y 6 no cuestan casi nada: el claim ya está en el token y puede verificarse en el borde o en el primer gateway, sin llamar a ningún PDP. La política Cedar de la funcionalidad 2 se ejecuta en un sidecar junto al servicio de transacciones, porque owner_id es un dato local de la aplicación que no tiene por qué salir de ese servicio. La de la funcionalidad 3 se ejecuta igual, en un sidecar junto al backend de la consola de soporte, donde ya viven los datos de asignación de tickets. La comprobación Casbin de la funcionalidad 4 se ejecuta dentro del proceso, embebida en el servicio de transacciones, que es justo el despliegue para el que se hizo Casbin; es una llamada a una función y no necesita sidecar. El Check de OpenFGA de la funcionalidad 5 se ejecuta contra un despliegue de OpenFGA compartido y consciente de la región, porque los datos de relaciones abarcan usuarios y equipos de una forma que ningún servicio posee entera.


La funcionalidad 7 es la que obliga a decidir de verdad. El claim de rol es barato de comprobar en cualquier sitio, pero los datos de relaciones y de recursos que toca una administradora global viven en dos almacenes particionados por región. De las opciones del artículo de autorización descentralizada, la app acepta la latencia de at_least_as_fresh para el camino poco frecuente de la administración global, en lugar de pagar la latencia completa de escritura entre regiones en cada escritura regional o de particionar hasta dejar fuera el único rol que tiene que cruzar la frontera de forma legítima. Queda escrito como una excepción conocida.


sequenceDiagram
  accTitle: Una petición seguida por las capas de perímetro, módulo y relación
  accDescr: El diagrama muestra una petición de un cliente para ver un informe compartido que primero pasa por una comprobación de perímetro en el borde o en el gateway, que verifica que el token es válido. Después llega a una comprobación de rol en la capa de módulo, que confirma que quien llama tiene el rol merchant, que en principio permite ese tipo de acción. Solo cuando se superan las dos comprobaciones baratas llega la petición a la capa de relación, donde OpenFGA comprueba si ese informe se compartió con un equipo al que pertenece quien llama. Si la comprobación de relación encuentra un camino, el servicio devuelve el informe; si no, lo deniega.
  Client->>Gateway: GET informe (con token)
  Gateway->>Gateway: perímetro: ¿token válido?
  Gateway->>Service: reenvía (rol: merchant)
  Service->>Service: módulo: ¿el rol permite ver informes?
  Service->>OpenFGA: Check(informe, viewer, usuario)
  OpenFGA-->>Service: Allow (hay camino)
  Service-->>Client: contenido del informe
Una petición representativa, una empleada de un comercio que abre un informe de ahorro compartido, seguida por todas las capas que usa la app. La comprobación del token y la barrera de rol son baratas y van primero; solo una petición que supera las dos llega a la comprobación de relación de OpenFGA, el paso más caro y el único que necesita saber algo de la pertenencia al equipo.

Paso 6: pruébalo todo en CI

Cada lenguaje de los anteriores trae su propia forma de probar, y la disciplina de las políticas como código vale sea cual sea la herramienta que escribió la regla: un cambio de autorización roto tiene que fallar en una pull request, no en producción.


Las políticas Cedar de las funcionalidades 2 y 3 tienen una batería de pruebas de Cedar validada contra el esquema de la app, más las herramientas de análisis comprobando que las dos reglas permit nunca se solapan de forma que concedan más de lo previsto. Los modelos de Casbin de las funcionalidades 1, 4 y 6 tienen pruebas unitarias normales en el lenguaje del servicio, que afirman que peticiones concretas dan el permitir o el denegar esperado. El modelo de OpenFGA de la funcionalidad 5 tiene un fichero .fga.yaml de aserciones: con las tuplas de Sara, Check(report, viewer, sara) tiene que dar true; sin la tupla de pertenencia, false; y para un usuario sin relación, false desde el principio.


flowchart LR
  accTitle: Un único pipeline de CI que prueba tres lenguajes de políticas distintos antes de publicar
  accDescr: El diagrama muestra una pull request que lanza tres trabajos de prueba en paralelo, uno por cada lenguaje de políticas de la app. El trabajo de Cedar ejecuta el validador y las herramientas de análisis de Cedar sobre las políticas Cedar. El de Casbin ejecuta pruebas unitarias normales en el lenguaje del servicio sobre los modelos de Casbin. El de OpenFGA ejecuta el comando fga test sobre el fichero de aserciones. Los tres tienen que pasar antes de que el pipeline publique un nuevo paquete de políticas, que es lo que acaban descargando los sidecars y los workers del borde del artículo de autorización descentralizada.
  PR[Pull request: cambio de política] --> Cedar[Validador Cedar + análisis]
  PR --> Casbin[Pruebas unitarias Casbin]
  PR --> FGA[Aserciones .fga.yaml de OpenFGA]
  Cedar --> Gate{¿Todo pasa?}
  Casbin --> Gate
  FGA --> Gate
  Gate -- sí --> Publish[Publica el paquete de políticas]
  Gate -- no --> Block[["Bloquea el merge"]]
Un único pipeline de CI que valida todos los lenguajes de políticas de la app antes de que nada llegue a producción. La herramienta de pruebas de cada motor se ejecuta por separado, el pipeline solo pasa si pasan las tres y solo un pipeline en verde puede publicar un nuevo paquete de políticas.

Atajos que este diseño rechazó

Hay tres atajos tan frecuentes en sistemas reales que merece la pena nombrarlos, porque cada uno parece de lo más razonable justo en el paso en el que este diseño fue más despacio.


El primero es saltarse la clasificación y tirar de la herramienta más nueva. Habría sido fácil modelar toda la app en OpenFGA, incluidas las dos barreras de rol puras. Funcionaría, pero cada petición pagaría el recorrido de un grafo para responder algo que siempre fue “¿el rol de quien llama es X?”, que un claim del token responde solo. Clasificar primero es lo que lo evitó.


El segundo es meter condiciones de recurso en el modelo de roles. Para la funcionalidad 3 habría sido tentador crear un rol support-agent-with-open-ticket que se concede y se retira ticket a ticket. Eso convierte una tabla de roles pensada para ser pequeña y estable en una que cambia con cada asignación de ticket. Es la explosión de roles de nuevo, traída por pedirle al RBAC solo que responda una pregunta que necesitaba ABAC encima.


El tercero es probar cada lenguaje por separado y no probar nunca las capas. Un pipeline que ejecuta las pruebas de Cedar, Casbin y OpenFGA pero nunca confirma que la comprobación de rol de la funcionalidad 3 va antes que la de atributos, para que un claim de rol mal formado no se cuele hasta una comprobación de recurso que da por hecho que ya pasó un rol válido, se deja justo la prueba que el artículo de granularidad señalaba como el hueco habitual.


Resumen

Una aplicación y todos los marcos del módulo, en orden. Daniel clasificó antes de elegir herramientas, y siete funcionalidades, cada una con su pregunta, se repartieron en capas antes de que existiera ninguna política. El modelo RBAC se quedó pequeño a propósito, cinco roles que dicen si un tipo de acción está sobre la mesa y nada sobre qué recurso. Los atributos ABAC son una lista corta y reutilizable con fuentes conocidas, nueve que cubren tres decisiones de recurso distintas. El lenguaje de políticas siguió a la capa y no al revés: Casbin para las barreras de rol embebidas y la comprobación de propiedad y estado, Cedar para las decisiones de recurso analizables, OpenFGA para la única relación de verdad. La ubicación fue una decisión aparte de la política, porque la lógica de una política Cedar no cambia según dónde se ejecute, pero su latencia y su coherencia sí. Y todos los lenguajes se prueban en el mismo pipeline, que solo es tan fiable como su capacidad de bloquear un merge.



Tres preguntas para ponerte a prueba

  1. La funcionalidad 3 usa una comprobación de rol y dos condiciones de atributos. Explica qué saldría mal, como agujero de seguridad o como tabla de roles inmanejable, si la expresaras solo con RBAC, y por otro lado qué saldría mal solo con ABAC y sin comprobación de rol.
  2. Explica por qué la funcionalidad 4 se implementó en Casbin y no en Cedar, usando el razonamiento de ubicación y granularidad de este artículo y no solo “porque es más simple”.
  3. Alguien propone una funcionalidad nueva: “los comercios pueden ver un informe agregado de cashback de todos los equipos de su región”. Con las tres preguntas de la tabla de clasificación, decide a qué capa pertenece y cuál de las herramientas actuales de la app, o una nueva, encajaría.

Ejercicios prácticos

  1. Clasifica las funcionalidades de tu propia app. Elige entre cinco y siete funcionalidades reales de una aplicación que uses o estés construyendo y monta para ellas la tabla de clasificación de este artículo, solo rol, atributos del recurso o relación, antes de elegir ninguna herramienta.
  2. Escribe una política para una funcionalidad de atributos del recurso. En Cedar o en Casbin, escribe la política real de una funcionalidad de tu tabla que dependa de propiedad o de estado, siguiendo la forma de la funcionalidad 2 o de la 4.
  3. Diseña la barrera de CI para tu política. Para esa misma funcionalidad, esboza cómo sería una prueba que pasa y otra que falla, y qué debería bloquear el pipeline antes de que la política llegue a producción, usando el paso 6 como plantilla.

Preguntas frecuentes

¿Por qué diseñar RBAC y ABAC juntos en lugar de elegir uno?

Porque las aplicaciones reales no viven en una sola capa de granularidad. La mayoría de las funcionalidades de la app de cashback de este artículo se modelan bien con una comprobación de rol, unas pocas necesitan condiciones de atributos encima de ese rol y una necesita un grafo de relaciones completo. El RBAC responde '¿permite el rol de quien llama este tipo de acción?', el ABAC responde '¿depende de hechos de esta petición concreta?', y tratarlos como rivales en lugar de como capas complementarias es justo el error del que avisaba el artículo de granularidad.

¿Cómo decido qué lenguaje de políticas usar para cada funcionalidad en un sistema real?

Clasifica primero la granularidad de la funcionalidad y luego elige la herramienta para esa capa. Una barrera de rol pura es un claim o un matcher de Casbin; una decisión sobre atributos del recurso que gana con el análisis formal encaja con Cedar; una decisión embebida en un servicio sin salto de red encaja con Casbin; una decisión que depende de un grafo de relaciones es OpenFGA. Este artículo recorre las cuatro en una sola aplicación para que la correspondencia sea concreta.

¿Necesito OpenFGA (o un ReBAC al estilo Zanzibar) en cualquier app que tenga una función de 'compartir'?

Solo si lo compartido puede anidarse o ramificarse de formas que no puedes enumerar como reglas planas: un grupo compartido con otro grupo, una carpeta dentro de otra. La app de cashback de este artículo tiene exactamente una funcionalidad así, un informe de ahorro compartido, y todas las demás, incluidas varias de propiedad, se resuelven bien y más barato con una comprobación de atributos del recurso. Recurrir al ReBAC cada vez que aparecen las palabras 'compartido con' es el error de modelar de más que señalaba el artículo de grano grueso frente a grano fino.

¿Cómo se combinan de verdad los roles RBAC y los atributos ABAC en una petición?

El rol responde si el puesto de quien llama permite en principio este tipo de acción; los atributos responden si esta petición concreta cumple las condiciones que esa acción exige. El rol de un agente de soporte permite ver cuentas de clientes en general, y eso es RBAC. Que pueda ver esta cuenta ahora mismo depende de que tenga asignado un ticket abierto y de que sea horario laboral, y eso es ABAC encima. Ninguno basta solo; juntos son la comprobación de la capa de recurso del artículo de granularidad, escrita aquí como una política Cedar real.

¿Dónde se ejecutan en producción todas estas comprobaciones (de rol, de atributos, de relación)?

Siguiendo el artículo de ubicación: las comprobaciones de perímetro y de módulo (validez del token, barreras de rol) son lo bastante baratas para ejecutarse en el borde o en un sidecar del mesh; las de atributos del recurso se ejecutan en un sidecar de OPA o Cedar por servicio, o dentro del proceso, porque necesitan datos locales de la aplicación; y la comprobación de relación de la única funcionalidad ReBAC se ejecuta contra un despliegue de OpenFGA consciente de la región, porque sus datos tienen requisitos reales de coherencia y de residencia. El artículo sitúa explícitamente cada funcionalidad de la app.

¿Cuál es el mayor error que cometen los equipos al aplicar esto en una app real?

Saltarse la clasificación y elegir herramienta por costumbre o por moda: montar un grafo de relaciones para algo que siempre iba a ser una comprobación de rol, o fijar una comprobación de rol para una funcionalidad que en silencio necesitaba propiedad por recurso y acabó siendo un agujero de seguridad que nadie vio hasta una auditoría. El remedio hacia el que iba todo el módulo es mecánico: clasificar cada funcionalidad de forma explícita antes de elegir su herramienta, como hace este artículo con las siete funcionalidades de la app.