I've written wrappers for Java's
X509KeyManager classes, and added a Provider so that you can get it hooked into the system automatically.
It's available at https://github.com/tersesystems/debugjsse.
This means you can say:
import com.tersesystems.debugjsse.DebugJSSEProvider; DebugJSSEProvider debugJSSEProvider = new DebugJSSEProvider(); Security.addProvider(debugJSSEProvider); debugJSSEProvider.setAsDefault();
and then anything you do after that point with JSSE will have entry/exit/exception on it.
For example, if you instantiate a trust manager and call
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(ks); TrustManager trustManagers = trustManagerFactory.getTrustManagers(); X509ExtendedTrustManager trustManager = (X509ExtendedTrustManager) trustManagers; X509Certificate acceptedIssuers = trustManager.getAcceptedIssuers();
will result in:
2018-07-27 06:30:04,545 TRACE [main] - getAcceptedIssuers: args =  with delegate = sun.security.ssl.X509TrustManagerImpl@29444d75 2018-07-27 06:30:04,549 TRACE [main] - getAcceptedIssuers: args =  with delegate = sun.security.ssl.X509TrustManagerImpl@29444d75, result = [Ljava.security.cert.X509Certificate;@7bfcd12c
You can also wrap your trust manager explicitly, of course:
X509ExtendedTrustManager delegate = ... Debug debug = ... X509ExtendedTrustManager tm = new DebugX509ExtendedTrustManager(delegate, debug);
but if you have libraries that instantiate their own trust managers, such as Kafka Client's SslFactory, then hooking in the provider is the only way to get at it.
Note that this debugging mechanism is distinct from using
javax.net.debug in a few ways. Here's what is wrong with JSSE debugging:
javax.net.debugis hardcoded to
javax.net.debugmixes outputs coming from different threads.
javax.net.debugdoes not give you timestamp information.
javax.net.debugdoes not give you method level granularity.
javax.net.debugsettings cannot be changed at runtime.
javax.net.debugdoes not respect verbosity settings.
By contrast, DebugJSSE:
- Works with any logging framework.
- Has flexibility to log only by delegate or by individual method or argument.
- Lets you swap out the results of the delegate's method call.
I've been meaning to write this for a while. What really cracked it was the
X509ExtendedKeyManager abstract class adds two methods,
chooseEngineServerAlias, but silently returns null for both of them. And then
javax.net.debug doesn't integrate with SLF4J, and an async appender and println do not get along.
It is all fixed. It is done. May you never have to go through this.
You may also like https://github.com/scholzj/AliasKeyManager which was used as inspiration, and will pick out a preferred client alias from a key manager. Also see the previous JSSE posts if you are morbidly curious.