Security/ Package Name changes
[portal.git] / ecomp-portal-BE-common / src / main / java / org / onap / portalapp / portal / service / ApplicationsRestClientServiceImpl.java
1 /*-
2  * ============LICENSE_START==========================================
3  * ONAP Portal
4  * ===================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ===================================================================
7  *
8  * Unless otherwise specified, all software contained herein is licensed
9  * under the Apache License, Version 2.0 (the "License");
10  * you may not use this software except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *             http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * Unless otherwise specified, all documentation contained herein is licensed
22  * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
23  * you may not use this documentation except in compliance with the License.
24  * You may obtain a copy of the License at
25  *
26  *             https://creativecommons.org/licenses/by/4.0/
27  *
28  * Unless required by applicable law or agreed to in writing, documentation
29  * distributed under the License is distributed on an "AS IS" BASIS,
30  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31  * See the License for the specific language governing permissions and
32  * limitations under the License.
33  *
34  * ============LICENSE_END============================================
35  *
36  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
37  */
38 package org.onap.portalapp.portal.service;
39
40 import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
41
42 import java.lang.reflect.Type;
43 import java.net.MalformedURLException;
44 import java.net.URL;
45 import java.util.Base64;
46 import java.util.Date;
47
48 import javax.annotation.PostConstruct;
49 import javax.servlet.http.HttpServletResponse;
50 import javax.ws.rs.core.MediaType;
51 import javax.ws.rs.core.Response;
52
53 import org.apache.commons.lang.StringUtils;
54 import org.apache.cxf.jaxrs.client.WebClient;
55 import org.apache.cxf.transport.http.HTTPException;
56 import org.onap.portalapp.portal.service.AppsCacheService;
57 import org.onap.portalapp.portal.domain.EPApp;
58 import org.onap.portalapp.portal.logging.aop.EPAuditLog;
59 import org.onap.portalapp.portal.logging.aop.EPMetricsLog;
60 import org.onap.portalapp.portal.logging.format.EPAppMessagesEnum;
61 import org.onap.portalapp.portal.logging.logic.EPLogUtil;
62 import org.onap.portalapp.portal.utils.EPCommonSystemProperties;
63 import org.onap.portalapp.portal.utils.EcompPortalUtils;
64 import org.onap.portalapp.util.SystemType;
65 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
66 import org.onap.portalsdk.core.onboarding.util.CipherUtil;
67 import org.onap.portalsdk.core.util.SystemProperties;
68 import org.slf4j.MDC;
69 import org.springframework.beans.factory.annotation.Autowired;
70 import org.springframework.context.annotation.EnableAspectJAutoProxy;
71 import org.springframework.stereotype.Service;
72
73 import com.fasterxml.jackson.databind.ObjectMapper;
74 import com.google.gson.Gson;
75 import com.google.gson.GsonBuilder;
76 import com.google.gson.JsonDeserializationContext;
77 import com.google.gson.JsonDeserializer;
78 import com.google.gson.JsonElement;
79 import com.google.gson.JsonParseException;
80
81 @Service("applicationsRestClientService")
82 @org.springframework.context.annotation.Configuration
83 @EnableAspectJAutoProxy
84 @EPAuditLog
85 public class ApplicationsRestClientServiceImpl implements ApplicationsRestClientService {
86
87         private static final String PASSWORD_HEADER = "password";
88
89         private static final String APP_USERNAME_HEADER = "username";
90
91         private static final String BASIC_AUTHENTICATION_HEADER = "Authorization";
92
93         private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ApplicationsRestClientServiceImpl.class);
94
95         @Autowired
96         private AppsCacheService appsCacheService;
97
98         Gson gson = null;
99
100         private final ObjectMapper mapper = new ObjectMapper();
101
102         @PostConstruct
103         private void init() {
104                 logger.debug(EELFLoggerDelegate.debugLogger, "initializing");
105                 GsonBuilder builder = new GsonBuilder();
106
107                 // Register an adapter to manage the date types as long values
108                 builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
109                         public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
110                                         throws JsonParseException {
111                                 return new Date(json.getAsJsonPrimitive().getAsLong());
112                         }
113                 });
114
115                 gson = builder.create();
116         }
117
118         // TODO: do we need to do additional logging for remote API calls?
119         private static WebClient createClientForPath(String baseUri, String path) {
120                 logger.info(EELFLoggerDelegate.debugLogger, "Creating web client for " + baseUri + "   +   " + path);
121                 WebClient client = WebClient.create(baseUri);
122                 client.type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
123                 client.path(path);
124                 return client;
125         }
126
127         @EPMetricsLog
128         private void verifyResponse(Response response) throws HTTPException {
129                 int status = response.getStatus();
130                 logger.debug(EELFLoggerDelegate.debugLogger, "http response status=" + status);
131                 MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE, Integer.toString(status));
132                 if (!isHttpSuccess(status)) {
133                         String errMsg = "Failed. Status=" + status + "; [" + response.getStatusInfo().getReasonPhrase().toString()
134                                         + "]";
135                         URL url = null;
136                         try {
137                                 // must not be null to avoid NPE in HTTPException constructor
138                                 url = new URL("http://null");
139                                 if (response.getLocation() != null)
140                                         url = response.getLocation().toURL();
141                         } catch (MalformedURLException e) {
142                                 // never mind. it is only for the debug message.
143                                 logger.warn(EELFLoggerDelegate.errorLogger, "Failed to build URL", e);
144                         }
145                         logger.error(EELFLoggerDelegate.errorLogger, "http response failed. " + errMsg + "; url=" + url);
146                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeIncorrectHttpStatusError);
147                         throw new HTTPException(status, errMsg, url);
148                 }
149         }
150
151         private static boolean isHttpSuccess(int status) {
152                 return status / 100 == 2;
153         }
154         
155         
156         private WebClient createClientForApp(long appId, String restPath) {
157                 return createClientFor(appId, restPath, SystemType.APPLICATION);
158         }
159
160         //TODO Need to implement the mylogins once the endpoint is confirmed
161         @EPMetricsLog
162         private WebClient createClientFor(long appSystemId, String restPath, SystemType type) {
163                 logger.debug(EELFLoggerDelegate.debugLogger, "creating client for appId=" + appSystemId + "; restPath=" + restPath);
164                 EPApp externalApp = null;
165                 
166                 if(type == SystemType.APPLICATION){
167                 externalApp = appsCacheService.getApp(appSystemId);
168                 }else{
169                         // TO DO 
170                 }
171                 
172                 if (externalApp != null) {
173                         String appBaseUri = (type == SystemType.APPLICATION) ? externalApp.getAppRestEndpoint() : "";
174                         String username = (type == SystemType.APPLICATION) ? externalApp.getUsername(): "";
175                         String encriptedPwd = (type == SystemType.APPLICATION) ? externalApp.getAppPassword(): "";
176                         String appName = (type == SystemType.APPLICATION) ? externalApp.getName(): "";
177                         String decreptedAppPwd = StringUtils.EMPTY;
178
179                         // Set local context
180                         MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTP);
181                         if (appBaseUri != null && appBaseUri.contains("https")) {
182                                 MDC.put(EPCommonSystemProperties.PROTOCOL, EPCommonSystemProperties.HTTPS);
183                         }
184                         MDC.put(EPCommonSystemProperties.FULL_URL, appBaseUri + restPath);
185                         MDC.put(EPCommonSystemProperties.TARGET_ENTITY, appName);
186                         MDC.put(EPCommonSystemProperties.TARGET_SERVICE_NAME, restPath);
187
188                         try {
189                                 decreptedAppPwd = CipherUtil.decryptPKC(encriptedPwd,
190                                                 SystemProperties.getProperty(SystemProperties.Decryption_Key));
191                         } catch (Exception e) {
192                                 logger.error(EELFLoggerDelegate.errorLogger, "createClientFor failed to decrypt", e);
193                         }
194                         
195                         WebClient client = createClientForPath(appBaseUri, restPath);
196
197                         // support basic authentication for some partners
198                         String encoding = Base64.getEncoder().encodeToString((username + ":" + decreptedAppPwd).getBytes());
199                         String encodingStr = "Basic " + encoding;
200                         client.header(BASIC_AUTHENTICATION_HEADER, encodingStr);
201
202                         // But still keep code downward compatible for non compliant apps
203                         client.header(APP_USERNAME_HEADER, username);
204                         client.header(PASSWORD_HEADER, decreptedAppPwd);
205
206                         client.header(SystemProperties.ECOMP_REQUEST_ID, MDC.get(MDC_KEY_REQUEST_ID));
207                         client.header(SystemProperties.USERAGENT_NAME, EPCommonSystemProperties.ECOMP_PORTAL_BE);
208                         
209                         logger.debug(EELFLoggerDelegate.debugLogger,
210                                         String.format("App %d found, baseUri=[%s], Headers: [%s=%s, %s=%s, %s=%s]", appSystemId, appBaseUri,
211                                                         APP_USERNAME_HEADER, username, PASSWORD_HEADER, encriptedPwd, BASIC_AUTHENTICATION_HEADER, encodingStr));
212
213                         return client;
214                 }
215                 return null;
216         }
217
218         @Override
219         public <T> T get(Class<T> clazz, long appId, String restPath) throws HTTPException {
220                 T t = null;
221                 Response response = getResponse(appId, restPath);
222
223                 if (response != null) {
224                         verifyResponse(response);
225                         String str = response.readEntity(String.class);
226                         EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str);
227                         try {
228                                 t = gson.fromJson(str, clazz);
229                         } catch (Exception e) {
230                                 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
231                         }
232                 }
233
234                 return t;
235         }
236         
237         @Override
238         public String getIncomingJsonString(long appId, String restPath) throws HTTPException {
239                 Response response = getResponse(appId, restPath);
240
241                 if (response != null) {
242                         verifyResponse(response);
243                         String incomingJson = response.readEntity(String.class);
244                         return incomingJson;
245                 }
246                 
247                 return "";
248         }
249
250
251         /*
252          * (non-Javadoc)
253          * 
254          * @see
255          * org.openecomp.portalapp.portal.service.ApplicationsRestClientService#get(
256          * java.lang.Class, long, java.lang.String, boolean)
257          */
258         @Override
259         public <T> T get(Class<T> clazz, long appId, String restPath, boolean useJacksonMapper) throws HTTPException {
260
261                 if (!useJacksonMapper)
262                         return get(clazz, appId, restPath);
263
264                 T t = null;
265                 Response response = getResponse(appId, restPath);
266
267                 if (response != null) {
268                         verifyResponse(response);
269                         String str = response.readEntity(String.class);
270                         EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET result =", str);
271
272                         try {
273                                 t = mapper.readValue(str, clazz);
274                         } catch (Exception e) {
275                                 e.printStackTrace();
276                                 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
277                         }
278                 }
279
280                 return t;
281         }
282
283         protected Response getResponse(long appId, String restPath) {
284                 WebClient webClient = null;
285                 Response response = null;
286
287                 webClient = createClientForApp(appId, restPath);
288                 EcompPortalUtils.logAndSerializeObject(logger, restPath, "GET request =", "no-payload");
289
290                 try {
291                         if (webClient != null) {
292                                 response = webClient.get();
293                         } else {
294                                 logger.error(EELFLoggerDelegate.errorLogger,
295                                                 "Unable to create the Webclient to make the '" + restPath + "' API call.");
296                         }
297                 } catch (Exception e) {
298                         MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
299                                         Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
300                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
301                         logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the GET REST API call", e);
302                 }
303                 return response;
304         }
305         
306         
307         @Override
308         public <T> T post(Class<T> clazz, long appId, Object payload, String restPath, SystemType type) throws HTTPException {
309                 WebClient client = null;
310                 Response response = null;
311                 T t = null;
312
313                 client = createClientFor(appId, restPath, type);
314                 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST request =", payload);
315
316                 try {
317                         if (client != null) {
318                                 response = client.post(payload);
319                         } else {
320                                 logger.error(EELFLoggerDelegate.errorLogger,
321                                                 "Unable to create the Webclient to make the '" + restPath + "' API call.");
322                         }
323                 } catch (Exception e) {
324                         MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
325                                         Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
326                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
327                         logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the POST REST API call", e);
328                 }
329
330                 if (response != null) {
331                         verifyResponse(response);
332
333                         // String contentType = response.getHeaderString("Content-Type");
334                         if (clazz != null) {
335                                 String str = response.readEntity(String.class);
336                                 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST result =", str);
337                                 try {
338                                         t = gson.fromJson(str, clazz);
339                                 } catch (Exception e) {
340                                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
341                                 }
342                         }
343                 }
344                 return t;
345         }
346
347         @Override
348         public <T> T post(Class<T> clazz, long appId, Object payload, String restPath) throws HTTPException {
349                 return post( clazz, appId, payload, restPath, SystemType.APPLICATION);
350         }
351
352         //@Override
353         public <T> T postForClass(Class<T> clazz, long appId, Object payload, String restPath, Class<T> forClass) throws HTTPException {
354                 WebClient client = null;
355                 Response response = null;
356                 T t = null;
357
358                 client = createClientForApp(appId, restPath);
359                 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST request =", payload);
360
361                 try {
362                         if (client != null) {
363                                 response = client.post(payload);
364                         } else {
365                                 logger.error(EELFLoggerDelegate.errorLogger,
366                                                 "Unable to create the Webclient to make the '" + restPath + "' API call.");
367                         }
368                 } catch (Exception e) {
369                         MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
370                                         Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
371                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
372                         logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the POST REST API call", e);
373                 }
374
375                 if (response != null) {
376                         verifyResponse(response);
377
378                         // String contentType = response.getHeaderString("Content-Type");
379                         if (clazz != null) {
380                                 String str = response.readEntity(String.class);
381                                 EcompPortalUtils.logAndSerializeObject(logger, restPath, "POST result =", str);
382                                 try {
383                                         t = gson.fromJson(str, clazz);
384                                 } catch (Exception e) {
385                                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
386                                 }
387                         }
388                 }
389                 return t;
390         }
391
392         
393         @Override
394         public <T> T put(Class<T> clazz, long appId, Object payload, String restPath) throws HTTPException {
395                 WebClient client = null;
396                 Response response = null;
397                 T t = null;
398
399                 client = createClientForApp(appId, restPath);
400                 EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT request =", payload);
401
402                 try {
403                         if (client != null) {
404                                 response = client.put(payload);
405                         } else {
406                                 logger.error(EELFLoggerDelegate.errorLogger,
407                                                 "Unable to create the Webclient to make the '" + restPath + "' API call.");
408                         }
409                 } catch (Exception e) {
410                         MDC.put(EPCommonSystemProperties.EXTERNAL_API_RESPONSE_CODE,
411                                         Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
412                         EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeRestApiGeneralError, e);
413                         logger.error(EELFLoggerDelegate.errorLogger, "Exception occurred while making the PUT REST API call", e);
414                 }
415
416                 if (response != null) {
417                         verifyResponse(response);
418                         String str = response.readEntity(String.class);
419                         EcompPortalUtils.logAndSerializeObject(logger, restPath, "PUT result =", str);
420                         try {
421                                 t = gson.fromJson(str, clazz);
422                         } catch (Exception e) {
423                                 EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput, e);
424                         }
425                 }
426                 return t;
427         }
428 }