21b838deada26760c97e1f4ebc2bbc67c4b6d02a
[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 static org.onap.dmaap.datarouter.provisioning.utils.HttpServletUtils.sendResponseError;
28
29 import com.att.eelf.configuration.EELFLogger;
30 import com.att.eelf.configuration.EELFManager;
31 import java.io.IOException;
32 import java.io.InvalidObjectException;
33 import java.util.Collection;
34 import javax.servlet.http.HttpServletRequest;
35 import javax.servlet.http.HttpServletResponse;
36 import org.json.JSONObject;
37
38 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
39 import org.onap.dmaap.datarouter.provisioning.beans.EventLogRecord;
40 import org.onap.dmaap.datarouter.provisioning.beans.Feed;
41 import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
42 import org.onap.dmaap.datarouter.provisioning.eelf.EelfMsgs;
43 import org.onap.dmaap.datarouter.provisioning.utils.JSONUtilities;
44
45
46 /**
47  * This servlet handles provisioning for the <subscribeURL> which is generated by the provisioning server to
48  * handle the creation and inspection of subscriptions to a specific feed.
49  *
50  * @author Robert Eby
51  * @version $Id$
52  */
53 @SuppressWarnings("serial")
54
55 public class SubscribeServlet extends ProxyServlet {
56
57     //Adding EELF Logger Rally:US664892
58     private static EELFLogger eelfLogger = EELFManager.getInstance()
59         .getLogger(SubscribeServlet.class);
60
61     /**
62      * DELETE on the <subscribeUrl> -- not supported.
63      */
64     @Override
65     public void doDelete(HttpServletRequest req, HttpServletResponse resp) {
66         setIpFqdnRequestIDandInvocationIDForEelf("doDelete", req);
67         eelfLogger.info(EelfMsgs.ENTRY);
68         try {
69             eelfLogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_SUBID,
70                     req.getHeader(BEHALF_HEADER), getIdFromPath(req) + "");
71             String message = "DELETE not allowed for the subscribeURL.";
72             EventLogRecord elr = new EventLogRecord(req);
73             elr.setMessage(message);
74             elr.setResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
75             eventlogger.error(elr.toString());
76             sendResponseError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED, message, eventlogger);
77         } finally {
78             eelfLogger.info(EelfMsgs.EXIT);
79         }
80     }
81
82     /**
83      * GET on the &lt;subscribeUrl&gt; -- get the list of subscriptions to a feed. See the <i>Subscription Collection
84      * Query</i> section in the <b>Provisioning API</b> document for details on how this method should be invoked.
85      */
86     @Override
87     public void doGet(HttpServletRequest req, HttpServletResponse resp) {
88         setIpFqdnRequestIDandInvocationIDForEelf("doGet", req);
89         eelfLogger.info(EelfMsgs.ENTRY);
90         try {
91             eelfLogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_SUBID,
92                     req.getHeader(BEHALF_HEADER), getIdFromPath(req) + "");
93             EventLogRecord elr = new EventLogRecord(req);
94             String message = isAuthorizedForProvisioning(req);
95             if (message != null) {
96                 elr.setMessage(message);
97                 elr.setResult(HttpServletResponse.SC_FORBIDDEN);
98                 eventlogger.error(elr.toString());
99                 sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
100                 return;
101             }
102             if (isProxyServer()) {
103                 super.doGet(req, resp);
104                 return;
105             }
106             String bhdr = req.getHeader(BEHALF_HEADER);
107             if (bhdr == null) {
108                 message = "Missing " + BEHALF_HEADER + " header.";
109                 elr.setMessage(message);
110                 elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
111                 eventlogger.error(elr.toString());
112                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
113                 return;
114             }
115             int feedid = getIdFromPath(req);
116             if (feedid < 0) {
117                 message = MISSING_FEED;
118                 elr.setMessage(message);
119                 elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
120                 eventlogger.error(elr.toString());
121                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
122                 return;
123             }
124             Feed feed = Feed.getFeedById(feedid);
125             if (feed == null || feed.isDeleted()) {
126                 message = MISSING_FEED;
127                 elr.setMessage(message);
128                 elr.setResult(HttpServletResponse.SC_NOT_FOUND);
129                 eventlogger.error(elr.toString());
130                 sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
131                 return;
132             }
133             // Display a list of URLs
134             Collection<String> list = Subscription.getSubscriptionUrlList(feedid);
135             String strList = JSONUtilities.createJSONArray(list);
136
137             // send response
138             elr.setResult(HttpServletResponse.SC_OK);
139             eventlogger.info(elr.toString());
140             resp.setStatus(HttpServletResponse.SC_OK);
141             resp.setContentType(SUBLIST_CONTENT_TYPE);
142             try {
143                 resp.getOutputStream().print(strList);
144             } catch (IOException ioe) {
145                 eventlogger.error("PROV0181 SubscribeServlet.doGet: " + ioe.getMessage(), ioe);
146             }
147         } finally {
148             eelfLogger.info(EelfMsgs.EXIT);
149         }
150     }
151
152     /**
153      * PUT on the &lt;subscribeUrl&gt; -- not supported.
154      */
155     @Override
156     public void doPut(HttpServletRequest req, HttpServletResponse resp) {
157         setIpFqdnRequestIDandInvocationIDForEelf("doPut", req);
158         eelfLogger.info(EelfMsgs.ENTRY);
159         try {
160             eelfLogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_SUBID,
161                     req.getHeader(BEHALF_HEADER), getIdFromPath(req) + "");
162             String message = "PUT not allowed for the subscribeURL.";
163             EventLogRecord elr = new EventLogRecord(req);
164             elr.setMessage(message);
165             elr.setResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
166             eventlogger.error(elr.toString());
167             sendResponseError(resp, HttpServletResponse.SC_METHOD_NOT_ALLOWED, message, eventlogger);
168         } finally {
169             eelfLogger.info(EelfMsgs.EXIT);
170         }
171     }
172
173     /**
174      * POST on the &lt;subscribeUrl&gt; -- create a new subscription to a feed. See the <i>Creating a Subscription</i>
175      * section in the <b>Provisioning API</b> document for details on how this method should be invoked.
176      */
177     @Override
178     public void doPost(HttpServletRequest req, HttpServletResponse resp) {
179         setIpFqdnRequestIDandInvocationIDForEelf("doPost", req);
180         eelfLogger.info(EelfMsgs.ENTRY);
181         try {
182             eelfLogger.info(EelfMsgs.MESSAGE_WITH_BEHALF, req.getHeader(BEHALF_HEADER));
183             EventLogRecord elr = new EventLogRecord(req);
184             String message = isAuthorizedForProvisioning(req);
185             if (message != null) {
186                 elr.setMessage(message);
187                 elr.setResult(HttpServletResponse.SC_FORBIDDEN);
188                 eventlogger.error(elr.toString());
189                 sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
190                 return;
191             }
192             if (isProxyServer()) {
193                 super.doPost(req, resp);
194                 return;
195             }
196             String bhdr = req.getHeader(BEHALF_HEADER);
197             if (bhdr == null) {
198                 message = "Missing " + BEHALF_HEADER + " header.";
199                 elr.setMessage(message);
200                 elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
201                 eventlogger.error(elr.toString());
202                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
203                 return;
204             }
205             int feedid = getIdFromPath(req);
206             if (feedid < 0) {
207                 message = MISSING_FEED;
208                 elr.setMessage(message);
209                 elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
210                 eventlogger.error(elr.toString());
211                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
212                 return;
213             }
214             Feed feed = Feed.getFeedById(feedid);
215             if (feed == null || feed.isDeleted()) {
216                 message = MISSING_FEED;
217                 elr.setMessage(message);
218                 elr.setResult(HttpServletResponse.SC_NOT_FOUND);
219                 eventlogger.error(elr.toString());
220                 sendResponseError(resp, HttpServletResponse.SC_NOT_FOUND, message, eventlogger);
221                 return;
222             }
223             // check content type is SUB_CONTENT_TYPE, version 1.0
224             ContentHeader ch = getContentHeader(req);
225             String ver = ch.getAttribute("version");
226             if (!ch.getType().equals(SUB_BASECONTENT_TYPE) || !("1.0".equals(ver) || "2.0".equals(ver))) {
227                 intlogger.debug("Content-type is: " + req.getHeader("Content-Type"));
228                 message = "Incorrect content-type";
229                 elr.setMessage(message);
230                 elr.setResult(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
231                 eventlogger.error(elr.toString());
232                 sendResponseError(resp, HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message, eventlogger);
233                 return;
234             }
235             JSONObject jo = getJSONfromInput(req);
236             if (jo == null) {
237                 message = BAD_JSON;
238                 elr.setMessage(message);
239                 elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
240                 eventlogger.error(elr.toString());
241                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
242                 return;
243             }
244             if (intlogger.isDebugEnabled()) {
245                 intlogger.debug(jo.toString());
246             }
247             if (++activeSubs > maxSubs) {
248                 activeSubs--;
249                 message = "Cannot create subscription; the maximum number of subscriptions has been configured.";
250                 elr.setMessage(message);
251                 elr.setResult(HttpServletResponse.SC_CONFLICT);
252                 eventlogger.error(elr.toString());
253                 sendResponseError(resp, HttpServletResponse.SC_CONFLICT, message, eventlogger);
254                 return;
255             }
256             Subscription sub;
257             try {
258                 sub = new Subscription(jo);
259             } catch (InvalidObjectException e) {
260                 activeSubs--;
261                 message = e.getMessage();
262                 elr.setMessage(message);
263                 elr.setResult(HttpServletResponse.SC_BAD_REQUEST);
264                 eventlogger.error(elr.toString(), e);
265                 sendResponseError(resp, HttpServletResponse.SC_BAD_REQUEST, message, eventlogger);
266                 return;
267             }
268             sub.setFeedid(feedid);
269             sub.setSubscriber(bhdr);    // set from X-DMAAP-DR-ON-BEHALF-OF header
270             /*
271              * START - AAF changes
272              * TDP EPIC US# 307413
273              * CADI code - check on permissions based on Legacy/AAF users to allow to create/add subscription
274              */
275             String feedAafInstance = feed.getAafInstance();
276             String subAafInstance = sub.getAafInstance();
277             boolean subAafLegacyEmptyOrNull = (subAafInstance == null
278                                          || "".equals(subAafInstance) || "legacy".equalsIgnoreCase(subAafInstance));
279
280             // This extra check added to verify AAF feed with AAF subscriber having empty aaf instance check
281             if (feedAafInstance == null || "".equals(feedAafInstance) || "legacy".equalsIgnoreCase(feedAafInstance)) {
282                 if (subAafLegacyEmptyOrNull) {
283                     AuthorizationResponse aresp = authz.decide(req);
284                     if (!aresp.isAuthorized()) {
285                         message = POLICY_ENGINE;
286                         elr.setMessage(message);
287                         elr.setResult(HttpServletResponse.SC_FORBIDDEN);
288                         eventlogger.error(elr.toString());
289                         sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
290                         return;
291                     }
292                 } else {
293                     //If Legacy Feed and AAF instance provided in Subscriber JSON
294                     message = "AAF Subscriber can not be added to legacy Feed- " + feedid;
295                     elr.setMessage(message);
296                     elr.setResult(HttpServletResponse.SC_FORBIDDEN);
297                     eventlogger.error(elr.toString());
298                     sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
299                     return;
300                 }
301             } else {
302                 //New AAF Requirement to add legacy subscriber to AAF Feed
303                 if (subAafLegacyEmptyOrNull) {
304                     AuthorizationResponse aresp = authz.decide(req);
305                     if (!aresp.isAuthorized()) {
306                         message = POLICY_ENGINE;
307                         elr.setMessage(message);
308                         elr.setResult(HttpServletResponse.SC_FORBIDDEN);
309                         eventlogger.error(elr.toString());
310                         sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
311                         return;
312                     }
313                 } else {
314                     //New AAF Requirement to add subscriber by publisher on publisher approval only
315                     String permission = getSubscriberPermission(subAafInstance, BaseServlet.APPROVE_SUB_PERMISSION);
316                     eventlogger.info("SubscribeServlet.doPost().. Permission String - " + permission);
317                     if (!req.isUserInRole(permission)) {
318                         message = "AAF disallows access to permission - " + permission;
319                         elr.setMessage(message);
320                         elr.setResult(HttpServletResponse.SC_FORBIDDEN);
321                         eventlogger.error(elr.toString());
322                         sendResponseError(resp, HttpServletResponse.SC_FORBIDDEN, message, eventlogger);
323                         return;
324                     }
325                 }
326             }
327             /*
328              * END - AAF changes
329              */
330             // Check if this subscription already exists; not an error (yet), just warn
331             Subscription sub2 = Subscription.getSubscriptionMatching(sub);
332             if (sub2 != null) {
333                 intlogger.warn(
334                     "PROV0011 Creating a duplicate subscription: new subid="
335                             + sub.getSubid() + ", old subid=" + sub2.getSubid());
336             }
337
338             // Create SUBSCRIPTIONS table entries
339             if (doInsert(sub)) {
340                 // send response
341                 elr.setResult(HttpServletResponse.SC_CREATED);
342                 eventlogger.info(elr.toString());
343                 resp.setStatus(HttpServletResponse.SC_CREATED);
344                 resp.setContentType(SUBFULL_CONTENT_TYPE);
345                 resp.setHeader("Location", sub.getLinks().getSelf());
346                 try {
347                     resp.getOutputStream().print(sub.asLimitedJSONObject().toString());
348                 } catch (IOException ioe) {
349                     eventlogger.error("PROV0182 SubscribeServlet.doPost: " + ioe.getMessage(), ioe);
350                 }
351
352                 provisioningDataChanged();
353             } else {
354                 // Something went wrong with the INSERT
355                 activeSubs--;
356                 elr.setResult(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
357                 eventlogger.error(elr.toString());
358                 sendResponseError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, DB_PROBLEM_MSG, eventlogger);
359             }
360         } finally {
361             eelfLogger.info(EelfMsgs.EXIT);
362         }
363     }
364 }