7c8a9a1d9b56fd05e6da04cec01b3dc75b5eba92
[ccsdk/features.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP : CCSDK.apps.sdnr.wt.apigateway
4  * ================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property.
6  * All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 package org.onap.ccsdk.features.sdnr.wt.apigateway;
22
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.net.HttpURLConnection;
27 import java.net.URL;
28 import java.net.URLConnection;
29 import java.nio.charset.StandardCharsets;
30 import java.security.KeyManagementException;
31 import java.security.NoSuchAlgorithmException;
32 import java.util.Enumeration;
33 import java.util.List;
34 import java.util.Map;
35 import javax.net.ssl.HostnameVerifier;
36 import javax.net.ssl.HttpsURLConnection;
37 import javax.net.ssl.SSLContext;
38 import javax.net.ssl.TrustManager;
39 import javax.servlet.ServletException;
40 import javax.servlet.http.HttpServlet;
41 import javax.servlet.http.HttpServletRequest;
42 import javax.servlet.http.HttpServletResponse;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 public abstract class BaseServlet extends HttpServlet {
47
48     private static final long serialVersionUID = 7403047480257892794L;
49     private static Logger LOG = LoggerFactory.getLogger(BaseServlet.class);
50     private static SSLContext sc;
51     private static TrustManager[] trustCerts = null;
52     private static final int BUFSIZE = 2048;
53
54     protected abstract String getOfflineResponse();
55
56     protected abstract boolean isOff();
57
58     protected abstract boolean doTrustAll();
59
60     protected abstract void trustAll(boolean trust);
61
62     protected abstract String getRemoteUrl(String uri);
63
64     private static void setupSslTrustAll(boolean trustall) throws NoSuchAlgorithmException, KeyManagementException {
65
66         sc = SSLContext.getInstance("TLSv1.2");
67         if (trustall) {
68             if (trustCerts == null) {
69                 trustCerts = new TrustManager[] {new javax.net.ssl.X509TrustManager() {
70                     @Override
71                     public java.security.cert.X509Certificate[] getAcceptedIssuers() {
72                         return new java.security.cert.X509Certificate[] {};
73                     }
74
75                     @Override
76                     public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
77                         // do not check anything when trust all
78                     }
79
80                     @Override
81                     public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
82                         // do not check anything when trust all
83                     }
84                 }};
85             }
86         } else {
87             if (trustCerts != null) {
88                 trustCerts = null;
89             }
90         }
91         // Init the SSLContext with a TrustManager[] and SecureRandom()
92         sc.init(null, trustCerts, new java.security.SecureRandom());
93     }
94
95     public BaseServlet() {
96         try {
97             MyProperties.Instantiate();
98         } catch (Exception e) {
99             LOG.error(e.getMessage());
100         }
101         this.trysslSetup(true);
102     }
103
104     private void trysslSetup() {
105         this.trysslSetup(false);
106     }
107
108     /**
109      * init or deinit ssl insecure mode regarding to property
110      *
111      * @param force init independent from property
112      */
113     private void trysslSetup(boolean force) {
114         // if trustall config has changed
115         boolean trustAll = MyProperties.getInstance().trustInsecure();
116         if (force || this.doTrustAll() != trustAll) {
117             this.trustAll(trustAll);
118             // resetup ssl config
119             try {
120                 setupSslTrustAll(trustAll);
121             } catch (Exception e) {
122                 LOG.error("problem setting up SSL: {}", e.getMessage());
123             }
124         }
125     }
126
127     protected void sendOffResponse(HttpServletResponse response) {
128         response.setStatus(200);// HTML/OK
129         response.setHeader("Content-Type", "text/html; charset=utf-8");
130         try {
131             response.getOutputStream().write(this.getOfflineResponse().getBytes(StandardCharsets.UTF_8));
132         } catch (IOException e) {
133             LOG.debug("problem writing offline response");
134         }
135
136     }
137
138     @Override
139     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
140         if (this.isOff()) {
141             this.sendOffResponse(resp);
142         } else {
143             this.trysslSetup();
144             HttpURLConnection http = null;
145             try {
146                 http = (HttpURLConnection) this.getConnection(req, "GET");
147             } catch (IOException e) {
148                 LOG.warn(e.getMessage());
149             }
150             if (http != null) {
151                 try {
152                     this.handleRequest(http, req, resp, "GET");
153                 } catch (IOException e) {
154                     LOG.warn(e.getMessage());
155                 }
156                 http.disconnect();
157             } else {
158                 this.set404Response(resp);
159             }
160         }
161     }
162
163     @Override
164     protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
165         if (this.isOff()) {
166             this.sendOffResponse(resp);
167         } else {
168             this.trysslSetup();
169             HttpURLConnection http = null;
170             try {
171                 http = (HttpURLConnection) this.getConnection(req, "PUT");
172             } catch (IOException e) {
173                 LOG.warn(e.getMessage());
174             }
175             if (http != null) {
176                 try {
177                     this.handleRequest(http, req, resp, "PUT");
178                 } catch (IOException e) {
179                     LOG.warn(e.getMessage());
180                 }
181                 http.disconnect();
182             } else {
183                 this.set404Response(resp);
184             }
185         }
186     }
187
188     @Override
189     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
190         if (this.isOff()) {
191             this.sendOffResponse(resp);
192         } else {
193             this.trysslSetup();
194             HttpURLConnection http = null;
195             try {
196                 http = (HttpURLConnection) this.getConnection(req, "POST");
197             } catch (IOException e) {
198                 LOG.warn(e.getMessage());
199             }
200             if (http != null) {
201                 try {
202                     this.handleRequest(http, req, resp, "POST");
203                 } catch (IOException e) {
204                     LOG.warn(e.getMessage());
205                 }
206                 http.disconnect();
207             } else {
208                 this.set404Response(resp);
209             }
210         }
211     }
212
213     @Override
214     protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
215         if (this.isOff()) {
216             this.sendOffResponse(resp);
217         } else {
218             this.trysslSetup();
219             HttpURLConnection http = null;
220             try {
221                 http = (HttpURLConnection) this.getConnection(req, "DELETE");
222             } catch (IOException e) {
223                 LOG.warn(e.getMessage());
224             }
225             if (http != null) {
226                 try {
227                     this.handleRequest(http, req, resp, "DELETE");
228                 } catch (IOException e) {
229                     LOG.warn(e.getMessage());
230                 }
231                 http.disconnect();
232             } else {
233                 this.set404Response(resp);
234             }
235         }
236     }
237
238     private void set404Response(HttpServletResponse resp) {
239         resp.setStatus(404);
240     }
241
242     private URLConnection getConnection(HttpServletRequest req, final String method) throws IOException {
243
244         LOG.debug("{} Request to {}", method, req.getRequestURL());
245         String surl = this.getRemoteUrl(req.getRequestURI());
246         if ("GET".equals(method)) {
247             Enumeration<?> params = req.getParameterNames();
248             if (params != null) {
249                 String param;
250                 if (params.hasMoreElements()) {
251                     param = (String) params.nextElement();
252                     surl += "?" + param + "=" + req.getParameter(param);
253                 }
254                 while (params.hasMoreElements()) {
255                     param = (String) params.nextElement();
256                     surl += "&" + param + "=" + req.getParameter(param);
257                 }
258             }
259         }
260         LOG.debug("RemoteURL: {}", surl);
261         if (surl == null) {
262             return null;
263         }
264         URL url = new URL(surl);
265         URLConnection http = url.openConnection();
266         ((HttpURLConnection) http).setRequestMethod(method);
267         if (url.toString().startsWith("https")) {
268             ((HttpsURLConnection) http).setSSLSocketFactory(sc.getSocketFactory());
269             if (this.doTrustAll()) {
270                 HostnameVerifier allHostsValid = (hostname, session) -> true;
271                 ((HttpsURLConnection) http).setHostnameVerifier(allHostsValid);
272             }
273         }
274         http.setDoOutput(true);
275         // copy request headers
276         String s = "";
277         Enumeration<?> headers = req.getHeaderNames();
278         while (headers.hasMoreElements()) {
279             String h = (String) headers.nextElement();
280             String v = req.getHeader(h);
281             if (h != null && h.equals("Host")) {
282                 v = url.getAuthority();
283             }
284             s += String.format("%s:%s;", h, v);
285             http.setRequestProperty(h, v);
286         }
287         LOG.debug("Request Headers: {}", s);
288         return http;
289     }
290
291     private void handleRequest(HttpURLConnection http, HttpServletRequest req, HttpServletResponse resp, String method)
292             throws IOException {
293         byte[] buffer = new byte[BUFSIZE];
294         int len = 0, lensum = 0;
295         // send request
296         // Send the message to destination
297         OutputStream output = null;
298         if (!method.equals("GET")) {
299             try {
300                 output = http.getOutputStream();
301             } catch (Exception e) {
302                 LOG.debug("problem reading output stream: {}", e.getMessage());
303             }
304         }
305         if (output != null) {
306             while (true) {
307                 len = req.getInputStream().read(buffer, 0, BUFSIZE);
308                 if (len <= 0) {
309                     break;
310                 }
311                 lensum += len;
312                 output.write(buffer, 0, len);
313             }
314         }
315         LOG.debug("written {} data out", lensum);
316         int responseCode = http.getResponseCode();
317         // Receive answer
318         InputStream response;
319         if (responseCode >= 200 && responseCode < 300) {
320             response = http.getInputStream();
321         } else {
322             response = http.getErrorStream();
323             if (response == null) {
324                 http.getInputStream();
325             }
326         }
327
328         LOG.debug("ResponseCode: {}", responseCode);
329         resp.setStatus(responseCode);
330         Map<String, List<String>> set = http.getHeaderFields();
331         String s = "";
332         if (set != null) {
333             for (Map.Entry<String, List<String>> entry : set.entrySet()) {
334                 if (entry.getKey() == null) {
335                     continue;
336                 }
337                 for (String v : entry.getValue()) {
338                     resp.setHeader(entry.getKey(), v);
339                     s += String.format("%s:%s;", entry.getKey(), v);
340                 }
341                 if (MyProperties.getInstance().corsEnabled()) {
342                     resp.setHeader("Access-Control-Allow-Origin", "*");
343                     // resp.setHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
344                     resp.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
345                 }
346
347             }
348         }
349         LOG.debug("Received Headers: {}", s);
350         lensum = 0;
351         if (response != null) {
352             while (true) {
353                 len = response.read(buffer, 0, BUFSIZE);
354                 if (len <= 0) {
355                     break;
356                 }
357                 lensum += len;
358                 resp.getOutputStream().write(buffer, 0, len);
359             }
360         } else {
361             LOG.debug("response is null");
362         }
363         LOG.debug("Received {} bytes", lensum);
364     }
365
366 }