I'm testing Keycloak and wanted to integrate it with OpenShift. I'm following these instructions
I got the bit where you configure the client scope and keycloak immediately dies with:
Default install, this is all I've done to it. Refreshing does nothing. To reproduce I just go to:
Clients -> openshift (the name of my client) -> Client Scopes. When I check the logs I see:
2024-07-15 19:32:02,456 ERROR [org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager] (executor-thread-27) Could not query server using DN [OU=Users,DC=openshift,DC=lan] and filter [(&(objectclass=person)(objectclass=organizationalPerson)(objectclass=user))]: javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-0310028D, problem 2001 (NO_OBJECT), data 0, best match of:
'DC=openshift,DC=lan'
]; remaining name 'OU=Users,DC=openshift,DC=lan'
at java.naming/com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3285)
at java.naming/com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3206)
at java.naming/com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2997)
at java.naming/com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1876)
at java.naming/com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1799)
at java.naming/com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:392)
at java.naming/com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:358)
at java.naming/javax.naming.directory.InitialDirContext.search(InitialDirContext.java:359)
at org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager$3.execute(LDAPOperationManager.java:258)
at org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager$3.execute(LDAPOperationManager.java:255)
at org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager.execute(LDAPOperationManager.java:729)
at org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager.execute(LDAPOperationManager.java:709)
at org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager.execute(LDAPOperationManager.java:704)
at org.keycloak.storage.ldap.idm.store.ldap.LDAPOperationManager.search(LDAPOperationManager.java:255)
at org.keycloak.storage.ldap.idm.store.ldap.LDAPIdentityStore.fetchQueryResults(LDAPIdentityStore.java:278)
at org.keycloak.storage.ldap.idm.query.internal.LDAPQuery.getResultList(LDAPQuery.java:174)
at org.keycloak.storage.ldap.LDAPStorageProvider.paginatedSearchLDAP(LDAPStorageProvider.java:1123)
at org.keycloak.storage.ldap.LDAPStorageProvider.searchLDAPByAttributes(LDAPStorageProvider.java:564)
at org.keycloak.storage.ldap.LDAPStorageProvider.searchForUserStream(LDAPStorageProvider.java:379)
at org.keycloak.storage.UserStorageManager.lambda$searchForUserStream$29(UserStorageManager.java:537)
at org.keycloak.storage.UserStorageManager.lambda$query$13(UserStorageManager.java:331)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:273)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:395)
at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:261)
at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:261)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310)
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
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.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEachOrdered(ReferencePipeline.java:601)
at com.fasterxml.jackson.datatype.jdk8.StreamSerializer.serialize(StreamSerializer.java:71)
at com.fasterxml.jackson.datatype.jdk8.StreamSerializer.serialize(StreamSerializer.java:15)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:502)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:341)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1574)
at com.fasterxml.jackson.databind.ObjectWriter._writeValueAndClose(ObjectWriter.java:1275)
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:1098)
at io.quarkus.resteasy.reactive.jackson.runtime.serialisers.FullyFeaturedServerJacksonMessageBodyWriter.writeResponse(FullyFeaturedServerJacksonMessageBodyWriter.java:79)
at org.jboss.resteasy.reactive.server.core.ServerSerialisers.invokeWriter(ServerSerialisers.java:216)
at org.jboss.resteasy.reactive.server.core.ServerSerialisers.invokeWriter(ServerSerialisers.java:184)
at org.jboss.resteasy.reactive.server.core.serialization.FixedEntityWriter.write(FixedEntityWriter.java:28)
at org.jboss.resteasy.reactive.server.handlers.ResponseWriterHandler.handle(ResponseWriterHandler.java:34)
at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:147)
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)
but as far as I can tell, that's correct based on my lab AD config:
Then one final sanity check in the LDAP config:
I'm not sure what Keycloak is looking for here. Everything is configured correctly.
In Active Directory "Users" is not an Organizational Unit, but a container.
You need to reference it using the DN
CN=Users,DC=openshift,DC=lan
.The same applies to "Builtin" and "Computers"; "Domain Controllers" is instead an actual OU, thus its DN would be
OU=Domain Controllers,DC=openshift,DC=lan
.This is also shown graphically in ADUC by the different icons used for OUs and containers.
Normally you don't have to deal with containers and you can't even create them easily; OUs are the way to go. But some containers (such as those in your image) exist in all Active Directory domains. If you want to reference them in a LDAP query, you need to keep in mind which kind of object you are actually dealing with.