-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FDP-94: Refactored, updated copyright
- Loading branch information
Showing
68 changed files
with
1,711 additions
and
1,831 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 3 additions & 1 deletion
4
application/src/integrationTest/kotlin/org/gxf/soapbridge/SoapBridgeApplicationTests.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
...ication/src/main/java/org/gxf/soapbridge/application/configuration/SoapConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package org.gxf.soapbridge.application.configuration; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import org.gxf.soapbridge.soap.endpoints.SoapEndpoint; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.servlet.handler.AbstractHandlerMapping; | ||
|
||
@Component | ||
public class SoapConfiguration extends AbstractHandlerMapping { | ||
private final SoapEndpoint soapEndpoint; | ||
|
||
public SoapConfiguration(final SoapEndpoint soapEndpoint) { | ||
this.soapEndpoint = soapEndpoint; | ||
} | ||
|
||
@Override | ||
protected Object getHandlerInternal(final HttpServletRequest request) { | ||
return soapEndpoint; | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
...ation/src/main/java/org/gxf/soapbridge/application/factories/HostnameVerifierFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package org.gxf.soapbridge.application.factories; | ||
|
||
import static org.gxf.soapbridge.configuration.properties.HostnameVerificationStrategy.ALLOW_ALL_HOSTNAMES; | ||
import static org.gxf.soapbridge.configuration.properties.HostnameVerificationStrategy.BROWSER_COMPATIBLE_HOSTNAMES; | ||
|
||
import javax.net.ssl.HostnameVerifier; | ||
import org.apache.http.conn.ssl.DefaultHostnameVerifier; | ||
import org.apache.http.conn.ssl.NoopHostnameVerifier; | ||
import org.gxf.soapbridge.configuration.properties.SoapConfigurationProperties; | ||
import org.gxf.soapbridge.soap.exceptions.ProxyServerException; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
public class HostnameVerifierFactory { | ||
private final SoapConfigurationProperties soapConfiguration; | ||
|
||
public HostnameVerifierFactory(final SoapConfigurationProperties soapConfiguration) { | ||
this.soapConfiguration = soapConfiguration; | ||
} | ||
|
||
public HostnameVerifier getHostnameVerifier() throws ProxyServerException { | ||
if (soapConfiguration.getHostnameVerificationStrategy() == ALLOW_ALL_HOSTNAMES) { | ||
return new NoopHostnameVerifier(); | ||
} else if (soapConfiguration.getHostnameVerificationStrategy() | ||
== BROWSER_COMPATIBLE_HOSTNAMES) { | ||
return new DefaultHostnameVerifier(); | ||
} else { | ||
throw new ProxyServerException("No hostname verification strategy set!"); | ||
} | ||
} | ||
} |
99 changes: 99 additions & 0 deletions
99
...ion/src/main/java/org/gxf/soapbridge/application/factories/HttpsUrlConnectionFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package org.gxf.soapbridge.application.factories; | ||
|
||
import java.io.IOException; | ||
import java.net.URL; | ||
import java.nio.charset.StandardCharsets; | ||
import javax.net.ssl.HttpsURLConnection; | ||
import javax.net.ssl.SSLContext; | ||
import org.gxf.soapbridge.application.services.SslContextCacheService; | ||
import org.gxf.soapbridge.soap.exceptions.ProxyServerException; | ||
import org.gxf.soapbridge.soap.exceptions.UnableToCreateHttpsURLConnectionException; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.util.StringUtils; | ||
|
||
/** This {@link @Component} class can create {@link HttpsURLConnection} instances. */ | ||
@Component | ||
public class HttpsUrlConnectionFactory { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(HttpsUrlConnectionFactory.class); | ||
|
||
/** Cache of {@link SSLContext} instances used to obtain {@link HttpsURLConnection} instances. */ | ||
@Autowired private SslContextCacheService sslContextCacheService; | ||
|
||
@Autowired private HostnameVerifierFactory hostnameVerifierFactory; | ||
|
||
/** | ||
* Create an {@link HttpsURLConnection} instance for the given arguments. | ||
* | ||
* @param uri The full URI of the end-point for this connection. | ||
* @param host The host consists of domain name, server name or IP address followed by the port. | ||
* Example: localhost:443 | ||
* @param contentLength The content length of the SOAP payload which will be sent to the end-point | ||
* using this connection. | ||
* @param commonName The common name for the organization. | ||
* @return Null in case the {@link SSLContext} cannot be created or fetched from the {@link | ||
* SslContextCacheService}, or a configured and initialized {@link HttpsURLConnection} | ||
* instance. | ||
* @throws UnableToCreateHttpsURLConnectionException In case the configuration and/or | ||
* initialization of an {@link HttpsURLConnection} instance fails. | ||
*/ | ||
public HttpsURLConnection createConnection( | ||
final String uri, final String host, final String contentLength, final String commonName) | ||
throws UnableToCreateHttpsURLConnectionException { | ||
try { | ||
// Get SSLContext instance. | ||
SSLContext sslContext = null; | ||
if (StringUtils.isEmpty(commonName)) { | ||
sslContext = sslContextCacheService.getSslContext(); | ||
} else { | ||
sslContext = sslContextCacheService.getSslContextForCommonName(commonName); | ||
} | ||
// Check SSLContext instance. | ||
if (sslContext == null) { | ||
LOGGER.error( | ||
"SSLContext instance is null. Unable to create HttpsURLConnection instance for uri: {}, host: {}, content length: {}, common name: {}", | ||
uri, | ||
host, | ||
contentLength, | ||
commonName); | ||
return null; | ||
} | ||
// Create connection. | ||
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifierFactory.getHostnameVerifier()); | ||
final HttpsURLConnection connection = (HttpsURLConnection) new URL(uri).openConnection(); | ||
connection.setSSLSocketFactory(sslContext.getSocketFactory()); | ||
connection.setDoInput(true); | ||
connection.setDoOutput(true); | ||
connection.setRequestMethod("POST"); | ||
connection.setRequestProperty( | ||
"Accept-Encoding", "text/xml;charset=" + StandardCharsets.UTF_8.name()); | ||
connection.setRequestProperty("Accept-Charset", StandardCharsets.UTF_8.name()); | ||
connection.setRequestProperty( | ||
"Content-Type", "text/xml;charset=" + StandardCharsets.UTF_8.name()); | ||
connection.setRequestProperty("SOAP-ACTION", ""); | ||
connection.setRequestProperty("Content-Length", contentLength); | ||
connection.setRequestProperty("Host", host); | ||
connection.setRequestProperty("Connection", "Keep-Alive"); | ||
connection.setRequestProperty( | ||
"User-Agent", | ||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36"); | ||
LOGGER.debug( | ||
"Created HttpsURLConnection instance for uri: {}, host: {}, content length: {}, common name: {}", | ||
uri, | ||
host, | ||
contentLength, | ||
commonName); | ||
|
||
return connection; | ||
} catch (final IOException | ProxyServerException e) { | ||
LOGGER.error("Creating connection failed.", e); | ||
throw new UnableToCreateHttpsURLConnectionException(e.getMessage()); | ||
} | ||
} | ||
} |
149 changes: 149 additions & 0 deletions
149
application/src/main/java/org/gxf/soapbridge/application/factories/SslContextFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
// SPDX-FileCopyrightText: Copyright Contributors to the GXF project | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
package org.gxf.soapbridge.application.factories; | ||
|
||
import java.io.FileInputStream; | ||
import java.io.InputStream; | ||
import java.security.KeyStore; | ||
import javax.net.ssl.*; | ||
import org.gxf.soapbridge.application.services.SslContextCacheService; | ||
import org.gxf.soapbridge.configuration.properties.SecurityConfigurationProperties; | ||
import org.gxf.soapbridge.configuration.properties.StoreConfigurationProperties; | ||
import org.gxf.soapbridge.soap.exceptions.UnableToCreateKeyManagersException; | ||
import org.gxf.soapbridge.soap.exceptions.UnableToCreateTrustManagersException; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.stereotype.Component; | ||
|
||
/** This {@link @Component} class can create {@link SSLContext} instances. */ | ||
@Component | ||
public class SslContextFactory { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(SslContextFactory.class); | ||
|
||
/** | ||
* In order to create a proper instance of {@link SSLContext}, a protocol must be specified. Note | ||
* that if {@link SSLContext#getDefault()} is used, the created instance does not support the | ||
* custom {@link TrustManager} and {@link KeyManager} which are needed for this application!!! | ||
*/ | ||
private static final String SSL_CONTEXT_PROTOCOL = "TLS"; | ||
|
||
@Autowired private SecurityConfigurationProperties securityConfiguration; | ||
|
||
/** | ||
* Using the trust store, a {@link TrustManager} instance is created. This instance is created | ||
* once, and assigned to this field. Subsequent calls to {@link | ||
* SslContextCacheService#getSslContext()} will use the instance in order to create {@link | ||
* SSLContext} instances. | ||
*/ | ||
private TrustManager[] trustManagersForHttps; | ||
|
||
/** | ||
* Using the trust store, a {@link TrustManager} instance is created. This instance is created | ||
* once, and assigned to this field. Subsequent calls to {@link | ||
* SslContextCacheService#getSslContextForCommonName(String)} will use the instance in order to | ||
* create {@link SSLContext} instances. | ||
*/ | ||
private TrustManager[] trustManagersForHttpsWithClientCertificate; | ||
|
||
/** | ||
* Create an {@link SSLContext} instance. | ||
* | ||
* @return An {@link SSLContext} instance. | ||
*/ | ||
public SSLContext createSslContext() { | ||
return createSslContext(""); | ||
} | ||
|
||
/** | ||
* Create an {@link SSLContext} instance for the given common name. | ||
* | ||
* @param commonName The common name used to open the key store for an organization. May be an | ||
* empty string if no client certificate is required. | ||
* @return An {@link SSLContext} instance. | ||
*/ | ||
public SSLContext createSslContext(final String commonName) { | ||
if (commonName.isEmpty()) { | ||
try { | ||
// Only create an instance of the trust manager array once. | ||
if (trustManagersForHttps == null) { | ||
trustManagersForHttps = openTrustStoreAndCreateTrustManagers(); | ||
} | ||
// Use the trust manager to initialize an SSLContext instance. | ||
final SSLContext sslContext = SSLContext.getInstance(SSL_CONTEXT_PROTOCOL); | ||
sslContext.init(null, trustManagersForHttps, null); | ||
LOGGER.info("Created SSL context using trust manager for HTTPS"); | ||
return sslContext; | ||
} catch (final Exception e) { | ||
LOGGER.error("Unexpected exception while creating SSL context using trust manager", e); | ||
return null; | ||
} | ||
} else { | ||
try { | ||
// Only create an instance of the trust manager array once. | ||
if (trustManagersForHttpsWithClientCertificate == null) { | ||
trustManagersForHttpsWithClientCertificate = openTrustStoreAndCreateTrustManagers(); | ||
} | ||
final KeyManager[] keyManagerArray = openKeyStoreAndCreateKeyManagers(commonName); | ||
// Use the key manager and trust manager to initialize an | ||
// SSLContext instance. | ||
final SSLContext sslContext = SSLContext.getInstance(SSL_CONTEXT_PROTOCOL); | ||
sslContext.init(keyManagerArray, trustManagersForHttpsWithClientCertificate, null); | ||
// It is not possible to set the SSLContext instance as default | ||
// using: "SSLContext.setDefault(sslContext);" The SSl context | ||
// is unique for each organization because each organization has | ||
// their own *.pfx key store, which is the client certificate. | ||
LOGGER.info("Created SSL context using trust manager and key manager for HTTPS"); | ||
return sslContext; | ||
} catch (final Exception e) { | ||
LOGGER.error( | ||
"Unexpected exception while creating SSL context using trust manager and key manager", | ||
e); | ||
return null; | ||
} | ||
} | ||
} | ||
|
||
private TrustManager[] openTrustStoreAndCreateTrustManagers() | ||
throws UnableToCreateTrustManagersException { | ||
final StoreConfigurationProperties trustStore = securityConfiguration.getTrustStore(); | ||
LOGGER.debug("Opening trust store, pathToTrustStore: {}", trustStore.getLocation()); | ||
try (final InputStream trustStream = new FileInputStream(trustStore.getLocation())) { | ||
// Create trust manager using *.jks file. | ||
final char[] trustPassword = trustStore.getPassword().toCharArray(); | ||
final KeyStore trustStoreInstance = KeyStore.getInstance(trustStore.getType()); | ||
trustStoreInstance.load(trustStream, trustPassword); | ||
final TrustManagerFactory trustFactory = | ||
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); | ||
trustFactory.init(trustStoreInstance); | ||
return trustFactory.getTrustManagers(); | ||
} catch (final Exception e) { | ||
throw new UnableToCreateTrustManagersException( | ||
"Unexpected exception while creating trust managers using trust store", e); | ||
} | ||
} | ||
|
||
private KeyManager[] openKeyStoreAndCreateKeyManagers(final String commonName) | ||
throws UnableToCreateKeyManagersException { | ||
// Assume the path does not have a trailing slash ( '/' ) and assume the | ||
// file extension to be *.pfx. | ||
final StoreConfigurationProperties keyStore = securityConfiguration.getKeyStore(); | ||
final String pathToKeyStore = String.format("%s/%s.pfx", keyStore.getLocation(), commonName); | ||
LOGGER.debug("Opening key store, pathToKeyStore: {}", pathToKeyStore); | ||
try (final InputStream keyStoreStream = new FileInputStream(pathToKeyStore)) { | ||
// Create key manager using *.pfx file. | ||
final KeyManagerFactory keyManagerFactory = | ||
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); | ||
final KeyStore keyStoreInstance = KeyStore.getInstance(keyStore.getType()); | ||
final char[] keyPassword = keyStore.getPassword().toCharArray(); | ||
keyStoreInstance.load(keyStoreStream, keyPassword); | ||
keyManagerFactory.init(keyStoreInstance, keyPassword); | ||
return keyManagerFactory.getKeyManagers(); | ||
} catch (final Exception e) { | ||
throw new UnableToCreateKeyManagersException( | ||
"Unexpected exception while creating key managers using key store", e); | ||
} | ||
} | ||
} |
Oops, something went wrong.