Fix name convention issue
[sdc/sdc-workflow-designer.git] / sdc-workflow-designer-be / src / main / java / org / onap / sdc / workflow / api / ArtifactAssociationService.java
1 /*
2  * Copyright © 2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.sdc.workflow.api;
18
19 import static org.apache.commons.codec.digest.DigestUtils.md5Hex;
20
21 import com.fasterxml.jackson.databind.ObjectMapper;
22
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.IOException;
26 import java.nio.charset.Charset;
27 import java.security.GeneralSecurityException;
28 import java.security.KeyStore;
29 import java.security.cert.CertificateException;
30 import java.security.cert.X509Certificate;
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.Map;
34 import java.util.Optional;
35
36 import org.apache.http.conn.ssl.TrustStrategy;
37 import org.openecomp.sdc.logging.api.Logger;
38 import org.openecomp.sdc.logging.api.LoggerFactory;
39
40 import java.util.Base64;
41
42 import org.apache.commons.io.IOUtils;
43 import org.apache.http.HttpHost;
44 import org.apache.http.conn.ssl.NoopHostnameVerifier;
45 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
46 import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
47 import org.apache.http.impl.client.CloseableHttpClient;
48 import org.apache.http.impl.client.HttpClients;
49 import org.apache.http.ssl.SSLContexts;
50 import org.onap.sdc.workflow.api.types.dto.ArtifactDeliveriesRequestDto;
51 import org.onap.sdc.workflow.persistence.types.ArtifactEntity;
52
53 import org.springframework.beans.factory.annotation.Autowired;
54 import org.springframework.beans.factory.annotation.Value;
55 import org.springframework.boot.web.client.RestTemplateBuilder;
56 import org.springframework.http.*;
57 import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
58 import org.springframework.stereotype.Component;
59 import org.springframework.web.client.RestTemplate;
60
61 import javax.net.ssl.SSLContext;
62
63
64 @Component("ArtifactAssociationHandler")
65 public class ArtifactAssociationService {
66
67     private static final String WORKFLOW_ARTIFACT_TYPE = "WORKFLOW";
68     private static final String WORKFLOW_ARTIFACT_DESCRIPTION = "Workflow Artifact Description";
69     private static final String USER_ID_HEADER = "USER_ID";
70     private static final String MD5_HEADER = "Content-MD5";
71     private static final String X_ECOMP_INSTANCE_ID_HEADER = "X-ECOMP-InstanceID";
72     private static final String INIT_ERROR_MSG =
73             "Failed while attaching workflow artifact to Operation in SDC. Parameters were not initialized: %s";
74     private static final String INIT_CLIENT_MSG =
75             "Failed while creating the HTTP client to SDC. Following exception: %s";
76     private static final Logger LOGGER = LoggerFactory.getLogger(ArtifactAssociationService.class);
77     @Value("${sdc.be.endpoint}")
78     private String sdcBeEndpoint;
79     @Value("${sdc.be.protocol}")
80     private String sdcBeProtocol;
81     @Value("${sdc.be.external.user}")
82     private String sdcUser;
83     @Value("${sdc.be.external.password}")
84     private String sdcPassword;
85
86     private RestTemplate restClient;
87
88     private KeyStore getKeyStore(String file, String password, String keyStoreType) throws IOException, GeneralSecurityException {
89         KeyStore keyStore = KeyStore.getInstance(keyStoreType);
90         File keyFile = new File(file);
91         try (FileInputStream inStr = new FileInputStream(keyFile)) {
92             keyStore.load(inStr, password.toCharArray());
93         }
94         return keyStore;
95
96     }
97
98
99     @Autowired
100     public ArtifactAssociationService(RestTemplateBuilder builder,
101                                       @Value("${server.ssl.trust-store}")
102                                               String truststorePath,
103                                       @Value("${server.ssl.trust-store-password}")
104                                               String truststorePassword,
105                                       @Value("${server.ssl.trust-store-type}")
106                                               String truststoreType,
107                                       @Value("${server.ssl.key-store}")
108                                               String keystorePath,
109                                       @Value("${server.ssl.key-password}")
110                                               String keystorePassword,
111                                       @Value("${server.ssl.key-store-type}")
112                                               String keystoreType,
113                                       @Value("${sdc.be.protocol}")
114                                               String protocol) {
115         if (protocol != null &&
116                 !protocol.equalsIgnoreCase(HttpHost.DEFAULT_SCHEME_NAME)) {
117             try {
118                 KeyStore trustStore = getKeyStore(truststorePath, truststorePassword, truststoreType);
119                 KeyStore keyStore = getKeyStore(keystorePath, keystorePassword, keystoreType);
120
121                 SSLContext sslcontext = SSLContexts.custom()
122                         .loadKeyMaterial(keyStore, keystorePassword.toCharArray())
123                         .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
124                         .build();
125                 SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
126                         sslcontext,
127                         new NoopHostnameVerifier()
128                 );
129                 CloseableHttpClient httpClient =
130                         HttpClients.custom()
131                                 .setSSLSocketFactory(sslsf)
132                                 .setSSLHostnameVerifier(new NoopHostnameVerifier())
133                                 .build();
134                 HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
135                 this.restClient = new RestTemplate(factory);
136             } catch (Exception e) {
137                 LOGGER.error(String.format(INIT_CLIENT_MSG, e.getMessage()), e);
138             }
139         } else {
140             this.restClient = builder.build();
141         }
142     }
143
144     void setRestClient(RestTemplate restClient) {
145         this.restClient = restClient;
146     }
147
148     void setSdcBeEndpoint(String value) {
149         this.sdcBeEndpoint = value;
150     }
151
152     ResponseEntity<String> execute(String userId, ArtifactDeliveriesRequestDto deliveriesRequestDto,
153                                    ArtifactEntity artifactEntity) {
154
155         Optional<String> initializationState = parametersInitializationState();
156         if (initializationState.isPresent()) {
157             LOGGER.error(String.format(INIT_ERROR_MSG, initializationState.get()));
158             return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(String.format(INIT_ERROR_MSG, initializationState.get()));
159         }
160
161         String formattedArtifact;
162         try {
163             formattedArtifact = getFormattedWorkflowArtifact(artifactEntity);
164         } catch (IOException e) {
165             LOGGER.error("Failed while attaching workflow artifact to Operation in SDC", e);
166             return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(e.getMessage());
167         }
168
169         HttpEntity<String> request = new HttpEntity<>(formattedArtifact, createHeaders(userId, formattedArtifact));
170
171         return restClient.exchange(sdcBeProtocol + "://" + sdcBeEndpoint + "/" + deliveriesRequestDto.getEndpoint(),
172                 HttpMethod.valueOf(deliveriesRequestDto.getMethod()), request, String.class);
173     }
174
175     Optional<String> parametersInitializationState() {
176         ArrayList<String> result = new ArrayList<>();
177         if (sdcBeEndpoint == null || sdcBeEndpoint.equals("")) {
178             result.add("SDC_ENDPOINT");
179         }
180         if (sdcBeProtocol == null || sdcBeProtocol.equals("")) {
181             result.add("SDC_PROTOCOL");
182         }
183         if (sdcUser == null || sdcUser.equals("")) {
184             result.add("SDC_USER");
185         }
186         if (sdcPassword == null || sdcPassword.equals("")) {
187             result.add("SDC_PASSWORD");
188         }
189
190         if (result.isEmpty() || this.restClient == null) {
191             return Optional.empty();
192         } else {
193             return Optional.of(result.toString());
194         }
195     }
196
197
198     private String getFormattedWorkflowArtifact(ArtifactEntity artifactEntity) throws IOException {
199
200         byte[] encodeBase64 = Base64.getEncoder().encode(IOUtils.toByteArray(artifactEntity.getArtifactData()));
201         String encodedPayloadData = new String(encodeBase64);
202
203         Map<String, String> artifactInfo = new HashMap<>();
204         artifactInfo.put("artifactName", artifactEntity.getFileName());
205         artifactInfo.put("payloadData", encodedPayloadData);
206         artifactInfo.put("artifactType", WORKFLOW_ARTIFACT_TYPE);
207         artifactInfo.put("description", WORKFLOW_ARTIFACT_DESCRIPTION);
208
209         ObjectMapper mapper = new ObjectMapper();
210         return mapper.writeValueAsString(artifactInfo);
211     }
212
213     private HttpHeaders createHeaders(String userId, String formattedArtifact) {
214         HttpHeaders headers = new HttpHeaders();
215         headers.add(USER_ID_HEADER, userId);
216         headers.add(HttpHeaders.AUTHORIZATION, createAuthorizationsHeaderValue(sdcUser, sdcPassword));
217         headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
218         headers.add(MD5_HEADER, calculateMD5Base64EncodedByString(formattedArtifact));
219         headers.add(X_ECOMP_INSTANCE_ID_HEADER, "InstanceId");
220         return headers;
221     }
222
223     private String calculateMD5Base64EncodedByString(String data) {
224         String calculatedMd5 = md5Hex(data);
225         // encode base-64 result
226         byte[] encodeBase64 = Base64.getEncoder().encode(calculatedMd5.getBytes());
227         return new String(encodeBase64);
228     }
229
230     private String createAuthorizationsHeaderValue(String username, String password) {
231         String auth = username + ":" + password;
232         byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(Charset.forName("US-ASCII")));
233         return "Basic " + new String(encodedAuth);
234     }
235 }