Recursos, alcances, permisos y políticas en keycloak


81

Quiero crear un sistema de control de acceso basado en roles bastante simple usando el sistema de autorización de Keycloak. El sistema que Keycloak está reemplazando nos permite crear un "usuario", que es miembro de uno o más "grupos". En este sistema heredado, un usuario recibe "permiso" para acceder a cada una de las aproximadamente 250 "capacidades", ya sea a través de la pertenencia a un grupo (donde se asignan permisos a los grupos) o mediante una concesión directa de un permiso al usuario.

Me gustaría asignar el sistema heredado a las autorizaciones de keycloak.

Debería ser sencillo para mí mapear cada "capacidad" en el sistema existente a un recurso de capa de clave y un conjunto de ámbitos de capa de clave. Por ejemplo, una capacidad "viewAccount" obviamente se asignaría a un recurso de "cuenta" y un alcance de "vista"; y "viewTransaction" se asigna a un recurso de "transacción" ... pero ¿es una buena práctica crear solo un alcance de "vista" y usarlo en varios recursos (cuenta, transacción, etc.)? ¿O debería crear un alcance "viewAccount", un alcance "viewTransaction", etc.?

Del mismo modo, estoy un poco confundido acerca de los permisos. Para cada combinación práctica de recurso y alcance, ¿es una práctica habitual crear un permiso? Si hay varios permisos que coinciden con un recurso / alcance determinado, ¿qué hace Keycloak? Supongo que la intención de Keycloak es permitirme configurar una matriz de permisos contra recursos y alcances, por ejemplo, podría tener permiso para acceder a "cuentas" y permiso para "ver" alcance, por lo que tendría permiso para ver las cuentas?

Lo pregunto porque el resultado de todo esto parece ser que mi vieja capacidad "viewAccount" termina creando un recurso "Account", con alcance "View", y un permiso "viewAccount", que parece llevarme de vuelta a donde estaba. Lo cual está bien, si es correcto.

Finalmente, obviamente necesito un conjunto de políticas que determinen si se debe aplicar viewAccount. Pero, ¿tengo razón en que esto significa que necesito una política para cada uno de los grupos heredados a los que podría pertenecer un usuario? Por ejemplo, si tengo un rol de "servicio de asistencia técnica", entonces necesito una política de "membresía de servicio de asistencia técnica", que luego podría agregar al permiso "ver cuenta". ¿Es esto correcto?

Gracias,

marca


26
Keycloak parece un sistema bastante maduro y muy capaz, pero lo que realmente puede hacer sigue siendo un misterio, ya que parece haber tantas preguntas y tan pocas respuestas. Literalmente, me hago todas las preguntas de su publicación y no puedo encontrar ninguna respuesta. ¿Por qué no existen buenos tutoriales? ¿Nadie realmente usa estas cosas? ¿O nadie se molesta en escribir sobre eso?
Stijn de Witt

3
Keycloak está funcionando muy bien para nosotros en producción (hasta ahora) con la excepción de la autorización, que fue realmente difícil de relacionar con mis problemas reales. Pero estoy de acuerdo, hay mucha documentación sobre cómo Keycloak hace OIDC, pero también una suposición generalizada de que conocemos OAuth y OIDC. Es difícil relacionar Keycloak con los problemas de la aplicación si aún no conoces OIDC, pero para mí Keycloak fue la introducción a OIDC, lo cual es un poco complicado. Descubrí que descargarlo y jugar con él era lo mejor.
Doctor Eval

6
de acuerdo con estos comentarios, la documentación de keycloak y los casos de uso
apestan

20
¡Desarrolladores de Keycloak, tomen nota de esta pregunta! Su documentación es bastante buena, pero necesita más tutoriales que aborden las preguntas planteadas aquí. También puede considerar migrar de la lista de correo de la vieja escuela a algo un poco más fácil de usar como un foro o simplemente Stackoverflow.
GGGforce

5
Respuesta tardía, pero todas sus suposiciones son básicamente correctas. En cuanto a cuál es la mejor práctica, creo que es difícil de decir ya que la capacidad es muy nueva. No estoy seguro de si incluso los desarrolladores de kc saben cuáles son las mejores prácticas en este momento.
cen

Respuestas:


119

Sé que llego más de 2 años tarde, pero me imagino que compartiría lo que sé y, con suerte, aliviaré un poco el dolor de los futuros lectores. Transparencia total: de ninguna manera soy un experto en Keycloak / OAuth / OIDC y lo que sé es principalmente de la lectura de documentos, libros, el buen YouTube y jugar con la herramienta.

Este artículo constará de dos partes:

  1. Intentaré responder todas sus preguntas lo mejor que pueda.
  2. Le mostraré cómo puede jugar con políticas / ámbitos / permisos en Keycloak sin necesidad de implementar una aplicación separada para comprender mejor algunos de los conceptos centrales de este hilo. Sin embargo, tenga en cuenta que esto está destinado principalmente a que todos comiencen. Estoy usando Keycloak 8.0.0.

Parte I

Algo de terminología antes de comenzar:

  • En Keycloak, puede crear 2 tipos de permisos: Basada en Recursos y Alcance-Based .
  • En pocas palabras, para los Resource-Basedpermisos, lo aplica directamente a su recurso
  • Para obtener Scoped-Basedpermiso, lo aplica a su (s) alcance (s) o alcance (s) y recurso.

¿Es una buena práctica crear un solo alcance de "vista" y utilizarlo en varios recursos (cuenta, transacción, etc.)? ¿O debería crear un alcance "viewAccount", un alcance "viewTransaction", etc.?

Los ámbitos representan un conjunto de derechos sobre un recurso protegido. En su caso, tiene 2 recursos: accounty transaction, por lo que me inclinaría hacia el segundo enfoque.

A la larga, tener un mundial viewalcance asociado con todos sus recursos (por ejemplo account, transaction, customer, settlement...) hace difícil la autorización tanto de manejo y la adaptación a cambios en los requisitos de seguridad.

Aquí hay algunos ejemplos que puede consultar para familiarizarse con el diseño.

Sin embargo, tenga en cuenta que no estoy afirmando que no deba compartir ámbitos entre recursos. De hecho, Keycloakpermite esto para recursos con el mismo type. Por ejemplo, podría necesitar ambos viewAccounty el viewTransactionalcance para leer una transacción en una cuenta determinada (después de todo, es posible que necesite acceder a la cuenta para ver las transacciones). Sus requisitos y estándares influirán en gran medida en su diseño.

Para cada combinación práctica de recurso y alcance, ¿es una práctica habitual crear un permiso?

Disculpas, no entiendo completamente la pregunta, así que seré un poco amplio. Para otorgar / denegar el acceso a un resource, debe:

  • Defina sus políticas
  • Defina sus permisos
  • Aplicar sus políticas a sus permisos
  • Asocie sus permisos a uno scopeo resource(o ambos)

para que la aplicación de la política surta efecto. Ver proceso de autorización .

La forma de configurar todo esto depende totalmente de usted. Podrías, por ejemplo:

  • Defina políticas individuales y vincule cada política con el permiso correspondiente.

  • Mejor aún, defina políticas individuales, luego agrupe todas sus políticas relacionadas bajo una aggregatedpolítica (una política de políticas) y luego asocie esa política agregada con el scope-basedpermiso. Puede hacer que ese scoped-basedpermiso se aplique tanto al recurso como a todo su alcance asociado.

  • O bien, podría dividir aún más sus permisos aprovechando los dos tipos separados. Puede crear permisos únicamente para sus recursos a través del resource-basedtipo de permiso y asociar por separado otros permisos únicamente con un alcance a través del scope-basedtipo de permiso.

Tienes opciones.

Si hay varios permisos que coinciden con un recurso / alcance determinado, ¿qué hace Keycloak?

Esto depende de

  1. El servidor de recursos Decision Strategy
  2. Cada permiso Decision Strategy
  3. El Logicvalor de cada póliza .

El Logicvalor es similar con el !operador de Java . Puede ser Positiveo Negative. Cuando Logices así Positive, la evaluación final de la política permanece sin cambios. Cuando es Negative, el resultado final se niega (por ejemplo, si una política se evalúa como falsa y Logices Negative, entonces lo será true). Para simplificar las cosas, supongamos que Logicsiempre está configurado en Positive.

Eso Decision Strategyes lo que realmente queremos abordar. El Decision Strategypuede ser tanto Unanimouso Affirmative. De los documentos,

Estrategia de decisión

Esta configuración cambia la forma en que el motor de evaluación de políticas decide si se debe otorgar o no un recurso o ámbito en función del resultado de todos los permisos evaluados. Afirmativo significa que al menos un permiso debe evaluar una decisión positiva para otorgar acceso a un recurso y sus alcances. Unánime significa que todos los permisos deben evaluar una decisión positiva para que la decisión final también sea positiva. Por ejemplo, si dos permisos para un mismo recurso o alcance están en conflicto (uno de ellos otorga acceso y el otro lo niega), el permiso para el recurso o alcance se otorgará si la estrategia elegida es Afirmativa. De lo contrario, una sola denegación de cualquier permiso también denegará el acceso al recurso o alcance.

Usemos un ejemplo para comprender mejor lo anterior. Suponga que tiene un recurso con 2 permisos y alguien está intentando acceder a ese recurso (recuerde, Logices Positivepara todas las políticas). Ahora:

  1. Permission Onetiene un Decision Strategyconjunto de Affirmative. También tiene 3 políticas donde cada uno evalúa:
    • true
    • false
    • false

Dado que una de las políticas está configurada en true, Permission Onese establece en true(Afirmativo; solo se necesita 1 true).

  1. Permission Twotiene un Decision Strategyconjunto de Unanimous2 políticas:
    • true
    • false

En este caso Permission Twoes falseporque una política es falsa (Unánime - todas deben serlo true).

  1. Ahora viene la evaluación final . Si el servidor de recursos Decision Strategyestá configurado en Affirmative, el acceso a ese recurso se otorgaría porque Permission Onees true. Si, por otro lado, el servidor de recursos Decision Strategyestá configurado en Unanimous, se denegará el acceso.

Ver:

Seguiremos revisando esto. Explico cómo configurar el servidor de recursos Decision Strategy en la Parte II.

entonces, por ejemplo, podría tener permiso para acceder a "cuentas" y permiso para "ver" el alcance, por lo tanto, ¿tendría permiso para ver cuentas?

La respuesta corta es sí. Ahora, ampliemos esto un poco :)

Si tiene el siguiente escenario:

  1. El servidor de recursos está Decision Strategyconfigurado en UnanimousoAffirmative
  2. El permiso para acceder al account/{id}recurso estrue
  3. El permiso para acceder al viewalcance estrue

Se le otorgará acceso para ver la cuenta.

  • true+ truees igual a truedebajo de Affirmativeo Unanimous Decision Strategy.

Ahora si tienes esto

  1. El servidor de recursos está Decision Strategyconfigurado enAffirmative
  2. El permiso para acceder al account/{id}recurso estrue
  3. El permiso para acceder al viewalcance esfalse

También se le otorgará acceso para ver la cuenta.

  • true+ falseestá truebajo la Affirmativeestrategia.

El punto aquí es que el acceso a un recurso determinado también depende de su configuración, así que tenga cuidado, ya que es posible que no desee el segundo escenario.

Pero, ¿tengo razón en que esto significa que necesito una política para cada uno de los grupos heredados a los que podría pertenecer un usuario?

No estoy seguro de cómo se comportó Keycloak hace 2 años, pero puede especificar una política basada en grupos y simplemente agregar todos sus grupos bajo esa política. Ciertamente, no es necesario que cree una política por grupo.

Por ejemplo, si tengo un rol de "servicio de asistencia técnica", entonces necesito una política de "membresía de servicio de asistencia técnica", que luego podría agregar al permiso "ver cuenta". ¿Es esto correcto?

Bastante. Hay muchas formas de configurar esto. Por ejemplo, puede:

  1. Cree su recurso (por ejemplo /account/{id}) y asócielo con el account:viewalcance.
  2. crear una política basada en roles y agregar el helpdeskrol bajo esa política
  3. Cree un Scope-Basedpermiso llamado viewAccounty átelo con scope, resourceypolicy

Configuraremos algo similar en la Parte II.

Parte II

Keycloak tiene una pequeña herramienta que le permite probar todas sus políticas. Mejor aún, en realidad no es necesario activar otro servidor de aplicaciones e implementar una aplicación separada para que esto funcione.

Este es el escenario que configuraremos:

  1. Crearemos un nuevo reino llamado stackoverflow-demo
  2. Crearemos un bank-apicliente bajo ese reino
  3. Definiremos un recurso llamado /account/{id}para ese cliente
  4. El account/{id}tendrá el account:viewalcance
  5. Crearemos un usuario llamado bobbajo el nuevo reino
  6. También vamos a crear tres funciones: bank_teller, account_owneryuser
    • No nos asociaremos bobcon ningún rol. Esto no es necesario en este momento.
  7. Configuraremos las siguientes dos Role-Basedpolíticas:
    • bank_tellery account_ownertener acceso al /account/{id}recurso
    • account_ownertiene acceso al account:viewalcance
    • user no tiene acceso al recurso o alcance
  8. Jugaremos con la Evaluateherramienta para ver cómo se puede otorgar o denegar el acceso.

Perdóname, este ejemplo no es realista pero no estoy familiarizado con el sector bancario :)

Configuración de Keycloak

Descarga y ejecuta Keycloak

cd tmp
wget https://downloads.jboss.org/keycloak/8.0.0/keycloak-8.0.0.zip 
unzip keycloak-8.0.0.zip
cd keycloak-8.0.0/bin
./standalone.sh 

Crear usuario administrador inicial

  1. Ir http://localhost:8080/auth
  2. Haga clic en el Administration Consoleenlace
  3. Cree el usuario administrador e inicie sesión

Visita Getting Started para obtener más información. Para nuestros propósitos, lo anterior es suficiente.

Preparando el escenario

Crea un nuevo reino

  1. Pase el mouse por el masterreino y haga clic en el Add Realmbotón.
  2. Ingrese stackoverflow-democomo el nombre.
  3. Haga clic en Create.
  4. La parte superior izquierda debería decir ahora en stackoverflow-demolugar del masterreino.

Ver Crear un nuevo reino

Crea un nuevo usuario

  1. Haga clic en el Usersenlace de la izquierda.
  2. Haga clic en el Add Userbotón
  3. Ingrese el username(por ejemplo bob)
  4. Asegúrese de que User Enabledesté encendido
  5. Hacer clic Save

Ver Creación de un nuevo usuario

Crear nuevos roles

  1. Haga clic en el Rolesenlace
  2. Haga clic en Add Role
  3. Añadir las siguientes funciones: bank_teller, account_owneryuser

Nuevamente, no asocie a su usuario con los roles. Para nuestros propósitos, esto no es necesario.

Ver roles

Crea un cliente

  1. Haga clic en el Clientsenlace
  2. Haga clic en Create
  3. Entrar bank-apipara elClient ID
  4. Para Root URLentrarhttp://127.0.0.1:8080/bank-api
  5. Haga clic en Save
  6. Asegúrese de que Client Protocolseaopenid-connect
  7. Cambiar el Access Typeaconfidential
  8. Cambiar Authorization EnabledaOn
  9. Desplácese hacia abajo y presione Save. AuthorizationDebería aparecer una nueva pestaña en la parte superior.
  10. Haga clic en la Authorizationpestaña y luegoSettings
  11. Asegúrese de que Decision Strategyesté configurado enUnanimous
    • Este es el servidor de recursos Decision Strategy

Ver:

Crear ámbitos personalizados

  1. Haga clic en la Authorizationpestaña
  2. Haga clic en Authorization Scopes> Createpara abrir la Add Scopepágina
  3. Ingrese account:viewel nombre y presione enter.

Crear "Ver recurso de cuenta"

  1. Haga clic en el Authorizationenlace de arriba
  2. Haga clic en Resources
  3. Haga clic en Create
  4. Ingrese View Account Resourcepara NameyDisplay name
  5. Entrar account/{id}para elURI
  6. Entrar account:viewen el Scopescuadro de texto
  7. Hacer clic Save

Ver Creación de recursos

Crea tus políticas

  1. De nuevo debajo de la Authorizationpestaña, haga clic enPolicies
  2. Seleccione Roledel Create Policymenú desplegable
  3. En la Namesección, escribaOnly Bank Teller and Account Owner Policy
  4. Bajo Realm Rolesseleccionar tanto el bank_tellery account_ownerpapel
  5. Asegúrese de que Logicesté configurado enPositive
  6. Hacer clic Save
  7. Haga clic en el Policiesenlace
  8. Seleccione Rolenuevamente del Create Policymenú desplegable.
  9. Esta vez utilícelo Only Account Owner PolicyparaName
  10. Bajo Realm Rolesseleccionaraccount_owner
  11. Asegúrese de que Logicesté configurado enPositive
  12. Hacer clic Save
  13. Haga clic en el Policiesenlace en la parte superior, ahora debería ver sus políticas recién creadas.

Ver política basada en roles

Tenga en cuenta que Keycloak tiene políticas mucho más poderosas. Ver Gestión de políticas

Crear permiso basado en recursos

  1. De nuevo debajo de la Authorizationpestaña, haga clic enPermissions
  2. Seleccione Resource-Based
  3. Escriba View Account Resource Permissionpara elName
  4. Bajo ResourcestipoView Account Resource Permission
  5. Bajo Apply PolicyseleccionarOnly Bank Teller and Account Owner Policy
  6. Asegúrese de que Decision Strategyesté configurado enUnanimous
  7. Hacer clic Save

Consulte Crear permisos basados ​​en recursos

Uf...

Evaluación del permiso basado en recursos

  1. De nuevo debajo de la Authorizationpestaña, seleccioneEvaluate
  2. Debajo de Userentrarbob
  3. Bajo Rolesseleccionaruser
    • Aquí es donde asociaremos a nuestro usuario con nuestros roles creados.
  4. En Resourcesseleccione View Account Resourcey haga clic enAdd
  5. Haga clic en Evaluar.
  6. Expanda View Account Resource with scopes [account:view]para ver los resultados y debería ver DENY.

ingrese la descripción de la imagen aquí

  1. Esto tiene sentido porque solo permitimos el acceso de dos roles a ese recurso a través de Only Bank Teller and Account Owner Policy. ¡Probemos esto para asegurarnos de que sea cierto!
  2. Haga clic en el Backenlace que está justo encima del resultado de la evaluación.
  3. Cambie el rol de Bob a account_ownery haga clic en Evaluate. Ahora debería ver el resultado como PERMIT. Mismo trato si regresa y cambia el rol abank_teller

Consulte Evaluación y prueba de políticas.

Crear permiso basado en alcance

  1. Volver a la Permissionssección
  2. Seleccione Scope-Basedeste tiempo en el Create Permissionmenú desplegable.
  3. Debajo Name, ingreseView Account Scope Permission
  4. Debajo Scopes, ingreseaccount:view
  5. Debajo Apply Policy, ingreseOnly Account Owner Policy
  6. Asegúrese de que Decision Strategyesté configurado enUnanimous
  7. Hacer clic Save

Consulte Creación de permisos basados ​​en el alcance

Segunda prueba de funcionamiento

Evaluando nuestros nuevos cambios

  1. Volver a la Authorizationsección
  2. Haga clic en Evaluate
  3. El usuario debe ser bob
  4. Los roles deben ser bank_teller
  5. Los recursos deben ser View Account Resourcey haga clicAdd
  6. Haga clic en Evaluatey deberíamos obtener DENY.
    • Una vez más, esto no debería sorprendernos, ya que bank_tellertiene acceso al resourcepero no al scope. Aquí, un permiso se evalúa como verdadero y el otro como falso. Dado que el servidor de recursos Decision Strategyestá configurado en Unanimous, la decisión final es DENY.
  7. Haga clic en Settingsdebajo de la Authorizationpestaña, cambie Decision Strategya Affirmativey vuelva a los pasos 1-6 nuevamente. Esta vez, el resultado final debería ser PERMIT(un permiso es verdadero, por lo que la decisión final es verdadera).
  8. En aras de la integridad, dé la vuelta al servidor de recursos Decision Strategya Unanimous. Nuevamente, vuelva a los pasos 1 a 6, pero esta vez configure el rol como account_owner. Esta vez, el resultado final es una vez más PERMITlo que tiene sentido, dado que la account_ownertiene acceso tanto a la resourcey scope.

Neat :) Espero que esto ayude.


1
@SANDEEPMACHIRAJU De nada :) ¡Buena pregunta! No hay suficientes caracteres para dar una respuesta en profundidad a través de un comentario, pero puede usar el punto final de introspección del token . Aquí hay una lista de todos sus puntos finales . Yo creo también puede utilizar su cliente autorización , pero no tengo ninguna experiencia con él
Andy

7
Gracias por la gran respuesta.
Markus

3
@JWo ¡De nada! Tbh, no hay ninguna razón en particular. Simplemente mantuve el ejemplo lo más simple posible para que cualquiera pudiera comenzar. Sé por experiencia que los documentos no son las cosas más emocionantes de leer. En cuanto a otro cliente que necesite acceso a la API del banco, parece que podría estar buscando User Management Access (UMA)dónde el propietario del recurso puede otorgar acceso a un recurso protegido a la parte solicitante (al menos esa es mi interpretación).
Andy

3
Definitivamente estás haciendo del mundo un lugar mejor gracias por tomarte el tiempo para juntar todo eso ... ¡Deberías escribir algunas publicaciones de blog sobre todo esto! Muy útil @Andy
José Carlos

1
@Andy ¡guau! Gracias por tomarse el tiempo de digerir toda la documentación de los Servicios de autenticación y compartirla con nosotros. ¡Has ahorrado muchas horas de estudio a muchas personas! Solo hay una cosa que no puedo ver. Dijiste account_owner has access to the account:view scope. ¿Cómo se establece la relación entre ese rol y ese ámbito?
codependiente

5

Estaba buscando hacer cumplir la autorización a través de métodos HTTP puros, sin usar el adaptador, ya que Lua no tenía un adaptador. Espero que esta respuesta ayude a las personas que buscan un método no basado en adaptadores.

Si está buscando el adaptador, la guía de inicio rápido es el mejor lugar para comenzar. Especialmente el ejemplo de autenticación de arranque de primavera .

Para una implementación puramente basada en HTTP:

Paso 1:

Defina las políticas y los permisos en la interfaz de usuario de administración de Keycloak

Paso 2

Tenga un mapeo interno de qué rutas HTTP pertenecen a qué recursos y los alcances necesarios para cada ruta. Esto también se puede guardar en el archivo de configuración . Cuando se invoca una ruta en particular, llame al extremo del token de Keycloak para validar las afirmaciones del token de acceso.

{
  "policy-enforcer": {
    "user-managed-access" : {},
    "enforcement-mode" : "ENFORCING"
    "paths": [
      {
        "path" : "/someUri/*",
        "methods" : [
          {
            "method": "GET",
            "scopes" : ["urn:app.com:scopes:view"]
          },
          {
            "method": "POST",
            "scopes" : ["urn:app.com:scopes:create"]
          }
        ]
      }
    ]
  }
}

Si está utilizando un adaptador y no especifica la ruta o el recurso, el adaptador buscará internamente las rutas y los recursos de Keycloak .

Paso 3:

Utilice el punto final del token para obtener o evaluar los permisos. Puede utilizar el response_modeparámetro para obtener la decisión final (si proporcionar acceso) o recuperar todos los permisos.

curl -X POST \
  http://${host}:${port}/auth/realms/${realm}/protocol/openid-connect/token \
  -H "Authorization: Bearer ${access_token}" \
  --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
  --data "permission=Resource A#Scope A"

Si la solicitud de autorización no se asigna a ningún permiso, 403se devuelve un código de estado HTTP en su lugar.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.