Merge "Fix Feed Vulnerabilities"
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / SubscribeServlet.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.Collection;
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.beans.Subscription;
39 import org.onap.dmaap.datarouter.provisioning.eelf.EelfMsgs;
40 import org.onap.dmaap.datarouter.provisioning.utils.JSONUtilities;
41
42 import com.att.eelf.configuration.EELFLogger;
43 import com.att.eelf.configuration.EELFManager;
44
45 import static org.onap.dmaap.datarouter.provisioning.utils.HttpServletUtils.sendResponseError;
46
47 /**
48  * This servlet handles provisioning for the <subscribeURL> which is generated by the provisioning server to
49  * handle the creation and inspection of subscriptions to a specific feed.
50  *
51  * @author Robert Eby
52  * @version $Id$
53  */
54 @SuppressWarnings("serial")
55 public class SubscribeServlet extends ProxyServlet {
56
57     //Adding EELF Logger Rally:US664892
58     private static EELFLogger eelflogger = EELFManager.getInstance()
59         .getLogger("org.onap.dmaap.datarouter.provisioning.SubscribeServlet");
60
61     /**
62      * DELETE on the <subscribeUrl> -- not supported.
63      */
64     @Override
65     public void doDelete(HttpServletRequest req, HttpServletResponse resp) {
66         setIpAndFqdnForEelf("doDelete");
67         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_SUBID, req.getHeader(BEHALF_HEADER), getIdFromPath(req) + "");
68         String message = "DELETE not allowed for the subscribeURL.";
69         EventLogRecord elr = new EventLogRecord(req);
70         elr.setMessage(message);
71         elr.setResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
72         eventlogger.info(elr);
73         sendResponseError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED, message, eventlogger);
74     }
75
76     /**
77      * GET on the &lt;subscribeUrl&gt; -- get the list of subscriptions to a feed. See the <i>Subscription Collection
78      * Query</i> section in the <b>Provisioning API</b> document for details on how this method should be invoked.
79      */
80     @Override
81     public void doGet(HttpServletRequest req, HttpServletResponse resp) {
82         setIpAndFqdnForEelf("doGet");
83         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_SUBID, req.getHeader(BEHALF_HEADER), getIdFromPath(req) + "");
84         EventLogRecord elr = new EventLogRecord(req);
85         String message = isAuthorizedForProvisioning(req);
86         if (message != null) {
87             elr.setMessage(message);
88             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
89             eventlogger.info(elr);
90             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
91             return;
92         }
93         if (isProxyServer()) {
94             super.doGet(req, resp);
95             return;
96         }
97         String bhdr = req.getHeader(BEHALF_HEADER);
98         if (bhdr == null) {
99             message = "Missing " + BEHALF_HEADER + " header.";
100             elr.setMessage(message);
101             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
102             eventlogger.info(elr);
103             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
104             return;
105         }
106         int feedid = getIdFromPath(req);
107         if (feedid < 0) {
108             message = "Missing or bad feed number.";
109             elr.setMessage(message);
110             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
111             eventlogger.info(elr);
112             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
113             return;
114         }
115         Feed feed = Feed.getFeedById(feedid);
116         if (feed == null || feed.isDeleted()) {
117             message = "Missing or bad feed number.";
118             elr.setMessage(message);
119             elr.setResult(HttpServletResponse.SC_NOT_FOUND);
120             eventlogger.info(elr);
121             sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
122             return;
123         }
124         // Check with the Authorizer
125         AuthorizationResponse aresp = authz.decide(req);
126         if (!aresp.isAuthorized()) {
127             message = "Policy Engine disallows access.";
128             elr.setMessage(message);
129             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
130             eventlogger.info(elr);
131             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
132             return;
133         }
134
135         // Display a list of URLs
136         Collection<String> list = Subscription.getSubscriptionUrlList(feedid);
137         String t = JSONUtilities.createJSONArray(list);
138
139         // send response
140         elr.setResult(HttpServletResponse.SC_OK);
141         eventlogger.info(elr);
142         resp.setStatus(HttpServletResponse.SC_OK);
143         resp.setContentType(SUBLIST_CONTENT_TYPE);
144         try {
145             resp.getOutputStream().print(t);
146         } catch (IOException ioe) {
147             eventlogger.error("IOException: " + ioe.getMessage());
148         }
149     }
150
151     /**
152      * PUT on the &lt;subscribeUrl&gt; -- not supported.
153      */
154     @Override
155     public void doPut(HttpServletRequest req, HttpServletResponse resp) {
156         setIpAndFqdnForEelf("doPut");
157         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_SUBID, req.getHeader(BEHALF_HEADER), getIdFromPath(req) + "");
158         String message = "PUT not allowed for the subscribeURL.";
159         EventLogRecord elr = new EventLogRecord(req);
160         elr.setMessage(message);
161         elr.setResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
162         eventlogger.info(elr);
163         sendResponseError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED, message, eventlogger);
164     }
165
166     /**
167      * POST on the &lt;subscribeUrl&gt; -- create a new subscription to a feed. See the <i>Creating a Subscription</i>
168      * section in the <b>Provisioning API</b> document for details on how this method should be invoked.
169      */
170     @Override
171     public void doPost(HttpServletRequest req, HttpServletResponse resp) {
172         setIpAndFqdnForEelf("doPost");
173         eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF, req.getHeader(BEHALF_HEADER));
174         EventLogRecord elr = new EventLogRecord(req);
175         String message = isAuthorizedForProvisioning(req);
176         if (message != null) {
177             elr.setMessage(message);
178             elr.setResult(HttpServletResponse.SC_FORBIDDEN);
179             eventlogger.info(elr);
180             sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
181             return;
182         }
183         if (isProxyServer()) {
184             super.doPost(req, resp);
185             return;
186         }
187         String bhdr = req.getHeader(BEHALF_HEADER);
188         if (bhdr == null) {
189             message = "Missing " + BEHALF_HEADER + " header.";
190             elr.setMessage(message);
191             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
192             eventlogger.info(elr);
193             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
194             return;
195         }
196         int feedid = getIdFromPath(req);
197         if (feedid < 0) {
198             message = "Missing or bad feed number.";
199             elr.setMessage(message);
200             elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
201             eventlogger.info(elr);
202             sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
203             return;
204         }
205         Feed feed = Feed.getFeedById(feedid);
206         if (feed == null || feed.isDeleted()) {
207             message = "Missing or bad feed number.";
208             elr.setMessage(message);
209             elr.setResult(HttpServletResponse.SC_NOT_FOUND);
210             eventlogger.info(elr);
211             sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
212             return;
213         }
214         // Check with the Authorizer
215         AuthorizationResponse aresp = authz.decide(req);
216         if (!aresp.isAuthorized()) {
217             message = "Policy Engine disallows access.";
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
225         // check content type is SUB_CONTENT_TYPE, version 1.0
226         ContentHeader ch = getContentHeader(req);
227         String ver = ch.getAttribute("version");
228         if (!ch.getType().equals(SUB_BASECONTENT_TYPE) || !(ver.equals("1.0") || ver.equals("2.0"))) {
229             intlogger.debug("Content-type is: " + req.getHeader("Content-Type"));
230             message = "Incorrect content-type";
231             elr.setMessage(message);
232             elr.setResult(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
233             eventlogger.info(elr);
234             sendResponseError(resp, HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message, eventlogger);
235             return;
236         }
237         JSONObject jo = getJSONfromInput(req);
238         if (jo == null) {
239             message = "Badly formed JSON";
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         if (intlogger.isDebugEnabled()) {
247             intlogger.debug(jo.toString());
248         }
249         if (++activeSubs > maxSubs) {
250             activeSubs--;
251             message = "Cannot create subscription; the maximum number of subscriptions has been configured.";
252             elr.setMessage(message);
253             elr.setResult(HttpServletResponse.SC_CONFLICT);
254             eventlogger.info(elr);
255             sendResponseError(resp, HttpServletResponse.SC_CONFLICT, message, eventlogger);
256             return;
257         }
258         Subscription sub = null;
259         try {
260             sub = new Subscription(jo);
261         } catch (InvalidObjectException e) {
262             activeSubs--;
263             message = e.getMessage();
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         sub.setFeedid(feedid);
271         sub.setSubscriber(bhdr);    // set from X-ATT-DR-ON-BEHALF-OF header
272
273         // Check if this subscription already exists; not an error (yet), just warn
274         Subscription sub2 = Subscription.getSubscriptionMatching(sub);
275         if (sub2 != null) {
276             intlogger.warn(
277                 "PROV0011 Creating a duplicate subscription: new subid=" + sub.getSubid() + ", old subid=" + sub2
278                     .getSubid());
279         }
280
281         // Create SUBSCRIPTIONS table entries
282         if (doInsert(sub)) {
283             // send response
284             elr.setResult(HttpServletResponse.SC_CREATED);
285             eventlogger.info(elr);
286             resp.setStatus(HttpServletResponse.SC_CREATED);
287             resp.setContentType(SUBFULL_CONTENT_TYPE);
288             resp.setHeader("Location", sub.getLinks().getSelf());
289             try {
290                 resp.getOutputStream().print(sub.asLimitedJSONObject().toString());
291             } catch (IOException ioe) {
292                 eventlogger.error("IOException: " + ioe.getMessage());
293             }
294
295             provisioningDataChanged();
296         } else {
297             // Something went wrong with the INSERT
298             activeSubs--;
299             elr.setResult(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
300             eventlogger.info(elr);
301             sendResponseError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, DB_PROBLEM_MSG, eventlogger);
302         }
303     }
304 }