Unable to Login to TDM Portal After Configuring with LDAPS

Document ID : KB000095767
Last Modified Date : 15/05/2018
Show Technical Document Details
Issue:
Logging in to Test Data Manager (TDM) Portal fails after configuring it to authenticate via LDAPS per the documentation:
TDM Portal 4.0-4.2

TDM Portal 4.3-4.5+

The TDM Portal will return a generic "Incorrect username or password" message:
User-added image
Cause:
The TDM Portal process is not accepting the LDAPS servers SSL Certificate. This is evident in the TdmWeb.log:

{date} {time} UTC [ERROR] [http-nio-8443-exec-10    ] --- [U:][M:][P:]                         o.s.b.c.w.ErrorPageFilter:  Forwarding to error page from request [/api/ca/v1/ssforms] due to exception [simple bind failed: {LDAP SERVER}:{LDAP PORT}; nested exception is javax.naming.CommunicationException: simple bind failed: {LDAP SERVER}:{LDAP PORT} [Root exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target]]
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.build(Unknown Source)
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
    at java.security.cert.CertPathBuilder.build(Unknown Source)
    ... 19 common frames omitted
Wrapped by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
    at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
    at sun.security.validator.Validator.validate(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    ... 13 common frames omitted
Wrapped by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.ssl.Alerts.getSSLException(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
    at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
    at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
    at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
    at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
    at sun.security.ssl.Handshaker.processLoop(Unknown Source)
    at sun.security.ssl.Handshaker.process_record(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readDataRecord(Unknown Source)
    at sun.security.ssl.AppInputStream.read(Unknown Source)
    at java.io.BufferedInputStream.fill(Unknown Source)
    at java.io.BufferedInputStream.read1(Unknown Source)
    at java.io.BufferedInputStream.read(Unknown Source)
    at com.sun.jndi.ldap.Connection.run(Unknown Source)
    ... 1 common frames omitted
Wrapped by: javax.naming.CommunicationException: simple bind failed: {LDAP SERVER}:{LDAP PORT}
    at com.sun.jndi.ldap.LdapClient.authenticate(Unknown Source)
    at com.sun.jndi.ldap.LdapCtx.connect(Unknown Source)
    at com.sun.jndi.ldap.LdapCtx.<init>(Unknown Source)
    at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(Unknown Source)
    at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(Unknown Source)
    at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(Unknown Source)
    at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(Unknown Source)
    at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
    at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
    at javax.naming.InitialContext.init(Unknown Source)
    at javax.naming.ldap.InitialLdapContext.<init>(Unknown Source)
    at org.springframework.ldap.core.support.LdapContextSource.getDirContextInstance(LdapContextSource.java:42)
    at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:344)
    ... 81 common frames omitted
Wrapped by: org.springframework.ldap.CommunicationException: simple bind failed: {LDAP SERVER}:{LDAP PORT}; nested exception is javax.naming.CommunicationException: simple bind failed: {LDAP SERVER}:{LDAP PORT} [Root exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target]
    at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:108)
    at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:356)
    at org.springframework.ldap.core.support.AbstractContextSource.doGetContext(AbstractContextSource.java:140)
    at org.springframework.ldap.core.support.AbstractContextSource.getReadOnlyContext(AbstractContextSource.java:159)
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:357)
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:309)
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:616)
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:586)
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:1651)
    at com.ca.tdm.security.LDAPUtil.isUserModified(LDAPUtil.java:178)
    at com.ca.tdm.security.SecurityUtil.verify(SecurityUtil.java:180)
    at com.ca.tdm.security.JWTVerificationFilter.doFilter(JWTVerificationFilter.java:59)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:168)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:120)
    at org.springframework.boot.context.web.ErrorPageFilter.access$000(ErrorPageFilter.java:61)
    at org.springframework.boot.context.web.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:95)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:113)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:94)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:509)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1104)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1524)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1480)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)
Resolution:
The LDAPS servers certificate needs to be added to the Java Keystore so the Portal process can load/accept this certificate accordingly.
  1. Get the certificate from the LDAPS server - if the LDAP Admins are unable to provide the cert, you can get a copy of it using the "openssl" command:
    1. openssl s_client -showcerts -connect {LDAP SERVER}:{LDAP PORT}
    2. Once the command is complete, CTRL + D  to complete the command.
    3. Copy the text between and including "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----". Example:
      -----BEGIN CERTIFICATE-----
      MIIDjTCCAnWgAwIBAgIEPDIatDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQKEwJD
      QTEoMCYGA1UECxMfVGVzdCBEYXRhIE1hbmFnZXIgLSBTZWxmIFNpZ25lZDEWMBQG
      A1UEAxMNa2Fpc2UwMS10ZG0wMTAeFw0xNzA5MjYyMTMzMTRaFw0zOTA5MjEyMTMz
      MTRaME8xCzAJBgNVBAoTAkNBMSgwJgYDVQQLEx9UZXN0IERhdGEgTWFuYWdlciAt
      IFNlbGYgU2lnbmVkMRYwFAYDVQQDEw1rYWlzZTAxLXRkbTAxMIIBIjANBgkqhkiG
      9w0BAQEFAAOCAQ8AMIIBCgKCAQEAi8FmJkoirW/KXoahC0S9N4+CR+IUGGmEO78P
      gV8YqwHCyQ1kuQNyA9U86zFxJzAcvnB9BMsfeqGXwDKyERiAjDFn/BGZvsU9zn24
      g96cuOIm6tWLkNAuChY5roFIIblPt2EKQO9zoKrY1opDgD8beGcpCnqzNe7wn7Ly
      FlX0QYV0WqJoumtYUV7ORXkKnwmEE63hiMUIBrr4ZAFFegvRrFfrft0DyyYA2FXR
      ssUEy3VRGngFQuLieyYI6gPuMC0/acVk0GuL1a1YPdKpKf66PZWXI8gzqmNz5wn7
      cGlXNsqYRUmoMwOZplgUR+C7B77IowifvUwfi03dxMc1jCgyBQIDAQABo3EwbzAT
      BgNVHSUEDDAKBggrBgEFBQcDATA5BgNVHREEMjAwghRrYWlzZTAxLXRkbTAxLmNh
      LmNvbYINa2Fpc2UwMS10ZG0wMYIJbG9jYWxob3N0MB0GA1UdDgQWBBS373hNBnB5
      akl5ujZ9E5T4UYf5/jANBgkqhkiG9w0BAQsFAAOCAQEANHW56pgRtdeta1AlNFyv
      Mcdebp08Fs2fOpZTOGAJ0nRL01T8ZrWaDQ01W+Y2lGY2BOX8mOPAVlOAuZ5xMkAw
      3AUDZG6XU6HMAh7NV5aFz1noYhjdfqYwFKgpv+/rC+NtWc0uqPR/M/i7QpTadN7v
      m+nHj7hnSL+0XmyNKUbAnGhVmG5R+IaSq4l4n+9duCc46c8fGv1parcxjhrYi2b8
      bsH2UBhnugC/IZjQo0SP9DKDCuJbr6lOLK7SevkMRjhIcZfiFo98ei4kKBa5CUNJ
      V64xetkc0B7TUpxEsGhnHv9VuzpTQgZlLmNNc/KwBdhgMMpoUGKvXrhR7v8d+r+Y
      Bg==
      -----END CERTIFICATE-----
    4. Save the text to a file.
    5. Copy/save the data in steps c and d for each certificate listed in the openssl output.
  2. Stop the "CA Test Data Manager Portal" service
  3. cd C:\Program Files\CA\CA Test Data Manager Portal\jre\bin
  4. keytool -import -keystore ..\lib\security\cacerts -storepass changeit -alias {unique alias name for this cert} -file {path to cert saved in step 1.d.}
  5. Repeat step 4 as needed for each certificate saved in steps 1.c-1.e.
  6. Start the "CA Test Data Manager Portal" service