Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
* Bugfix: Better error handling in CloudconductorPropertyProvider
* Fixed vulnerabilities: CVE-2024-13009(Jetty), CVE-2025-23184(Apache CXF), CVE-2024-57699 (Json-smart),CVE-2025-27533 (ActiveMQ)
* Logging improvement and extension options for DaemonMessageListener
* Add TLS server parameters for JAX-RS

# 1.37
* Major bug in interconnect core: DaemonScanner causes IllegalArgumentException due to wrong path of TimeoutException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ protected boolean hasAnnotation(Class<?> clz, Class<? extends Annotation> ann) {

protected void configureServerURL(OpenAPI openAPI) {
String port = System.getProperty(SpringCXFProperties.JAXRS_BINDPORT, System.getProperty("svc.port", "8080"));
String serverUrl = System.getProperty(SpringCXFProperties.SERVER_URL, "http://localhost:" + port);
String serverUrl = System.getProperty(SpringCXFProperties.SERVER_URL, System.getProperty("jaxrs.protocol", "http") + "://localhost:" + port);
String path = System.getProperty(SpringCXFProperties.JAXRS_PATH, "");
if (!path.startsWith("/")) {
serverUrl += "/";
Expand Down
8 changes: 8 additions & 0 deletions jaxrs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ password hashes secured by the SHA-512 function using a 512 bit salt and a dynam
Several settings of the dvalin framework can be customized using system properties which are described
in `de.taimos.dvalin.jaxrs.SpringCXFProperties`.

For HTTPS, configure protocol and KeyStore via system properties:
```
jaxrs.protocol=https
jaxrs.server.keyStore=/path/to/keystore.jks
jaxrs.server.keyStorePassword=password
jaxrs.server.keyStoreType=JKS
```

### Testing

moved to `test` sub-project.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import de.taimos.dvalin.jaxrs.websocket.WebSocketContextHandler;
import org.apache.cxf.Bus;
import org.apache.cxf.configuration.jsse.TLSServerParameters;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.transport.http_jetty.JettyHTTPServerEngine;
import org.apache.cxf.transport.http_jetty.JettyHTTPServerEngineFactory;
Expand All @@ -19,9 +20,18 @@
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.annotation.Order;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.nio.file.Files;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.List;

/**
Expand All @@ -43,6 +53,14 @@ public class JAXRSServerConfig {
protected int port;
@Value("${jaxrs.protocol:http}")
protected String protocol;

@Value("${jaxrs.server.keyStore:}")
protected String keyStorePath;
@Value("${jaxrs.server.keyStorePassword:}")
protected String keyStorePassword;
@Value("${jaxrs.server.keyStoreType:JKS}")
protected String keyStoreType;

@Value("${jetty.minThreads:5}")
protected int minThreads;
@Value("${jetty.maxThreads:150}")
Expand Down Expand Up @@ -78,6 +96,9 @@ public JettyHTTPServerEngineFactory serverEngineFactory(Bus cxf, //
}

protected void createServerEngine(JettyHTTPServerEngineFactory factory, List<Handler> handlers) throws GeneralSecurityException, IOException {
if (this.protocol.equals("https")) {
factory.setTLSServerParametersForPort(this.port, this.createTLSServerParameters());
}
JettyHTTPServerEngine engine = factory.createJettyHTTPServerEngine(this.host, this.port, this.protocol);
engine.setThreadingParameters(this.createThreadingParameters());
engine.setSendServerVersion(this.sendVersion);
Expand All @@ -92,6 +113,20 @@ protected ThreadingParameters createThreadingParameters() {
return threadingParams;
}

protected TLSServerParameters createTLSServerParameters() throws KeyStoreException, NoSuchAlgorithmException, IOException, CertificateException, UnrecoverableKeyException {
TLSServerParameters tlsParams = new TLSServerParameters();
KeyStore keyStore = KeyStore.getInstance(this.keyStoreType);
keyStore.load(Files.newInputStream(new File(this.keyStorePath).toPath()), this.keyStorePassword.toCharArray());
KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, this.keyStorePassword.toCharArray());
tlsParams.setKeyManagers(keyFactory.getKeyManagers());

TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
tlsParams.setTrustManagers(trustFactory.getTrustManagers());
return tlsParams;
}

protected ContextHandler createResourceContext(String contextPath, Resource base) {
ContextHandler context = new ContextHandler(contextPath);
ResourceHandler res = new ResourceHandler();
Expand All @@ -103,19 +138,19 @@ protected ContextHandler createResourceContext(String contextPath, Resource base
@Order(1)
@Bean(name = "web-server-context-static")
public ContextHandler staticContextHandler() throws IOException {
return createResourceContext("/static", Resource.newResource("./static"));
return this.createResourceContext("/static", Resource.newResource("./static"));
}

@Order(2)
@Bean(name = "web-server-context-web-fs")
public ContextHandler webFSContextHandler() throws IOException {
return createResourceContext("/", Resource.newResource("./web"));
return this.createResourceContext("/", Resource.newResource("./web"));
}

@Order(3)
@Bean(name = "web-server-context-web")
public ContextHandler webContextHandler() {
return createResourceContext("/", Resource.newClassPathResource("/web"));
return this.createResourceContext("/", Resource.newClassPathResource("/web"));
}

@Order(10)
Expand All @@ -129,4 +164,4 @@ public WebSocketContextHandler websocketContextHandler() {
public DefaultHandler defaultHandler() {
return new DefaultHandler();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
@Component
public class JAXRSContextImpl implements DvalinRSContext {

@Value("${server.url:http://localhost:${jaxrs.bindport:${svc.port:8080}}}")
@Value("${server.url:${jaxrs.protocol:http}://localhost:${jaxrs.bindport:${svc.port:8080}}}")
private String serverURL;

@Override
Expand Down
6 changes: 3 additions & 3 deletions jaxrs/src/main/resources/spring/jaxrs-server.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd"
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd"
profile="http">

<jaxrs:server id="restService" address="http://${jaxrs.bindhost:0.0.0.0}:${jaxrs.bindport:${svc.port:8080}}${jaxrs.path:}"
<jaxrs:server id="restService" address="${jaxrs.protocol:http}://${jaxrs.bindhost:0.0.0.0}:${jaxrs.bindport:${svc.port:8080}}${jaxrs.path:}"
depends-on="cxf-engine" serviceAnnotation="${jaxrs.annotation:de.taimos.dvalin.jaxrs.JaxRsComponent}">
</jaxrs:server>

Expand Down