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 {

Reply via email to