From 75d642902350562a790cf034ea92568ba5d52168 Mon Sep 17 00:00:00 2001 From: ilanap Date: Mon, 18 Nov 2019 13:38:23 +0200 Subject: Changes for backend to support SSL Changes to support starting in https mode and changes to support making a secured call to the SDC backend (cherry picked from commit 820f4ec65a28ed822d4205b05ac6fbbd910a46cc) Issue-ID: SDC-2405 Change-Id: I0588484fdcb0903934814906672f4fc9a76eca2c Signed-off-by: ilanap --- .../workflow/api/ArtifactAssociationService.java | 108 +++++++++++++++++---- 1 file changed, 89 insertions(+), 19 deletions(-) (limited to 'workflow-designer-be/src/main/java') diff --git a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/ArtifactAssociationService.java b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/ArtifactAssociationService.java index 621d1803..2b24577a 100644 --- a/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/ArtifactAssociationService.java +++ b/workflow-designer-be/src/main/java/org/onap/sdc/workflow/api/ArtifactAssociationService.java @@ -19,30 +19,47 @@ package org.onap.sdc.workflow.api; import static org.apache.commons.codec.digest.DigestUtils.md5Hex; import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.nio.charset.Charset; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; import java.util.ArrayList; -import java.util.Base64; import java.util.HashMap; import java.util.Map; import java.util.Optional; + +import org.apache.http.conn.ssl.TrustStrategy; +import org.openecomp.sdc.logging.api.Logger; +import org.openecomp.sdc.logging.api.LoggerFactory; + +import java.util.Base64; + import org.apache.commons.io.IOUtils; +import org.apache.http.HttpHost; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.TrustSelfSignedStrategy; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.ssl.SSLContexts; import org.onap.sdc.workflow.api.types.dto.ArtifactDeliveriesRequestDto; import org.onap.sdc.workflow.persistence.types.ArtifactEntity; -import org.openecomp.sdc.logging.api.Logger; -import org.openecomp.sdc.logging.api.LoggerFactory; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; +import org.springframework.http.*; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; +import javax.net.ssl.SSLContext; + @Component("ArtifactAssociationHandler") public class ArtifactAssociationService { @@ -54,6 +71,8 @@ public class ArtifactAssociationService { private static final String X_ECOMP_INSTANCE_ID_HEADER = "X-ECOMP-InstanceID"; private static final String INIT_ERROR_MSG = "Failed while attaching workflow artifact to Operation in SDC. Parameters were not initialized: %s"; + private static final String INIT_CLIENT_MSG = + "Failed while creating the HTTP client to SDC. Following exception: %s"; private static final Logger LOGGER = LoggerFactory.getLogger(ArtifactAssociationService.class); @Value("${sdc.be.endpoint}") private String sdcBeEndpoint; @@ -66,12 +85,63 @@ public class ArtifactAssociationService { private RestTemplate restClient; + private KeyStore getKeyStore(String file, String password, String keyStoreType) throws IOException, GeneralSecurityException { + KeyStore keyStore = KeyStore.getInstance(keyStoreType); + File keyFile = new File(file); + try (FileInputStream inStr = new FileInputStream(keyFile)) { + keyStore.load(inStr, password.toCharArray()); + } + return keyStore; + + } + + @Autowired - public ArtifactAssociationService(RestTemplateBuilder builder) { - this.restClient = builder.build(); + public ArtifactAssociationService(RestTemplateBuilder builder, + @Value("${server.ssl.trust-store}") + String truststorePath, + @Value("${server.ssl.trust-store-password}") + String truststorePassword, + @Value("${server.ssl.trust-store-type}") + String truststoreType, + @Value("${server.ssl.key-store}") + String keystorePath, + @Value("${server.ssl.key-password}") + String keystorePassword, + @Value("${server.ssl.key-store-type}") + String keystoreType, + @Value("${sdc.be.protocol}") + String protocol) { + if (protocol != null && + !protocol.equalsIgnoreCase(HttpHost.DEFAULT_SCHEME_NAME)) { + try { + KeyStore trustStore = getKeyStore(truststorePath, truststorePassword, truststoreType); + KeyStore keyStore = getKeyStore(keystorePath, keystorePassword, keystoreType); + + SSLContext sslcontext = SSLContexts.custom() + .loadKeyMaterial(keyStore, keystorePassword.toCharArray()) + .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()) + .build(); + SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( + sslcontext, + new NoopHostnameVerifier() + ); + CloseableHttpClient httpClient = + HttpClients.custom() + .setSSLSocketFactory(sslsf) + .setSSLHostnameVerifier(new NoopHostnameVerifier()) + .build(); + HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); + this.restClient = new RestTemplate(factory); + } catch (Exception e) { + LOGGER.error(String.format(INIT_CLIENT_MSG, e.getMessage()), e); + } + } else { + this.restClient = builder.build(); + } } - void setRestClient(RestTemplate restClient) { + void setRestClient(RestTemplate restClient) { this.restClient = restClient; } @@ -80,12 +150,12 @@ public class ArtifactAssociationService { } ResponseEntity execute(String userId, ArtifactDeliveriesRequestDto deliveriesRequestDto, - ArtifactEntity artifactEntity) { + ArtifactEntity artifactEntity) { Optional initializationState = parametersInitializationState(); - if(initializationState.isPresent()) { - LOGGER.error(String.format(INIT_ERROR_MSG,initializationState.get())); - return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(String.format(INIT_ERROR_MSG,initializationState.get())); + if (initializationState.isPresent()) { + LOGGER.error(String.format(INIT_ERROR_MSG, initializationState.get())); + return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(String.format(INIT_ERROR_MSG, initializationState.get())); } String formattedArtifact; @@ -96,7 +166,7 @@ public class ArtifactAssociationService { return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(e.getMessage()); } - HttpEntity request = new HttpEntity<>(formattedArtifact, createHeaders(userId,formattedArtifact)); + HttpEntity request = new HttpEntity<>(formattedArtifact, createHeaders(userId, formattedArtifact)); return restClient.exchange(sdcBeProtocol + "://" + sdcBeEndpoint + "/" + deliveriesRequestDto.getEndpoint(), HttpMethod.valueOf(deliveriesRequestDto.getMethod()), request, String.class); @@ -117,7 +187,7 @@ public class ArtifactAssociationService { result.add("SDC_PASSWORD"); } - if (result.isEmpty()) { + if (result.isEmpty() || this.restClient == null) { return Optional.empty(); } else { return Optional.of(result.toString()); @@ -143,7 +213,7 @@ public class ArtifactAssociationService { private HttpHeaders createHeaders(String userId, String formattedArtifact) { HttpHeaders headers = new HttpHeaders(); headers.add(USER_ID_HEADER, userId); - headers.add(HttpHeaders.AUTHORIZATION, createAuthorizationsHeaderValue(sdcUser,sdcPassword)); + headers.add(HttpHeaders.AUTHORIZATION, createAuthorizationsHeaderValue(sdcUser, sdcPassword)); headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); headers.add(MD5_HEADER, calculateMD5Base64EncodedByString(formattedArtifact)); headers.add(X_ECOMP_INSTANCE_ID_HEADER, "InstanceId"); -- cgit 1.2.3-korg