Merge "Fix Vulnerabilities in BaseServlet"
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / DRFeedsServlet.java
1 /*******************************************************************************
2  * ============LICENSE_START==================================================
3  * * org.onap.dmaap
4  * * ===========================================================================
5  * * Copyright © 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  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  * *
22  ******************************************************************************/
23
24
25 package org.onap.dmaap.datarouter.provisioning;
26
27 import java.io.IOException;
28 import java.io.InvalidObjectException;
29 import java.util.List;
30
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpServletResponse;
33
34 import org.json.JSONObject;
35 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
36 import org.onap.dmaap.datarouter.provisioning.beans.EventLogRecord;
37 import org.onap.dmaap.datarouter.provisioning.beans.Feed;
38 import org.onap.dmaap.datarouter.provisioning.eelf.EelfMsgs;
39 import org.onap.dmaap.datarouter.provisioning.utils.JSONUtilities;
40
41 import com.att.eelf.configuration.EELFLogger;
42 import com.att.eelf.configuration.EELFManager;
43
44 import static org.onap.dmaap.datarouter.provisioning.utils.HttpServletUtils.sendResponseError;
45
46 /**
47  * This servlet handles provisioning for the <drFeedsURL> which is the URL on the provisioning server used to
48  * create new feeds.  It supports POST to create new feeds, and GET to support the Feeds Collection Query function.
49  *
50  * @author Robert Eby
51  * @version $Id$
52  */
53 @SuppressWarnings("serial")
54 public class DRFeedsServlet extends ProxyServlet {
55
56     //Adding EELF Logger Rally:US664892
57     private static EELFLogger eelflogger = EELFManager.getInstance()
58         .getLogger("org.onap.dmaap.datarouter.provisioning.DRFeedsServlet");
59
60     /**
61      * DELETE on the <drFeedsURL> -- not supported.
62      */
63     @Override
64     public void doDelete(HttpServletRequest req, HttpServletResponse resp) {
65         setIpAndFqdnForEelf("doDelete");
66         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_FEEDID, req.getHeader(BEHALF_HEADER), getIdFromPath(req) + "");
67         String message = "DELETE not allowed for the drFeedsURL.";
68         EventLogRecord elr = new EventLogRecord(req);
69         elr.setMessage(message);
70         elr.setResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
71         eventlogger.info(elr);
72         sendResponseError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED, message, eventlogger);
73     }
74
75     /**
76      * GET on the &lt;drFeedsURL&gt; -- query the list of feeds already existing in the DB. See the <i>Feeds Collection
77      * Queries</i> section in the <b>Provisioning API</b> document for details on how this method should be invoked.
78      */
79     @Override
80     public void doGet(HttpServletRequest req, HttpServletResponse resp) {
81         setIpAndFqdnForEelf("doGet");
82         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_FEEDID, req.getHeader(BEHALF_HEADER), getIdFromPath(req) + "");
83         EventLogRecord elr = new EventLogRecord(req);
84         String message = isAuthorizedForProvisioning(req);
85         if (message != null) {
86             elr.setMessage(message);
87             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
88             eventlogger.info(elr);
89             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
90             return;
91         }
92         if (isProxyServer()) {
93             try {
94                 super.doGet(req, resp);
95             } catch (IOException ioe) {
96                 eventlogger.error("IOException" + ioe.getMessage());
97             }
98             return;
99         }
100         String bhdr = req.getHeader(BEHALF_HEADER);
101         if (bhdr == null) {
102             message = "Missing " + BEHALF_HEADER + " header.";
103             elr.setMessage(message);
104             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
105             eventlogger.info(elr);
106             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
107             return;
108         }
109         String path = req
110             .getRequestURI(); // Note: I think this should be getPathInfo(), but that doesn't work (Jetty bug?)
111         if (path != null && !path.equals("/")) {
112             message = "Bad URL.";
113             elr.setMessage(message);
114             elr.setResult(HttpServletResponse.SC_NOT_FOUND);
115             eventlogger.info(elr);
116             sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
117             return;
118         }
119         // Check with the Authorizer
120         AuthorizationResponse aresp = authz.decide(req);
121         if (!aresp.isAuthorized()) {
122             message = "Policy Engine disallows access.";
123             elr.setMessage(message);
124             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
125             eventlogger.info(elr);
126             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
127             return;
128         }
129
130         String name = req.getParameter("name");
131         String vers = req.getParameter("version");
132         String publ = req.getParameter("publisher");
133         String subs = req.getParameter("subscriber");
134         if (name != null && vers != null) {
135             // Display a specific feed
136             Feed feed = Feed.getFeedByNameVersion(name, vers);
137             if (feed == null || feed.isDeleted()) {
138                 message = "This feed does not exist in the database.";
139                 elr.setMessage(message);
140                 elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
141                 eventlogger.info(elr);
142                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
143             } else {
144                 // send response
145                 elr.setResult(HttpServletResponse.SC_OK);
146                 eventlogger.info(elr);
147                 resp.setStatus(HttpServletResponse.SC_OK);
148                 resp.setContentType(FEEDFULL_CONTENT_TYPE);
149                 try {
150                     resp.getOutputStream().print(feed.asJSONObject(true).toString());
151                 } catch (IOException ioe) {
152                     eventlogger.error("IOException" + ioe.getMessage());
153                 }
154             }
155         } else {
156             // Display a list of URLs
157             List<String> list = null;
158             if (name != null) {
159                 list = Feed.getFilteredFeedUrlList("name", name);
160             } else if (publ != null) {
161                 list = Feed.getFilteredFeedUrlList("publ", publ);
162             } else if (subs != null) {
163                 list = Feed.getFilteredFeedUrlList("subs", subs);
164             } else {
165                 list = Feed.getFilteredFeedUrlList("all", null);
166             }
167             String t = JSONUtilities.createJSONArray(list);
168             // send response
169             elr.setResult(HttpServletResponse.SC_OK);
170             eventlogger.info(elr);
171             resp.setStatus(HttpServletResponse.SC_OK);
172             resp.setContentType(FEEDLIST_CONTENT_TYPE);
173             try {
174                 resp.getOutputStream().print(t);
175             } catch (IOException ioe) {
176                 eventlogger.error("IOException" + ioe.getMessage());
177             }
178         }
179     }
180
181     /**
182      * PUT on the &lt;drFeedsURL&gt; -- not supported.
183      */
184     @Override
185     public void doPut(HttpServletRequest req, HttpServletResponse resp) {
186         setIpAndFqdnForEelf("doPut");
187         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_FEEDID, req.getHeader(BEHALF_HEADER), getIdFromPath(req) + "");
188         String message = "PUT not allowed for the drFeedsURL.";
189         EventLogRecord elr = new EventLogRecord(req);
190         elr.setMessage(message);
191         elr.setResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
192         eventlogger.info(elr);
193         sendResponseError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED, message, eventlogger);
194     }
195
196     /**
197      * POST on the &lt;drFeedsURL&gt; -- create a new feed. See the <i>Creating a Feed</i> section in the
198      * <b>Provisioning API</b> document for details on how this method should be invoked.
199      */
200     @Override
201     public void doPost(HttpServletRequest req, HttpServletResponse resp) {
202         setIpAndFqdnForEelf("doPost");
203         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF, req.getHeader(BEHALF_HEADER));
204         EventLogRecord elr = new EventLogRecord(req);
205         String message = isAuthorizedForProvisioning(req);
206         if (message != null) {
207             elr.setMessage(message);
208             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
209             eventlogger.info(elr);
210             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
211             return;
212         }
213         if (isProxyServer()) {
214             try {
215                 super.doPost(req, resp);
216             } catch (IOException ioe) {
217                 eventlogger.error("IOException" + ioe.getMessage());
218             }
219             return;
220         }
221         String bhdr = req.getHeader(BEHALF_HEADER);
222         if (bhdr == null) {
223             message = "Missing " + BEHALF_HEADER + " header.";
224             elr.setMessage(message);
225             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
226             eventlogger.info(elr);
227             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
228             return;
229         }
230         String path = req
231             .getRequestURI(); // Note: I think this should be getPathInfo(), but that doesn't work (Jetty bug?)
232         if (path != null && !path.equals("/")) {
233             message = "Bad URL.";
234             elr.setMessage(message);
235             elr.setResult(HttpServletResponse.SC_NOT_FOUND);
236             eventlogger.info(elr);
237             sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
238             return;
239         }
240         // check content type is FEED_CONTENT_TYPE, version 1.0
241         ContentHeader ch = getContentHeader(req);
242         String ver = ch.getAttribute("version");
243         if (!ch.getType().equals(FEED_BASECONTENT_TYPE) || !(ver.equals("1.0") || ver.equals("2.0"))) {
244             message = "Incorrect content-type";
245             elr.setMessage(message);
246             elr.setResult(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
247             eventlogger.info(elr);
248             sendResponseError(resp, HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message, eventlogger);
249             return;
250         }
251         // Check with the Authorizer
252         AuthorizationResponse aresp = authz.decide(req);
253         if (!aresp.isAuthorized()) {
254             message = "Policy Engine disallows access.";
255             elr.setMessage(message);
256             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
257             eventlogger.info(elr);
258             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
259             return;
260         }
261         JSONObject jo = getJSONfromInput(req);
262         if (jo == null) {
263             message = "Badly formed JSON";
264             elr.setMessage(message);
265             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
266             eventlogger.info(elr);
267             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
268             return;
269         }
270         if (intlogger.isDebugEnabled()) {
271             intlogger.debug(jo.toString());
272         }
273         if (++activeFeeds > maxFeeds) {
274             activeFeeds--;
275             message = "Cannot create feed; the maximum number of feeds has been configured.";
276             elr.setMessage(message);
277             elr.setResult(HttpServletResponse.SC_CONFLICT);
278             eventlogger.info(elr);
279             sendResponseError(resp, HttpServletResponse.SC_CONFLICT, message, eventlogger);
280             return;
281         }
282         Feed feed = null;
283         try {
284             feed = new Feed(jo);
285         } catch (InvalidObjectException e) {
286             message = e.getMessage();
287             elr.setMessage(message);
288             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
289             eventlogger.info(elr);
290             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
291             return;
292         }
293         feed.setPublisher(bhdr);    // set from X-ATT-DR-ON-BEHALF-OF header
294
295         // Check if this feed already exists
296         Feed feed2 = Feed.getFeedByNameVersion(feed.getName(), feed.getVersion());
297         if (feed2 != null) {
298             message = "This feed already exists in the database.";
299             elr.setMessage(message);
300             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
301             eventlogger.info(elr);
302             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
303             return;
304         }
305
306         // Create FEED table entries
307         if (doInsert(feed)) {
308             // send response
309             elr.setResult(HttpServletResponse.SC_CREATED);
310             eventlogger.info(elr);
311             resp.setStatus(HttpServletResponse.SC_CREATED);
312             resp.setContentType(FEEDFULL_CONTENT_TYPE);
313             resp.setHeader("Location", feed.getLinks().getSelf());
314             try {
315                 resp.getOutputStream().print(feed.asLimitedJSONObject().toString());
316             } catch (IOException ioe) {
317                 eventlogger.error("IOException" + ioe.getMessage());
318             }
319             provisioningDataChanged();
320         } else {
321             // Something went wrong with the INSERT
322             elr.setResult(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
323             eventlogger.info(elr);
324             sendResponseError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, DB_PROBLEM_MSG, eventlogger);
325         }
326     }
327 }