EDITED - After further testing on my side, it seems that the approach of using a Groovy init script to set this particular property doesn't work, as it is not provided early enough for the AD plugin to consume it. But it does show up in the /systemInfo page because it IS set, so it is not obvious until reading the jenkins.log that the ordering is wrong.
Having made a change to the CentOS sysconfig/jenkins file the property is now correctly set, and Jenkins will honour it and use LDAPS on port 3269 correctly, and fails on port 3268 as expected.
I may file a separate bug for the confusing behaviour around "trust all certificates" as it seems that this would still allow a silent fallback to plain text if forceLdaps is not true and STARTTLS serves an untrusted certificate but could still be used for encryption.
— original comment follows
I'm having some pretty major issues with that property set using v2.1.6 of the plugin and Jenkins 2.190.2 (which I will shortly be upgrading).
I have the forceLdaps property set (by using a Groovy init script in JENKINS_HOME), and it is correctly shown as true in /systemInfo BUT:
- During a "Test connection" the LDAP URL is NOT being updated to LDAPS (the fine-level logger shows "Connecting to ldap://eu.ldap.company.com:3269/") - if forceLdaps is true then it appears this should be changed by ActiveDirectorySecurityRealm.java:658 however it is not
- If I set the port to 3269 in the Global Security settings:
Failed to start TLS. Authentication will be done via plain-text LDAP javax.naming.NamingException: LDAP response read timed out, timeout used:-1ms. at com.sun.jndi.ldap.Connection.readReply(Connection.java:471) at com.sun.jndi.ldap.LdapClient.extendedOp(LdapClient.java:1199) at com.sun.jndi.ldap.LdapCtx.extendedOperation(LdapCtx.java:3274)
- If I set the port to 3268 in the Global Security settings:
- It looks like this is supposed to be silently changed to 3269 by ActiveDirectorySecurityRealm.java:830 - but it isn't
Failed to start TLS. Authentication will be done via plain-text LDAP java.security.cert.CertificateException: No subject alternative DNS name matching eu.ldap.company.com found. at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:214) at sun.security.util.HostnameChecker.match(HostnameChecker.java:96) at com.sun.jndi.ldap.ext.StartTlsResponseImpl.verify(StartTlsResponseImpl.java:426)
If I have enabled something called FORCE LDAPS then I feel like ANY scenario that could possibly fall back to plain text must be disabled. If you have force-enabled encryption (rather than relying on the default "opportunistic" behaviour) then an explicit failure is probably better than silently doing something insecure
I have even tried enabling the "Trust all certificates" configuration option - this still fails the TLS verification and falls back to plain text. In this case, I would expect that the traffic would still be encrypted even though potentially it cannot be trusted. With this option set, if the encryption was done anyway then only the party operating the other end of the connection should be able to see the credentials. By falling back to plain text, those credentials are exposed to the party operating the other end, the party(ies) running networking equipment between the two endpoints, and potentially others.
The end result of this is that a configuration that I thought would always send encrypted data (because forceLdaps=true, and "Trust all certificates" is enabled so even if the trust fails we will still encrypt the data with some key) has actually been silently falling back to plain-text LDAP for an unknown period of time. I feel like this is Very Bad.