mirror of
https://github.com/pcvolkmer/etl-processor.git
synced 2025-04-19 17:26:51 +00:00
refactor: move custom rest template init to config class
This commit is contained in:
parent
effffcfc1a
commit
b809a2da02
@ -23,40 +23,17 @@ import ca.uhn.fhir.context.FhirContext;
|
|||||||
import ca.uhn.fhir.parser.IParser;
|
import ca.uhn.fhir.parser.IParser;
|
||||||
import dev.dnpm.etl.processor.config.GPasConfigProperties;
|
import dev.dnpm.etl.processor.config.GPasConfigProperties;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
|
||||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
|
||||||
import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager;
|
|
||||||
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
|
|
||||||
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
|
|
||||||
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
|
|
||||||
import org.apache.hc.core5.http.config.Registry;
|
|
||||||
import org.apache.hc.core5.http.config.RegistryBuilder;
|
|
||||||
import org.hl7.fhir.r4.model.Identifier;
|
import org.hl7.fhir.r4.model.Identifier;
|
||||||
import org.hl7.fhir.r4.model.Parameters;
|
import org.hl7.fhir.r4.model.Parameters;
|
||||||
import org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent;
|
import org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent;
|
||||||
import org.hl7.fhir.r4.model.StringType;
|
import org.hl7.fhir.r4.model.StringType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.*;
|
import org.springframework.http.*;
|
||||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
|
||||||
import org.springframework.retry.support.RetryTemplate;
|
import org.springframework.retry.support.RetryTemplate;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.KeyManagementException;
|
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.KeyStoreException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.security.cert.CertificateFactory;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
|
|
||||||
public class GpasPseudonymGenerator implements Generator {
|
public class GpasPseudonymGenerator implements Generator {
|
||||||
|
|
||||||
private final static FhirContext r4Context = FhirContext.forR4();
|
private final static FhirContext r4Context = FhirContext.forR4();
|
||||||
@ -68,33 +45,13 @@ public class GpasPseudonymGenerator implements Generator {
|
|||||||
|
|
||||||
private final RestTemplate restTemplate;
|
private final RestTemplate restTemplate;
|
||||||
|
|
||||||
private SSLContext customSslContext;
|
|
||||||
|
|
||||||
public GpasPseudonymGenerator(GPasConfigProperties gpasCfg, RetryTemplate retryTemplate, RestTemplate restTemplate) {
|
public GpasPseudonymGenerator(GPasConfigProperties gpasCfg, RetryTemplate retryTemplate, RestTemplate restTemplate) {
|
||||||
this.retryTemplate = retryTemplate;
|
this.retryTemplate = retryTemplate;
|
||||||
|
this.restTemplate = restTemplate;
|
||||||
this.gPasUrl = gpasCfg.getUri();
|
this.gPasUrl = gpasCfg.getUri();
|
||||||
this.psnTargetDomain = gpasCfg.getTarget();
|
this.psnTargetDomain = gpasCfg.getTarget();
|
||||||
httpHeader = getHttpHeaders(gpasCfg.getUsername(), gpasCfg.getPassword());
|
httpHeader = getHttpHeaders(gpasCfg.getUsername(), gpasCfg.getPassword());
|
||||||
|
|
||||||
try {
|
|
||||||
if (StringUtils.isNotBlank(gpasCfg.getSslCaLocation())) {
|
|
||||||
customSslContext = getSslContext(gpasCfg.getSslCaLocation());
|
|
||||||
log.warn(String.format("%s has been initialized with SSL certificate %s. This is deprecated in favor of including Root CA.",
|
|
||||||
this.getClass().getName(), gpasCfg.getSslCaLocation()));
|
|
||||||
|
|
||||||
if (customSslContext == null) {
|
|
||||||
this.restTemplate = restTemplate;
|
|
||||||
} else {
|
|
||||||
this.restTemplate = getCustomRestTemplate();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.restTemplate = restTemplate;
|
|
||||||
}
|
|
||||||
} catch (IOException | KeyManagementException | KeyStoreException | CertificateException |
|
|
||||||
NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
log.debug(String.format("%s has been initialized", this.getClass().getName()));
|
log.debug(String.format("%s has been initialized", this.getClass().getName()));
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -188,53 +145,4 @@ public class GpasPseudonymGenerator implements Generator {
|
|||||||
headers.setBasicAuth(gPasUserName, gPasPassword);
|
headers.setBasicAuth(gPasUserName, gPasPassword);
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Read SSL root certificate and return SSLContext
|
|
||||||
*
|
|
||||||
* @param certificateLocation file location to root certificate (PEM)
|
|
||||||
* @return initialized SSLContext
|
|
||||||
* @throws IOException file cannot be read
|
|
||||||
* @throws CertificateException in case we have an invalid certificate of type X.509
|
|
||||||
* @throws KeyStoreException keystore cannot be initialized
|
|
||||||
* @throws NoSuchAlgorithmException missing trust manager algorithmus
|
|
||||||
* @throws KeyManagementException key management failed at init SSLContext
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
protected SSLContext getSslContext(String certificateLocation)
|
|
||||||
throws IOException, CertificateException, KeyStoreException, KeyManagementException, NoSuchAlgorithmException {
|
|
||||||
|
|
||||||
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
||||||
|
|
||||||
FileInputStream fis = new FileInputStream(certificateLocation);
|
|
||||||
X509Certificate ca = (X509Certificate) CertificateFactory.getInstance("X.509")
|
|
||||||
.generateCertificate(new BufferedInputStream(fis));
|
|
||||||
|
|
||||||
ks.load(null, null);
|
|
||||||
ks.setCertificateEntry(Integer.toString(1), ca);
|
|
||||||
|
|
||||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
|
|
||||||
TrustManagerFactory.getDefaultAlgorithm());
|
|
||||||
tmf.init(ks);
|
|
||||||
|
|
||||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
|
||||||
sslContext.init(null, tmf.getTrustManagers(), null);
|
|
||||||
|
|
||||||
return sslContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected RestTemplate getCustomRestTemplate() {
|
|
||||||
final var sslsf = new SSLConnectionSocketFactory(customSslContext);
|
|
||||||
final Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
|
|
||||||
.register("https", sslsf).register("http", new PlainConnectionSocketFactory()).build();
|
|
||||||
|
|
||||||
final BasicHttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager(
|
|
||||||
socketFactoryRegistry);
|
|
||||||
final CloseableHttpClient httpClient = HttpClients.custom()
|
|
||||||
.setConnectionManager(connectionManager).build();
|
|
||||||
|
|
||||||
final HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(
|
|
||||||
httpClient);
|
|
||||||
return new RestTemplate(requestFactory);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,10 @@
|
|||||||
package dev.dnpm.etl.processor.config
|
package dev.dnpm.etl.processor.config
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import dev.dnpm.etl.processor.monitoring.*
|
import dev.dnpm.etl.processor.monitoring.ConnectionCheckResult
|
||||||
|
import dev.dnpm.etl.processor.monitoring.ConnectionCheckService
|
||||||
|
import dev.dnpm.etl.processor.monitoring.GPasConnectionCheckService
|
||||||
|
import dev.dnpm.etl.processor.monitoring.ReportService
|
||||||
import dev.dnpm.etl.processor.pseudonym.AnonymizingGenerator
|
import dev.dnpm.etl.processor.pseudonym.AnonymizingGenerator
|
||||||
import dev.dnpm.etl.processor.pseudonym.Generator
|
import dev.dnpm.etl.processor.pseudonym.Generator
|
||||||
import dev.dnpm.etl.processor.pseudonym.GpasPseudonymGenerator
|
import dev.dnpm.etl.processor.pseudonym.GpasPseudonymGenerator
|
||||||
@ -29,12 +32,19 @@ import dev.dnpm.etl.processor.services.TokenRepository
|
|||||||
import dev.dnpm.etl.processor.services.TokenService
|
import dev.dnpm.etl.processor.services.TokenService
|
||||||
import dev.dnpm.etl.processor.services.Transformation
|
import dev.dnpm.etl.processor.services.Transformation
|
||||||
import dev.dnpm.etl.processor.services.TransformationService
|
import dev.dnpm.etl.processor.services.TransformationService
|
||||||
|
import org.apache.hc.client5.http.impl.classic.HttpClients
|
||||||
|
import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager
|
||||||
|
import org.apache.hc.client5.http.socket.ConnectionSocketFactory
|
||||||
|
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory
|
||||||
|
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory
|
||||||
|
import org.apache.hc.core5.http.config.RegistryBuilder
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties
|
import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||||
import org.springframework.context.annotation.Bean
|
import org.springframework.context.annotation.Bean
|
||||||
import org.springframework.context.annotation.Configuration
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
|
||||||
import org.springframework.retry.RetryCallback
|
import org.springframework.retry.RetryCallback
|
||||||
import org.springframework.retry.RetryContext
|
import org.springframework.retry.RetryContext
|
||||||
import org.springframework.retry.RetryListener
|
import org.springframework.retry.RetryListener
|
||||||
@ -46,6 +56,13 @@ import org.springframework.security.crypto.password.PasswordEncoder
|
|||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager
|
||||||
import org.springframework.web.client.RestTemplate
|
import org.springframework.web.client.RestTemplate
|
||||||
import reactor.core.publisher.Sinks
|
import reactor.core.publisher.Sinks
|
||||||
|
import java.io.BufferedInputStream
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.security.KeyStore
|
||||||
|
import java.security.cert.CertificateFactory
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
import javax.net.ssl.SSLContext
|
||||||
|
import javax.net.ssl.TrustManagerFactory
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
import kotlin.time.toJavaDuration
|
import kotlin.time.toJavaDuration
|
||||||
|
|
||||||
@ -84,6 +101,66 @@ class AppConfiguration {
|
|||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
@Bean
|
@Bean
|
||||||
fun gpasPseudonymGeneratorOnDeprecatedProperty(configProperties: GPasConfigProperties, retryTemplate: RetryTemplate, restTemplate: RestTemplate): Generator {
|
fun gpasPseudonymGeneratorOnDeprecatedProperty(configProperties: GPasConfigProperties, retryTemplate: RetryTemplate, restTemplate: RestTemplate): Generator {
|
||||||
|
fun getSslContext(certificateLocation: String): SSLContext? {
|
||||||
|
val ks = KeyStore.getInstance(KeyStore.getDefaultType())
|
||||||
|
|
||||||
|
val fis = FileInputStream(certificateLocation)
|
||||||
|
val ca = CertificateFactory.getInstance("X.509")
|
||||||
|
.generateCertificate(BufferedInputStream(fis)) as X509Certificate
|
||||||
|
|
||||||
|
ks.load(null, null)
|
||||||
|
ks.setCertificateEntry(1.toString(), ca)
|
||||||
|
|
||||||
|
val tmf = TrustManagerFactory.getInstance(
|
||||||
|
TrustManagerFactory.getDefaultAlgorithm()
|
||||||
|
)
|
||||||
|
tmf.init(ks)
|
||||||
|
|
||||||
|
val sslContext = SSLContext.getInstance("TLS")
|
||||||
|
sslContext.init(null, tmf.trustManagers, null)
|
||||||
|
|
||||||
|
return sslContext
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCustomRestTemplate(customSslContext: SSLContext): RestTemplate {
|
||||||
|
val sslsf = SSLConnectionSocketFactory(customSslContext)
|
||||||
|
val socketFactoryRegistry = RegistryBuilder.create<ConnectionSocketFactory>()
|
||||||
|
.register("https", sslsf).register("http", PlainConnectionSocketFactory()).build()
|
||||||
|
|
||||||
|
val connectionManager = BasicHttpClientConnectionManager(
|
||||||
|
socketFactoryRegistry
|
||||||
|
)
|
||||||
|
val httpClient = HttpClients.custom()
|
||||||
|
.setConnectionManager(connectionManager).build()
|
||||||
|
|
||||||
|
val requestFactory = HttpComponentsClientHttpRequestFactory(
|
||||||
|
httpClient
|
||||||
|
)
|
||||||
|
return RestTemplate(requestFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!configProperties.sslCaLocation.isNullOrBlank()) {
|
||||||
|
val customSslContext = getSslContext(configProperties.sslCaLocation)
|
||||||
|
logger.warn(
|
||||||
|
String.format(
|
||||||
|
"%s has been initialized with SSL certificate %s. This is deprecated in favor of including Root CA.",
|
||||||
|
this.javaClass.name, configProperties.sslCaLocation
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (customSslContext != null) {
|
||||||
|
return GpasPseudonymGenerator(
|
||||||
|
configProperties,
|
||||||
|
retryTemplate,
|
||||||
|
getCustomRestTemplate(customSslContext)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
throw RuntimeException(e)
|
||||||
|
}
|
||||||
|
|
||||||
return GpasPseudonymGenerator(configProperties, retryTemplate, restTemplate)
|
return GpasPseudonymGenerator(configProperties, retryTemplate, restTemplate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user