Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CXF-9039: Support SeBootstrap HTTPS configuration #2195

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -49,17 +50,22 @@
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;
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() {
Expand Down Expand Up @@ -155,16 +161,19 @@ public CompletionStage<Instance> 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 "/"
Expand All @@ -177,8 +186,11 @@ public CompletionStage<Instance> 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();
Expand All @@ -192,12 +204,17 @@ public CompletionStage<Instance> 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<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
Expand Down Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand Down Expand Up @@ -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())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;



Expand Down Expand Up @@ -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())) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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());
Expand Down
Loading
Loading