1 /*******************************************************************************
2 * ============LICENSE_START==================================================
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
11 * * http://www.apache.org/licenses/LICENSE-2.0
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====================================================
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 ******************************************************************************/
23 package org.onap.dmaap.datarouter.provisioning;
25 import static org.mockito.ArgumentMatchers.anyString;
26 import static org.mockito.Mockito.contains;
27 import static org.mockito.Mockito.eq;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.verify;
30 import static org.mockito.Mockito.when;
31 import static org.onap.dmaap.datarouter.provisioning.BaseServlet.BEHALF_HEADER;
33 import ch.qos.logback.classic.spi.ILoggingEvent;
34 import ch.qos.logback.core.read.ListAppender;
35 import java.sql.Connection;
36 import java.sql.SQLException;
37 import java.util.HashSet;
39 import javax.persistence.EntityManager;
40 import javax.persistence.EntityManagerFactory;
41 import javax.persistence.Persistence;
42 import javax.servlet.ServletInputStream;
43 import javax.servlet.ServletOutputStream;
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpServletResponse;
46 import org.apache.commons.lang3.reflect.FieldUtils;
47 import org.jetbrains.annotations.NotNull;
48 import org.json.JSONArray;
49 import org.json.JSONObject;
50 import org.junit.AfterClass;
51 import org.junit.Before;
52 import org.junit.BeforeClass;
53 import org.junit.Test;
54 import org.junit.runner.RunWith;
55 import org.mockito.Mock;
56 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
57 import org.onap.dmaap.datarouter.authz.Authorizer;
58 import org.onap.dmaap.datarouter.provisioning.beans.Feed;
59 import org.onap.dmaap.datarouter.provisioning.beans.Updateable;
60 import org.onap.dmaap.datarouter.provisioning.utils.ProvDbUtils;
61 import org.powermock.core.classloader.annotations.PowerMockIgnore;
62 import org.powermock.modules.junit4.PowerMockRunner;
65 @RunWith(PowerMockRunner.class)
66 @PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "org.w3c.*", "com.sun.org.apache.xalan.*"})
67 public class FeedServletTest extends DrServletTestBase {
69 private static FeedServlet feedServlet;
72 private HttpServletRequest request;
74 private HttpServletResponse response;
76 private static EntityManagerFactory emf;
77 private static EntityManager em;
79 private ListAppender<ILoggingEvent> listAppender;
82 public static void init() {
83 emf = Persistence.createEntityManagerFactory("dr-unit-tests");
84 em = emf.createEntityManager();
86 "org.onap.dmaap.datarouter.provserver.properties",
87 "src/test/resources/h2Database.properties");
91 public static void tearDownClass() {
98 public void setUp() throws Exception {
99 listAppender = setTestLogger(FeedServlet.class);
100 feedServlet = new FeedServlet();
101 setAuthoriserToReturnRequestIsAuthorized();
102 setUpValidAuthorisedRequest();
103 setUpValidSecurityOnHttpRequest();
104 setUpValidContentHeadersAndJSONOnHttpRequest();
108 public void Given_Request_Is_HTTP_DELETE_And_Is_Not_Secure_When_HTTPS_Is_Required_Then_Forbidden_Response_Is_Generated()
110 when(request.isSecure()).thenReturn(false);
111 feedServlet.doDelete(request, response);
112 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), anyString());
113 verifyEnteringExitCalled(listAppender);
117 public void Given_Request_Is_HTTP_DELETE_And_BEHALF_HEADER_Is_Not_Set_In_Request_Then_Bad_Request_Response_Is_Generated()
119 setBehalfHeader(null);
120 feedServlet.doDelete(request, response);
121 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
125 public void Given_Request_Is_HTTP_DELETE_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated() throws Exception {
126 when(request.getPathInfo()).thenReturn(null);
127 feedServlet.doDelete(request, response);
128 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
132 public void Given_Request_Is_HTTP_DELETE_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated() throws Exception {
133 when(request.getPathInfo()).thenReturn("/123");
134 feedServlet.doDelete(request, response);
135 verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
139 public void Given_Request_Is_HTTP_DELETE_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
140 setAuthoriserToReturnRequestNotAuthorized();
141 feedServlet.doDelete(request, response);
142 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), anyString());
146 public void Given_Request_Is_HTTP_DELETE_And_AAF_Feed_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
147 when(request.getPathInfo()).thenReturn("/2");
148 feedServlet.doDelete(request, response);
149 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
153 public void Given_Request_Is_HTTP_DELETE_And_AAF_Feed_With_Permissions_Then_A_NO_CONTENT_Response_Is_Generated() {
154 when(request.getPathInfo()).thenReturn("/3");
155 when(request.isUserInRole("org.onap.dmaap-dr.feed|*|delete")).thenReturn(true);
156 feedServlet.doDelete(request, response);
157 verify(response).setStatus(eq(HttpServletResponse.SC_NO_CONTENT));
158 verifyEnteringExitCalled(listAppender);
162 public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Fails_An_Internal_Server_Error_Is_Reported()
164 FeedServlet feedServlet = new FeedServlet() {
165 protected boolean doUpdate(Updateable bean) {
169 feedServlet.doDelete(request, response);
171 .sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), anyString());
175 public void Given_Request_Is_HTTP_DELETE_And_Delete_On_Database_Succeeds_A_NO_CONTENT_Response_Is_Generated() throws Exception {
176 feedServlet.doDelete(request, response);
177 verify(response).setStatus(eq(HttpServletResponse.SC_NO_CONTENT));
178 reinsertFeedIntoDb();
179 verifyEnteringExitCalled(listAppender);
183 public void Given_Request_Is_HTTP_GET_And_Is_Not_Secure_When_HTTPS_Is_Required_Then_Forbidden_Response_Is_Generated()
185 when(request.isSecure()).thenReturn(false);
186 feedServlet.doGet(request, response);
187 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), anyString());
188 verifyEnteringExitCalled(listAppender);
192 public void Given_Request_Is_HTTP_GET_And_BEHALF_HEADER_Is_Not_Set_In_Request_Then_Bad_Request_Response_Is_Generated()
194 setBehalfHeader(null);
195 feedServlet.doGet(request, response);
196 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
200 public void Given_Request_Is_HTTP_GET_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated()
202 when(request.getPathInfo()).thenReturn(null);
203 feedServlet.doGet(request, response);
204 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
208 public void Given_Request_Is_HTTP_GET_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated()
210 when(request.getPathInfo()).thenReturn("/123");
211 feedServlet.doGet(request, response);
212 verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
216 public void Given_Request_Is_HTTP_GET_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated()
218 setAuthoriserToReturnRequestNotAuthorized();
219 when(request.getPathInfo()).thenReturn("/2");
220 feedServlet.doGet(request, response);
221 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), anyString());
225 public void Given_Request_Is_HTTP_GET_And_Request_Succeeds() throws Exception {
226 ServletOutputStream outStream = mock(ServletOutputStream.class);
227 when(response.getOutputStream()).thenReturn(outStream);
228 when(request.getPathInfo()).thenReturn("/2");
229 feedServlet.doGet(request, response);
230 verify(response).setStatus(eq(HttpServletResponse.SC_OK));
231 verifyEnteringExitCalled(listAppender);
235 public void Given_Request_Is_HTTP_PUT_And_Is_Not_Secure_When_HTTPS_Is_Required_Then_Forbidden_Response_Is_Generated()
237 when(request.isSecure()).thenReturn(false);
238 feedServlet.doPut(request, response);
239 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), anyString());
240 verifyEnteringExitCalled(listAppender);
244 public void Given_Request_Is_HTTP_PUT_And_BEHALF_HEADER_Is_Not_Set_In_Request_Then_Bad_Request_Response_Is_Generated()
246 setBehalfHeader(null);
247 feedServlet.doPut(request, response);
248 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
252 public void Given_Request_Is_HTTP_PUT_And_Path_Header_Is_Not_Set_In_Request_With_Valid_Path_Then_Bad_Request_Response_Is_Generated()
254 when(request.getPathInfo()).thenReturn(null);
255 feedServlet.doPut(request, response);
256 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
260 public void Given_Request_Is_HTTP_PUT_And_Feed_Id_Is_Invalid_Then_Not_Found_Response_Is_Generated()
262 when(request.getPathInfo()).thenReturn("/123");
263 feedServlet.doPut(request, response);
264 verify(response).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString());
268 public void Given_Request_Is_HTTP_PUT_And_Content_Header_Is_Not_Supported_Type_Then_Unsupported_Media_Type_Response_Is_Generated()
270 when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed-fail; version=2.0");
271 when(request.getContentType()).thenReturn("stub_contentType");
272 when(request.getPathInfo()).thenReturn("/2");
273 feedServlet.doPut(request, response);
274 verify(response).sendError(eq(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE), anyString());
278 public void Given_Request_Is_HTTP_PUT_And_Request_Contains_Badly_Formed_JSON_Then_Bad_Request_Response_Is_Generated()
280 ServletInputStream inStream = mock(ServletInputStream.class);
281 when(request.getInputStream()).thenReturn(inStream);
282 when(request.getPathInfo()).thenReturn("/2");
283 FeedServlet feedServlet = new FeedServlet() {
284 public JSONObject getJSONfromInput(HttpServletRequest req) {
288 feedServlet.doPut(request, response);
289 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("Badly formed JSON"));
293 public void Given_Request_Is_HTTP_PUT_And_Request_Contains_Invalid_JSON_Then_Bad_Request_Response_Is_Generated() throws Exception {
294 when(request.getPathInfo()).thenReturn("/2");
295 FeedServlet feedServlet = new FeedServlet() {
296 public JSONObject getJSONfromInput(HttpServletRequest req) {
297 return new JSONObject();
300 feedServlet.doPut(request, response);
301 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), anyString());
305 public void Given_Request_Is_HTTP_PUT_And_Feed_Change_Is_Not_Publisher_Who_Requested_Feed_Bad_Request_Response_Is_Generated() throws Exception {
306 when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn(null);
307 when(request.getPathInfo()).thenReturn("/2");
308 JSONObject JSObject = buildRequestJsonObject();
309 FeedServlet feedServlet = new FeedServlet() {
310 public JSONObject getJSONfromInput(HttpServletRequest req) {
311 JSONObject jo = new JSONObject();
312 jo.put("name", "stub_name");
313 jo.put("version", "1.0");
314 jo.put("authorization", JSObject);
318 feedServlet.doPut(request, response);
319 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("must be modified by the same publisher"));
323 public void Given_Request_Is_HTTP_PUT_And_Feed_Name_Change_is_Requested_Bad_Request_Response_Is_Generated() throws Exception {
324 when(request.getPathInfo()).thenReturn("/2");
325 JSONObject JSObject = buildRequestJsonObject();
326 FeedServlet feedServlet = new FeedServlet() {
327 public JSONObject getJSONfromInput(HttpServletRequest req) {
328 JSONObject jo = new JSONObject();
329 jo.put("name", "not_stub_name");
330 jo.put("version", "1.0");
331 jo.put("authorization", JSObject);
335 feedServlet.doPut(request, response);
336 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("name of the feed may not be updated"));
340 public void Given_Request_Is_HTTP_PUT_And_Feed_Version_Change_is_Requested_Bad_Request_Response_Is_Generated() throws Exception {
341 when(request.getPathInfo()).thenReturn("/2");
342 JSONObject JSObject = buildRequestJsonObject();
343 FeedServlet feedServlet = new FeedServlet() {
344 public JSONObject getJSONfromInput(HttpServletRequest req) {
345 JSONObject jo = new JSONObject();
346 jo.put("name", "AafFeed");
347 jo.put("version", "v0.2");
348 jo.put("authorization", JSObject);
352 feedServlet.doPut(request, response);
353 verify(response).sendError(eq(HttpServletResponse.SC_BAD_REQUEST), contains("version of the feed may not be updated"));
357 public void Given_Request_Is_HTTP_PUT_And_Request_Is_Not_Authorized_Then_Forbidden_Response_Is_Generated() throws Exception {
358 setAuthoriserToReturnRequestNotAuthorized();
359 when(request.getPathInfo()).thenReturn("/2");
360 JSONObject JSObject = buildRequestJsonObject();
361 FeedServlet feedServlet = new FeedServlet() {
362 public JSONObject getJSONfromInput(HttpServletRequest req) {
363 JSONObject jo = new JSONObject();
364 jo.put("name", "AafFeed");
365 jo.put("version", "v0.1");
366 jo.put("authorization", JSObject);
370 feedServlet.doPut(request, response);
371 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("Policy Engine disallows access"));
375 public void Given_Request_Is_HTTP_PUT_And_AAF_Feed_Without_Permissions_Then_Forbidden_Response_Is_Generated() throws Exception {
376 when(request.getPathInfo()).thenReturn("/2");
377 JSONObject JSObject = buildRequestJsonObject();
378 FeedServlet feedServlet = new FeedServlet() {
379 public JSONObject getJSONfromInput(HttpServletRequest req) {
380 JSONObject jo = new JSONObject();
381 jo.put("name", "AafFeed");
382 jo.put("version", "v0.1");
383 jo.put("authorization", JSObject);
384 jo.put("aaf_instance", "https://aaf-onap-test.osaaf.org:8095");
388 feedServlet.doPut(request, response);
389 verify(response).sendError(eq(HttpServletResponse.SC_FORBIDDEN), contains("AAF disallows access to permission"));
393 public void Given_Request_Is_HTTP_PUT_And_AAF_Feed_With_Permissions_Then_STATUS_OK__Response_Is_Generated() throws Exception {
394 ServletOutputStream outStream = mock(ServletOutputStream.class);
395 when(response.getOutputStream()).thenReturn(outStream);
396 when(request.getPathInfo()).thenReturn("/2");
397 when(request.isUserInRole("org.onap.dmaap-dr.feed|*|edit")).thenReturn(true);
398 JSONObject JSObject = buildRequestJsonObject();
399 FeedServlet feedServlet = new FeedServlet() {
400 public JSONObject getJSONfromInput(HttpServletRequest req) {
401 JSONObject jo = new JSONObject();
402 jo.put("name", "AafFeed");
403 jo.put("version", "v0.1");
404 jo.put("authorization", JSObject);
405 jo.put("aaf_instance", "*");
409 protected boolean doUpdate(Updateable bean) {
414 feedServlet.doPut(request, response);
415 verify(response).setStatus(eq(HttpServletResponse.SC_OK));
416 verifyEnteringExitCalled(listAppender);
420 public void Given_Request_Is_HTTP_PUT_And_Change_On_Feeds_Fails_An_Internal_Server_Error_Response_Is_Generated() throws Exception {
421 ServletOutputStream outStream = mock(ServletOutputStream.class);
422 when(response.getOutputStream()).thenReturn(outStream);
423 when(request.getPathInfo()).thenReturn("/2");
424 JSONObject JSObject = buildRequestJsonObject();
425 FeedServlet feedServlet = new FeedServlet() {
426 public JSONObject getJSONfromInput(HttpServletRequest req) {
427 JSONObject jo = new JSONObject();
428 jo.put("name", "AafFeed");
429 jo.put("version", "v0.1");
430 jo.put("authorization", JSObject);
435 protected boolean doUpdate(Updateable bean) {
439 feedServlet.doPut(request, response);
440 verify(response).sendError(eq(HttpServletResponse.SC_INTERNAL_SERVER_ERROR), anyString());
444 public void Given_Request_Is_HTTP_PUT_And_Change_On_Feeds_Suceeds_A_STATUS_OK_Response_Is_Generated() throws Exception {
445 ServletOutputStream outStream = mock(ServletOutputStream.class);
446 when(response.getOutputStream()).thenReturn(outStream);
447 when(request.getPathInfo()).thenReturn("/2");
448 JSONObject JSObject = buildRequestJsonObject();
449 FeedServlet feedServlet = new FeedServlet() {
450 public JSONObject getJSONfromInput(HttpServletRequest req) {
451 JSONObject jo = new JSONObject();
452 jo.put("name", "AafFeed");
453 jo.put("version", "v0.1");
454 jo.put("authorization", JSObject);
458 protected boolean doUpdate(Updateable bean) {
463 feedServlet.doPut(request, response);
464 verify(response).setStatus(eq(HttpServletResponse.SC_OK));
465 verifyEnteringExitCalled(listAppender);
469 public void Given_Request_Is_HTTP_POST_SC_METHOD_NOT_ALLOWED_Response_Is_Generated() throws Exception {
470 feedServlet.doPost(request, response);
471 verify(response).sendError(eq(HttpServletResponse.SC_METHOD_NOT_ALLOWED), anyString());
472 verifyEnteringExitCalled(listAppender);
476 private JSONObject buildRequestJsonObject() {
477 JSONObject JSObject = new JSONObject();
478 JSONArray endpointIDs = new JSONArray();
479 JSONObject JOEndpointIDs = new JSONObject();
480 JOEndpointIDs.put("id", "stub_endpoint_id");
481 JOEndpointIDs.put("password", "stub_endpoint_password");
482 endpointIDs.put(JOEndpointIDs);
484 JSONArray endpointAddresses = new JSONArray();
485 endpointAddresses.put("127.0.0.1");
487 JSObject.put("classification", "stub_classification");
488 JSObject.put("endpoint_ids", endpointIDs);
489 JSObject.put("endpoint_addrs", endpointAddresses);
493 private void setUpValidSecurityOnHttpRequest() throws Exception {
494 when(request.isSecure()).thenReturn(true);
495 Set<String> authAddressesAndNetworks = new HashSet<>();
496 authAddressesAndNetworks.add(("127.0.0.1"));
497 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authorizedAddressesAndNetworks", authAddressesAndNetworks,true);
498 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "requireCert", false, true);
501 private void setBehalfHeader(String headerValue) {
502 when(request.getHeader(BEHALF_HEADER)).thenReturn(headerValue);
505 private void setValidPathInfoInHttpHeader() {
506 when(request.getPathInfo()).thenReturn("/1");
509 private void setAuthoriserToReturnRequestNotAuthorized() throws IllegalAccessException {
510 AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
511 Authorizer authorizer = mock(Authorizer.class);
512 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authz", authorizer, true);
513 when(authorizer.decide(request)).thenReturn(authResponse);
514 when(authResponse.isAuthorized()).thenReturn(false);
517 private void setAuthoriserToReturnRequestIsAuthorized() throws IllegalAccessException {
518 AuthorizationResponse authResponse = mock(AuthorizationResponse.class);
519 Authorizer authorizer = mock(Authorizer.class);
520 FieldUtils.writeDeclaredStaticField(BaseServlet.class, "authz", authorizer, true);
521 when(authorizer.decide(request)).thenReturn(authResponse);
522 when(authResponse.isAuthorized()).thenReturn(true);
525 private void setUpValidAuthorisedRequest() throws Exception {
526 setUpValidSecurityOnHttpRequest();
527 setBehalfHeader("Stub_Value");
528 setValidPathInfoInHttpHeader();
531 private void setUpValidContentHeadersAndJSONOnHttpRequest() {
532 when(request.getHeader("Content-Type")).thenReturn("application/vnd.dmaap-dr.feed; version=1.0");
533 when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_subjectGroup");
536 private void reinsertFeedIntoDb() throws SQLException {
537 Feed feed = new Feed("Feed1","v0.1", "First Feed for testing", "First Feed for testing");
540 feed.setDeleted(false);
541 try (Connection conn = ProvDbUtils.getInstance().getConnection()) {