diff options
Diffstat (limited to 'catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets')
8 files changed, 1169 insertions, 0 deletions
diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/ConfigMgrServlet.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/ConfigMgrServlet.java new file mode 100644 index 0000000000..7792225742 --- /dev/null +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/ConfigMgrServlet.java @@ -0,0 +1,88 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.fe.servlets; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; + +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.rest.api.RestConfigurationInfo; +import org.openecomp.sdc.common.servlets.BasicServlet; +import org.openecomp.sdc.fe.config.Configuration; +import org.openecomp.sdc.fe.config.ConfigurationManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Root resource (exposed at "/" path) + */ +@Path("/configmgr") +public class ConfigMgrServlet extends BasicServlet { + + private static Logger log = LoggerFactory.getLogger(ConfigMgrServlet.class.getName()); + + @GET + @Path("/get") + @Produces(MediaType.APPLICATION_JSON) + public String getConfig(@Context final HttpServletRequest request, @QueryParam("type") String type) { + + String result = null; + + ServletContext context = request.getSession().getServletContext(); + + ConfigurationManager configurationManager = (ConfigurationManager) context + .getAttribute(Constants.CONFIGURATION_MANAGER_ATTR); + + if (type == null || type.equals("configuration")) { + + Configuration configuration = configurationManager.getConfiguration(); + if (configuration == null) { + log.warn("Configuration of type " + Configuration.class + " was not found"); + } else { + log.info("The value returned from getConfig is " + configuration); + + result = gson.toJson(configuration); + + } + } else if (type.equals("rest")) { + + RestConfigurationInfo configuration = configurationManager.getRestClientConfiguration(); + if (configuration == null) { + log.warn("Configuration of type " + RestConfigurationInfo.class + " was not found"); + } else { + log.info("The value returned from getConfig is " + configuration); + + result = gson.toJson(configuration); + + } + + } + return result; + + } + +} diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/ConfigServlet.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/ConfigServlet.java new file mode 100644 index 0000000000..92bb9e8743 --- /dev/null +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/ConfigServlet.java @@ -0,0 +1,114 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.fe.servlets; + +import java.util.concurrent.TimeUnit; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.container.AsyncResponse; +import javax.ws.rs.container.Suspended; +import javax.ws.rs.container.TimeoutHandler; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.openecomp.sdc.common.api.ConfigurationSource; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.servlets.BasicServlet; +import org.openecomp.sdc.fe.config.Configuration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Root resource (exposed at "/" path) + */ +@Path("/config") +public class ConfigServlet extends BasicServlet { + + private static Logger log = LoggerFactory.getLogger(ConfigServlet.class.getName()); + + @GET + @Path("/get") + @Produces(MediaType.APPLICATION_JSON) + public String getConfig(@Context final HttpServletRequest request) { + + String result = null; + + ServletContext context = request.getSession().getServletContext(); + + ConfigurationSource configurationSource = (ConfigurationSource) context + .getAttribute(Constants.CONFIGURATION_SOURCE_ATTR); + if (configurationSource != null) { + Configuration configuration = configurationSource.getAndWatchConfiguration(Configuration.class, null); + + if (configuration == null) { + log.warn("Configuration of type " + Configuration.class + " was not found"); + } + log.debug("{}", configuration); + if (log.isInfoEnabled()) { + log.info("Info level ENABLED..."); + } + log.info("The value returned from getConfig is " + configuration); + + result = gson.toJson(configuration); + + } else { + log.warn("Source Configuration object was not initialized in the context."); + } + + return result; + + } + + @GET + @Path("/asyncget") + public void asyncGet(@Suspended final AsyncResponse asyncResponse) { + + asyncResponse.setTimeoutHandler(new TimeoutHandler() { + + @Override + public void handleTimeout(AsyncResponse asyncResponse) { + asyncResponse.resume( + Response.status(Response.Status.SERVICE_UNAVAILABLE).entity("Operation time out.").build()); + } + }); + asyncResponse.setTimeout(3, TimeUnit.SECONDS); + + new Thread(new Runnable() { + @Override + public void run() { + String result = veryExpensiveOperation(); + asyncResponse.resume(result); + } + + private String veryExpensiveOperation() { + + return "veryExpensiveOperation SUCCESS"; + + } + }).start(); + } + +} diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeHealthCheckServlet.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeHealthCheckServlet.java new file mode 100644 index 0000000000..da5b321339 --- /dev/null +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeHealthCheckServlet.java @@ -0,0 +1,49 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.fe.servlets; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; + +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.servlets.BasicServlet; + +import com.jcabi.aspects.Loggable; + +@Loggable(prepend = true, value = Loggable.TRACE, trim = false) +@Path("/healthCheck") +public class FeHealthCheckServlet extends BasicServlet { + + // private static Logger log = + // LoggerFactory.getLogger(FeHealthCheckServlet.class.getName()); + + @GET + public Response getFEandBeHealthCheck(@Context final HttpServletRequest request) { + ServletContext context = request.getSession().getServletContext(); + HealthCheckService hcs = ((HealthCheckService) context.getAttribute(Constants.HEALTH_CHECK_SERVICE_ATTR)); + return hcs.getFeHealth(); + } + +} diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java new file mode 100644 index 0000000000..1cd28deb7a --- /dev/null +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/FeProxyServlet.java @@ -0,0 +1,214 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.fe.servlets; + +import java.net.URI; +import java.util.concurrent.TimeUnit; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.client.api.Response; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.config.EcompErrorName; +import org.openecomp.sdc.fe.config.Configuration; +import org.openecomp.sdc.fe.config.ConfigurationManager; +import org.openecomp.sdc.fe.config.FeEcompErrorManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; + +public class FeProxyServlet extends SSLProxyServlet { + private static final long serialVersionUID = 1L; + private static final String URL = "%s://%s:%s%s"; + private static Logger log = LoggerFactory.getLogger(FeProxyServlet.class.getName()); + private static Cache<String, MdcData> mdcDataCache = CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).build(); + + @Override + public URI rewriteURI(HttpServletRequest request) { + try { + logFeRequest(request); + } catch (Exception e) { + FeEcompErrorManager.getInstance().processEcompError(EcompErrorName.FeHttpLoggingError, "FE Request"); + FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Request"); + log.error("Unexpected FE request logging error :", e); + } + String originalUrl = request.getRequestURL().toString(); + String redirectedUrl = getModifiedUrl(request); + + log.debug("FeProxyServlet Redirecting request from: {} , to: {}", originalUrl, redirectedUrl); + + return URI.create(redirectedUrl); + } + + @Override + protected void onResponseSuccess(HttpServletRequest request, HttpServletResponse response, Response proxyResponse) { + try { + logFeResponse(request, proxyResponse); + } catch (Exception e) { + FeEcompErrorManager.getInstance().processEcompError(EcompErrorName.FeHttpLoggingError, "FE Response"); + FeEcompErrorManager.getInstance().logFeHttpLoggingError("FE Response"); + log.error("Unexpected FE response logging error :", e); + } + super.onResponseSuccess(request, response, proxyResponse); + } + + private void logFeRequest(HttpServletRequest httpRequest) { + + MDC.clear(); + + Long transactionStartTime = System.currentTimeMillis(); + // UUID - In FE, we are supposed to get the below header from UI. + // We do not generate it if it's missing - BE does. + String uuid = httpRequest.getHeader(Constants.X_ECOMP_REQUEST_ID_HEADER); + String serviceInstanceID = httpRequest.getHeader(Constants.X_ECOMP_SERVICE_ID_HEADER); + + if (uuid != null && uuid.length() > 0) { + // User Id for logging + String userId = httpRequest.getHeader(Constants.USER_ID_HEADER); + + String remoteAddr = httpRequest.getRemoteAddr(); + String localAddr = httpRequest.getLocalAddr(); + + mdcDataCache.put(uuid, new MdcData(serviceInstanceID, userId, remoteAddr, localAddr, transactionStartTime)); + + updateMdc(uuid, serviceInstanceID, userId, remoteAddr, localAddr, null); + } + inHttpRequest(httpRequest); + } + + private void logFeResponse(HttpServletRequest request, Response proxyResponse) { + String uuid = request.getHeader(Constants.X_ECOMP_REQUEST_ID_HEADER); + String transactionRoundTime = null; + + if (uuid != null) { + MdcData mdcData = mdcDataCache.getIfPresent(uuid); + if (mdcData != null) { + Long transactionStartTime = mdcData.getTransactionStartTime(); + if (transactionStartTime != null) {// should'n ever be null, but + // just to be defensive + transactionRoundTime = Long.toString(System.currentTimeMillis() - transactionStartTime); + } + updateMdc(uuid, mdcData.getServiceInstanceID(), mdcData.getUserId(), mdcData.getRemoteAddr(), mdcData.getLocalAddr(), transactionRoundTime); + } + } + outHttpResponse(proxyResponse); + + MDC.clear(); + } + + // Extracted for purpose of clear method name, for logback %M parameter + private void inHttpRequest(HttpServletRequest httpRequest) { + log.info("{} {} {}", httpRequest.getMethod(), httpRequest.getRequestURI(), httpRequest.getProtocol()); + } + + // Extracted for purpose of clear method name, for logback %M parameter + private void outHttpResponse(Response proxyResponse) { + log.info("SC=\"{}\"", proxyResponse.getStatus()); + } + + private void updateMdc(String uuid, String serviceInstanceID, String userId, String remoteAddr, String localAddr, String transactionStartTime) { + MDC.put("uuid", uuid); + MDC.put("serviceInstanceID", serviceInstanceID); + MDC.put("userId", userId); + MDC.put("remoteAddr", remoteAddr); + MDC.put("localAddr", localAddr); + MDC.put("timer", transactionStartTime); + } + + private class MdcData { + private String serviceInstanceID; + private String userId; + private String remoteAddr; + private String localAddr; + private Long transactionStartTime; + + public MdcData(String serviceInstanceID, String userId, String remoteAddr, String localAddr, Long transactionStartTime) { + super(); + this.serviceInstanceID = serviceInstanceID; + this.userId = userId; + this.remoteAddr = remoteAddr; + this.localAddr = localAddr; + this.transactionStartTime = transactionStartTime; + } + + public Long getTransactionStartTime() { + return transactionStartTime; + } + + public String getUserId() { + return userId; + } + + public String getRemoteAddr() { + return remoteAddr; + } + + public String getLocalAddr() { + return localAddr; + } + + public String getServiceInstanceID() { + return serviceInstanceID; + } + } + + public String getModifiedUrl(HttpServletRequest request) { + + Configuration config = getConfiguration(request); + if (config == null) { + log.error("failed to retrive configuration."); + } + String scheme = config.getBeProtocol(); + String uri = request.getRequestURI().toString(); + StringBuilder url = new StringBuilder(); + url.append(scheme).append("://").append(config.getBeHost()); + url.append(":"); + if (config.getBeProtocol().equals(BE_PROTOCOL.HTTP.getProtocolName())) { + url.append(config.getBeHttpPort()); + } else { + url.append(config.getBeSslPort()); + } + url.append(uri); + String queryString = request.getQueryString(); // d=789 + if (queryString != null) { + url.append("?").append(queryString); + } + + String redirectedUrl = url.toString(); + String onboardingForwardContext = config.getOnboardingForwardContext(); + if (onboardingForwardContext == null || onboardingForwardContext.isEmpty()) { + onboardingForwardContext = "/onboarding-api"; + } + redirectedUrl = redirectedUrl.replace("/sdc1/feProxy/onboarding-api", onboardingForwardContext); + redirectedUrl = redirectedUrl.replace("/sdc1/feProxy", "/sdc2"); + return redirectedUrl; + + } + + private Configuration getConfiguration(HttpServletRequest request) { + Configuration config = ((ConfigurationManager) request.getSession().getServletContext().getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getConfiguration(); + return config; + } +} diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/HealthCheckService.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/HealthCheckService.java new file mode 100644 index 0000000000..338e8d4c01 --- /dev/null +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/HealthCheckService.java @@ -0,0 +1,219 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.fe.servlets; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; + +import javax.servlet.ServletContext; +import javax.ws.rs.core.Response; + +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.api.HealthCheckInfo; +import org.openecomp.sdc.common.api.HealthCheckInfo.HealthCheckComponent; +import org.openecomp.sdc.common.api.HealthCheckInfo.HealthCheckStatus; +import org.openecomp.sdc.common.api.HealthCheckWrapper; +import org.openecomp.sdc.common.config.EcompErrorName; +import org.openecomp.sdc.common.impl.ExternalConfiguration; +import org.openecomp.sdc.fe.config.Configuration; +import org.openecomp.sdc.fe.config.ConfigurationManager; +import org.openecomp.sdc.fe.config.FeEcompErrorManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; + +public class HealthCheckService { + + private class HealthStatus { + public String body; + public int statusCode; + + public HealthStatus(int code, String body) { + this.body = body; + this.statusCode = code; + } + } + + private static final String URL = "%s://%s:%s/sdc2/rest/healthCheck"; + private static Logger healthLogger = LoggerFactory.getLogger("asdc.fe.healthcheck"); + private static Logger log = LoggerFactory.getLogger(HealthCheckService.class.getName()); + + private HealthStatus lastHealthStatus = new HealthStatus(500, "{}"); + + private class HealthCheckScheduledTask implements Runnable { + @Override + public void run() { + healthLogger.trace("Executing FE Health Check Task - Start"); + HealthStatus currentHealth = checkHealth(); + int currentHealthStatus = currentHealth.statusCode; + healthLogger.trace("Executing FE Health Check Task - Status = {}", currentHealthStatus); + + // In case health status was changed, issue alarm/recovery + if (currentHealthStatus != lastHealthStatus.statusCode) { + log.trace("FE Health State Changed to {}. Issuing alarm / recovery alarm...", currentHealthStatus); + logFeAlarm(currentHealthStatus); + } + + // Anyway, update latest response + lastHealthStatus = currentHealth; + } + } + + /** + * This executor will execute the health check task. + */ + ScheduledExecutorService healthCheckExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "FE-Health-Check-Thread"); + } + }); + private ServletContext context; + + public HealthCheckService(ServletContext context) { + this.context = context; + } + + public void start(int interval) { + this.healthCheckExecutor.scheduleAtFixedRate(new HealthCheckScheduledTask(), 0, interval, TimeUnit.SECONDS); + } + + /** + * To be used by the HealthCheckServlet + * + * @return + */ + public Response getFeHealth() { + return this.buildResponse(lastHealthStatus.statusCode, lastHealthStatus.body); + } + + private HealthStatus checkHealth() { + CloseableHttpClient httpClient = null; + try { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + Configuration config = ((ConfigurationManager) context.getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)) + .getConfiguration(); + String redirectedUrl = String.format(URL, config.getBeProtocol(), config.getBeHost(), + config.getBeHttpPort()); + httpClient = getHttpClient(config); + HttpGet httpGet = new HttpGet(redirectedUrl); + CloseableHttpResponse beResponse; + int beStatus; + String feAggHealthCheck; + try { + beResponse = httpClient.execute(httpGet); + beStatus = beResponse.getStatusLine().getStatusCode(); + String beJsonResponse = EntityUtils.toString(beResponse.getEntity()); + feAggHealthCheck = getFeHealthCheckInfos(gson, beJsonResponse); + } catch (Exception e) { + log.error("Health Check error when trying to connect to BE", e); + String beDowneResponse = gson.toJson(getBeDownCheckInfos()); + return new HealthStatus(500, beDowneResponse); + } + return new HealthStatus(beStatus, feAggHealthCheck); + } catch (Exception e) { + FeEcompErrorManager.getInstance().processEcompError(EcompErrorName.FeHealthCheckGeneralError, "Unexpected FE Health check error"); + FeEcompErrorManager.getInstance().logFeHealthCheckGeneralError("Unexpected FE Health check error"); + log.error("Unexpected FE health check error {}", e.getMessage()); + return new HealthStatus(500, e.getMessage()); + } finally { + if (httpClient != null) { + try { + httpClient.close(); + } catch (IOException e) { + } + } + } + } + + private Response buildResponse(int status, String jsonResponse) { + healthLogger.trace("FE and BE health check status: {}", jsonResponse); + return Response.status(status).entity(jsonResponse).build(); + } + + private void logFeAlarm(int lastFeStatus) { + + switch (lastFeStatus) { + case 200: + FeEcompErrorManager.getInstance().processEcompError(EcompErrorName.FeHealthCheckRecovery, + "FE Health Recovered"); + FeEcompErrorManager.getInstance().logFeHealthCheckRecovery("FE Health Recovered"); + break; + case 500: + FeEcompErrorManager.getInstance().processEcompError(EcompErrorName.FeHealthCheckConnectionError, + "Connection with ASDC-BE is probably down"); + FeEcompErrorManager.getInstance().logFeHealthCheckError("Connection with ASDC-BE is probably down"); + break; + default: + break; + } + + } + + private String getFeHealthCheckInfos(Gson gson, String responseString) { + Type wrapperType = new TypeToken<HealthCheckWrapper>() { + }.getType(); + HealthCheckWrapper healthCheckWrapper = gson.fromJson(responseString, wrapperType); + String appVersion = ExternalConfiguration.getAppVersion(); + String description = "OK"; + healthCheckWrapper.getComponentsInfo() + .add(new HealthCheckInfo(HealthCheckComponent.FE, HealthCheckStatus.UP, appVersion, description)); + return gson.toJson(healthCheckWrapper); + } + + private HealthCheckWrapper getBeDownCheckInfos() { + List<HealthCheckInfo> healthCheckInfos = new ArrayList<HealthCheckInfo>(); + healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.FE, HealthCheckStatus.UP, + ExternalConfiguration.getAppVersion(), "OK")); + healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.BE, HealthCheckStatus.DOWN, null, null)); + healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.ES, HealthCheckStatus.UNKNOWN, null, null)); + healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.TITAN, HealthCheckStatus.UNKNOWN, null, null)); + healthCheckInfos.add(new HealthCheckInfo(HealthCheckComponent.DE, HealthCheckStatus.UNKNOWN, null, null)); + HealthCheckWrapper hcWrapper = new HealthCheckWrapper(healthCheckInfos, "UNKNOWN", "UNKNOWN"); + return hcWrapper; + } + + private CloseableHttpClient getHttpClient(Configuration config) { + int timeout = 3000; + int socketTimeout = config.getHealthCheckSocketTimeoutInMs(5000); + RequestConfig.Builder requestBuilder = RequestConfig.custom(); + requestBuilder.setConnectTimeout(timeout).setConnectionRequestTimeout(timeout).setSocketTimeout(socketTimeout); + + HttpClientBuilder builder = HttpClientBuilder.create(); + builder.setDefaultRequestConfig(requestBuilder.build()); + return builder.build(); + } +} diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/KibanaServlet.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/KibanaServlet.java new file mode 100644 index 0000000000..64784b3265 --- /dev/null +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/KibanaServlet.java @@ -0,0 +1,98 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.fe.servlets; + +import java.net.URI; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.api.Response; +import org.eclipse.jetty.proxy.ProxyServlet; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.fe.config.Configuration; +import org.openecomp.sdc.fe.config.ConfigurationManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class KibanaServlet extends ProxyServlet { + private static final long serialVersionUID = 1L; + private static Logger log = LoggerFactory.getLogger(KibanaServlet.class.getName()); + + @Override + public URI rewriteURI(HttpServletRequest request) { + + String originalUrl = request.getRequestURI(); + + String redirectedUrl = getModifiedUrl(request); + + log.debug("KibanaServlet Redirecting request from: {} , to: {}", originalUrl, redirectedUrl); + + return URI.create(redirectedUrl); + } + + @Override + public void customizeProxyRequest(Request proxyRequest, HttpServletRequest request) { + super.customizeProxyRequest(proxyRequest, request); + + } + + @Override + protected void onResponseSuccess(HttpServletRequest request, HttpServletResponse response, Response proxyResponse) { + + super.onResponseSuccess(request, response, proxyResponse); + } + + public String getModifiedUrl(HttpServletRequest request) { + Configuration config = getConfiguration(request); + if (config == null) { + log.error("failed to retrive configuration."); + } + // String scheme = request.getScheme(); + String contextPath = request.getContextPath(); // /mywebapp + String servletPath = request.getServletPath(); // /servlet/MyServlet + String pathInfo = request.getPathInfo(); // /a/b;c=123 + String queryString = request.getQueryString(); // d=789 + + StringBuilder url = new StringBuilder(); + url.append(config.getKibanaProtocol()).append("://").append(config.getKibanaHost()); + url.append(":").append(config.getKibanaPort()); + url.append(contextPath).append(servletPath); + + if (pathInfo != null) { + url.append(pathInfo); + } + if (queryString != null) { + url.append("?").append(queryString); + } + + String redirectedUrl = url.toString().replace("/sdc1/kibanaProxy/", "/"); + return redirectedUrl; + + } + + private Configuration getConfiguration(HttpServletRequest request) { + Configuration config = ((ConfigurationManager) request.getSession().getServletContext() + .getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getConfiguration(); + return config; + } +} diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/PortalServlet.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/PortalServlet.java new file mode 100644 index 0000000000..4eba2e5eb5 --- /dev/null +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/PortalServlet.java @@ -0,0 +1,279 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.fe.servlets; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.List; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.core.Context; + +import org.openecomp.portalsdk.core.onboarding.crossapi.ECOMPSSO; +import org.openecomp.sdc.common.config.EcompErrorName; +import org.openecomp.sdc.common.impl.MutableHttpServletRequest; +import org.openecomp.sdc.fe.Constants; +import org.openecomp.sdc.fe.config.Configuration; +import org.openecomp.sdc.fe.config.ConfigurationManager; +import org.openecomp.sdc.fe.config.FeEcompErrorManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Root resource (exposed at "/" path) + */ +@Path("/") +public class PortalServlet extends HttpServlet { + + private static Logger log = LoggerFactory.getLogger(PortalServlet.class.getName()); + private static final long serialVersionUID = 1L; + public static final String MISSING_HEADERS_MSG = "Missing Headers In Request"; + public static final String AUTHORIZATION_ERROR_MSG = "Autherization error"; + public static final String NEW_LINE = System.getProperty("line.separator"); + + /** + * Entry point from ECOMP portal + */ + @GET + @Path("/portal") + public void doGet(@Context final HttpServletRequest request, @Context final HttpServletResponse response) { + try { + addRequestHeadersUsingWebseal(request, response); + } catch (Exception e) { + FeEcompErrorManager.getInstance().processEcompError(EcompErrorName.FePortalServletError, "Portal Servlet"); + FeEcompErrorManager.getInstance().logFePortalServletError("Portal Servlet"); + log.error("Error during getting portal page", e); + } + } + + /** + * Building new HTTP request and setting headers for the request The request + * will dispatch to index.html + * + * @param request + * @param response + * @throws ServletException + * @throws IOException + */ + private void addRequestHeadersUsingWebseal(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + + response.setContentType("text/html"); + + // Create new request object to dispatch + MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(request); + + // Get configuration object (reads data from configuration.yaml) + Configuration configuration = getConfiguration(request); + + // Check if we got header from webseal + String userId = request.getHeader(Constants.WEBSEAL_USER_ID_HEADER); + if (null == userId) { + // Authentication via ecomp portal + try { + String valdiateECOMPSSO = ECOMPSSO.valdiateECOMPSSO(request); + String userIdFromCookie = ECOMPSSO.getUserIdFromCookie(request); + if (valdiateECOMPSSO == null || ("").equals(userIdFromCookie)) { + // This is probably a webseal request, so missing header in request should be printed. + response.sendError(HttpServletResponse.SC_USE_PROXY, MISSING_HEADERS_MSG); + } + userId = userIdFromCookie; + } catch (Exception e) { + response.sendError(HttpServletResponse.SC_USE_PROXY, AUTHORIZATION_ERROR_MSG); + } + } + + // Replace webseal header with open source header + mutableRequest.putHeader(Constants.USER_ID, userId); + + // Getting identification headers from configuration.yaml + // (identificationHeaderFields) and setting them to new request + // mutableRequest + List<List<String>> identificationHeaderFields = configuration.getIdentificationHeaderFields(); + for (List<String> possibleHeadersToRecieve : identificationHeaderFields) { + String allowedHeaderToPass = possibleHeadersToRecieve.get(0); + setNewHeader(possibleHeadersToRecieve, allowedHeaderToPass, request, mutableRequest); + } + + // Getting optional headers from configuration.yaml + // (optionalHeaderFields) and setting them to new request mutableRequest + List<List<String>> optionalHeaderFields = configuration.getOptionalHeaderFields(); + for (List<String> possibleHeadersToRecieve : optionalHeaderFields) { + String allowedHeaderToPass = possibleHeadersToRecieve.get(0); + setNewHeader(possibleHeadersToRecieve, allowedHeaderToPass, request, mutableRequest); + } + + // Print headers from original request for debug purposes + printHeaders(request); + + // In case using webseal, validate all mandatory headers (identificationHeaderFields) are included in the new request (mutableRequest). + // Via ecomp portal do not need to check the headers. + boolean allHeadersExist = true; + if (null != request.getHeader(Constants.WEBSEAL_USER_ID_HEADER)) { + allHeadersExist = checkHeaders(mutableRequest); + } + + if (allHeadersExist) { + addCookies(response, mutableRequest, getMandatoryHeaders(request)); + addCookies(response, mutableRequest, getOptionalHeaders(request)); + RequestDispatcher rd = request.getRequestDispatcher("index.html"); + rd.forward(mutableRequest, response); + } else { + response.sendError(HttpServletResponse.SC_USE_PROXY, MISSING_HEADERS_MSG); + } + } + + /** + * Print all request headers to the log + * + * @param request + */ + private void printHeaders(HttpServletRequest request) { + + if (log.isDebugEnabled()) { + StringBuilder builder = new StringBuilder(); + String sessionId = ""; + if (request.getSession() != null) { + String id = request.getSession().getId(); + if (id != null) { + sessionId = id; + } + } + + builder.append("Receiving request with headers:" + NEW_LINE); + log.debug("{}", request.getHeaderNames()); + @SuppressWarnings("unchecked") + Enumeration<String> headerNames = request.getHeaderNames(); + if (headerNames != null) { + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + String headerValue = request.getHeader(headerName); + builder.append("session " + sessionId + " header: name = " + headerName + ", value = " + headerValue + NEW_LINE); + } + } + + log.debug(builder.toString()); + } + + } + + /** + * Add cookies (that where set in the new request headers) in the response + * + * @param response + * @param request + * @param headers + */ + private void addCookies(HttpServletResponse response, HttpServletRequest request, String[] headers) { + for (int i = 0; i < headers.length; i++) { + String currHeader = headers[i]; + String headerValue = request.getHeader(currHeader); + if (headerValue != null) { + response.addCookie(new Cookie(currHeader, headerValue)); + } + } + } + + /** + * Get mandatory headers (identificationHeaderFields) String array, and + * checks that each header exists in the new request + * + * @param request + * @return boolean + */ + private boolean checkHeaders(HttpServletRequest request) { + String[] mandatoryHeaders = getMandatoryHeaders(request); + + boolean allHeadersExist = true; + for (int i = 0; i < mandatoryHeaders.length; i++) { + String headerValue = request.getHeader(mandatoryHeaders[i]); + if (headerValue == null) { + allHeadersExist = false; + break; + } + } + return allHeadersExist; + } + + /** + * Get mandatory headers (identificationHeaderFields) from + * configuration.yaml file and return String[] + * + * @param request + * @return String[] + */ + private String[] getMandatoryHeaders(HttpServletRequest request) { + Configuration configuration = getConfiguration(request); + List<List<String>> identificationHeaderFields = configuration.getIdentificationHeaderFields(); + String[] mandatoryHeaders = new String[identificationHeaderFields.size()]; + for (int i = 0; i < identificationHeaderFields.size(); i++) { + mandatoryHeaders[i] = identificationHeaderFields.get(i).get(0); + } + return mandatoryHeaders; + } + + /** + * Get optional headers (optionalHeaderFields) from configuration.yaml file + * and return String[] + * + * @param request + * @return String[] + */ + private String[] getOptionalHeaders(HttpServletRequest request) { + Configuration configuration = getConfiguration(request); + List<List<String>> optionalHeaderFields = configuration.getOptionalHeaderFields(); + String[] optionalHeaders = new String[optionalHeaderFields.size()]; + for (int i = 0; i < optionalHeaderFields.size(); i++) { + optionalHeaders[i] = optionalHeaderFields.get(i).get(0); + } + return optionalHeaders; + } + + /** + * Return Configuration object to read from configuration.yaml + * + * @param request + * @return Configuration + */ + private Configuration getConfiguration(HttpServletRequest request) { + ConfigurationManager configManager = (ConfigurationManager) request.getSession().getServletContext().getAttribute(org.openecomp.sdc.common.api.Constants.CONFIGURATION_MANAGER_ATTR); + return configManager.getConfiguration(); + } + + private boolean setNewHeader(List<String> possibleOldHeaders, String newHeaderToSet, HttpServletRequest oldRequest, MutableHttpServletRequest newRequest) { + boolean newHeaderIsSet = false; + for (int i = 0; i < possibleOldHeaders.size() && !newHeaderIsSet; i++) { + String headerValue = oldRequest.getHeader(possibleOldHeaders.get(i)); + if (headerValue != null) { + newRequest.putHeader(newHeaderToSet, headerValue); + newHeaderIsSet = true; + } + } + return newHeaderIsSet; + } + +} diff --git a/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/SSLProxyServlet.java b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/SSLProxyServlet.java new file mode 100644 index 0000000000..c3ba279c8c --- /dev/null +++ b/catalog-fe/src/main/java/org/openecomp/sdc/fe/servlets/SSLProxyServlet.java @@ -0,0 +1,108 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.fe.servlets; + +import java.util.Enumeration; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.proxy.ProxyServlet; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.fe.config.Configuration; +import org.openecomp.sdc.fe.config.ConfigurationManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class SSLProxyServlet extends ProxyServlet { + + private static final long serialVersionUID = 1L; + private static Logger log = LoggerFactory.getLogger(SSLProxyServlet.class.getName()); + + public enum BE_PROTOCOL { + HTTP("http"), SSL("ssl"); + private String protocolName; + + public String getProtocolName() { + return protocolName; + } + + BE_PROTOCOL(String protocolName) { + this.protocolName = protocolName; + } + }; + + @Override + public void customizeProxyRequest(Request proxyRequest, HttpServletRequest request) { + super.customizeProxyRequest(proxyRequest, request); + // Add Missing Headers to proxy request + @SuppressWarnings("unchecked") + Enumeration<String> headerNames = request.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + if (!proxyRequest.getHeaders().containsKey(headerName)) { + String headerVal = request.getHeader(headerName); + log.debug("Adding missing header to request, header name: {} , header value: {}", headerName, + headerVal); + proxyRequest.header(headerName, headerVal); + } + } + proxyRequest.getHeaders().remove(HttpHeader.HOST); + + } + + @Override + protected HttpClient createHttpClient() throws ServletException { + Configuration config = ((ConfigurationManager) getServletConfig().getServletContext() + .getAttribute(Constants.CONFIGURATION_MANAGER_ATTR)).getConfiguration(); + boolean isSecureClient = !config.getBeProtocol().equals(BE_PROTOCOL.HTTP.getProtocolName()); + HttpClient client = (isSecureClient) ? getSecureHttpClient() : super.createHttpClient(); + setTimeout(600000); + client.setIdleTimeout(600000); + client.setStopTimeout(600000); + + return client; + } + + private HttpClient getSecureHttpClient() throws ServletException { + // Instantiate and configure the SslContextFactory + SslContextFactory sslContextFactory = new SslContextFactory(true); + + // Instantiate HttpClient with the SslContextFactory + HttpClient httpClient = new HttpClient(sslContextFactory); + + // Configure HttpClient, for example: + httpClient.setFollowRedirects(false); + + // Start HttpClient + try { + httpClient.start(); + + return httpClient; + } catch (Exception x) { + throw new ServletException(x); + } + } +} |