Replace the hand-rolled LdapContextSource of the embedded server
with an LdapConnectionDetails implementation, so that
LdapAutoConfiguration creates the context source for both the external
and the embedded case. Previously, the embedded context source derived
the URL scheme from spring.ldap.ssl and never applied an SSL bundle to
the JNDI environment, leaving an embedded LDAPS server unreachable. It
also ignored spring.ldap.anonymous-read-only, spring.ldap.referral,
spring.ldap.base-environment and any DirContextAuthenticationStrategy
bean, all of which now apply.
The embedded server provides everything that describes a connection to
it, so spring.ldap.urls, spring.ldap.username, spring.ldap.password and
spring.ldap.ssl are now ignored while it is used. A spring.ldap
configuration meant for a production server therefore no longer has to
be unset for a test to run against the embedded server. This is a
behavior change: spring.ldap.urls used to take precedence and silently
pointed the client away from the embedded server.
As spring.ldap.base-environment now applies to the embedded case, a
socket factory set there would be replaced by the one of the SSL
bundle. Startup fails instead of using either silently.
LdapProperties.determineUrls has been removed. Its local.ldap.port
handling only ever served the embedded case, which the embedded
connection details now cover, and the default URL derivation has moved
to PropertiesLdapConnectionDetails, its only caller.
Closes gh-51465
Setting spring.ldap.embedded.ssl.enabled without an SSL bundle started a
plain LDAP listener silently. It now fails at startup as a bundle is
required to provide the server's certificate and private key.
Closes gh-51471
Configure the SSL bundle through the context source's base environment
rather than a DirContextAuthenticationStrategy. The strategy is not
consulted when read-only operations use an anonymous environment,
which is the default when no username is set, so LDAPS connections
silently used the JVM's default trust material. It was also bypassed
entirely when a custom strategy bean was defined.
Register an SSL bundle update handler so that reloaded key and trust
material is used by subsequent connections.
Target LDAPS rather than StartTLS by setting the JNDI
java.naming.ldap.factory.socket property, and fail at startup if a
bundle is combined with a non-ldaps URL or with a socket factory that
has also been set through spring.ldap.base-environment. Delegate all
socket factory methods so that a configured connect timeout is
applied.
Add spring.ldap.ssl.enabled to use the platform's default trust and
key material without a bundle, default the URL to
ldaps://localhost:636 when SSL is enabled, and register the reflection
hint that JNDI needs to load the socket factory by name in a native
image. Cover the result with integration tests that search over LDAPS
against OpenLDAP and LLDAP containers, including certificates that are
untrusted or issued to a different host.
See gh-51382
Tomcat's SSL configuration is applied to an `SSLHostConfig` for each
host name. When an SSL bundle was updated, a new `SSLHostConfig` was
created and used to replace the existing one for that host name,
discarding any customizations that had been applied to it (for example
by a `TomcatConnectorCustomizer`).
Reuse the existing `SSLHostConfig` for the host name when one is
present, applying the updated bundle to it rather than replacing it. The
existing `SSLHostConfigCertificate` is also reused, as adding a second
certificate with an undefined type to an `SSLHostConfig` is rejected by
Tomcat.
See gh-51290
Signed-off-by: Scott Frederick <scottyfred@gmail.com>