LDAP successfully working, LDAPS failing

Must-share information (formatted with Markdown):

  • which versions are you using (SonarQube, Scanner, Plugin, and any relevant extension)
    Windows Server 2019 in Azure Environment
    SonarQube 9.3.0.51899

  • what are you trying to achieve
    Set up LDAPS authentication

  • what have you tried so far to achieve this

I currently have a working LDAP configuration that I need to change to LDAPs. Using LDAP I can login using AD credentials + passwords, and the group mapping works correctly. Setting the log to DEBUG and checking web.log shows that it authenticates users and returns their correct groups
Untitled
Untitled2

However, as soon as I add the little ‘s’ making it ‘ldaps’ everything breaks

Abridged web.log of a failed instance using LDAPs:

2022.04.21 14:32:41 INFO web[org.sonar.INFO] Security realm: LDAP
2022.04.21 14:32:41 INFO web[o.s.a.l.LdapSettingsManager] User mapping: LdapUserMapping{baseDn=dc=[DOMAIN],dc=com, request=(&(objectClass=user)(sAMAccountName={0})), realNameAttribute=cn, emailAttribute=mail}
2022.04.21 14:32:41 INFO web[o.s.a.l.LdapSettingsManager] Group mapping: LdapGroupMapping{baseDn=ou=[GROUP],dc=[DOMAIN],dc=com, idAttribute=cn, requiredUserAttributes=[dn], request=(&(objectClass=group)(member={0}))}
2022.04.21 14:32:41 DEBUG web[o.s.a.l.LdapContextFactory] Initializing LDAP context {java.naming.referral=follow, java.naming.security.principal=CN=[USER],OU=[GROUP],DC=[DOMAIN],DC=com, com.sun.jndi.ldap.connect.pool=true, java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory, java.naming.provider.url=ldaps://[DOMAIN.COM], java.naming.security.authentication=simple}
2022.04.21 14:32:41 INFO web[o.s.a.l.LdapContextFactory] Test LDAP connection: FAIL
2022.04.21 14:32:41 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
Caused by: org.sonar.auth.ldap.LdapException: Unable to open LDAP connection
Caused by: javax.naming.CommunicationException: simple bind failed: [DOMAIN.COM]:636
Caused by: java.net.SocketException: Connection or outbound has closed
2022.04.21 14:32:41 DEBUG web[o.s.s.p.Platform] Background initialization of SonarQube done
2022.04.21 14:32:42 INFO web[o.s.p.ProcessEntryPoint] Hard stopping process
2022.04.21 14:32:42 DEBUG web[o.a.h.i.n.c.PoolingNHttpClientConnectionManager] Connection manager is shutting down
2022.04.21 14:32:42 DEBUG web[o.a.h.i.n.c.ManagedNHttpClientConnectionImpl] http-outgoing-0 127.0.0.1:51941<->127.0.0.1:9001[ACTIVE][r:r]: Close
2022.04.21 14:32:42 DEBUG web[o.a.h.i.n.c.InternalIODispatch] http-outgoing-0 [CLOSED]: Disconnected
2022.04.21 14:32:42 DEBUG web[o.a.h.i.n.c.PoolingNHttpClientConnectionManager] Connection manager shut down
2022.04.21 14:32:42 DEBUG web[o.s.s.a.TomcatAccessLog] Tomcat is stopped

Things to note

  • I have imported a wildcard domain certificate (e.g., *.domainname.com) into the Java keystore, and tested the import completed successfully by viewing the keystore certificates (“keytool -list -v -cacerts”). Additionally, viewing the cacerts file with KeyStore Explorer also shows the key is in place

  • The thumbprint for this certificate matches the one used for Azure AD Domain Services, in the Secure LDAP section

  • Using ADSI Edit and LDP.exe, I have tested the credentials used by SonarQube, and the connection to Port 636 using SSL:
    Untitled3
    – I can both connect and authenticate successfully.

  • Using LDP.exe I can:
    – connect to both [exampledomain.com] and [exampledomain] on port 636 using SSL
    – Perform simple binds using the same user as SonarQube uses

  • I have been through Delegating Authentication | SonarQube Docs, and have set all required properties. In the sonar.properties file I have set the following variables:

sonar.security.realm=LDAP
ldap.url=ldaps://[DOMAIN.COM]
ldap.bindDn=CN=[USER],OU=[GROUP],DC=[DOMAIN],DC=com
ldap.bindPassword={aes-gcm}[01234567890abcdefgh]
ldap.StartTLS=false
dap.user.baseDn=dc=[DOMAIN],dc=com
ldap.user.request=(&(objectClass=user)(sAMAccountName={login}))
ldap.group.baseDn=ou=[GROUP],dc=c[DOMAIN],dc=com
ldap.group.request=(&(objectClass=group)(member={dn}))

These properties work with LDAP but not LDAPS

Troubleshooting attempted:

Set the LDAP server the via IP rather than hostname

  • No difference

Manually setting the port number

  • No difference

Changing authentication from Simple to DIGEST, GSSAPI

  • Breaks SonarQube, even though the server supports it?
    5

I have set up an encrypted password in the Sonar.properties file, however using a plain-text password makes no difference

I have also tried a few different settings in the wrapper.conf file that have helped similar Java / LDAPS errors in other programs:
4

  • No difference

Thoughts:

I can connect to Port 636 on [DOMAIN.COM] with both ADSI Edit and LDP.exe, so isn’t a firewall issue

I can use ADSI Edit and LDP.exe to connect using the same username/password combination as SonarQube, so it isn’t an authentication issue.

The domain certificate is installed in the Java keystore, so this shouldn’t be an issue (does anyone know an easy way to test this?)

This project requires secure federated login, so my choice is either LDAPS or Azure SSO. Azure SSO required HTTPS (which has already been set up using a reverse proxy in IIS as described by the SonarQube documentation ( Operating the Server | SonarQube Docs) ), however the documentation also states that the setup is ‘not appropriate for SAML through IIS.’ (which Azure SSO uses).

Request:
Can anyone point out why my LDAPS settings fail so spectactualy even though LDAP works?
Alternately, can anyone point me in the direction of a guide to correctly implimenting proxying for SAML in IIS?

Thanks for any help :slight_smile:

Hey @user2254126

Thanks for the detailed report.

  • I find SSLPoke super useful, running from the same host machine as my SonarQube server and making sure the same Java installation being used to run my SonarQube server is being used to run SSLPoke.java.
  • If you have any proxy configuration set in your conf/sonar.properties file (http.proxyHost, etc.) , you may want to check to see if you need to exclude your LDAP server from using this proxy (setting http.nonProxyHosts)

Related to SAML, there’s a useful guide here:

With a follow-up I wrote some time later on because of changing requirements in how we handle SAML (preserving host headers, forwarding certain headers, etc.)

Hope this is helpful.

Hello Colin, thanks for getting back to me.

I did test with SSLPoke at some point, and it connects via Port 636 successfully
Untitled

There is only 1 Java installation on the server (fresh install)
There is no proxy configuration set in the properties file.

I’m currently working through your guides for SAML, I’ll get back to you with a result :slight_smile:

Thanks for the help!

Thanks for the followup.

If you run into some more issues or want to return to debugging LDAP, I can also suggest:

  • Hiking up sonar.log.level to DEBUG or TRACE for more detailed logs
  • Adding -Djavax.net.debug=all to sonar.web.javaAdditionalOpts and see everything happening at the Java layer when it tries to make the connection

Hello Colin,

Yeah, the sonar.properties was already set to TRACE, and unfortunately the ‘-Djavax.net.debug=all’ didn’t add any extra details to the LDAP section of the web.log.

One thing I did notice:
When setting “-Djdk.tls.trustNameService=true”, in the Java additional settings in sonar.properties, it changed the error that SonarQube halted on to:
“java.security.cert.CertificateException: No subject alternative DNS name matching [DOMAIN] found.”
even though the certificate clearly lists the SAN
Untitled

Removing the trustNameService command reverts the error to the original ‘simple bind failed: [DOMAIN]:636’

This is a Java issue somewhere, because I discovered that by adding:
-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true
in the additional Java settings in sonar.properties, the LDAPS configuration works. I did originally attempt this in the wrapper.conf (see original post), however it made no difference there.

So, I now have a working LDAPS configuration (with slightly reduced security unfortunately).

Thanks for your help in this matter :slight_smile: