e2a2bc21bb68de2e27d1fd68b5579d1369ec7e2f
[dmaap/datarouter.git] / datarouter-prov / src / test / java / org / onap / dmaap / datarouter / provisioning / DRFeedsServletTest.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 package org.onap.dmaap.datarouter.provisioning;
24
25 import ch.qos.logback.classic.spi.ILoggingEvent;
26 import ch.qos.logback.core.read.ListAppender;
27 import org.apache.commons.lang3.reflect.FieldUtils;
28 import org.jetbrains.annotations.NotNull;
29 import org.json.JSONArray;
30 import org.json.JSONObject;
31 import org.junit.AfterClass;
32 import org.junit.Before;
33 import org.junit.BeforeClass;
34 import org.junit.Test;
35 import org.junit.runner.RunWith;
36 import org.mockito.Mock;
37 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
38 import org.onap.dmaap.datarouter.authz.Authorizer;
39 import org.onap.dmaap.datarouter.provisioning.beans.Insertable;
40 import org.onap.dmaap.datarouter.provisioning.utils.DB;
41 import org.powermock.modules.junit4.PowerMockRunner;
42
43 import javax.persistence.EntityManager;
44 import javax.persistence.EntityManagerFactory;
45 import javax.persistence.Persistence;
46 import javax.servlet.ServletOutputStream;
47 import javax.servlet.http.HttpServletRequest;
48 import javax.servlet.http.HttpServletResponse;
49 import java.io.IOException;
50 import java.util.HashSet;
51 import java.util.Set;
52
53 import static org.hamcrest.Matchers.notNullValue;
54 import static org.mockito.Mockito.*;
55 import static org.onap.dmaap.datarouter.provisioning.BaseServlet.BEHALF_HEADER;
56
57
58 @RunWith(PowerMockRunner.class)
59 public class DRFeedsServletTest extends DrServletTestBase {
60
61     private static DRFeedsServlet drfeedsServlet;
62     private static EntityManagerFactory emf;
63     private static EntityManager em;
64     private DB db;
65
66     @Mock
67     private HttpServletRequest request;
68     @Mock
69     private HttpServletResponse response;
70
71     private ListAppender<ILoggingEvent> listAppender;
72
73     @BeforeClass
74     public static void init() {
75         emf = Persistence.createEntityManagerFactory("dr-unit-tests");
76         em = emf.createEntityManager();
77         System.setProperty(
78                 "org.onap.dmaap.datarouter.provserver.properties",
79                 "src/test/resources/h2Database.properties");
80     }
81
82     @AfterClass
83     public static void tearDownClass() {
84         em.clear();
85         em.close();
86         emf.close();
87     }
88
89     @Before
90     public void setUp() throws Exception {
91         listAppender = setTestLogger(DRFeedsServlet.class);
92         drfeedsServlet = new DRFeedsServlet();
93         db = new DB();
94         setAuthoriserToReturnRequestIsAuthorized();
95         setPokerToNotCreateTimersWhenDeleteFeedIsCalled();
96         setupValidAuthorisedRequest();
97         setUpValidSecurityOnHttpRequest();
98         setUpValidContentHeadersAndJSONOnHttpRequest();
99     }
100
101     @Test
102     public void Given_Request_Is_HTTP_DELETE_SC_METHOD_NOT_ALLOWED_Response_Is_Generated() throws Exception {
103         drfeedsServlet.doDelete(request, response);
104         verify(response).sendError(eq(HttpServletResponse.SC_METHOD_NOT_ALLOWED), argThat(notNullValue(String.class)));
105         verifyEnteringExitCalled(listAppender);
106     }
107
108     @Test
109     public void Given_Request_Is_HTTP_GET_And_Is_Not_Secure_When_HTTPS_Is_Required_Then_Forbidden_Response_Is_Generated()
110         throws Exception {
111         when(request.isSecure()).thenReturn(false);
112         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isAddressAuthEnabled", "true", true);
113         drfeedsServlet.doGet(request, response);
114         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
115         verifyEnteringExitCalled(listAppender);
116     }
117
118     @Test
119     public void Given_Request_Is_HTTP_GET_And_BEHALF_HEADER_Is_Not_Set_In_Request_Then_Bad_Request_Response_Is_Generated()
120         throws Exception {
121         setBehalfHeader(null);
122         drfeedsServlet.doGet(request, response);
123         verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
124     }
125
126
127     @Test
128     public void Given_Request_Is_HTTP_GET_And_URL_Path_Not_Valid_Then_Bad_Request_Response_Is_Generated()
129         throws Exception {
130         when(request.getRequestURI()).thenReturn("/123");
131         drfeedsServlet.doGet(request, response);
132         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
133     }
134
135
136     @Test
137     public void Given_Request_Is_HTTP_GET_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
138         throws Exception {
139         setAuthoriserToReturnRequestNotAuthorized();
140         drfeedsServlet.doGet(request, response);
141         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
142     }
143
144     @Test
145     public void Given_Request_Is_HTTP_GET_And_Request_Fails_With_Valid_Name_And_Version() throws Exception {
146         when(request.getParameter("name")).thenReturn("stub_name");
147         when(request.getParameter("version")).thenReturn("stub_version");
148         drfeedsServlet.doGet(request, response);
149         verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
150     }
151
152     @Test
153     public void Given_Request_Is_HTTP_GET_And_Request_Succeeds_With_Valid_Name_And_Version() throws Exception {
154         ServletOutputStream outStream = mock(ServletOutputStream.class);
155         when(response.getOutputStream()).thenReturn(outStream);
156         when(request.getParameter("name")).thenReturn("Feed1");
157         when(request.getParameter("version")).thenReturn("v0.1");
158         drfeedsServlet.doGet(request, response);
159         verify(response).setStatus(eq(HttpServletResponse.SC_OK));
160         verify(response).setContentType(BaseServlet.FEEDFULL_CONTENT_TYPE);
161         verifyEnteringExitCalled(listAppender);
162     }
163
164
165     @Test
166     public void Given_Request_Is_HTTP_GET_And_Request_Succeeds_With_Invalid_Name_And_Version() throws Exception {
167         ServletOutputStream outStream = mock(ServletOutputStream.class);
168         when(response.getOutputStream()).thenReturn(outStream);
169         drfeedsServlet.doGet(request, response);
170         verify(response).setStatus(eq(HttpServletResponse.SC_OK));
171     }
172
173
174     @Test
175     public void Given_Request_Is_HTTP_PUT_SC_METHOD_NOT_ALLOWED_Response_Is_Generated() throws Exception {
176         drfeedsServlet.doPut(request, response);
177         verify(response).sendError(eq(HttpServletResponse.SC_METHOD_NOT_ALLOWED), argThat(notNullValue(String.class)));
178         verifyEnteringExitCalled(listAppender);
179     }
180
181
182     @Test
183     public void Given_Request_Is_HTTP_POST_And_Is_Not_Secure_When_HTTPS_Is_Required_Then_Forbidden_Response_Is_Generated()
184         throws Exception {
185         when(request.isSecure()).thenReturn(false);
186         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isAddressAuthEnabled", "true", true);
187         drfeedsServlet.doPost(request, response);
188         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
189         verifyEnteringExitCalled(listAppender);
190     }
191
192     @Test
193     public void Given_Request_Is_HTTP_POST_And_BEHALF_HEADER_Is_Not_Set_In_Request_Then_Bad_Request_Response_Is_Generated()
194         throws Exception {
195         setBehalfHeader(null);
196         drfeedsServlet.doPost(request, response);
197         verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
198     }
199
200
201     @Test
202     public void Given_Request_Is_HTTP_POST_And_URL_Path_Not_Valid_Then_Bad_Request_Response_Is_Generated()
203         throws Exception {
204         when(request.getRequestURI()).thenReturn("/123");
205         drfeedsServlet.doPost(request, response);
206         verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), argThat(notNullValue(String.class)));
207     }
208
209
210     @Test
211     public void Given_Request_Is_HTTP_POST_And_Content_Header_Is_Not_Supported_Type_Then_Unsupported_Media_Type_Response_Is_Generated()
212         throws Exception {
213         when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed; version=1.1");
214         when(request.getContentType()).thenReturn("stub_contentType");
215         drfeedsServlet.doPost(request, response);
216         verify(response)
217             .sendError(eq(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE), argThat(notNullValue(String.class)));
218     }
219
220     @Test
221     public void Given_Request_Is_HTTP_POST_And_CadiEnabled_Is_True_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
222         throws Exception {
223         setAuthoriserToReturnRequestNotAuthorized();
224         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "true", true);
225         when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("true");
226         JSONObject JSObject = buildRequestJsonObject();
227         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
228             protected JSONObject getJSONfromInput(HttpServletRequest req) {
229                 JSONObject jo = new JSONObject();
230                 jo.put("name", "not_stub_name");
231                 jo.put("version", "1.0");
232                 jo.put("authorization", JSObject);
233                 jo.put("aaf_instance", "legacy");
234                 return jo;
235             }
236         };
237         drfeedsServlet.doPost(request, response);
238         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
239     }
240
241     @Test
242     public void Given_Request_Is_HTTP_POST_And_CadiEnabled_Is_False_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
243             throws Exception {
244         setAuthoriserToReturnRequestNotAuthorized();
245         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "false", true);
246         when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("true");
247         JSONObject JSObject = buildRequestJsonObject();
248         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
249             protected JSONObject getJSONfromInput(HttpServletRequest req) {
250                 JSONObject jo = new JSONObject();
251                 jo.put("name", "not_stub_name");
252                 jo.put("version", "1.0");
253                 jo.put("authorization", JSObject);
254                 jo.put("aaf_instance", "legacy");
255                 return jo;
256             }
257         };
258         drfeedsServlet.doPost(request, response);
259         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), argThat(notNullValue(String.class)));
260     }
261
262     @Test
263     public void Given_Request_Is_HTTP_POST_And_AAF_DRFeed_And_Exclude_AAF_Is_True_Then_Forbidden_Response_Is_Generated() throws Exception {
264         when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("true");
265         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "true", true);
266         JSONObject JSObject = buildRequestJsonObject();
267         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
268             protected JSONObject getJSONfromInput(HttpServletRequest req) {
269                 JSONObject jo = new JSONObject();
270                 jo.put("name", "not_stub_name");
271                 jo.put("version", "1.0");
272                 jo.put("authorization", JSObject);
273                 jo.put("aaf_instance", "https://aaf-onap-test.osaaf.org:8095");
274                 return jo;
275             }
276         };
277         drfeedsServlet.doPost(request, response);
278         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("Invalid request exclude_AAF"));
279     }
280
281     @Test
282     public void Given_Request_Is_HTTP_POST_And_AAF_DRFeed_And_Exclude_AAF_Is_False_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
283         when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("false");
284         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "true", true);
285         JSONObject JSObject = buildRequestJsonObject();
286         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
287             protected JSONObject getJSONfromInput(HttpServletRequest req) {
288                 JSONObject jo = new JSONObject();
289                 jo.put("name", "not_stub_name");
290                 jo.put("version", "1.0");
291                 jo.put("authorization", JSObject);
292                 jo.put("aaf_instance", "*");
293                 return jo;
294             }
295         };
296         drfeedsServlet.doPost(request, response);
297         verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
298     }
299
300     @Test
301     public void Given_Request_Is_HTTP_POST_And_AAF_DRFeed_And_Exclude_AAF_Is_False_With_Permissions_Then_Created_OK_Response_Is_Generated() throws Exception {
302         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "isCadiEnabled", "true", true);
303         ServletOutputStream outStream = mock(ServletOutputStream.class);
304         when(response.getOutputStream()).thenReturn(outStream);
305         when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("false");
306         JSONObject JSObject = buildRequestJsonObject();
307         when(request.isUserInRole("org.onap.dmaap-dr.feed|*|create")).thenReturn(true);
308         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
309             protected JSONObject getJSONfromInput(HttpServletRequest req) {
310                 JSONObject jo = new JSONObject();
311                 jo.put("name", "not_stub_name");
312                 jo.put("version", "1.0");
313                 jo.put("authorization", JSObject);
314                 jo.put("aaf_instance", "*");
315                 return jo;
316             }
317
318             @Override
319             protected boolean doInsert(Insertable bean) {
320                 return true;
321             }
322         };
323         drfeedsServlet.doPost(request, response);
324         verify(response).setStatus(eq(HttpServletResponse.SC_CREATED));
325         verifyEnteringExitCalled(listAppender);
326     }
327
328     @Test
329     public void Given_Request_Is_HTTP_POST_And_Request_Contains_Badly_Formed_JSON_Then_Bad_Request_Response_Is_Generated()
330         throws Exception {
331         drfeedsServlet.doPost(request, response);
332         verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
333     }
334
335     @Test
336     public void Given_Request_Is_HTTP_POST_And_Active_Feeds_Equals_Max_Feeds_Then_Bad_Request_Response_Is_Generated()
337         throws Exception {
338         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "maxFeeds", 0, true);
339         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
340             protected JSONObject getJSONfromInput(HttpServletRequest req) {
341                 return new JSONObject();
342             }
343         };
344         drfeedsServlet.doPost(request, response);
345         verify(response).sendError(eq(HttpServletResponse.SC_CONFLICT), argThat(notNullValue(String.class)));
346     }
347
348     @Test
349     public void Given_Request_Is_HTTP_POST_And_Feed_Is_Not_Valid_Object_Bad_Request_Response_Is_Generated()
350         throws Exception {
351         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
352             protected JSONObject getJSONfromInput(HttpServletRequest req) {
353                 return new JSONObject();
354             }
355         };
356
357         drfeedsServlet.doPost(request, response);
358         verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), argThat(notNullValue(String.class)));
359     }
360
361     @Test
362     public void Given_Request_Is_HTTP_POST_And_Feed_Already_Exists_Bad_Request_Response_Is_Generated()
363         throws Exception {
364         when(request.getParameter("name")).thenReturn("AafFeed");
365         when(request.getParameter("version")).thenReturn("v0.1");
366         when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("false");
367         when(request.isUserInRole("org.onap.dmaap-dr.feed|*|create")).thenReturn(true);
368         JSONObject JSObject = buildRequestJsonObject();
369         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
370             protected JSONObject getJSONfromInput(HttpServletRequest req) {
371                 JSONObject jo = new JSONObject();
372                 jo.put("name", "AafFeed");
373                 jo.put("version", "v0.1");
374                 jo.put("authorization", JSObject);
375                 jo.put("aaf_instance", "*");
376                 return jo;
377             }
378         };
379         drfeedsServlet.doPost(request, response);
380         verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("This feed already exists in the database"));
381     }
382
383     @Test
384     public void Given_Request_Is_HTTP_POST_And_POST_Fails_Bad_Request_Response_Is_Generated() throws Exception {
385         JSONObject JSObject = buildRequestJsonObject();
386         when(request.getHeader(DRFeedsServlet.EXCLUDE_AAF_HEADER)).thenReturn("true");
387         DRFeedsServlet drfeedsServlet = new DRFeedsServlet() {
388             protected JSONObject getJSONfromInput(HttpServletRequest req) {
389                 JSONObject jo = new JSONObject();
390                 jo.put("name", "stub_name");
391                 jo.put("version", "2.0");
392                 jo.put("authorization", JSObject);
393                 jo.put("aaf_instance", "legacy");
394                 return jo;
395             }
396
397             @Override
398             protected boolean doInsert(Insertable bean) {
399                 return false;
400             }
401         };
402         drfeedsServlet.doPost(request, response);
403         verify(response)
404             .sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), argThat(notNullValue(String.class)));
405     }
406
407     @NotNull
408     private JSONObject buildRequestJsonObject() {
409         JSONObject JSObject = new JSONObject();
410         JSONArray endpointIDs = new JSONArray();
411         JSONObject JOEndpointIDs = new JSONObject();
412         JOEndpointIDs.put("id", "stub_endpoint_id");
413         JOEndpointIDs.put("password", "stub_endpoint_password");
414         endpointIDs.put(JOEndpointIDs);
415
416         JSONArray endpointAddresses = new JSONArray();
417         endpointAddresses.put("127.0.0.1");
418
419         JSObject.put("classification", "stub_classification");
420         JSObject.put("endpoint_ids", endpointIDs);
421         JSObject.put("endpoint_addrs", endpointAddresses);
422         return JSObject;
423     }
424
425     private void setUpValidSecurityOnHttpRequest() throws Exception {
426         when(request.isSecure()).thenReturn(true);
427         Set<String> authAddressesAndNetworks = new HashSet<>();
428         authAddressesAndNetworks.add(("127.0.0.1"));
429         FieldUtils
430             .writeDeclaredStaticField(BaseServlet.class, "authorizedAddressesAndNetworks", authAddressesAndNetworks,
431                 true);
432         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "requireCert", false, true);
433         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "maxFeeds", 100, true);
434     }
435
436     private void setBehalfHeader(String headerValue) {
437         when(request.getHeader(BEHALF_HEADER)).thenReturn(headerValue);
438     }
439
440     private void setAuthoriserToReturnRequestNotAuthorized() throws IllegalAccessException {
441         AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
442         Authorizer authorizer = mock(Authorizer.class);
443         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authz", authorizer, true);
444         when(authorizer.decide(request)).thenReturn(authResponse);
445         when(authResponse.isAuthorized()).thenReturn(false);
446     }
447
448     private void setAuthoriserToReturnRequestIsAuthorized() throws IllegalAccessException {
449         AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
450         Authorizer authorizer = mock(Authorizer.class);
451         FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authz", authorizer, true);
452         when(authorizer.decide(request)).thenReturn(authResponse);
453         when(authResponse.isAuthorized()).thenReturn(true);
454     }
455
456     private void setPokerToNotCreateTimersWhenDeleteFeedIsCalled() throws Exception {
457         Poker poker = mock(Poker.class);
458         FieldUtils.writeDeclaredStaticField(Poker.class, "poker", poker, true);
459     }
460
461     private void setupValidAuthorisedRequest() throws Exception {
462         setUpValidSecurityOnHttpRequest();
463         setBehalfHeader("Stub_Value");
464     }
465
466     private void setUpValidContentHeadersAndJSONOnHttpRequest() throws IllegalAccessException {
467         when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed; version=1.0");
468         when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_subjectGroup");
469     }
470 }