Ir al contenido principal

Diseñando un Sistema de Control de Acceso Declarativo para Microservicios

¿Cómo mantener el control de acceso bajo control cuando tu arquitectura crece en microservicios, roles y recursos? Este enfoque declarativo te ayuda a definir reglas legibles, seguras y escalables, sin caer en la complejidad ni perder el gobierno.

En el desarrollo de sistemas distribuidos basados en microservicios, uno de los mayores retos técnicos y de gobernanza es establecer un modelo de control de acceso que sea:

  • Centralizado, pero no invasivo
  • Flexible, pero seguro por defecto
  • Expresivo, pero fácil de mantener
  • Y sobre todo, escalable, sin volverse una pesadilla al crecer el número de recursos, roles y reglas

En este artículo te presento un enfoque declarativo para la definición de permisos en un ecosistema de microservicios, inspirado en ideas de RBAC, pero diseñado para ser portable, semántico y extrapolable.

🎯 Objetivo

Construir un sistema de autorización que permita:

  • Definir permisos a nivel de acciones y atributos por recurso
  • Asociarlos a roles con posibles relaciones de herencia
  • Evaluar condiciones simples (ej. role == "admin", role in (...))
  • Ser consumido por los microservicios de forma eficiente y cacheable
  • Evolucionar fácilmente en el tiempo con cambios mínimos

🧱 Estructura conceptual

El modelo se basa en tres conceptos principales:

  • Roles: identificadores semánticos (viewer, editor, admin) que pueden heredar de otros roles.
  • Recursos: entidades lógicas del sistema (tenant, invoice, user) que tienen acciones (read, update, ...) y atributos (name, secretKey, ...).
  • Reglas de acceso: expresadas en un DSL (lenguaje específico de dominio) muy legible y conciso, con soporte para condiciones básicas.

✍️ Ejemplo de reglas declaradas

role editor extends viewer;
role admin extends editor;

resource tenant:author extends tenant;

match tenant {
  actions {
    allow read, list if role in ("admin", "editor");
    allow update, delete if role == "admin";
  }

  attributes {
    allow name, description if role in ("admin", "editor");
    deny secretKey if role != "admin";
  }
}

match tenant:author {
  actions {
    allow update if role == "admin" or user.id == resource.authorId;
  }
}

🧠 Consideraciones de diseño

1. Política de evaluación conservadora

Se aplica una estrategia deny-by-default y deny-prevalece-sobre-allow, con las siguientes reglas:

  • Si no hay ninguna regla que coincida con una acción o campo → se deniega el acceso.
  • Si alguna regla coincidente dice deny → se deniega, aunque otras digan allow.
  • Solo si todas las reglas coincidentes dicen allow → se permite.

2. Herencia estructural opcional

La herencia de roles y recursos se define explícitamente:

role admin extends editor;
resource invoice:summary extends invoice;

Esto permite un modelo de seguridad evolutivo, donde roles más generales pueden delegar permisos en roles más especializados, o recursos secundarios heredan comportamientos por defecto.

⚙️ Aplicación en un sistema de microservicios

🔄 Flujo de integración:

  • Cada microservicio registra sus recursos (acciones, atributos) durante el arranque.
  • El servicio IAM central mantiene el conjunto completo de reglas de acceso.
  • Las reglas se evalúan y extrapolan para cada combinación de rol y recurso.
  • El resultado se convierte en una estructura cacheable, fácilmente consumible vía API o como archivos estáticos por los microservicios.
  • Cuando las reglas cambian, los microservicios pueden utilizar ETag o If-Modified-Since para minimizar el tráfico y evitar recálculos innecesarios.

✅ Ventajas del enfoque

Ventaja Descripción
🔒 Seguro por defecto Las omisiones no abren puertas: sin regla explícita no hay acceso
✨ Legibilidad humana El DSL es limpio, mantenible y fácil de versionar en Git
📦 Compatible con caché Los permisos extrapolados pueden entregarse como JSON estático
🧩 Modular y extensible Puedes añadir condiciones más expresivas, etiquetas, herencia condicional, etc.
🔁 Desacoplado Los microservicios no necesitan saber cómo se evalúan las reglas

🧪 Posibles extensiones

  • Condiciones más complejas: soporte para and, or, valores de user, resource o context.
  • Tags de atributos: por ejemplo, permitir el acceso a todos los campos con tag:public.
  • Soporte para scopes OAuth2: mapeo entre permisos y scopes API.
  • UI de administración: formularios dinámicos generados a partir del árbol de recursos y reglas.

🚀 Conclusión

Este modelo ofrece un equilibrio ideal entre declaratividad, seguridad y mantenibilidad para entornos distribuidos modernos. A través de una DSL ligera y una política de evaluación coherente, puedes mantener el control de acceso en crecimiento sin perder la visibilidad ni caer en la complejidad.

Si estás construyendo una plataforma orientada a microservicios, adoptar un enfoque así puede ahorrarte meses de trabajo y evitar errores costosos en el futuro.

Comentarios