Federated users cannot delete groups they are a member of with LDAP_ONLY mode
#30.938 aperta il 28 giu 2024
Metriche repository
- Star
- (34.398 star)
- Metriche merge PR
- (Merge medio 6g 19h) (384 PR mergiate in 30 g)
Descrizione
Before reporting an issue
- I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.
Area
ldap
Describe the bug
If a federated user has the roles to delete groups in a realm and they try to delete a group they are a member of while using an ldap-group mapper with mode LDAP_ONLY, the admin console shows an error Network response was not OK. Press here to refresh and continue.
Version
25.0.1
Regression
- The issue is a regression
Expected behavior
Keycloak should delete the group and propagate the deletion to LDAP (related to #29099), effectively removing the user from the no-longer existing group in LDAP and Keycloak.
Actual behavior
Admin console shows an error message
When following the link the group has not been deleted.
A workaround is for the user trying to delete the group to leave the group first.
The Keycloak logs show a unique key constraint violation:
2024-06-28 18:23:16,671 DEBUG [org.hibernate.orm.jdbc.batch] (executor-thread-38) PreparedStatementDetails did not contain PreparedStatement on #releaseStatements : delete from public.KEYCLOAK_GROUP where ID=?
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.keycloak.connections.jpa.PersistenceExceptionConverter.invoke(PersistenceExceptionConverter.java:66)
... 45 more
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "sibling_names"
Detail: Key (realm_id, parent_group, name)=(5b350cda-0cd5-4745-af22-7ccc3bcfe746, , Test3) already exists.
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2725)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2412)
... 65 more
2024-06-28 18:23:17,079 DEBUG [org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl] (executor-thread-39) HHH000420: Closing un-released batch
2024-06-28 18:23:17,079 DEBUG [org.hibernate.orm.jdbc.batch] (executor-thread-39) PreparedStatementDetails did not contain PreparedStatement on #releaseStatements : insert into public.KEYCLOAK_GROUP (NAME,PARENT_GROUP,REALM_ID
2024-06-28 18:23:17,079 DEBUG [org.hibernate.orm.jdbc.batch] (executor-thread-39) PreparedStatementDetails did not contain PreparedStatement on #releaseStatements : insert into public.KEYCLOAK_GROUP (NAME,PARENT_GROUP,REALM_ID
2024-06-28 18:23:17,079 DEBUG [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-38) Error response 409: org.keycloak.models.ModelDuplicateException: Duplicate resource error
at org.keycloak.connections.jpa.PersistenceExceptionConverter.convert(PersistenceExceptionConverter.java:103)
at org.keycloak.connections.jpa.PersistenceExceptionConverter.invoke(PersistenceExceptionConverter.java:68)
at jdk.proxy2/jdk.proxy2.$Proxy66.flush(Unknown Source)
at org.keycloak.models.jpa.JpaRealmProvider.createGroup(JpaRealmProvider.java:717)
at org.keycloak.storage.GroupStorageManager.createGroup(GroupStorageManager.java:123)
at org.keycloak.models.cache.infinispan.RealmCacheSession.createGroup(RealmCacheSession.java:1109)
at org.keycloak.models.cache.infinispan.RealmAdapter.createGroup(RealmAdapter.java:1489)
at org.keycloak.models.RealmModel.createGroup(RealmModel.java:643)
at org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapper.createKcGroup(GroupLDAPStorageMapper.java:805)
at org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapper.updateKeycloakGroupTreeEntry(GroupLDAPStorageMapper.java:320)
at org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapper.updateKeycloakGroupTree(GroupLDAPStorageMapper.java:299)
at org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapper.syncDataFromFederationProviderToKeycloak(GroupLDAPStorageMapper.java:184)
at org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapper.findKcGroupOrSyncFromLDAP(GroupLDAPStorageMapper.java:388)
at org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapper$LDAPGroupMappingsUserDelegate.lambda$getLDAPGroupMappingsConverted$0(GroupLDAPStorageMapper.java:770)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapper$LDAPGroupMappingsUserDelegate.getLDAPGroupMappingsConverted(GroupLDAPStorageMapper.java:772)
at org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapper$LDAPGroupMappingsUserDelegate.getGroupsStream(GroupLDAPStorageMapper.java:703)
at org.keycloak.models.cache.infinispan.entities.CachedUser.lambda$new$3(CachedUser.java:74)
at org.keycloak.models.cache.infinispan.DefaultLazyLoader.get(DefaultLazyLoader.java:43)
at org.keycloak.models.cache.infinispan.entities.CachedUser.getGroups(CachedUser.java:130)
at org.keycloak.models.cache.infinispan.UserAdapter.getGroupsStream(UserAdapter.java:400)
at org.keycloak.models.cache.infinispan.UserAdapter.hasRole(UserAdapter.java:364)
at org.keycloak.authorization.common.UserModelIdentity.hasOneClientRole(UserModelIdentity.java:65)
at org.keycloak.services.resources.admin.permissions.MgmtPermissions.hasOneAdminRole(MgmtPermissions.java:177)
at org.keycloak.services.resources.admin.permissions.MgmtPermissions.hasOneAdminRole(MgmtPermissions.java:164)
at org.keycloak.services.resources.admin.permissions.UserPermissions.canViewDefault(UserPermissions.java:597)
at org.keycloak.services.resources.admin.permissions.GroupPermissions.canView(GroupPermissions.java:287)
at org.keycloak.services.resources.admin.permissions.GroupPermissions.canList(GroupPermissions.java:150)
at org.keycloak.services.resources.admin.permissions.GroupPermissions.requireList(GroupPermissions.java:155)
at org.keycloak.services.resources.admin.GroupsResource.getGroups(GroupsResource.java:96)
at org.keycloak.services.resources.admin.GroupsResource$quarkusrestinvoker$getGroups_7b020fd0a44403122f36a3a47bc8b7638a5dc3e8.invoke(Unknown Source)
at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.sql.BatchUpdateException: Batch entry 0 insert into public.KEYCLOAK_GROUP (NAME,PARENT_GROUP,REALM_ID,ID) values (('Test3'),(' '),('5b350cda-0cd5-4745-af22-7ccc3bcfe746'),('51284f2a-bc6c-4993-8696-c47946805f06'
Detail: Key (realm_id, parent_group, name)=(5b350cda-0cd5-4745-af22-7ccc3bcfe746, , Test3) already exists. Call getNextException to see other errors in the batch.
at org.postgresql.jdbc.BatchResultHandler.handleError(BatchResultHandler.java:165)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2413)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:579)
at org.postgresql.jdbc.PgStatement.internalExecuteBatch(PgStatement.java:912)
at org.postgresql.jdbc.PgStatement.executeBatch(PgStatement.java:936)
at org.postgresql.jdbc.PgPreparedStatement.executeBatch(PgPreparedStatement.java:1733)
at io.agroal.pool.wrapper.StatementWrapper.executeBatch(StatementWrapper.java:340)
at org.hibernate.engine.jdbc.batch.internal.BatchImpl.lambda$performExecution$2(BatchImpl.java:279)
at org.hibernate.engine.jdbc.mutation.internal.PreparedStatementGroupSingleTable.forEachStatement(PreparedStatementGroupSingleTable.java:59)
at org.hibernate.engine.jdbc.batch.internal.BatchImpl.performExecution(BatchImpl.java:264)
at org.hibernate.engine.jdbc.batch.internal.BatchImpl.execute(BatchImpl.java:242)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.executeBatch(JdbcCoordinatorImpl.java:188)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:662)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:499)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:363)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:41)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1407)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1393)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.keycloak.connections.jpa.PersistenceExceptionConverter.invoke(PersistenceExceptionConverter.java:66)
... 45 more
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "sibling_names"
Detail: Key (realm_id, parent_group, name)=(5b350cda-0cd5-4745-af22-7ccc3bcfe746, , Test3) already exists.
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2725)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2412)
... 65 more
How to Reproduce?
- Set up user federation with LDAP and add an ldap-group mapper for syncing LDAP groups to Keycloak
- Create a group in Keycloak and add a federated user to it
- Assign the federated user the proper roles to delete groups in Admin Console (I used the
adminrole of themasterrealm for testing) - Log in to the Admin Console with that federated user
- Delete the group they are a member of
Anything else?
No response