From a71766ad4db3de5833b797e453cc3fc8bfeb4a74 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 12 May 2021 08:56:51 +0200 Subject: [PATCH] Add TrustManagerProvider (#1654) --- gradle/changelog/trust_manager_provider.yaml | 2 + .../lifecycle/modules/ScmServletModule.java | 7 +- .../sonia/scm/net/SSLContextProvider.java | 27 +++---- .../sonia/scm/net/TrustManagerProvider.java | 72 +++++++++++++++++++ .../scm/net/TrustManagerProviderTest.java | 61 ++++++++++++++++ 5 files changed, 151 insertions(+), 18 deletions(-) create mode 100644 gradle/changelog/trust_manager_provider.yaml create mode 100644 scm-webapp/src/main/java/sonia/scm/net/TrustManagerProvider.java create mode 100644 scm-webapp/src/test/java/sonia/scm/net/TrustManagerProviderTest.java diff --git a/gradle/changelog/trust_manager_provider.yaml b/gradle/changelog/trust_manager_provider.yaml new file mode 100644 index 0000000000..117af90479 --- /dev/null +++ b/gradle/changelog/trust_manager_provider.yaml @@ -0,0 +1,2 @@ +- type: added + description: Add trust manager provider ([#1654](https://github.com/scm-manager/scm-manager/pull/1654)) diff --git a/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ScmServletModule.java index a02cf006c5..36145b7087 100644 --- a/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/lifecycle/modules/ScmServletModule.java @@ -58,6 +58,7 @@ import sonia.scm.group.xml.XmlGroupDAO; import sonia.scm.metrics.MeterRegistryProvider; import sonia.scm.migration.MigrationDAO; import sonia.scm.net.SSLContextProvider; +import sonia.scm.net.TrustManagerProvider; import sonia.scm.net.ahc.AdvancedHttpClient; import sonia.scm.net.ahc.ContentTransformer; import sonia.scm.net.ahc.DefaultAdvancedHttpClient; @@ -125,6 +126,7 @@ import sonia.scm.web.security.AdministrationContext; import sonia.scm.web.security.DefaultAdministrationContext; import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; /** * @author Sebastian Sdorra @@ -211,9 +213,12 @@ class ScmServletModule extends ServletModule { bind(CGIExecutorFactory.class, DefaultCGIExecutorFactory.class); bind(StoreExporter.class, FileStoreExporter.class); - // bind sslcontext provider + // bind ssl context provider bind(SSLContext.class).toProvider(SSLContextProvider.class); + // bind trust manager provider + bind(TrustManager.class).toProvider(TrustManagerProvider.class); + // bind ahc Multibinder transformers = Multibinder.newSetBinder(binder(), ContentTransformer.class); diff --git a/scm-webapp/src/main/java/sonia/scm/net/SSLContextProvider.java b/scm-webapp/src/main/java/sonia/scm/net/SSLContextProvider.java index e5843cdb5d..d7370c7f78 100644 --- a/scm-webapp/src/main/java/sonia/scm/net/SSLContextProvider.java +++ b/scm-webapp/src/main/java/sonia/scm/net/SSLContextProvider.java @@ -21,15 +21,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.net; import com.google.common.base.Throwables; import com.google.inject.Inject; + import java.security.NoSuchAlgorithmException; import javax.inject.Named; import javax.inject.Provider; import javax.net.ssl.SSLContext; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,8 +42,7 @@ import org.slf4j.LoggerFactory; * @author Sebastian Sdorra * @version 1.47 */ -public final class SSLContextProvider implements Provider -{ +public final class SSLContextProvider implements Provider { /** * the logger for SSLContextProvider @@ -53,28 +54,20 @@ public final class SSLContextProvider implements Provider private Provider sslContextProvider; @Override - public SSLContext get() - { + public SSLContext get() { SSLContext context = null; - if (sslContextProvider != null) - { + if (sslContextProvider != null) { context = sslContextProvider.get(); } - if (context == null) - { - try - { + if (context == null) { + try { logger.trace("could not find ssl context provider, use jvm default"); context = SSLContext.getDefault(); - } - catch (NoSuchAlgorithmException ex) - { + } catch (NoSuchAlgorithmException ex) { throw Throwables.propagate(ex); } - } - else - { + } else { logger.trace("use custom ssl context from provider"); } return context; diff --git a/scm-webapp/src/main/java/sonia/scm/net/TrustManagerProvider.java b/scm-webapp/src/main/java/sonia/scm/net/TrustManagerProvider.java new file mode 100644 index 0000000000..43835c0d1d --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/net/TrustManagerProvider.java @@ -0,0 +1,72 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.net; + +import com.google.common.annotations.VisibleForTesting; +import com.google.inject.Inject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Named; +import javax.inject.Provider; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; + +public class TrustManagerProvider implements Provider { + + private static final Logger LOG = LoggerFactory.getLogger(TrustManagerProvider.class); + + @Named("default") + @Inject(optional = true) + private Provider customTrustManagerProvider; + + @VisibleForTesting + void setCustomTrustManagerProvider(Provider customTrustManagerProvider) { + this.customTrustManagerProvider = customTrustManagerProvider; + } + + @Override + public TrustManager get() { + if (customTrustManagerProvider != null) { + LOG.trace("use custom trust manager from provider"); + return customTrustManagerProvider.get(); + } else { + LOG.trace("could not find trust manager provider, use jvm default"); + return createDefaultTrustManager(); + } + } + private TrustManager createDefaultTrustManager() { + try { + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init((KeyStore) null); + return trustManagerFactory.getTrustManagers()[0]; + } catch (NoSuchAlgorithmException | KeyStoreException ex) { + throw new IllegalStateException(ex); + } + } +} diff --git a/scm-webapp/src/test/java/sonia/scm/net/TrustManagerProviderTest.java b/scm-webapp/src/test/java/sonia/scm/net/TrustManagerProviderTest.java new file mode 100644 index 0000000000..9af4b9cfb5 --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/net/TrustManagerProviderTest.java @@ -0,0 +1,61 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.net; + +import com.google.inject.util.Providers; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import static org.assertj.core.api.Assertions.assertThat; + +class TrustManagerProviderTest { + + @Test + void shouldReturnDefaultTrustManager() { + TrustManager trustManager = new TrustManagerProvider().get(); + + assertThat(trustManager).isInstanceOf(X509TrustManager.class); + } + + @Nested + class WithCustomTrustManagerProvider { + + @Test + void shouldReturnCustomTrustManager() { + TrustManagerProvider trustManagerProvider = new TrustManagerProvider(); + trustManagerProvider.setCustomTrustManagerProvider(Providers.of(new CustomTrustManager())); + + TrustManager trustManager = trustManagerProvider.get(); + + assertThat(trustManager).isInstanceOf(CustomTrustManager.class); + } + } + + static class CustomTrustManager implements TrustManager { + } +}