-/*******************************************************************************\r
- * ============LICENSE_START==================================================\r
- * * org.onap.dmaap\r
- * * ===========================================================================\r
- * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
- * * ===========================================================================\r
- * * Licensed under the Apache License, Version 2.0 (the "License");\r
- * * you may not use this file except in compliance with the License.\r
- * * You may obtain a copy of the License at\r
- * * \r
- * * http://www.apache.org/licenses/LICENSE-2.0\r
- * * \r
- * * Unless required by applicable law or agreed to in writing, software\r
- * * distributed under the License is distributed on an "AS IS" BASIS,\r
- * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * * See the License for the specific language governing permissions and\r
- * * limitations under the License.\r
- * * ============LICENSE_END====================================================\r
- * *\r
- * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
- * *\r
- ******************************************************************************/\r
-\r
-\r
-package org.onap.dmaap.datarouter.provisioning;\r
-\r
-import java.io.File;\r
-import java.io.FileInputStream;\r
-import java.io.FileNotFoundException;\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.net.URI;\r
-import java.security.KeyStore;\r
-import java.security.KeyStoreException;\r
-import java.util.Collections;\r
-import java.util.List;\r
-import java.util.Properties;\r
-\r
-import javax.servlet.ServletConfig;\r
-import javax.servlet.ServletException;\r
-import javax.servlet.http.HttpServletRequest;\r
-import javax.servlet.http.HttpServletResponse;\r
-\r
-import org.apache.commons.io.IOUtils;\r
-import org.apache.http.Header;\r
-import org.apache.http.HttpEntity;\r
-import org.apache.http.HttpResponse;\r
-import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;\r
-import org.apache.http.client.methods.HttpGet;\r
-import org.apache.http.client.methods.HttpRequestBase;\r
-import org.apache.http.conn.scheme.Scheme;\r
-import org.apache.http.conn.ssl.SSLSocketFactory;\r
-import org.apache.http.entity.BasicHttpEntity;\r
-import org.apache.http.impl.client.AbstractHttpClient;\r
-import org.apache.http.impl.client.DefaultHttpClient;\r
-import org.onap.dmaap.datarouter.provisioning.utils.DB;\r
-import org.onap.dmaap.datarouter.provisioning.utils.URLUtilities;\r
-\r
-/**\r
- * This class is the base class for those servlets that need to proxy their requests from the\r
- * standby to active server. Its methods perform the proxy function to the active server. If the\r
- * active server is not reachable, a 503 (SC_SERVICE_UNAVAILABLE) is returned. Only\r
- * DELETE/GET/PUT/POST are supported.\r
- *\r
- * @author Robert Eby\r
- * @version $Id: ProxyServlet.java,v 1.3 2014/03/24 18:47:10 eby Exp $\r
- */\r
-@SuppressWarnings("serial")\r
-public class ProxyServlet extends BaseServlet {\r
- private boolean inited = false;\r
- private Scheme sch;\r
-\r
- /**\r
- * Initialize this servlet, by setting up SSL.\r
- */\r
- @SuppressWarnings("deprecation")\r
- @Override\r
- public void init(ServletConfig config) throws ServletException {\r
- super.init(config);\r
- try {\r
- // Set up keystore\r
- Properties props = (new DB()).getProperties();\r
- String type = props.getProperty(Main.KEYSTORE_TYPE_PROPERTY, "jks");\r
- String store = props.getProperty(Main.KEYSTORE_PATH_PROPERTY);\r
- String pass = props.getProperty(Main.KEYSTORE_PASSWORD_PROPERTY);\r
- KeyStore keyStore = readStore(store, pass, type);\r
-\r
- store = props.getProperty(Main.TRUSTSTORE_PATH_PROPERTY);\r
- pass = props.getProperty(Main.TRUSTSTORE_PASSWORD_PROPERTY);\r
- if (store == null || store.length() == 0) {\r
- store = Main.DEFAULT_TRUSTSTORE;\r
- pass = "changeit";\r
- }\r
- KeyStore trustStore = readStore(store, pass, KeyStore.getDefaultType());\r
-\r
- // We are connecting with the node name, but the certificate will have the CNAME\r
- // So we need to accept a non-matching certificate name\r
- SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore, "changeit", trustStore);\r
- socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);\r
- sch = new Scheme("https", 443, socketFactory);\r
- inited = true;\r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }\r
- intlogger.info("ProxyServlet: inited = "+inited);\r
- }\r
- private KeyStore readStore(String store, String pass, String type) throws KeyStoreException, FileNotFoundException {\r
- KeyStore ks = KeyStore.getInstance(type);\r
- FileInputStream instream = new FileInputStream(new File(store));\r
- try {\r
- ks.load(instream, pass.toCharArray());\r
- } catch (Exception x) {\r
- System.err.println("READING TRUSTSTORE: "+x);\r
- } finally {\r
- try { instream.close(); } catch (Exception ignore) {}\r
- }\r
- return ks;\r
- }\r
- /**\r
- * Return <i>true</i> if the requester has NOT set the <i>noproxy</i> CGI variable.\r
- * If they have, this indicates they want to forcibly turn the proxy off.\r
- * @param req the HTTP request\r
- * @return true or false\r
- */\r
- protected boolean isProxyOK(final HttpServletRequest req) {\r
- String t = req.getQueryString();\r
- if (t != null) {\r
- t = t.replaceAll("&", "&");\r
- for (String s : t.split("&")) {\r
- if (s.equals("noproxy") || s.startsWith("noproxy="))\r
- return false;\r
- }\r
- }\r
- return true;\r
- }\r
- /**\r
- * Is this the standby server? If it is, the proxy functions can be used.\r
- * If not, the proxy functions should not be called, and will send a response of 500\r
- * (Internal Server Error).\r
- * @return true if this server is the standby (and hence a proxy server).\r
- */\r
- public boolean isProxyServer() {\r
- SynchronizerTask st = SynchronizerTask.getSynchronizer();\r
- return st.getState() == SynchronizerTask.STANDBY;\r
- }\r
- /**\r
- * Issue a proxy DELETE to the active provisioning server.\r
- */\r
- @Override\r
- public void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException {\r
- doProxy(req, resp, "DELETE");\r
- }\r
- /**\r
- * Issue a proxy GET to the active provisioning server.\r
- */\r
- @Override\r
- public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {\r
- doProxy(req, resp, "GET");\r
- }\r
- /**\r
- * Issue a proxy PUT to the active provisioning server.\r
- */\r
- @Override\r
- public void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException {\r
- doProxy(req, resp, "PUT");\r
- }\r
- /**\r
- * Issue a proxy POST to the active provisioning server.\r
- */\r
- @Override\r
- public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {\r
- doProxy(req, resp, "POST");\r
- }\r
- /**\r
- * Issue a proxy GET to the active provisioning server. Unlike doGet() above,\r
- * this method will allow the caller to fall back to other code if the remote server is unreachable.\r
- * @return true if the proxy succeeded\r
- */\r
- public boolean doGetWithFallback(HttpServletRequest req, HttpServletResponse resp) throws IOException {\r
- boolean rv = false;\r
- if (inited) {\r
- String url = buildUrl(req);\r
- intlogger.info("ProxyServlet: proxying with fallback GET "+url);\r
- AbstractHttpClient httpclient = new DefaultHttpClient();\r
- HttpRequestBase proxy = new HttpGet(url);\r
- try {\r
- httpclient.getConnectionManager().getSchemeRegistry().register(sch);\r
-\r
- // Copy request headers and request body\r
- copyRequestHeaders(req, proxy);\r
-\r
- // Execute the request\r
- HttpResponse pxy_response = httpclient.execute(proxy);\r
-\r
- // Get response headers and body\r
- int code = pxy_response.getStatusLine().getStatusCode();\r
- resp.setStatus(code);\r
- copyResponseHeaders(pxy_response, resp);\r
-\r
- HttpEntity entity = pxy_response.getEntity();\r
- if (entity != null) {\r
- InputStream in = entity.getContent();\r
- IOUtils.copy(in, resp.getOutputStream());\r
- in.close();\r
- }\r
- rv = true;\r
- } catch (IOException e) {\r
- System.err.println("ProxyServlet: "+e);\r
- e.printStackTrace();\r
- } finally {\r
- proxy.releaseConnection();\r
- httpclient.getConnectionManager().shutdown();\r
- }\r
- } else {\r
- intlogger.warn("ProxyServlet: proxy disabled");\r
- }\r
- return rv;\r
- }\r
- private void doProxy(HttpServletRequest req, HttpServletResponse resp, final String method) throws IOException {\r
- if (inited && isProxyServer()) {\r
- String url = buildUrl(req);\r
- intlogger.info("ProxyServlet: proxying "+method + " "+url);\r
- AbstractHttpClient httpclient = new DefaultHttpClient();\r
- ProxyHttpRequest proxy = new ProxyHttpRequest(method, url);\r
- try {\r
- httpclient.getConnectionManager().getSchemeRegistry().register(sch);\r
-\r
- // Copy request headers and request body\r
- copyRequestHeaders(req, proxy);\r
- if (method.equals("POST") || method.equals("PUT")){\r
- BasicHttpEntity body = new BasicHttpEntity();\r
- body.setContent(req.getInputStream());\r
- body.setContentLength(-1); // -1 = unknown\r
- proxy.setEntity(body);\r
- }\r
-\r
- // Execute the request\r
- HttpResponse pxy_response = httpclient.execute(proxy);\r
-\r
- // Get response headers and body\r
- int code = pxy_response.getStatusLine().getStatusCode();\r
- resp.setStatus(code);\r
- copyResponseHeaders(pxy_response, resp);\r
-\r
- HttpEntity entity = pxy_response.getEntity();\r
- if (entity != null) {\r
- InputStream in = entity.getContent();\r
- IOUtils.copy(in, resp.getOutputStream());\r
- in.close();\r
- }\r
- } catch (IOException e) {\r
- intlogger.warn("ProxyServlet: "+e);\r
- resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);\r
- e.printStackTrace();\r
- } finally {\r
- proxy.releaseConnection();\r
- httpclient.getConnectionManager().shutdown();\r
- }\r
- } else {\r
- intlogger.warn("ProxyServlet: proxy disabled");\r
- resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);\r
- }\r
- }\r
- private String buildUrl(HttpServletRequest req) {\r
- StringBuilder sb = new StringBuilder("https://");\r
- sb.append(URLUtilities.getPeerPodName());\r
- sb.append(req.getRequestURI());\r
- String q = req.getQueryString();\r
- if (q != null)\r
- sb.append("?").append(q);\r
- return sb.toString();\r
- }\r
- private void copyRequestHeaders(HttpServletRequest from, HttpRequestBase to) {\r
- @SuppressWarnings("unchecked")\r
- List<String> list = Collections.list(from.getHeaderNames());\r
- for (String name : list) {\r
- // Proxy code will add this one\r
- if (!name.equalsIgnoreCase("Content-Length"))\r
- to.addHeader(name, from.getHeader(name));\r
- }\r
- }\r
- private void copyResponseHeaders(HttpResponse from, HttpServletResponse to) {\r
- for (Header hdr : from.getAllHeaders()) {\r
- // Don't copy Date: our Jetty will add another Date header\r
- if (!hdr.getName().equals("Date"))\r
- to.addHeader(hdr.getName(), hdr.getValue());\r
- }\r
- }\r
-\r
- public class ProxyHttpRequest extends HttpEntityEnclosingRequestBase {\r
- private final String method;\r
-\r
- public ProxyHttpRequest(final String method, final String uri) {\r
- super();\r
- this.method = method;\r
- setURI(URI.create(uri));\r
- }\r
- @Override\r
- public String getMethod() {\r
- return method;\r
- }\r
- }\r
-}\r
+/*******************************************************************************
+ * ============LICENSE_START==================================================
+ * * org.onap.dmaap
+ * * ===========================================================================
+ * * Copyright © 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+
+
+package org.onap.dmaap.datarouter.provisioning;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.IOUtils;
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.entity.BasicHttpEntity;
+import org.apache.http.impl.client.AbstractHttpClient;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.onap.dmaap.datarouter.provisioning.utils.DB;
+import org.onap.dmaap.datarouter.provisioning.utils.URLUtilities;
+
+/**
+ * This class is the base class for those servlets that need to proxy their requests from the standby to active server.
+ * Its methods perform the proxy function to the active server. If the active server is not reachable, a 503
+ * (SC_SERVICE_UNAVAILABLE) is returned. Only DELETE/GET/PUT/POST are supported.
+ *
+ * @author Robert Eby
+ * @version $Id: ProxyServlet.java,v 1.3 2014/03/24 18:47:10 eby Exp $
+ */
+@SuppressWarnings("serial")
+public class ProxyServlet extends BaseServlet {
+
+ private boolean inited = false;
+ private Scheme sch;
+
+ /**
+ * Initialize this servlet, by setting up SSL.
+ */
+ @SuppressWarnings("deprecation")
+ @Override
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ try {
+ // Set up keystore
+ Properties props = (new DB()).getProperties();
+ String type = props.getProperty(Main.KEYSTORE_TYPE_PROPERTY, "jks");
+ String store = props.getProperty(Main.KEYSTORE_PATH_PROPERTY);
+ String pass = props.getProperty(Main.KEYSTORE_PASSWORD_PROPERTY);
+ KeyStore keyStore = readStore(store, pass, type);
+
+ store = props.getProperty(Main.TRUSTSTORE_PATH_PROPERTY);
+ pass = props.getProperty(Main.TRUSTSTORE_PASSWORD_PROPERTY);
+ if (store == null || store.length() == 0) {
+ store = Main.DEFAULT_TRUSTSTORE;
+ pass = "changeit";
+ }
+ KeyStore trustStore = readStore(store, pass, KeyStore.getDefaultType());
+
+ // We are connecting with the node name, but the certificate will have the CNAME
+ // So we need to accept a non-matching certificate name
+ SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore,
+ props.getProperty(Main.KEYSTORE_PASSWORD_PROPERTY), trustStore);
+ socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+ sch = new Scheme("https", 443, socketFactory);
+ inited = true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ intlogger.info("ProxyServlet: inited = " + inited);
+ }
+
+ private KeyStore readStore(String store, String pass, String type) throws KeyStoreException {
+ KeyStore ks = KeyStore.getInstance(type);
+ try (FileInputStream instream = new FileInputStream(new File(store))) {
+ ks.load(instream, pass.toCharArray());
+ } catch (FileNotFoundException fileNotFoundException) {
+ intlogger.error("ProxyServlet: " + fileNotFoundException.getMessage());
+ } catch (Exception x) {
+ System.err.println("READING TRUSTSTORE: " + x);
+ }
+ return ks;
+ }
+
+ /**
+ * Return <i>true</i> if the requester has NOT set the <i>noproxy</i> CGI variable. If they have, this indicates
+ * they want to forcibly turn the proxy off.
+ *
+ * @param req the HTTP request
+ * @return true or false
+ */
+ protected boolean isProxyOK(final HttpServletRequest req) {
+ String t = req.getQueryString();
+ if (t != null) {
+ t = t.replaceAll("&", "&");
+ for (String s : t.split("&")) {
+ if (s.equals("noproxy") || s.startsWith("noproxy=")) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Is this the standby server? If it is, the proxy functions can be used. If not, the proxy functions should not be
+ * called, and will send a response of 500 (Internal Server Error).
+ *
+ * @return true if this server is the standby (and hence a proxy server).
+ */
+ public boolean isProxyServer() {
+ SynchronizerTask st = SynchronizerTask.getSynchronizer();
+ return st.getState() == SynchronizerTask.STANDBY;
+ }
+
+ /**
+ * Issue a proxy DELETE to the active provisioning server.
+ */
+ @Override
+ public void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ doProxy(req, resp, "DELETE");
+ }
+
+ /**
+ * Issue a proxy GET to the active provisioning server.
+ */
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ doProxy(req, resp, "GET");
+ }
+
+ /**
+ * Issue a proxy PUT to the active provisioning server.
+ */
+ @Override
+ public void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ doProxy(req, resp, "PUT");
+ }
+
+ /**
+ * Issue a proxy POST to the active provisioning server.
+ */
+ @Override
+ public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ doProxy(req, resp, "POST");
+ }
+
+ /**
+ * Issue a proxy GET to the active provisioning server. Unlike doGet() above, this method will allow the caller to
+ * fall back to other code if the remote server is unreachable.
+ *
+ * @return true if the proxy succeeded
+ */
+ public boolean doGetWithFallback(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ boolean rv = false;
+ if (inited) {
+ String url = buildUrl(req);
+ intlogger.info("ProxyServlet: proxying with fallback GET " + url);
+ try (AbstractHttpClient httpclient = new DefaultHttpClient()) {
+ HttpRequestBase proxy = new HttpGet(url);
+ try {
+ httpclient.getConnectionManager().getSchemeRegistry().register(sch);
+
+ // Copy request headers and request body
+ copyRequestHeaders(req, proxy);
+
+ // Execute the request
+ HttpResponse pxy_response = httpclient.execute(proxy);
+
+ // Get response headers and body
+ int code = pxy_response.getStatusLine().getStatusCode();
+ resp.setStatus(code);
+ copyResponseHeaders(pxy_response, resp);
+
+ HttpEntity entity = pxy_response.getEntity();
+ if (entity != null) {
+ InputStream in = entity.getContent();
+ IOUtils.copy(in, resp.getOutputStream());
+ in.close();
+ }
+ rv = true;
+
+ } catch (IOException e) {
+ System.err.println("ProxyServlet: " + e);
+ e.printStackTrace();
+ } finally {
+ proxy.releaseConnection();
+ httpclient.getConnectionManager().shutdown();
+ }
+ }
+ } else {
+ intlogger.warn("ProxyServlet: proxy disabled");
+ }
+ return rv;
+ }
+
+ private void doProxy(HttpServletRequest req, HttpServletResponse resp, final String method) throws IOException {
+ if (inited && isProxyServer()) {
+ String url = buildUrl(req);
+ intlogger.info("ProxyServlet: proxying " + method + " " + url);
+ try (AbstractHttpClient httpclient = new DefaultHttpClient()) {
+ ProxyHttpRequest proxy = new ProxyHttpRequest(method, url);
+ try {
+ httpclient.getConnectionManager().getSchemeRegistry().register(sch);
+
+ // Copy request headers and request body
+ copyRequestHeaders(req, proxy);
+ if (method.equals("POST") || method.equals("PUT")) {
+ BasicHttpEntity body = new BasicHttpEntity();
+ body.setContent(req.getInputStream());
+ body.setContentLength(-1); // -1 = unknown
+ proxy.setEntity(body);
+ }
+
+ // Execute the request
+ HttpResponse pxy_response = httpclient.execute(proxy);
+
+ // Get response headers and body
+ int code = pxy_response.getStatusLine().getStatusCode();
+ resp.setStatus(code);
+ copyResponseHeaders(pxy_response, resp);
+
+ HttpEntity entity = pxy_response.getEntity();
+ if (entity != null) {
+ InputStream in = entity.getContent();
+ IOUtils.copy(in, resp.getOutputStream());
+ in.close();
+ }
+ } catch (IOException e) {
+ intlogger.warn("ProxyServlet: " + e);
+ resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
+ e.printStackTrace();
+ } finally {
+ proxy.releaseConnection();
+ httpclient.getConnectionManager().shutdown();
+ }
+ }
+ } else {
+ intlogger.warn("ProxyServlet: proxy disabled");
+ resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ private String buildUrl(HttpServletRequest req) {
+ StringBuilder sb = new StringBuilder("https://");
+ sb.append(URLUtilities.getPeerPodName());
+ sb.append(req.getRequestURI());
+ String q = req.getQueryString();
+ if (q != null) {
+ sb.append("?").append(q);
+ }
+ return sb.toString();
+ }
+
+ private void copyRequestHeaders(HttpServletRequest from, HttpRequestBase to) {
+ @SuppressWarnings("unchecked")
+ List<String> list = Collections.list(from.getHeaderNames());
+ for (String name : list) {
+ // Proxy code will add this one
+ if (!name.equalsIgnoreCase("Content-Length")) {
+ to.addHeader(name, from.getHeader(name));
+ }
+ }
+ }
+
+ private void copyResponseHeaders(HttpResponse from, HttpServletResponse to) {
+ for (Header hdr : from.getAllHeaders()) {
+ // Don't copy Date: our Jetty will add another Date header
+ if (!hdr.getName().equals("Date")) {
+ to.addHeader(hdr.getName(), hdr.getValue());
+ }
+ }
+ }
+
+ public class ProxyHttpRequest extends HttpEntityEnclosingRequestBase {
+
+ private final String method;
+
+ public ProxyHttpRequest(final String method, final String uri) {
+ super();
+ this.method = method;
+ setURI(URI.create(uri));
+ }
+
+ @Override
+ public String getMethod() {
+ return method;
+ }
+ }
+}