Repository navigation
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1344 +/- ##
============================================
+ Coverage 70.79% 71.51% +0.72%
- Complexity 2270 2297 +27
============================================
Files 161 161
Lines 9077 9094 +17
Branches 1192 1193 +1
============================================
+ Hits 6426 6504 +78
+ Misses 2198 2139 -59
+ Partials 453 451 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Allow applications to supply the SSLContext for SSL-enabled sessions instead of having SSLContextFactory load stores from files, e.g. when key material is delivered by a secrets manager as environment variables. - Add SSLContextProvider, keyed by SSLConfig; the default is SSLContextFactory::getInstance, so existing behaviour is unchanged. - Add setSSLContextProvider on SessionConnector and withSSLContextProvider on the connector builders. - Report provider failures and null contexts as initialization errors, honouring ContinueInitializationOnError; no fallback to file stores. - Document usage in the secure communications user manual. Relates to quickfix-j#1343, quickfix-j#678
d4dd222 to
93736f6
Compare
the-thing
left a comment
There was a problem hiding this comment.
Useful feature. Can we just make the field final and if specific provider logic is required can we make it in the builder?
| log.info("Installing SSL filter for {}", descriptor.getAddress()); | ||
| SSLConfig sslConfig = descriptor.getSslConfig(); | ||
| SSLContext sslContext = SSLContextFactory.getInstance(sslConfig); | ||
| SSLContext sslContext = getSSLContextProvider().getSSLContext(sslConfig); |
There was a problem hiding this comment.
This probably shouldn't be a method, but just a final field that is never null.
| .newSingleThreadScheduledExecutor(new QFTimerThreadFactory()); | ||
| private ScheduledFuture<?> sessionTimerFuture; | ||
| private IoFilterChainBuilder ioFilterChainBuilder; | ||
| private SSLContextProvider sslContextProvider = SSLContextFactory::getInstance; |
There was a problem hiding this comment.
instead of initializing it like that this should be created via builder pattern.
| /** | ||
| * Sets the provider of SSL contexts, or null for the default. Must be set before the connector is started. | ||
| */ | ||
| public void setSSLContextProvider(SSLContextProvider sslContextProvider) { |
There was a problem hiding this comment.
Mentioned before. Can we remove it and make the field final?
| @Override | ||
| protected SocketAcceptor doBuild() throws ConfigError { | ||
| return new SocketAcceptor(this); | ||
| SocketAcceptor socketAcceptor = new SocketAcceptor(this); |
There was a problem hiding this comment.
This kinds of break builder pattern. The field should be set to final field in the socket acceptor constructor.
| @Override | ||
| protected SocketInitiator doBuild() throws ConfigError { | ||
| return new SocketInitiator(this); | ||
| SocketInitiator socketInitiator = new SocketInitiator(this); |
There was a problem hiding this comment.
Same here. This method shouldn't change.
| @Override | ||
| protected ThreadedSocketAcceptor doBuild() throws ConfigError { | ||
| return new ThreadedSocketAcceptor(this); | ||
| ThreadedSocketAcceptor threadedSocketAcceptor = new ThreadedSocketAcceptor(this); |
| @Override | ||
| protected ThreadedSocketInitiator doBuild() throws ConfigError { | ||
| return new ThreadedSocketInitiator(this); | ||
| ThreadedSocketInitiator threadedSocketInitiator = new ThreadedSocketInitiator(this); |
Address review: remove SessionConnector.setSSLContextProvider and the wrapping getter, keep the provider in a final, never-null field of the socket acceptor and initiator, and pass it through their constructors. The builder defaults the provider to SSLContextFactory::getInstance in build(), like the log and message factories.
|
Hello @the-thing , thank you for your comments, moved everything to builders and made the field final. Could you please review again when you have a chance? |
|
Will do. It might take a few days, but I will. Stay tuned. |
the-thing
left a comment
There was a problem hiding this comment.
LGTM.
SSLContextProviderTest start / stop could have been wrapped in separate try / finally blocks.
Not for this PR, but I have a feeling that these overloaded super constructors are too large and probably every one of them should have a single parameter builder and take whatever they need from there.
Give each connector in SSLContextProviderTest its own try/finally, so a failing stop cannot leave the other connector running. Load the trust store in the user manual example with its password: PKCS12 trust stores created by current JDKs encrypt their certificates, so loading them without a password yields an empty trust store.
|
Thank you @the-thing , addressed this comment:
Also will take a look whether we can replace the ctors' parameters with builders, will create an issue for that if this is feasible. |
Summary
Adds a pluggable
SSLContextProviderso applications can supply theSSLContextfor SSL-enabled sessions instead of havingSSLContextFactoryload key and trust stores from files. This lets key material held in memory, e.g. delivered by a secrets manager as environment variables, be used without writing it to disk.Closes #1343. Follows the approach suggested in #678 / discussion #679.
Changes
SSLContextProvider(quickfix.mina.ssl): a functional interface,SSLContext getSSLContext(SSLConfig). The default isSSLContextFactory::getInstance, so existing behaviour is unchanged.withSSLContextProvider(...)on the builders ofSocketInitiator,SocketAcceptorand their threaded variants. Without it (or withnull), the builder usesSSLContextFactory::getInstance.final, never-null field ofAbstractSocketAcceptor/AbstractSocketInitiator, set through new constructor overloads; the existing constructors use the default.GeneralSecurityException, the session (initiator) or listening address (acceptor) fails to initialize, honouringContinueInitializationOnError. The provider must not returnnull. There is no silent fallback to file stores.SSLContextcomes from the provider; protocols, cipher suites,NeedClientAuth, SNI and endpoint identification are still applied from the settings.secure_communications.html.Usage
The provider receives the
SSLConfigof each session or acceptor address, so it can also return different contexts per session, or delegate toSSLContextFactory.getInstance(sslConfig)for stores that should still be loaded from files.Compatibility
SSLContextFactoryandSessionConnectorare unchanged, and connectors created with the existing constructors keep loading stores from files.IoSessionInitiatorconstructor is kept and delegates to the new one.Testing
New
SSLContextProviderTest:GeneralSecurityException;ContinueInitializationOnError=Y, a failing provider skips the acceptor address and the initiator session.Existing
SSLCertificateTest,SecureSocketTest,IoSessionInitiatorTest,SocketInitiatorTestandSocketAcceptorTestpass unchanged.