Having trouble with LDAPS connection to Active Directory

Current Version SonarQube 7.9.1 LTS Enterprise.
Trying to connect to Active Directory using LDAPS connection.

I have my signer Certificates loaded into a cacerts truststore that lives in %java path%\lib\security.

I can start and successfully connect to LDAP Active Directory using “ldap.url=ldap://hostname:389”

When it starts I can find the following in the logs as stated in the online documentation.

INFO org.sonar.INFO Security realm: LDAP …
INFO o.s.p.l.LdapContextFactory Test LDAP connection: OK

When I change the ldap connection string to LDAPS, “ldap.url=ldaps://hostname:636”

I receive the following error in the logs. I have logging set to “DEBUG”

Thanks in advance for any help!

2019.09.16 08:52:54 WARN  web[][o.s.s.a.LogOAuthWarning] For security reasons, OAuth authentication should use HTTPS. You should set the property 'Administration > Configuration > Server base URL' to a HTTPS URL.
2019.09.16 08:52:54 INFO  web[][org.sonar.INFO] Security realm: LDAP
2019.09.16 08:52:54 INFO  web[][o.s.p.l.LdapSettingsManager] User mapping: LdapUserMapping{baseDn=OU=THIS,DC=IS,DC=NOT,DC=REAL, request=(&(objectClass=user)(sAMAccountName={0})), realNameAttribute=serviceaccountname, emailAttribute=mail}
2019.09.16 08:52:54 INFO  web[][o.s.p.l.LdapSettingsManager] Group mapping: LdapGroupMapping{baseDn=OU=THIS,DC=IS,DC=NOT,DC=REAL, idAttribute=sAMAccountName, requiredUserAttributes=[dn], request=(&(objectClass=group)(member={0}))}
2019.09.16 08:52:55 INFO  web[][o.s.p.l.LdapContextFactory] Test LDAP connection: FAIL
2019.09.16 08:52:55 ERROR web[][o.s.s.p.Platform] Background initialization failed. Stopping SonarQube
at org.sonar.server.user.SecurityRealmFactory.start(SecurityRealmFactory.java:93)
	at org.sonar.core.platform.StartableCloseableSafeLifecyleStrategy.start(StartableCloseableSafeLifecyleStrategy.java:40)
	at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.start(AbstractInjectionFactory.java:84)
	at org.picocontainer.behaviors.AbstractBehavior.start(AbstractBehavior.java:169)
	at org.picocontainer.behaviors.Stored$RealComponentLifecycle.start(Stored.java:132)
	at org.picocontainer.behaviors.Stored.start(Stored.java:110)
	at org.picocontainer.DefaultPicoContainer.potentiallyStartAdapter(DefaultPicoContainer.java:1016)
	at org.picocontainer.DefaultPicoContainer.startAdapters(DefaultPicoContainer.java:1009)
	at org.picocontainer.DefaultPicoContainer.start(DefaultPicoContainer.java:767)
	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:135)
	at org.sonar.server.platform.platformlevel.PlatformLevel.start(PlatformLevel.java:90)
	at org.sonar.server.platform.platformlevel.PlatformLevel4.start(PlatformLevel4.java:545)
	at org.sonar.server.platform.Platform.start(Platform.java:211)
	at org.sonar.server.platform.Platform.startLevel34Containers(Platform.java:185)
	at org.sonar.server.platform.Platform.access$500(Platform.java:46)
	at org.sonar.server.platform.Platform$1.lambda$doRun$0(Platform.java:119)
	at org.sonar.server.platform.Platform$1$$Lambda$1371.0000000019A54E90.run(Unknown Source)
	at org.sonar.server.platform.Platform$AutoStarterRunnable.runIfNotAborted(Platform.java:371)
	at org.sonar.server.platform.Platform$1.doRun(Platform.java:119)
	at org.sonar.server.platform.Platform$AutoStarterRunnable.run(Platform.java:355)
	at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.sonar.plugins.ldap.LdapException: Unable to open LDAP connection
	at org.sonar.plugins.ldap.LdapContextFactory.testConnection(LdapContextFactory.java:211)
	at org.sonar.plugins.ldap.LdapRealm.init(LdapRealm.java:63)
	at org.sonar.server.user.SecurityRealmFactory.start(SecurityRealmFactory.java:87)
	... 20 common frames omitted
Caused by: javax.naming.CommunicationException: Connection or outbound has closed
	at java.naming/com.sun.jndi.ldap.LdapCtx.extendedOperation(Unknown Source)
	at java.naming/javax.naming.ldap.InitialLdapContext.extendedOperation(Unknown Source)
	at org.sonar.plugins.ldap.LdapContextFactory.createInitialDirContext(LdapContextFactory.java:120)
	at org.sonar.plugins.ldap.LdapContextFactory.createBindContext(LdapContextFactory.java:96)
	at org.sonar.plugins.ldap.LdapContextFactory.testConnection(LdapContextFactory.java:207)
	... 22 common frames omitted
Caused by: java.net.SocketException: Connection or outbound has closed
	at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(Unknown Source)
	at java.base/java.io.BufferedOutputStream.flushBuffer(Unknown Source)
	at java.base/java.io.BufferedOutputStream.flush(Unknown Source)
	at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Unknown Source)
	at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Unknown Source)
	at java.naming/com.sun.jndi.ldap.LdapClient.extendedOp(Unknown Source)
	... 27 common frames omitted
2019.09.16 08:52:55 DEBUG web[][o.s.s.p.Platform] Background initialization of SonarQube done
2019.09.16 08:52:56 INFO  web[][o.s.p.ProcessEntryPoint] Hard stopping process
2019.09.16 08:52:57 WARN  web[][o.s.p.ProcessEntryPoint$HardStopperThread] Can not stop in 1000ms
2019.09.16 08:52:57 WARN  web[][o.s.s.a.EmbeddedTomcat] Failed to stop web server
org.apache.catalina.LifecycleException: Failed to stop component [StandardServer[-1]]
	at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:238)
	at org.apache.catalina.startup.Tomcat.stop(Tomcat.java:437)
	at org.sonar.server.app.EmbeddedTomcat.terminate(EmbeddedTomcat.java:104)
	at org.sonar.server.app.WebServer.hardStop(WebServer.java:83)
	at org.sonar.process.ProcessEntryPoint$HardStopperThread.lambda$new$0(ProcessEntryPoint.java:219)
	at org.sonar.process.ProcessEntryPoint$HardStopperThread$$Lambda$1599.00000000250E77C0.run(Unknown Source)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
	at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.apache.catalina.LifecycleException: Failed to stop component [StandardService[Tomcat]]
	at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:238)
	at org.apache.catalina.core.StandardServer.stopInternal(StandardServer.java:814)
	at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226)
	... 10 common frames omitted
Caused by: org.apache.catalina.LifecycleException: Failed to stop component [StandardEngine[Tomcat]]
	at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:238)
	at org.apache.catalina.core.StandardService.stopInternal(StandardService.java:486)
	at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226)
	... 12 common frames omitted
Caused by: org.apache.catalina.LifecycleException: A child container failed during stop
	at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1008)
	at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226)
	... 14 common frames omitted
2019.09.16 08:52:57 INFO  web[][o.s.s.p.d.EmbeddedDatabase] Embedded database stopped
1 Like

Hi @hopkitj,

Do you have access to the LDAP logs? Can you check whether:

  • SonarQube can connect to port 636? (i.e.: do you see a connection attempt?)
  • If no:
    • Can you double check if the certificate is indeed correct (the stack shows a java.net.SocketException thrown by java.base/sun.security.ssl.SSLSocketImpl, which could indicate a certificate issue)?
    • Is there a firewall that could block specific ports?
  • If yes:
    • Do you see any errors in the LDAP logs? Are the credentials correct, for instance?

If you do not have access to the LDAP logs, can you test your connection to LDAP directly from the same server as SonarQube is hosted on? It seems you’re on Windows; I’m not sure what tool is best suited on that OS, but if this were Linux, I’d do some testing using ldapsearch.

Let us know how that goes.

Thanks for your response.

You said:
Do you have access to the LDAP logs? Can you check whether:.

I don’t have access to the Active Directory logs. Another group, in another building has control over those logs. Sorry. I put a packet sniffer on and ran a trace.
I can see the initial handshake between AD and SonarQube. The certificate checking seems to go alright. Then there is a fatal error of some kind. Wireshark just give an error that means the error is encrypted and I can’t read it. So communication between AD
and Sonarqube on port 636 is working. It just fails for some unknown reason. Maybe my LDAP configuration is wrong? Maybe I am missing a custom configuration item that is not listed in the default sonar.properties file so that the truststore can be read properly?
It seems like there is some configuration setting that I am missing somewhere. The thing that confuses me is that it works on port 389.

o
You said:
Is there a firewall that could block specific ports?

·
If yes:

o
Do you see any errors in the LDAP logs? Are the credentials correct, for instance?

I don’t believe there are any firewalls because I can successfully connect and Sonarqube will run using ldap.url=ldap://hostname:389. I run into trouble when I change the ldap.url=ldaps://hostname:636

I am wondering if there is a sample sonar.properties, LDAP config that shows settings for ldap.url=ldaps://hostname:636. I downloaded the OpenJDK11U-jre_x64_windows_openj9_11.0.4_11_openj9-0.15.1.zip
file for java. Is there some kind of seeting that can be put in the sonar.properties so you can tell sonarqube where the truststore is? I have seen reference to things like adding “sonar.web.javaAdditionalOpts=-Djavax.net.ssl.trustStore=C:/Java_Path/lib/security/cacerts”
to the properties file. Any suggestions on this?

Ok, I found the answer. This string needs to be added to you sonar.properties file so the truststore can be found.

sonar.web.javaAdditionalOpts=-Djavax.net.ssl.trustStore=path to truststore -Djavax.net.ssl.trustStorePassword=top secret password for truststore

I hope this helps others. Might be a good idea to add this information to the formal documentation.

1 Like

I am wondering. Is this the best way to go about getting LDAPS to work? or is there another way. Say, a SonarQube way?

Thanks in advance for your responses!

Hi Hopkins,

I added the same parameter in the properties file but it is not working.

sonar.web.javaOpts=-Xmx512m -Xms128m -XX:+HeapDumpOnOutOfMemoryError -Djava.security.egd=file:///dev/urandom -Djavax.net.ssl.trustStore=path to truststore -Djavax.net.ssl.trustStorePassword=top secret password for truststore

Regards,
Guru

I put:

sonar.web.javaAdditionalOpts=-Djavax.net.ssl.trustStore=path to truststore -Djavax.net.ssl.trustStorePassword=top secret password for truststore

This worked for me. Even though I was not getting any handshake errors, I seems sonarqube could not find the trust store.

Hi @hopkitj,

Sorry for the late reply (was on paternity leave :wink:). Great you found the answer, although I’m surprised this is necessary. Isn’t this related to your JRE setup, rather than SonarQube?

In any case, thanks for posting the solution here :+1:. I’ll check with our documentation and support teams, to see if this deserves to be in our official doc.

Cheers.

As far as I know, the only thing one needs to do for the JRE, is set the environment variables, JAVA_HOME and set the path. Is there something else? Did I miss
something?

Thanks and congratulations!

Thanks :smile:.

I believe you can use keytool to add certs and keys to your default store, which would make it available to any Java app running on that machine. But that is not always desirable either… I guess it depends on the use-case.

I used keytool to add my signer certs to the cacerts truststore. I still had to add the sonar.web.javaAdditionalOpts=-Djavax.net.ssl.trustStore=C:/Java/cacerts
-Djavax.net.ssl.trustStorePassword=(password) to the sonar.properties file so that LDAPS will work. Can you tell me what I should be doing differently?

Thanks!

Hm, strange. Perhaps it is always needed. Or perhaps it’s only the -Djavax.net.ssl.trustStorePassword that’s required in your case? Although it shouldn’t, as it’s read-only in this case. Anyway, it works now :slightly_smiling_face:.

Yes, but the strange thing to me is that there is no mention of this apparent requirement for LDAPS to work in the regular documentation. Nor do I find a thread,
other than mine, that talks about LDAPS in community. It seems most people are just using LDAP on port 389 when talking to Active Directory. All those passwords being sent across the network in plane text. Just seems like a bad idea to me. It seems to me that
SonarQube would want to help user’s define secure communications.

1 Like

Hi,

have you set the following line in your sonar.properties ?
ldap.StartTLS=true

Yes, we tried that. It didn’t seem to make a difference. LDAPS did not work until we used the string,
sonar.web.javaAdditionalOpts=-Djavax.net.ssl.trustStore=C:/Java/cacerts -Djavax.net.ssl.trustStorePassword=(password).

Hi,

I am getting the same error when i tried to connect to my ldap server. Getting SSL error.
Tried providing the
sonar.web.javaAdditionalOpts=-Djavax.net.ssl.trustStore=/usr/local/openjdk-11/lib/security/cacerts -Djavax.net.ssl.trustStorePassword=top secret password for truststore

But no use.

my sonarqube server version: 7.9.3
Ldap plugin version : 2.2.0.608

java keystore is under /usr/local/openjdk-11/lib/security/cacerts

Pasting the entire log. Can anyone help me resolve this. Appreciate your help.

sonar.properties file

#General configuration
sonar.security.realm=LDAP
ldap.url=ldaps://:636
ldap.bindDn=uid=,cn=CN,OU=ServiceAccounts,DC=NA,DC=NA,DC=com
ldap.bindPassword=

#Authentication
ldap.StartTLS=true

#User configuration
ldap.user.baseDn=OU=ServiceAccounts,DC=,DC=,DC=com
ldap.user.request=(uid={login})
ldap.user.realNameAttribute=

#Group configuration
ldap.group.baseDn=OU=Groups,DC=,DC=,DC=com
ldap.group.idAttribute=

sonar.web.javaAdditionalOpts=-Djavax.net.ssl.trustStore=/usr/local/openjdk-11/lib/security/cacerts -Djavax.net.ssl.trustStorePassword=pasword

Error Snip:
2020.04.13 05:25:44 INFO web[org.sonar.INFO] Security realm: LDAP
2020.04.13 05:25:45 INFO web[o.s.p.l.LdapContextFactory] Test LDAP connection: FAIL
2020.04.13 06:06:47 INFO web[o.s.p.l.LdapContextFactory] Test LDAP connection: FAIL
2020.04.13 06:06:47 ERROR web[o.s.s.p.Platform] Background initialization failed. Stopping SonarQube
org.sonar.api.utils.SonarException: Security realm fails to start: Unable to open LDAP connection
at org.sonar.server.user.SecurityRealmFactory.start(SecurityRealmFactory.java:93)
at org.sonar.core.platform.StartableCloseableSafeLifecyleStrategy.start(StartableCloseableSafeLifecyleStrategy.java:40)
at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.start(AbstractInjectionFactory.java:84)
at org.picocontainer.behaviors.AbstractBehavior.start(AbstractBehavior.java:169)
at org.picocontainer.behaviors.Stored$RealComponentLifecycle.start(Stored.java:132)
at org.picocontainer.behaviors.Stored.start(Stored.java:110)
at org.picocontainer.DefaultPicoContainer.potentiallyStartAdapter(DefaultPicoContainer.java:1016)
at org.picocontainer.DefaultPicoContainer.startAdapters(DefaultPicoContainer.java:1009)
at org.picocontainer.DefaultPicoContainer.start(DefaultPicoContainer.java:767)
at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:135)
at org.sonar.server.platform.platformlevel.PlatformLevel.start(PlatformLevel.java:90)
at org.sonar.server.platform.platformlevel.PlatformLevel4.start(PlatformLevel4.java:545)
at org.sonar.server.platform.Platform.start(Platform.java:211)
at org.sonar.server.platform.Platform.startLevel34Containers(Platform.java:185)
at org.sonar.server.platform.Platform.access$500(Platform.java:46)
at org.sonar.server.platform.Platform$1.lambda$doRun$0(Platform.java:119)
at org.sonar.server.platform.Platform$AutoStarterRunnable.runIfNotAborted(Platform.java:371)
at org.sonar.server.platform.Platform$1.doRun(Platform.java:119)
at org.sonar.server.platform.Platform$AutoStarterRunnable.run(Platform.java:355)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.sonar.plugins.ldap.LdapException: Unable to open LDAP connection
at org.sonar.plugins.ldap.LdapContextFactory.testConnection(LdapContextFactory.java:211)
at org.sonar.plugins.ldap.LdapRealm.init(LdapRealm.java:63)
at org.sonar.server.user.SecurityRealmFactory.start(SecurityRealmFactory.java:87)
… 19 common frames omitted
Caused by: javax.naming.NamingException: StartTLS failed
at org.sonar.plugins.ldap.LdapContextFactory.createInitialDirContext(LdapContextFactory.java:124)
at org.sonar.plugins.ldap.LdapContextFactory.createBindContext(LdapContextFactory.java:96)
at org.sonar.plugins.ldap.LdapContextFactory.testConnection(LdapContextFactory.java:207)
… 21 common frames omitted
Caused by: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
at java.base/sun.security.ssl.SSLSocketImpl.handleEOF(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.decode(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(Unknown Source)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at java.naming/com.sun.jndi.ldap.ext.StartTlsResponseImpl.startHandshake(Unknown Source)
at java.naming/com.sun.jndi.ldap.ext.StartTlsResponseImpl.negotiate(Unknown Source)
at java.naming/com.sun.jndi.ldap.ext.StartTlsResponseImpl.negotiate(Unknown Source)
at org.sonar.plugins.ldap.LdapContextFactory.createInitialDirContext(LdapContextFactory.java:122)
… 23 common frames omitted
Suppressed: java.net.SocketException: Connection or outbound has closed
at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(Unknown Source)
at java.base/sun.security.ssl.SSLSocketOutputRecord.encodeAlert(Unknown Source)
at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source)
… 28 common frames omitted
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at java.base/sun.security.ssl.SSLSocketInputRecord.decode(Unknown Source)
at java.base/sun.security.ssl.SSLTransport.decode(Unknown Source)
… 30 common frames omitted
2020.04.13 06:06:47 INFO web[o.s.p.ProcessEntryPoint] Hard stopping process