This is an automated email from the ASF dual-hosted git repository.
reta pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/main by this push:
new 650a19442a CXF-9039: Support SeBootstrap HTTPS configuration (#2195)
650a19442a is described below
commit 650a19442a78b2bb330212bb680ed94c486c3e95
Author: Andriy Redko <[email protected]>
AuthorDate: Sat Feb 22 13:28:21 2025 -0500
CXF-9039: Support SeBootstrap HTTPS configuration (#2195)
---
.../jsse/SSLContextServerParameters.java | 54 ++++++++++++
.../apache/cxf/jaxrs/impl/RuntimeDelegateImpl.java | 43 +++++++---
.../transport/http_jetty/JettyHTTPDestination.java | 2 +-
.../http_jetty/JettyHTTPServerEngine.java | 6 ++
.../http_jetty/JettyHTTPServerEngineFactory.java | 10 +++
.../netty/server/NettyHttpServerEngineFactory.java | 12 +++
.../http_undertow/UndertowHTTPServerEngine.java | 6 ++
.../UndertowHTTPServerEngineFactory.java | 10 +++
.../HTTPServerEngineFactoryParametersProvider.java | 47 +++++++++++
.../org/apache/cxf/transport/https/SSLUtils.java | 12 ++-
.../systest/jaxrs/bootstrap/SeBootstrapTest.java | 96 +++++++++++++++++++++-
11 files changed, 281 insertions(+), 17 deletions(-)
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 0000000000..f74a00bfe5
--- /dev/null
+++
b/core/src/main/java/org/apache/cxf/configuration/jsse/SSLContextServerParameters.java
@@ -0,0 +1,54 @@
+/**
+ * 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 java.util.Arrays;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+
+/**
+ * Allows to supply to the HTTP Server the complete SSLContext already
preconfigured.
+ */
+public class SSLContextServerParameters extends TLSServerParameters {
+ private final SSLContext sslContext;
+
+ public SSLContextServerParameters(SSLContext sslContext) {
+ this.sslContext = sslContext;
+ setSecureSocketProtocol(sslContext.getProtocol());
+ setJsseProvider(sslContext.getProvider().getName());
+
setCipherSuites(Arrays.asList(sslContext.getServerSocketFactory().getSupportedCipherSuites()));
+ }
+
+ public SSLContext getSslContext() {
+ return sslContext;
+ }
+
+ @Override
+ public TrustManager[] getTrustManagers() {
+ throw new UnsupportedOperationException("The operation is not
supported by SSLContextServerParameters");
+ }
+
+ @Override
+ public KeyManager[] getKeyManagers() {
+ throw new UnsupportedOperationException("The operation is not
supported by SSLContextServerParameters");
+ }
+}
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 03ceeca44c..acef30a93f 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.security.PrivilegedExceptionAction;
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.Response.ResponseBuilder;
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.JAXRSServerFactoryBean;
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<Class<?>, HeaderDelegate<?>> headerProviders = new
HashMap<>();
public RuntimeDelegateImpl() {
@@ -155,16 +161,19 @@ public class RuntimeDelegateImpl extends RuntimeDelegate {
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 class RuntimeDelegateImpl extends RuntimeDelegate {
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 class RuntimeDelegateImpl extends RuntimeDelegate {
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<TLSServerParameters>
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 class RuntimeDelegateImpl extends RuntimeDelegate {
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 cd4a8ca9f6..7595065009 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 class JettyHTTPDestination extends
ServletDestination {
}
/**
- * 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 aa99222681..e73b9c00b6 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.PropertyUtils;
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 class JettyHTTPServerEngine implements
ServerEngine, HttpServerEngineSupp
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 cfad8c9993..45d59eb177 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.injection.NoJSR250Annotations;
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 class JettyHTTPServerEngineFactory {
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 de9585da52..2076bb8c2f 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.buslifecycle.BusLifeCycleManager;
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 class NettyHttpServerEngineFactory implements
BusLifeCycleListener {
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 4bc41b9083..83eea18873 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.i18n.Message;
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 @@ public class UndertowHTTPServerEngine implements
ServerEngine, HttpServerEngineS
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 34671c1b86..69c7f3da32 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.injection.NoJSR250Annotations;
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 class UndertowHTTPServerEngineFactory {
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 0000000000..0b59861070
--- /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<TLSServerParameters> 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 ba34a645c7..bbc886806a 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.X509KeyManager;
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 final class SSLUtils {
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 final class SSLUtils {
}
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 9f59c8b014..fa7f00b641 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.Client;
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 class SeBootstrapTest {
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()
+ .protocol("HTTPS")
+ .sslContext(createSSLContext());
+
+ final SeBootstrap.Configuration requestedConfiguration =
bootstrapConfigurationBuilder.build();
+ final CompletionStage<SeBootstrap.Instance> 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 {