Merge "Fix IngressRoute Vulnerabilities"
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / FeedServlet.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
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpServletResponse;
32
33 import org.json.JSONException;
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
40 import com.att.eelf.configuration.EELFLogger;
41 import com.att.eelf.configuration.EELFManager;
42
43 import static org.onap.dmaap.datarouter.provisioning.utils.HttpServletUtils.sendResponseError;
44
45 /**
46  * This servlet handles provisioning for the <feedURL> which is generated by the provisioning
47  * server to handle a particular feed. It supports DELETE to mark the feed as deleted,
48  * and GET to retrieve information about the feed, and PUT to modify the feed.
49  *
50  * @author Robert Eby
51  * @version $Id$
52  */
53 @SuppressWarnings("serial")
54 public class FeedServlet extends ProxyServlet {
55
56     //Adding EELF Logger Rally:US664892
57     private static EELFLogger eelflogger = EELFManager.getInstance().getLogger("org.onap.dmaap.datarouter.provisioning.FeedServlet");
58
59     /**
60      * Delete the Feed at the address /feed/<feednumber>.
61      * See the <i>Deleting a Feed</i> section in the <b>Provisioning API</b>
62      * document for details on how this method should be invoked.
63      */
64     @Override
65     public void doDelete(HttpServletRequest req, HttpServletResponse resp) {
66         setIpAndFqdnForEelf("doDelete");
67         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_FEEDID, req.getHeader(BEHALF_HEADER),getIdFromPath(req)+"");
68         EventLogRecord elr = new EventLogRecord(req);
69         String message = isAuthorizedForProvisioning(req);
70         if (message != null) {
71             elr.setMessage(message);
72             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
73             eventlogger.info(elr);
74             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
75             return;
76         }
77         if (isProxyServer()) {
78             super.doDelete(req, resp);
79             return;
80         }
81         String bhdr = req.getHeader(BEHALF_HEADER);
82         if (bhdr == null) {
83             message = "Missing "+BEHALF_HEADER+" header.";
84             elr.setMessage(message);
85             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
86             eventlogger.info(elr);
87             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
88             return;
89         }
90         int feedid = getIdFromPath(req);
91         if (feedid < 0) {
92             message = "Missing or bad feed number.";
93             elr.setMessage(message);
94             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
95             eventlogger.info(elr);
96             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
97             return;
98         }
99         Feed feed = Feed.getFeedById(feedid);
100         if (feed == null || feed.isDeleted()) {
101             message = "Missing or bad feed number.";
102             elr.setMessage(message);
103             elr.setResult(HttpServletResponse.SC_NOT_FOUND);
104             eventlogger.info(elr);
105             sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
106             return;
107         }
108         // Check with the Authorizer
109         AuthorizationResponse aresp = authz.decide(req);
110         if (! aresp.isAuthorized()) {
111             message = "Policy Engine disallows access.";
112             elr.setMessage(message);
113             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
114             eventlogger.info(elr);
115             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
116             return;
117         }
118
119         // Delete FEED table entry (set DELETED flag)
120         feed.setDeleted(true);
121         if (doUpdate(feed)) {
122             activeFeeds--;
123             // send response
124             elr.setResult(HttpServletResponse.SC_NO_CONTENT);
125             eventlogger.info(elr);
126             resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
127             provisioningDataChanged();
128         } else {
129             // Something went wrong with the UPDATE
130             elr.setResult(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
131             eventlogger.info(elr);
132             sendResponseError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, DB_PROBLEM_MSG, eventlogger);
133         }
134     }
135     /**
136      * Get information on the feed at the address /feed/&lt;feednumber&gt;.
137      * See the <i>Retrieving Information about a Feed</i> section in the <b>Provisioning API</b>
138      * document for details on how this method should be invoked.
139      */
140     @Override
141     public void doGet(HttpServletRequest req, HttpServletResponse resp) {
142         setIpAndFqdnForEelf("doGet");
143         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_FEEDID, req.getHeader(BEHALF_HEADER),getIdFromPath(req)+"");
144         EventLogRecord elr = new EventLogRecord(req);
145         String message = isAuthorizedForProvisioning(req);
146         if (message != null) {
147             elr.setMessage(message);
148             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
149             eventlogger.info(elr);
150             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
151             return;
152         }
153         if (isProxyServer()) {
154             super.doGet(req, resp);
155             return;
156         }
157         String bhdr = req.getHeader(BEHALF_HEADER);
158         if (bhdr == null) {
159             message = "Missing "+BEHALF_HEADER+" header.";
160             elr.setMessage(message);
161             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
162             eventlogger.info(elr);
163             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
164             return;
165         }
166         int feedid = getIdFromPath(req);
167         if (feedid < 0) {
168             message = "Missing or bad feed number.";
169             elr.setMessage(message);
170             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
171             eventlogger.info(elr);
172             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
173             return;
174         }
175         Feed feed = Feed.getFeedById(feedid);
176         if (feed == null || feed.isDeleted()) {
177             message = "Missing or bad feed number.";
178             elr.setMessage(message);
179             elr.setResult(HttpServletResponse.SC_NOT_FOUND);
180             eventlogger.info(elr);
181             sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
182             return;
183         }
184         // Check with the Authorizer
185         AuthorizationResponse aresp = authz.decide(req);
186         if (! aresp.isAuthorized()) {
187             message = "Policy Engine disallows access.";
188             elr.setMessage(message);
189             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
190             eventlogger.info(elr);
191             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
192             return;
193         }
194
195         // send response
196         elr.setResult(HttpServletResponse.SC_OK);
197         eventlogger.info(elr);
198         resp.setStatus(HttpServletResponse.SC_OK);
199         resp.setContentType(FEEDFULL_CONTENT_TYPE);
200         try {
201             resp.getOutputStream().print(feed.asJSONObject(true).toString());
202         } catch (IOException ioe) {
203             eventlogger.error("IOException" + ioe.getMessage());
204         }
205     }
206     /**
207      * PUT on the &lt;feedURL&gt; for a feed.
208      * See the <i>Modifying a Feed</i> section in the <b>Provisioning API</b>
209      * document for details on how this method should be invoked.
210      */
211     @Override
212     public void doPut(HttpServletRequest req, HttpServletResponse resp) {
213         setIpAndFqdnForEelf("doPut");
214         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_FEEDID, req.getHeader(BEHALF_HEADER),getIdFromPath(req)+"");
215         EventLogRecord elr = new EventLogRecord(req);
216         String message = isAuthorizedForProvisioning(req);
217         if (message != null) {
218             elr.setMessage(message);
219             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
220             eventlogger.info(elr);
221             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
222             return;
223         }
224         if (isProxyServer()) {
225             super.doPut(req, resp);
226             return;
227         }
228         String bhdr = req.getHeader(BEHALF_HEADER);
229         if (bhdr == null) {
230             message = "Missing "+BEHALF_HEADER+" header.";
231             elr.setMessage(message);
232             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
233             eventlogger.info(elr);
234             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
235             return;
236         }
237         int feedid = getIdFromPath(req);
238         if (feedid < 0) {
239             message = "Missing or bad feed number.";
240             elr.setMessage(message);
241             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
242             eventlogger.info(elr);
243             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
244             return;
245         }
246         Feed oldFeed = Feed.getFeedById(feedid);
247         if (oldFeed == null || oldFeed.isDeleted()) {
248             message = "Missing or bad feed number.";
249             elr.setMessage(message);
250             elr.setResult(HttpServletResponse.SC_NOT_FOUND);
251             eventlogger.info(elr);
252             sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
253             return;
254         }
255         // check content type is FEED_CONTENT_TYPE, version 1.0
256         ContentHeader ch = getContentHeader(req);
257         String ver = ch.getAttribute("version");
258         if (!ch.getType().equals(FEED_BASECONTENT_TYPE) || !(ver.equals("1.0") || ver.equals("2.0"))) {
259             message = "Incorrect content-type";
260             elr.setMessage(message);
261             elr.setResult(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
262             eventlogger.info(elr);
263             sendResponseError(resp, HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message, eventlogger);
264             return;
265         }
266         JSONObject jo = getJSONfromInput(req);
267         if (jo == null) {
268             message = "Badly formed JSON";
269             elr.setMessage(message);
270             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
271             eventlogger.info(elr);
272             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
273             return;
274         }
275         if (intlogger.isDebugEnabled())
276             intlogger.debug(jo.toString());
277         Feed feed = null;
278         try {
279             feed = new Feed(jo);
280         } catch (InvalidObjectException e) {
281             message = e.getMessage();
282             elr.setMessage(message);
283             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
284             eventlogger.info(elr);
285             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
286             return;
287         }
288         feed.setFeedid(feedid);
289         feed.setPublisher(bhdr);    // set from X-ATT-DR-ON-BEHALF-OF header
290
291         String subjectgroup = (req.getHeader("X-ATT-DR-ON-BEHALF-OF-GROUP"));  //Adding for group feature:Rally US708115
292         if (!oldFeed.getPublisher().equals(feed.getPublisher()) && subjectgroup == null) {
293             message = "This feed must be modified by the same publisher that created it.";
294             elr.setMessage(message);
295             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
296             eventlogger.info(elr);
297             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
298             return;
299         }
300         if (!oldFeed.getName().equals(feed.getName())) {
301             message = "The name of the feed may not be updated.";
302             elr.setMessage(message);
303             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
304             eventlogger.info(elr);
305             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
306             return;
307         }
308         if (!oldFeed.getVersion().equals(feed.getVersion())) {
309             message = "The version of the feed may not be updated.";
310             elr.setMessage(message);
311             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
312             eventlogger.info(elr);
313             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
314             return;
315         }
316         // Check with the Authorizer
317         AuthorizationResponse aresp = authz.decide(req);
318         if (! aresp.isAuthorized()) {
319             message = "Policy Engine disallows access.";
320             elr.setMessage(message);
321             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
322             eventlogger.info(elr);
323             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
324             return;
325         }
326
327         // Update FEEDS table entries
328         if (doUpdate(feed)) {
329             // send response
330             elr.setResult(HttpServletResponse.SC_OK);
331             eventlogger.info(elr);
332             resp.setStatus(HttpServletResponse.SC_OK);
333             resp.setContentType(FEEDFULL_CONTENT_TYPE);
334             try {
335                 resp.getOutputStream().print(feed.asLimitedJSONObject().toString());
336             } catch (IOException ioe) {
337                 eventlogger.error("IOException" + ioe.getMessage());
338             }
339
340
341             /**Change Owner ship of Feed //Adding for group feature:Rally US708115*/
342             if (jo.has("changeowner") && subjectgroup != null) {
343                 try {
344                     Boolean changeowner = (Boolean) jo.get("changeowner");
345                     if (changeowner != null && changeowner.equals(true)) {
346                         feed.setPublisher(req.getHeader(BEHALF_HEADER));
347                         feed.changeOwnerShip();
348                     }
349                 } catch (JSONException je) {
350                     eventlogger.error("JSONException" + je.getMessage());
351                 }
352             }
353             /***End of change ownership*/
354
355             provisioningDataChanged();
356         } else {
357             // Something went wrong with the UPDATE
358             elr.setResult(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
359             eventlogger.info(elr);
360             sendResponseError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, DB_PROBLEM_MSG, eventlogger);
361         }
362     }
363     /**
364      * POST on the &lt;feedURL&gt; -- not supported.
365      */
366     @Override
367     public void doPost(HttpServletRequest req, HttpServletResponse resp) {
368         setIpAndFqdnForEelf("doPost");
369         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF, req.getHeader(BEHALF_HEADER));
370         String message = "POST not allowed for the feedURL.";
371         EventLogRecord elr = new EventLogRecord(req);
372         elr.setMessage(message);
373         elr.setResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
374         eventlogger.info(elr);
375         sendResponseError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED, message, eventlogger);
376     }
377 }