diff --git a/core/src/main/java/org/apache/cxf/configuration/jsse/SSLContextServerParameters.java b/core/src/main/java/org/apache/cxf/configuration/jsse/SSLContextServerParameters.java new file mode 100644 index 00000000000..00e44b3cd96 --- /dev/null +++ b/core/src/main/java/org/apache/cxf/configuration/jsse/SSLContextServerParameters.java @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cxf.configuration.jsse; + +import javax.net.ssl.SSLContext; + +public class SSLContextServerParameters extends TLSServerParameters { + private final SSLContext sslContext; + + public SSLContextServerParameters(SSLContext sslContext) { + this.sslContext = sslContext; + setSecureSocketProtocol(sslContext.getProtocol()); + } + + public SSLContext getSslContext() { + return sslContext; + } +} diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RuntimeDelegateImpl.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RuntimeDelegateImpl.java index 03ceeca44c5..acef30a93f7 100644 --- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RuntimeDelegateImpl.java +++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RuntimeDelegateImpl.java @@ -28,6 +28,7 @@ import java.util.Date; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -49,6 +50,8 @@ import jakarta.ws.rs.core.UriBuilder; import jakarta.ws.rs.core.Variant.VariantListBuilder; import jakarta.ws.rs.ext.RuntimeDelegate; +import org.apache.cxf.Bus; +import org.apache.cxf.configuration.jsse.SSLContextServerParameters; import org.apache.cxf.configuration.jsse.TLSServerParameters; import org.apache.cxf.configuration.security.ClientAuthentication; import org.apache.cxf.endpoint.Server; @@ -56,10 +59,13 @@ import org.apache.cxf.jaxrs.bootstrap.ConfigurationBuilderImpl; import org.apache.cxf.jaxrs.bootstrap.InstanceImpl; import org.apache.cxf.jaxrs.utils.ResourceUtils; +import org.apache.cxf.transport.http.HTTPServerEngineFactoryParametersProvider; public class RuntimeDelegateImpl extends RuntimeDelegate { - // The default value is implementation specific, using non-priviledged default port + // The default value is implementation specific, using non-priviledged default ports private static final int DEFAULT_HTTP_PORT = 8080; + private static final int DEFAULT_HTTPS_PORT = 8443; + protected Map, HeaderDelegate> headerProviders = new HashMap<>(); public RuntimeDelegateImpl() { @@ -155,16 +161,19 @@ public CompletionStage bootstrap(Application application, Configuratio instanceConfigurationBuilder = instanceConfigurationBuilder.host("localhost"); } + String protocol = "HTTP"; if (!configuration.hasProperty(Configuration.PROTOCOL)) { // The default value is "HTTP" - instanceConfigurationBuilder = instanceConfigurationBuilder.protocol("HTTP"); + instanceConfigurationBuilder = instanceConfigurationBuilder.protocol(protocol); + } else if (configuration.property(Configuration.PROTOCOL) instanceof String p) { + protocol = p; } if (!configuration.hasProperty(Configuration.PORT)) { - instanceConfigurationBuilder = instanceConfigurationBuilder.port(DEFAULT_HTTP_PORT); + instanceConfigurationBuilder = instanceConfigurationBuilder.port(getDefaultPort(protocol)); } else if (configuration.port() == Configuration.FREE_PORT) { instanceConfigurationBuilder = instanceConfigurationBuilder.port(findFreePort()); /* free port */ } else if (configuration.port() == Configuration.DEFAULT_PORT) { - instanceConfigurationBuilder = instanceConfigurationBuilder.port(DEFAULT_HTTP_PORT); + instanceConfigurationBuilder = instanceConfigurationBuilder.port(getDefaultPort(protocol)); } if (!configuration.hasProperty(Configuration.ROOT_PATH)) { // The default value is "/" @@ -177,8 +186,11 @@ public CompletionStage bootstrap(Application application, Configuratio factory.setStart(true); if ("https".equalsIgnoreCase(configuration.protocol())) { - final TLSServerParameters parameters = new TLSServerParameters(); + final SSLContext sslContext = configuration.sslContext(); + final TLSServerParameters parameters = (sslContext != null) + ? new SSLContextServerParameters(sslContext) : new TLSServerParameters(); + final SSLClientAuthentication sslClientAuthentication = configuration.sslClientAuthentication(); if (sslClientAuthentication != null) { final ClientAuthentication clientAuthentication = new ClientAuthentication(); @@ -192,12 +204,17 @@ public CompletionStage bootstrap(Application application, Configuratio parameters.setClientAuthentication(clientAuthentication); } - final SSLContext sslContext = configuration.sslContext(); - if (sslContext != null) { - parameters.setSecureSocketProtocol(sslContext.getProtocol()); - } - - // TODO: Support SSL context propagation down to HTTP engine + factory.getBus().setExtension(new HTTPServerEngineFactoryParametersProvider() { + @Override + public Optional getDefaultTlsServerParameters(Bus bus, String host, + int port, String protocol, String id) { + if ("https".equalsIgnoreCase(protocol) && port == instanceConfiguration.port()) { + return Optional.of(parameters); + } else { + return Optional.empty(); + } + } + }, HTTPServerEngineFactoryParametersProvider.class); } return CompletableFuture @@ -227,6 +244,10 @@ public Application run() throws Exception { public EntityPart.Builder createEntityPartBuilder(String partName) throws IllegalArgumentException { return new EntityPartBuilderImpl(partName); } + + private static int getDefaultPort(String protocol) { + return (protocol.equalsIgnoreCase("http")) ? DEFAULT_HTTP_PORT : DEFAULT_HTTPS_PORT; + } @SuppressWarnings({ "removal", "deprecation" }) private static int findFreePort() { diff --git a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java b/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java index cd4a8ca9f67..75950650097 100644 --- a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java +++ b/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPDestination.java @@ -113,7 +113,7 @@ public void setServletContext(ServletContext sc) { } /** - * Post-configure retreival of server engine. + * Post-configure retrieval of server engine. */ protected void retrieveEngine() throws GeneralSecurityException, diff --git a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPServerEngine.java b/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPServerEngine.java index aa992226819..e73b9c00b60 100644 --- a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPServerEngine.java +++ b/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPServerEngine.java @@ -53,6 +53,7 @@ import org.apache.cxf.common.util.ReflectionUtil; import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.common.util.SystemPropertyAction; +import org.apache.cxf.configuration.jsse.SSLContextServerParameters; import org.apache.cxf.configuration.jsse.SSLUtils; import org.apache.cxf.configuration.jsse.TLSServerParameters; import org.apache.cxf.configuration.security.ClientAuthentication; @@ -854,6 +855,11 @@ public Connection upgradeConnection(Connector c, EndPoint endPoint, return result; } protected SSLContext createSSLContext(SslContextFactory scf) throws Exception { + // The full SSL context is provided by SSLContextServerParameters + if (tlsServerParameters instanceof SSLContextServerParameters sslContextServerParameters) { + return sslContextServerParameters.getSslContext(); + } + String proto = tlsServerParameters.getSecureSocketProtocol() == null ? "TLS" : tlsServerParameters.getSecureSocketProtocol(); diff --git a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPServerEngineFactory.java b/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPServerEngineFactory.java index cfad8c9993e..45d59eb1774 100644 --- a/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPServerEngineFactory.java +++ b/rt/transports/http-jetty/src/main/java/org/apache/cxf/transport/http_jetty/JettyHTTPServerEngineFactory.java @@ -38,6 +38,7 @@ import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.configuration.jsse.TLSServerParameters; import org.apache.cxf.management.InstrumentationManager; +import org.apache.cxf.transport.http.HTTPServerEngineFactoryParametersProvider; import org.eclipse.jetty.util.component.Container; @@ -265,6 +266,15 @@ public synchronized JettyHTTPServerEngine createJettyHTTPServerEngine(String hos if (id != null && tlsParametersMap != null && tlsParametersMap.containsKey(id)) { tlsParameters = tlsParametersMap.get(id); } + + if (tlsParameters == null) { + final HTTPServerEngineFactoryParametersProvider provider = + bus.getExtension(HTTPServerEngineFactoryParametersProvider.class); + if (provider != null) { + tlsParameters = provider.getDefaultTlsServerParameters(bus, host, port, protocol, id).orElse(null); + } + } + JettyHTTPServerEngine ref = getOrCreate(this, host, port, tlsParameters); // checking the protocol if (!protocol.equals(ref.getProtocol())) { diff --git a/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineFactory.java b/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineFactory.java index de9585da52b..2076bb8c2f5 100644 --- a/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineFactory.java +++ b/rt/transports/http-netty/netty-server/src/main/java/org/apache/cxf/transport/http/netty/server/NettyHttpServerEngineFactory.java @@ -35,6 +35,7 @@ import org.apache.cxf.common.injection.NoJSR250Annotations; import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.configuration.jsse.TLSServerParameters; +import org.apache.cxf.transport.http.HTTPServerEngineFactoryParametersProvider; @NoJSR250Annotations(unlessNull = "bus") @@ -176,6 +177,17 @@ public synchronized NettyHttpServerEngine createNettyHttpServerEngine(String hos if ("https".equals(protocol) && tlsServerParametersMap != null) { tlsServerParameters = tlsServerParametersMap.get(Integer.toString(port)); } + + if (tlsServerParameters == null) { + final HTTPServerEngineFactoryParametersProvider provider = + bus.getExtension(HTTPServerEngineFactoryParametersProvider.class); + if (provider != null) { + tlsServerParameters = provider + .getDefaultTlsServerParameters(bus, host, port, protocol, null) + .orElse(null); + } + } + NettyHttpServerEngine ref = getOrCreate(this, host, port, tlsServerParameters); // checking the protocol if (!protocol.equals(ref.getProtocol())) { diff --git a/rt/transports/http-undertow/src/main/java/org/apache/cxf/transport/http_undertow/UndertowHTTPServerEngine.java b/rt/transports/http-undertow/src/main/java/org/apache/cxf/transport/http_undertow/UndertowHTTPServerEngine.java index 4bc41b9083c..83eea18873b 100644 --- a/rt/transports/http-undertow/src/main/java/org/apache/cxf/transport/http_undertow/UndertowHTTPServerEngine.java +++ b/rt/transports/http-undertow/src/main/java/org/apache/cxf/transport/http_undertow/UndertowHTTPServerEngine.java @@ -40,6 +40,7 @@ import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.common.util.PropertyUtils; import org.apache.cxf.common.util.SystemPropertyAction; +import org.apache.cxf.configuration.jsse.SSLContextServerParameters; import org.apache.cxf.configuration.jsse.SSLUtils; import org.apache.cxf.configuration.jsse.TLSServerParameters; import org.apache.cxf.interceptor.Fault; @@ -512,6 +513,11 @@ private boolean shouldDestroyPort() { protected SSLContext createSSLContext() throws Exception { + // The full SSL context is provided by SSLContextServerParameters + if (tlsServerParameters instanceof SSLContextServerParameters sslContextServerParameters) { + return sslContextServerParameters.getSslContext(); + } + String proto = tlsServerParameters.getSecureSocketProtocol() == null ? "TLS" : tlsServerParameters.getSecureSocketProtocol(); diff --git a/rt/transports/http-undertow/src/main/java/org/apache/cxf/transport/http_undertow/UndertowHTTPServerEngineFactory.java b/rt/transports/http-undertow/src/main/java/org/apache/cxf/transport/http_undertow/UndertowHTTPServerEngineFactory.java index 34671c1b865..69c7f3da32c 100644 --- a/rt/transports/http-undertow/src/main/java/org/apache/cxf/transport/http_undertow/UndertowHTTPServerEngineFactory.java +++ b/rt/transports/http-undertow/src/main/java/org/apache/cxf/transport/http_undertow/UndertowHTTPServerEngineFactory.java @@ -37,6 +37,7 @@ import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.configuration.jsse.TLSServerParameters; import org.apache.cxf.management.InstrumentationManager; +import org.apache.cxf.transport.http.HTTPServerEngineFactoryParametersProvider; @@ -263,6 +264,15 @@ public synchronized UndertowHTTPServerEngine createUndertowHTTPServerEngine(Stri if (id != null && tlsParametersMap != null && tlsParametersMap.containsKey(id)) { tlsParameters = tlsParametersMap.get(id); } + + if (tlsParameters == null) { + final HTTPServerEngineFactoryParametersProvider provider = + bus.getExtension(HTTPServerEngineFactoryParametersProvider.class); + if (provider != null) { + tlsParameters = provider.getDefaultTlsServerParameters(bus, host, port, protocol, id).orElse(null); + } + } + UndertowHTTPServerEngine ref = getOrCreate(this, host, port, tlsParameters); // checking the protocol if (!protocol.equals(ref.getProtocol())) { diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPServerEngineFactoryParametersProvider.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPServerEngineFactoryParametersProvider.java new file mode 100644 index 00000000000..0b598610708 --- /dev/null +++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPServerEngineFactoryParametersProvider.java @@ -0,0 +1,47 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cxf.transport.http; + +import java.util.Optional; + +import jakarta.annotation.Nullable; +import org.apache.cxf.Bus; +import org.apache.cxf.configuration.jsse.TLSServerParameters; + +/** + * Provides programmatic defaults to the different HTTP server engine + * factories implementations (that do not share any common interfaces or other + * abstractions). + */ +public interface HTTPServerEngineFactoryParametersProvider { + /** + * Returns the default {@link TLSServerParameters} instance that the HTTP server + * engine could use if there are no {@link TLSServerParameters} provided to by the + * configuration. + * @param bus {@link Bus} instance + * @param host host name + * @param port port + * @param protocol protocol + * @param id server transport identifier (if available) + * @return the default {@link TLSServerParameters} instance, if available + */ + Optional getDefaultTlsServerParameters(Bus bus, String host, + int port, String protocol, @Nullable String id); +} diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLUtils.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLUtils.java index 9c6da933baf..28ab8c2c042 100644 --- a/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLUtils.java +++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLUtils.java @@ -51,6 +51,7 @@ import javax.net.ssl.X509TrustManager; import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.configuration.jsse.SSLContextServerParameters; import org.apache.cxf.configuration.jsse.TLSClientParameters; import org.apache.cxf.configuration.jsse.TLSParameterBase; import org.apache.cxf.configuration.jsse.TLSServerParameters; @@ -123,7 +124,7 @@ public static SSLContext getSSLContext(TLSParameterBase parameters, boolean addH HostnameVerifier hnv = getHostnameVerifier((TLSClientParameters)parameters); for (int i = 0; i < tms.length; i++) { if (tms[i] instanceof X509TrustManager) { - tms[i] = new X509TrustManagerWrapper((X509TrustManager)tms[i], hnv); + tms[i] = new X509TrustManagerWrapper((X509TrustManager)tms[i], hnv); } } } @@ -160,7 +161,14 @@ public static KeyManager[] configureKeyManagersWithCertAlias(TLSParameterBase tl } public static SSLEngine createServerSSLEngine(TLSServerParameters parameters) throws Exception { - SSLContext sslContext = getSSLContext(parameters); + SSLContext sslContext = null; + // The full SSL context is provided by SSLContextServerParameters + if (parameters instanceof SSLContextServerParameters sslContextServerParameters) { + sslContext = sslContextServerParameters.getSslContext(); + } else { + sslContext = getSSLContext(parameters); + } + SSLEngine serverEngine = sslContext.createSSLEngine(); serverEngine.setUseClientMode(false); serverEngine.setNeedClientAuth(parameters.getClientAuthentication().isRequired()); diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/bootstrap/SeBootstrapTest.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/bootstrap/SeBootstrapTest.java index 9f59c8b014d..767ba91fbea 100644 --- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/bootstrap/SeBootstrapTest.java +++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/bootstrap/SeBootstrapTest.java @@ -19,10 +19,16 @@ package org.apache.cxf.systest.jaxrs.bootstrap; +import java.io.InputStream; +import java.security.KeyStore; import java.util.Collections; import java.util.Set; import java.util.concurrent.CompletionStage; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; + import jakarta.ws.rs.ApplicationPath; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; @@ -31,25 +37,53 @@ import jakarta.ws.rs.client.ClientBuilder; import jakarta.ws.rs.core.Application; import jakarta.ws.rs.core.UriBuilder; +import org.apache.cxf.Bus; +import org.apache.cxf.BusFactory; +import org.apache.cxf.common.classloader.ClassLoaderUtils; +import org.apache.cxf.configuration.jsse.TLSClientParameters; +import org.apache.cxf.jaxrs.model.AbstractResourceInfo; +import org.apache.cxf.transport.https.SSLUtils; +import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.junit.After; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; -import static org.junit.Assert.assertThat; /** * Some tests are taken from {@linkplain https://github.com/jakartaee/rest/blob/tck-3.1.2/jaxrs-tck * /src/main/java/ee/jakarta/tck/ws/rs/sebootstrap/SeBootstrapIT.java} */ public class SeBootstrapTest { + private static Bus bus; private Client client; + @BeforeClass + public static void createBus() throws Exception { + AbstractResourceInfo.clearAllMaps(); + bus = BusFactory.newInstance().createBus(); + BusFactory.setDefaultBus(bus); + } + + + @AfterClass + public static void destroyBus() throws Exception { + bus.shutdown(true); + bus = null; + } + @Before - public void setUp() { - client = ClientBuilder.newClient(); + public void setUp() throws Exception { + client = ClientBuilder + .newBuilder() + .sslContext(createSSLContext()) + .hostnameVerifier(new NoopHostnameVerifier()) + .build(); } @After @@ -131,6 +165,62 @@ public final void shouldBootInstanceUsingImplementationsDefaultIpPort() { assertThat(actualConfiguration.rootPath(), is(requestedConfiguration.rootPath())); instance.stop().toCompletableFuture().join(); } + + /** + * Verifies that an instance will boot using default configuration. + */ + @Test + public final void shouldBootInstanceUsingHttps() throws Exception { + final Application application = new StaticApplication(); + final SeBootstrap.Configuration.Builder bootstrapConfigurationBuilder = SeBootstrap.Configuration.builder(); + bootstrapConfigurationBuilder.protocol("HTTPS"); + bootstrapConfigurationBuilder.sslContext(createSSLContext()); + + final SeBootstrap.Configuration requestedConfiguration = bootstrapConfigurationBuilder.build(); + final CompletionStage completionStage = SeBootstrap.start(application, + requestedConfiguration); + final SeBootstrap.Instance instance = completionStage.toCompletableFuture().join(); + final SeBootstrap.Configuration actualConfiguration = instance.configuration(); + + final String actualResponse = client.target(UriBuilder.newInstance().scheme(actualConfiguration.protocol()) + .host(actualConfiguration.host()).port(actualConfiguration.port()).path(actualConfiguration.rootPath()) + .path("application/resource")).request().get(String.class); + + assertThat(actualResponse, is("OK")); + assertThat(actualConfiguration.protocol(), is("HTTPS")); + assertThat(actualConfiguration.host(), is("localhost")); + assertThat(actualConfiguration.port(), is(8443)); + assertThat(actualConfiguration.rootPath(), is("/")); + + instance.stop().toCompletableFuture().join(); + } + + private SSLContext createSSLContext() throws Exception { + final TLSClientParameters tlsParams = new TLSClientParameters(); + tlsParams.setHostnameVerifier(new NoopHostnameVerifier()); + + try (InputStream keystore = ClassLoaderUtils.getResourceAsStream("keys/Truststore.jks", this.getClass())) { + KeyStore trustStore = loadStore(keystore, "password"); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(trustStore); + tlsParams.setTrustManagers(tmf.getTrustManagers()); + } + + try (InputStream keystore = ClassLoaderUtils.getResourceAsStream("keys/Morpit.jks", this.getClass())) { + KeyStore keyStore = loadStore(keystore, "password"); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(keyStore, "password".toCharArray()); + tlsParams.setKeyManagers(kmf.getKeyManagers()); + } + + return SSLUtils.getSSLContext(tlsParams); + } + + private KeyStore loadStore(InputStream inputStream, String password) throws Exception { + KeyStore store = KeyStore.getInstance("JKS"); + store.load(inputStream, password.toCharArray()); + return store; + } @ApplicationPath("application") public static final class StaticApplication extends Application {