diff --git a/keystores/src/main/java/com/palantir/conjure/java/config/ssl/KeyStores.java b/keystores/src/main/java/com/palantir/conjure/java/config/ssl/KeyStores.java index 5ed2ff463..2726ac129 100644 --- a/keystores/src/main/java/com/palantir/conjure/java/config/ssl/KeyStores.java +++ b/keystores/src/main/java/com/palantir/conjure/java/config/ssl/KeyStores.java @@ -122,6 +122,12 @@ static KeyStore createTrustStoreFromCertificates(Map KeyStore keyStore; keyStore = createKeyStore(); + addCertificatesToKeystore(certificatesByAlias, keyStore); + + return keyStore; + } + + static void addCertificatesToKeystore(Map certificatesByAlias, KeyStore keyStore) { for (Map.Entry entry : certificatesByAlias.entrySet()) { try (InputStream certIn = new ByteArrayInputStream(entry.getValue().pemCertificate().getBytes(StandardCharsets.UTF_8))) { @@ -135,8 +141,6 @@ static KeyStore createTrustStoreFromCertificates(Map e); } } - - return keyStore; } private static void addCertificatesToKeystore( diff --git a/keystores/src/main/java/com/palantir/conjure/java/config/ssl/SslSocketFactories.java b/keystores/src/main/java/com/palantir/conjure/java/config/ssl/SslSocketFactories.java index ddddff50c..e20230d1b 100644 --- a/keystores/src/main/java/com/palantir/conjure/java/config/ssl/SslSocketFactories.java +++ b/keystores/src/main/java/com/palantir/conjure/java/config/ssl/SslSocketFactories.java @@ -18,6 +18,7 @@ import com.google.common.base.Throwables; import com.palantir.conjure.java.api.config.ssl.SslConfiguration; +import com.palantir.conjure.java.api.config.ssl.SslConfiguration.StoreType; import com.palantir.logsafe.SafeArg; import com.palantir.logsafe.exceptions.SafeRuntimeException; import java.nio.file.Path; @@ -91,6 +92,20 @@ public static SSLSocketFactory createSslSocketFactory( return sslContext.getSocketFactory(); } + /** + * Create a {@link SSLSocketFactory} by merging the provided certificates and configuration. + * + * @param trustCertificatesByAlias a map of X.509 certificate in PEM or DER format by the alias to load the + * certificate as. + * @param config an {@link SslConfiguration} describing the trust store configuration + * @param provider The preferred security {@link Provider} + */ + public static SSLSocketFactory createSslSocketFactory( + Map trustCertificatesByAlias, SslConfiguration config, Provider provider) { + SSLContext sslContext = createSslContext(config, trustCertificatesByAlias, provider); + return sslContext.getSocketFactory(); + } + /** * Create an {@link SSLContext} initialized from the provided configuration. * @@ -142,6 +157,20 @@ public static SSLContext createSslContext( return createSslContext(trustManagers, new KeyManager[] {}, provider); } + /** + * Create an {@link SSLContext} by merging the provided configuration and certificates. + * + * @param trustCertificatesByAlias a map of X.509 certificate in PEM or DER format by the alias to load the + * certificate as. + * @param config an {@link SslConfiguration} describing the trust store configuration + * @param provider The preferred security {@link Provider} + */ + public static SSLContext createSslContext( + SslConfiguration config, Map trustCertificatesByAlias, Provider provider) { + TrustManager[] trustManagers = createMergedTrustManagers(config, trustCertificatesByAlias); + return createSslContext(trustManagers, new KeyManager[] {}, provider); + } + /** * Create an {@link SSLContext} initialized from the provided certificates. * @see SSLContext#init(KeyManager[], TrustManager[], SecureRandom) @@ -200,6 +229,20 @@ public static TrustManager[] createTrustManagers(Map } } + /** + * Create SSL socket factory and trust manager by merging the given certificates and configuration, + * see {@link #createX509TrustManager} and {@link #createSslSocketFactory}. + */ + public static TrustManager[] createMergedTrustManagers( + SslConfiguration config, Map trustCertificatesByAlias) { + KeyStore keystore = getCombinedTrustStoreAndDefaultCas(config.trustStorePath(), config.trustStoreType()); + + KeyStores.addCertificatesToKeystore(trustCertificatesByAlias, keystore); + + return ConscryptCompatTrustManagers.wrap( + getTrustManagerFactory(keystore).getTrustManagers()); + } + /** * Create SSL socket factory and trust manager from the given configuration, see {@link #createX509TrustManager} and * {@link #createSslSocketFactory}. @@ -269,6 +312,23 @@ public static KeyManager[] createKeyManagers(SslConfiguration config) { private static TrustManagerFactory createTrustManagerFactory( Path trustStorePath, SslConfiguration.StoreType trustStoreType) { + KeyStore keyStore = getCombinedTrustStoreAndDefaultCas(trustStorePath, trustStoreType); + + return getTrustManagerFactory(keyStore); + } + + private static TrustManagerFactory getTrustManagerFactory(KeyStore keyStore) { + try { + TrustManagerFactory trustManagerFactory = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(keyStore); + return trustManagerFactory; + } catch (GeneralSecurityException e) { + throw Throwables.propagate(e); + } + } + + private static KeyStore getCombinedTrustStoreAndDefaultCas(Path trustStorePath, StoreType trustStoreType) { KeyStore keyStore; switch (trustStoreType) { case JKS: @@ -299,15 +359,7 @@ private static TrustManagerFactory createTrustManagerFactory( "Unable to add certificate to store", e, SafeArg.of("certificateAlias", certAlias)); } }); - - try { - TrustManagerFactory trustManagerFactory = - TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - trustManagerFactory.init(keyStore); - return trustManagerFactory; - } catch (GeneralSecurityException e) { - throw Throwables.propagate(e); - } + return keyStore; } private static KeyManagerFactory createKeyManagerFactory(