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
fuente

Respuestas:
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:
Keycloak 8.0.0.Parte I
Algo de terminología antes de comenzar:
Resource-Basedpermisos, lo aplica directamente a su recursoScoped-Basedpermiso, lo aplica a su (s) alcance (s) o alcance (s) y recurso.Los ámbitos representan un conjunto de derechos sobre un recurso protegido. En su caso, tiene 2 recursos:
accountytransaction, por lo que me inclinaría hacia el segundo enfoque.A la larga, tener un mundial
viewalcance asociado con todos sus recursos (por ejemploaccount,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 mismotype. Por ejemplo, podría necesitar ambosviewAccounty elviewTransactionalcance 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.Disculpas, no entiendo completamente la pregunta, así que seré un poco amplio. Para otorgar / denegar el acceso a un
resource, debe:scopeoresource(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 elscope-basedpermiso. Puede hacer que esescoped-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 delscope-basedtipo de permiso.Tienes opciones.
Esto depende de
Decision StrategyDecision StrategyLogicvalor de cada póliza .El
Logicvalor es similar con el!operador de Java . Puede serPositiveoNegative. CuandoLogices asíPositive, la evaluación final de la política permanece sin cambios. Cuando esNegative, el resultado final se niega (por ejemplo, si una política se evalúa como falsa yLogicesNegative, entonces lo serátrue). Para simplificar las cosas, supongamos queLogicsiempre está configurado enPositive.Eso
Decision Strategyes lo que realmente queremos abordar. ElDecision Strategypuede ser tantoUnanimousoAffirmative. De los documentos,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,
LogicesPositivepara todas las políticas). Ahora:Permission Onetiene unDecision Strategyconjunto deAffirmative. También tiene 3 políticas donde cada uno evalúa:truefalsefalseDado que una de las políticas está configurada en
true,Permission Onese establece entrue(Afirmativo; solo se necesita 1true).Permission Twotiene unDecision Strategyconjunto deUnanimous2 políticas:truefalseEn este caso
Permission Twoesfalseporque una política es falsa (Unánime - todas deben serlotrue).Decision Strategyestá configurado enAffirmative, el acceso a ese recurso se otorgaría porquePermission Oneestrue. Si, por otro lado, el servidor de recursosDecision Strategyestá configurado enUnanimous, se denegará el acceso.Ver:
Seguiremos revisando esto. Explico cómo configurar el servidor de recursos
Decision Strategyen la Parte II.La respuesta corta es sí. Ahora, ampliemos esto un poco :)
Si tiene el siguiente escenario:
Decision Strategyconfigurado enUnanimousoAffirmativeaccount/{id}recurso estrueviewalcance estrueSe le otorgará acceso para ver la cuenta.
true+truees igual atruedebajo deAffirmativeoUnanimousDecision Strategy.Ahora si tienes esto
Decision Strategyconfigurado enAffirmativeaccount/{id}recurso estrueviewalcance esfalseTambién se le otorgará acceso para ver la cuenta.
true+falseestátruebajo laAffirmativeestrategia.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.
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.
Bastante. Hay muchas formas de configurar esto. Por ejemplo, puede:
/account/{id}) y asócielo con elaccount:viewalcance.helpdeskrol bajo esa políticaScope-Basedpermiso llamadoviewAccounty átelo conscope,resourceypolicyConfiguraremos 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:
stackoverflow-demobank-apicliente bajo ese reino/account/{id}para ese clienteaccount/{id}tendrá elaccount:viewalcancebobbajo el nuevo reinobank_teller,account_owneryuserbobcon ningún rol. Esto no es necesario en este momento.Role-Basedpolíticas:bank_telleryaccount_ownertener acceso al/account/{id}recursoaccount_ownertiene acceso alaccount:viewalcanceuserno tiene acceso al recurso o alcanceEvaluateherramienta 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
Crear usuario administrador inicial
http://localhost:8080/authAdministration ConsoleenlaceVisita Getting Started para obtener más información. Para nuestros propósitos, lo anterior es suficiente.
Preparando el escenario
Crea un nuevo reino
masterreino y haga clic en elAdd Realmbotón.stackoverflow-democomo el nombre.Create.stackoverflow-demolugar delmasterreino.Ver Crear un nuevo reino
Crea un nuevo usuario
Usersenlace de la izquierda.Add Userbotónusername(por ejemplobob)User Enabledesté encendidoSaveVer Creación de un nuevo usuario
Crear nuevos roles
RolesenlaceAdd Rolebank_teller,account_owneryuserNuevamente, no asocie a su usuario con los roles. Para nuestros propósitos, esto no es necesario.
Ver roles
Crea un cliente
ClientsenlaceCreatebank-apipara elClient IDRoot URLentrarhttp://127.0.0.1:8080/bank-apiSaveClient Protocolseaopenid-connectAccess TypeaconfidentialAuthorization EnabledaOnSave.AuthorizationDebería aparecer una nueva pestaña en la parte superior.Authorizationpestaña y luegoSettingsDecision Strategyesté configurado enUnanimousDecision StrategyVer:
Crear ámbitos personalizados
AuthorizationpestañaAuthorization Scopes>Createpara abrir laAdd Scopepáginaaccount:viewel nombre y presione enter.Crear "Ver recurso de cuenta"
Authorizationenlace de arribaResourcesCreateView Account ResourceparaNameyDisplay nameaccount/{id}para elURIaccount:viewen elScopescuadro de textoSaveVer Creación de recursos
Crea tus políticas
Authorizationpestaña, haga clic enPoliciesRoledelCreate Policymenú desplegableNamesección, escribaOnly Bank Teller and Account Owner PolicyRealm Rolesseleccionar tanto elbank_telleryaccount_ownerpapelLogicesté configurado enPositiveSavePoliciesenlaceRolenuevamente delCreate Policymenú desplegable.Only Account Owner PolicyparaNameRealm Rolesseleccionaraccount_ownerLogicesté configurado enPositiveSavePoliciesenlace 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
Authorizationpestaña, haga clic enPermissionsResource-BasedView Account Resource Permissionpara elNameResourcestipoView Account Resource PermissionApply PolicyseleccionarOnly Bank Teller and Account Owner PolicyDecision Strategyesté configurado enUnanimousSaveConsulte Crear permisos basados en recursos
Uf...
Evaluación del permiso basado en recursos
Authorizationpestaña, seleccioneEvaluateUserentrarbobRolesseleccionaruserResourcesseleccioneView Account Resourcey haga clic enAddView Account Resource with scopes [account:view]para ver los resultados y debería verDENY.Only Bank Teller and Account Owner Policy. ¡Probemos esto para asegurarnos de que sea cierto!Backenlace que está justo encima del resultado de la evaluación.account_ownery haga clic enEvaluate. Ahora debería ver el resultado comoPERMIT. Mismo trato si regresa y cambia el rol abank_tellerConsulte Evaluación y prueba de políticas.
Crear permiso basado en alcance
PermissionssecciónScope-Basedeste tiempo en elCreate Permissionmenú desplegable.Name, ingreseView Account Scope PermissionScopes, ingreseaccount:viewApply Policy, ingreseOnly Account Owner PolicyDecision Strategyesté configurado enUnanimousSaveConsulte Creación de permisos basados en el alcance
Segunda prueba de funcionamiento
Evaluando nuestros nuevos cambios
AuthorizationsecciónEvaluatebobbank_tellerView Account Resourcey haga clicAddEvaluatey deberíamos obtenerDENY.bank_tellertiene acceso alresourcepero no alscope. Aquí, un permiso se evalúa como verdadero y el otro como falso. Dado que el servidor de recursosDecision Strategyestá configurado enUnanimous, la decisión final esDENY.Settingsdebajo de laAuthorizationpestaña, cambieDecision StrategyaAffirmativey vuelva a los pasos 1-6 nuevamente. Esta vez, el resultado final debería serPERMIT(un permiso es verdadero, por lo que la decisión final es verdadera).Decision StrategyaUnanimous. Nuevamente, vuelva a los pasos 1 a 6, pero esta vez configure el rol comoaccount_owner. Esta vez, el resultado final es una vez másPERMITlo que tiene sentido, dado que laaccount_ownertiene acceso tanto a laresourceyscope.Neat :) Espero que esto ayude.
fuente
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).account_owner has access to the account:view scope. ¿Cómo se establece la relación entre ese rol y ese ámbito?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.fuente