Revert "Support SIP TLS"
[sdc.git] / catalog-fe / src / main / java / org / openecomp / sdc / fe / servlets / FeProxyServlet.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.openecomp.sdc.fe.servlets;
21
22 import static org.apache.commons.lang3.StringUtils.isEmpty;
23
24 import com.google.common.annotations.VisibleForTesting;
25 import java.net.MalformedURLException;
26 import java.net.URL;
27 import java.util.Base64;
28 import javax.servlet.http.HttpServletRequest;
29 import org.apache.commons.lang3.NotImplementedException;
30 import org.apache.commons.lang3.StringUtils;
31 import org.eclipse.jetty.client.api.Request;
32 import org.eclipse.jetty.client.api.Response;
33 import org.eclipse.jetty.http.HttpHeader;
34 import org.openecomp.sdc.common.api.Constants;
35 import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
36 import org.openecomp.sdc.common.log.wrappers.Logger;
37 import org.openecomp.sdc.fe.config.Configuration;
38 import org.openecomp.sdc.fe.config.Configuration.BasicAuthConfig;
39 import org.openecomp.sdc.fe.config.Configuration.CatalogFacadeMsConfig;
40 import org.openecomp.sdc.fe.config.ConfigurationManager;
41 import org.openecomp.sdc.fe.config.FeEcompErrorManager;
42 import org.openecomp.sdc.fe.config.PluginsConfiguration;
43 import org.openecomp.sdc.fe.config.PluginsConfiguration.Plugin;
44 import org.openecomp.sdc.fe.impl.LogHandler;
45 import org.openecomp.sdc.fe.utils.BeProtocol;
46
47 public class FeProxyServlet extends SSLProxyServlet {
48
49     public static final String UUID = "uuid";
50     public static final String TRANSACTION_START_TIME = "transactionStartTime";
51     private static final long serialVersionUID = 1L;
52     private static final String URL = "%s://%s%s%s";
53     private static final String MS_URL = "%s://%s:%s";
54     private static final String ONBOARDING_CONTEXT = "/onboarding-api";
55     private static final String DCAED_CONTEXT = "/dcae-api";
56     private static final String WORKFLOW_CONTEXT = "/wf";
57     private static final String SDC1_FE_PROXY = "/sdc1/feProxy";
58     private static final String PLUGIN_ID_WORKFLOW = "WORKFLOW";
59     private static final String FACADE_PATH_IDENTIFIER = "uicache";
60     private static final String CATALOG_REQUEST_IDENTIFIER = "/v1/catalog";
61     private static final String ARCHIVE_PATH_IDENTIFIER = String.format("%s/archive/", CATALOG_REQUEST_IDENTIFIER);
62     private static final String HOME_REQUEST_IDENTIFIER = "/v1/followed";
63     private static Logger log = Logger.getLogger(FeProxyServlet.class.getName());
64     private static String msUrl;
65
66     @Override
67     protected String rewriteTarget(HttpServletRequest request) {
68         String originalUrl = "";
69         String redirectedUrl = "";
70         try {
71             logFeRequest(request);
72             originalUrl = request.getRequestURL().toString();
73             Configuration config = getConfiguration(request);
74             if (config == null) {
75                 log.error("failed to retrieve configuration.");
76             }
77             if (isMsRequest(request.getRequestURL().toString())) {
78                 redirectedUrl = redirectMsRequestToMservice(request, config);
79             } else {
80                 redirectedUrl = getModifiedUrl(config, getPluginConfiguration(request), request.getRequestURI(), getQueryString(request));
81             }
82         } catch (MalformedURLException mue) {
83             FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Request");
84             log.error(EcompLoggerErrorCode.DATA_ERROR, "FeProxyServlet rewriteTarget", "sdc-FE", "Malformed URL Exception: ", mue);
85         } catch (Exception e) {
86             log.error(EcompLoggerErrorCode.UNKNOWN_ERROR, "FeProxyServlet rewriteTarget", "sdc-FE", "Unexpected FE request processing error: ", e);
87         }
88         if (log.isDebugEnabled()) {
89             log.debug("FeProxyServlet Redirecting request from: {} , to: {}", originalUrl, redirectedUrl);
90         }
91         return redirectedUrl;
92     }
93
94     @Override
95     protected void addProxyHeaders(HttpServletRequest clientRequest, Request proxyRequest) {
96         Configuration config = getConfiguration(clientRequest);
97         if (config == null) {
98             log.error("Failed to retrieve configuration. Adding proxy header failed.");
99             return;
100         }
101         BasicAuthConfig basicAuth = config.getBasicAuth();
102         if (basicAuth.isEnabled()) {
103             proxyRequest.header(HttpHeader.AUTHORIZATION,
104                 "Basic " + Base64.getEncoder().encodeToString((basicAuth.getUserName() + ":" + basicAuth.getUserPass()).getBytes()));
105         }
106         super.addProxyHeaders(clientRequest, proxyRequest);
107     }
108
109     private void logFeRequest(HttpServletRequest httpRequest) {
110         LogHandler.logFeRequest(httpRequest);
111         inHttpRequest(httpRequest);
112     }
113
114     private void logFeResponse(HttpServletRequest request, Response proxyResponse) {
115         LogHandler.logFeResponse(request);
116         outHttpResponse(proxyResponse);
117     }
118
119     // Extracted for purpose of clear method name, for logback %M parameter
120     private void inHttpRequest(HttpServletRequest httpRequest) {
121         log.info("{} {} {}", httpRequest.getMethod(), httpRequest.getRequestURI(), httpRequest.getProtocol());
122     }
123
124     // Extracted for purpose of clear method name, for logback %M parameter
125     private void outHttpResponse(Response proxyResponse) {
126         log.info("SC=\"{}\"", proxyResponse.getStatus());
127     }
128
129     private String getModifiedUrl(Configuration config, PluginsConfiguration pluginConf, String uri, String queryString)
130         throws MalformedURLException {
131         if (config == null) {
132             log.error(EcompLoggerErrorCode.UNKNOWN_ERROR, "FeProxyServlet getModifiedUrl", "sdc-FE", "failed to retrieve configuration.");
133             throw new RuntimeException("failed to read FE configuration");
134         }
135         String protocol;
136         String host;
137         String port;
138         String path = "";
139         if (uri.contains(ONBOARDING_CONTEXT)) {
140             uri = uri.replace(SDC1_FE_PROXY + ONBOARDING_CONTEXT, ONBOARDING_CONTEXT);
141             protocol = config.getOnboarding().getProtocolBe();
142             host = config.getOnboarding().getHostBe();
143             port = config.getOnboarding().getPortBe().toString();
144         } else if (uri.contains(DCAED_CONTEXT)) {
145             uri = uri.replace(SDC1_FE_PROXY + DCAED_CONTEXT, DCAED_CONTEXT);
146             protocol = config.getBeProtocol();
147             host = config.getBeHost();
148             if (config.getBeProtocol().equals(BeProtocol.HTTP.getProtocolName())) {
149                 port = config.getBeHttpPort().toString();
150             } else {
151                 port = config.getBeSslPort().toString();
152             }
153         } else if (uri.contains(WORKFLOW_CONTEXT)) {
154             uri = uri.replace(SDC1_FE_PROXY + WORKFLOW_CONTEXT, WORKFLOW_CONTEXT);
155             String workflowPluginURL = pluginConf.getPluginsList().stream()
156                 .filter(plugin -> plugin.getPluginId().equalsIgnoreCase(PLUGIN_ID_WORKFLOW)).map(Plugin::getPluginDiscoveryUrl).findFirst()
157                 .orElse(null);
158             java.net.URL workflowURL = new URL(workflowPluginURL);
159             protocol = workflowURL.getProtocol();
160             host = workflowURL.getHost();
161             path = workflowURL.getPath();
162             port = String.valueOf(workflowURL.getPort());
163         } else {
164             uri = uri.replace(SDC1_FE_PROXY, "/sdc2");
165             protocol = config.getBeProtocol();
166             host = config.getBeHost();
167             if (config.getBeProtocol().equals(BeProtocol.HTTP.getProtocolName())) {
168                 port = config.getBeHttpPort().toString();
169             } else {
170                 port = config.getBeSslPort().toString();
171             }
172         }
173         final String authority = getAuthority(host, port);
174         String modifiedUrl = String.format(URL, protocol, authority, path, uri);
175         if (StringUtils.isNotEmpty(queryString)) {
176             modifiedUrl += "?" + queryString;
177         }
178         return modifiedUrl;
179     }
180
181     @VisibleForTesting
182     String redirectMsRequestToMservice(HttpServletRequest request, Configuration config) throws MalformedURLException {
183         boolean isMsToggledOn = isMsToggleOn(config);
184         String redirectValue;
185         if (isMsToggledOn) {
186             redirectValue = handleMsToggleOnRedirect(request, config);
187         } else {
188             redirectValue = handleMsToggleOffRedirect(request, config);
189         }
190         return redirectValue;
191     }
192
193     private PluginsConfiguration getPluginConfiguration(HttpServletRequest request) {
194         return ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR))
195             .getPluginsConfiguration();
196     }
197
198     private boolean isMsToggleOn(Configuration config) {
199         boolean toggleOn = true;
200         final CatalogFacadeMsConfig catalogFacadeMs = config.getCatalogFacadeMs();
201         if (catalogFacadeMs == null) {
202             toggleOn = false;
203             ;
204         } else if (isEmpty(catalogFacadeMs.getHealthCheckUri())) {
205             toggleOn = false;
206         } else if (isEmpty(catalogFacadeMs.getHost())) {
207             toggleOn = false;
208         } else if (isEmpty(catalogFacadeMs.getPath())) {
209             toggleOn = false;
210         } else if (isEmpty(catalogFacadeMs.getProtocol())) {
211             toggleOn = false;
212         } else if (catalogFacadeMs.getPort() == null) {
213             toggleOn = false;
214         }
215         return toggleOn;
216     }
217
218     private String handleMsToggleOffRedirect(HttpServletRequest request, Configuration config) throws MalformedURLException {
219         String redirectValue;
220         String currentURI = request.getRequestURI();
221         if (isEmpty(request.getQueryString())) {
222             // Catalog
223             if (currentURI.endsWith(CATALOG_REQUEST_IDENTIFIER)) {
224                 String facadeSuffix = String.format("%s%s", FACADE_PATH_IDENTIFIER, CATALOG_REQUEST_IDENTIFIER);
225                 String nonFacadeUrl = currentURI.replace(facadeSuffix, "rest/v1/screen");
226                 redirectValue = getModifiedUrl(config, getPluginConfiguration(request), nonFacadeUrl,
227                     "excludeTypes=VFCMT&excludeTypes=Configuration");
228             }
229             // Home
230             else if (currentURI.endsWith(HOME_REQUEST_IDENTIFIER)) {
231                 redirectValue = getModifiedUrl(config, getPluginConfiguration(request), currentURI, getQueryString(request));
232             }
233             // Archive
234             else if (currentURI.endsWith(ARCHIVE_PATH_IDENTIFIER)) {
235                 redirectValue = getModifiedUrl(config, getPluginConfiguration(request), currentURI, getQueryString(request));
236             } else {
237                 String message = String.format("facade is toggled off, Could not rediret url %s", currentURI);
238                 log.error(message);
239                 throw new NotImplementedException(message);
240             }
241         } else {
242             // Left Pallet
243             if (currentURI.contains("/latestversion/notabstract/metadata")) {
244                 String nonFacadeUrl = currentURI.replace(FACADE_PATH_IDENTIFIER, "rest");
245                 redirectValue = getModifiedUrl(config, getPluginConfiguration(request), nonFacadeUrl, getQueryString(request));
246             }
247             // Catalog with Query Params
248             else if (currentURI.endsWith(CATALOG_REQUEST_IDENTIFIER)) {
249                 String facadeSuffix = String.format("%s%s", FACADE_PATH_IDENTIFIER, CATALOG_REQUEST_IDENTIFIER);
250                 String nonFacadeUrl = currentURI.replace(facadeSuffix, "rest/v1/screen");
251                 redirectValue = getModifiedUrl(config, getPluginConfiguration(request), nonFacadeUrl,
252                     "excludeTypes=VFCMT&excludeTypes=Configuration");
253             } else {
254                 String message = String
255                     .format("facade is toggled off, Could not rediret url %s with query params %s", currentURI, getQueryString(request));
256                 log.error(message);
257                 throw new NotImplementedException(message);
258             }
259         }
260         return redirectValue;
261     }
262
263     private String handleMsToggleOnRedirect(HttpServletRequest request, Configuration config) {
264         String currentUrl = request.getRequestURL().toString();
265         if (StringUtils.isEmpty(msUrl)) {
266             // do that only once
267             msUrl = String.format(MS_URL, config.getCatalogFacadeMs().getProtocol(), config.getCatalogFacadeMs().getHost(),
268                 config.getCatalogFacadeMs().getPort());
269         }
270         StringBuilder url;
271         String queryString;
272         String msPath = config.getCatalogFacadeMs().getPath();
273         if (currentUrl.endsWith(ARCHIVE_PATH_IDENTIFIER)) {
274             url = new StringBuilder(msUrl + msPath + CATALOG_REQUEST_IDENTIFIER);
275             queryString = "arc=true";
276         } else {
277             url = new StringBuilder(msUrl + currentUrl.substring(currentUrl.indexOf(msPath)));
278             queryString = request.getQueryString();
279         }
280         if (queryString != null) {
281             url.append("?").append(queryString);
282         }
283         if (log.isDebugEnabled()) {
284             log.debug("Redirect catalog request to {}", url.toString());
285         }
286         return url.toString();
287     }
288
289     @VisibleForTesting
290     boolean isMsRequest(String currentUrl) {
291         return currentUrl.contains(FACADE_PATH_IDENTIFIER) || currentUrl.endsWith(ARCHIVE_PATH_IDENTIFIER);
292     }
293
294     private Configuration getConfiguration(HttpServletRequest request) {
295         return ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR))
296             .getConfiguration();
297     }
298
299     private String getAuthority(String host, String port) {
300         String authority;
301         if (port == null) {
302             authority = host;
303         } else {
304             authority = host + ":" + port;
305         }
306         return authority;
307     }
308
309     private String getQueryString(HttpServletRequest request) {
310         final String queryString = request.getQueryString();
311         return StringUtils.isEmpty(queryString) ? StringUtils.EMPTY : queryString;
312     }
313 }