keycloak/keycloak

Federated users cannot delete groups they are a member of with LDAP_ONLY mode

Open

#30.938 aperta il 28 giu 2024

Vedi su GitHub
 (8 commenti) (4 reazioni) (0 assegnatari)Java (8346 fork)batch import
area/ldaphelp wantedkind/bugpriority/normalstatus/auto-bumpteam/core-iam

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 image 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?

  1. Set up user federation with LDAP and add an ldap-group mapper for syncing LDAP groups to Keycloak
  2. Create a group in Keycloak and add a federated user to it
  3. Assign the federated user the proper roles to delete groups in Admin Console (I used the admin role of the master realm for testing)
  4. Log in to the Admin Console with that federated user
  5. Delete the group they are a member of

Anything else?

No response

Guida contributor