XACMLRequestFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext context) throws IOException { log.debug("Authorizing..."); long start = System.currentTimeMillis(); MultivaluedMap<String, String> pathParameters = uriInfo.getPathParameters(); MultivaluedMap<String, String> queryParameters = uriInfo.getQueryParameters(); Method method = resourceInfo.getResourceMethod(); if (method.getAnnotation(ResourceId.class) == null) { log.info(String.format("Request authorization skipped. %dms", System.currentTimeMillis() - start)); return; } IRI subjectIdIri = (IRI) RestUtils.optActiveUser(context, engineManager).map(User::getResource) .orElse(vf.createIRI(ANON_USER)); SubjectAttributes subjectAttributesAnnotation = method.getAnnotation(SubjectAttributes.class); Map<String, Literal> subjectAttributes = new HashMap<>(); if (subjectAttributesAnnotation != null) { setAttributes(subjectAttributes, subjectAttributesAnnotation.value(), pathParameters, queryParameters, context); } ResourceId resourceIdAnnotation = method.getAnnotation(ResourceId.class); IRI resourceIdIri; try { resourceIdIri = getResourceIdIri(resourceIdAnnotation, context, queryParameters, pathParameters); } catch (MobiWebException ex) { DefaultResourceId[] defaultValArr = resourceIdAnnotation.defaultValue(); if (defaultValArr.length != 0) { log.info("Attempting to resolve a default Resource ID."); DefaultResourceId defaultVal = defaultValArr[0]; ResourceId defaultResourceId = getResourceIdFromDefault(defaultVal); resourceIdIri = getResourceIdIri(defaultResourceId, context, queryParameters, pathParameters); } else { throw ex; } } ResourceAttributes resourceAttributesAnnotation = method.getAnnotation(ResourceAttributes.class); Map<String, Literal> resourceAttributes = new HashMap<>(); if (resourceAttributesAnnotation != null) { setAttributes(resourceAttributes, resourceAttributesAnnotation.value(), pathParameters, queryParameters, context); } ActionId actionIdAnnotation = method.getAnnotation(ActionId.class); IRI actionId; if (actionIdAnnotation == null) { switch (context.getMethod()) { case "POST": actionId = vf.createIRI(Create.TYPE); break; case "DELETE": actionId = vf.createIRI(Delete.TYPE); break; case "PUT": actionId = vf.createIRI(Update.TYPE); break; case "GET": default: actionId = vf.createIRI(Read.TYPE); break; } } else { actionId = vf.createIRI(actionIdAnnotation.value()); } ActionAttributes actionAttributesAnnotation = method.getAnnotation(ActionAttributes.class); Map<String, Literal> actionAttributes = new HashMap<>(); if (actionAttributesAnnotation != null) { setAttributes(actionAttributes, actionAttributesAnnotation.value(), pathParameters, queryParameters, context); } Request request = pdp.createRequest(subjectIdIri, subjectAttributes, resourceIdIri, resourceAttributes, actionId, actionAttributes); log.debug(request.toString()); Response response = pdp.evaluate(request, vf.createIRI(POLICY_PERMIT_OVERRIDES)); log.debug(response.toString()); Decision decision = response.getDecision(); if (decision != Decision.PERMIT) { if (decision == Decision.DENY) { String statusMessage = getMessageOrDefault(response, "You do not have permission to perform this action"); throw ErrorUtils.sendError(statusMessage, UNAUTHORIZED); } if (decision == Decision.INDETERMINATE) { String statusMessage = getMessageOrDefault(response, "Request indeterminate"); throw ErrorUtils.sendError(statusMessage, INTERNAL_SERVER_ERROR); } } log.info(String.format("Request permitted. %dms", System.currentTimeMillis() - start)); }  @Override void filter(ContainerRequestContext context);  }
@Test public void decisionIsPermitTest() throws Exception { when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdStringClass.class.getDeclaredMethod("resourceIdString")); filter.filter(context); IRI actionId = VALUE_FACTORY.createIRI(Read.TYPE); IRI resourceId = VALUE_FACTORY.createIRI("http: IRI subjectId = VALUE_FACTORY.createIRI(ANON_USER); Mockito.verify(pdp).createRequest(subjectId, new HashMap<>(), resourceId, new HashMap<>(), actionId, new HashMap<>()); }
@Test public void decisionIsDenyTest() throws Exception { when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdStringClass.class.getDeclaredMethod("resourceIdString")); when(response.getDecision()).thenReturn(Decision.DENY); try { filter.filter(context); fail("Expected MobiWebException to have been thrown"); } catch (MobiWebException e) { assertEquals("You do not have permission to perform this action", e.getMessage()); assertEquals(401, e.getResponse().getStatus()); } }
@Test public void decisionIsIndeterminateTest() throws Exception { when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdStringClass.class.getDeclaredMethod("resourceIdString")); when(response.getDecision()).thenReturn(Decision.INDETERMINATE); try { filter.filter(context); fail("Expected MobiWebException to have been thrown"); } catch (MobiWebException e) { assertEquals("Request indeterminate", e.getMessage()); assertEquals(500, e.getResponse().getStatus()); } }
@Test public void decisionIsNotApplicableTest() throws Exception { when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdStringClass.class.getDeclaredMethod("resourceIdString")); when(response.getDecision()).thenReturn(Decision.NOT_APPLICABLE); filter.filter(context); IRI actionId = VALUE_FACTORY.createIRI(Read.TYPE); IRI resourceId = VALUE_FACTORY.createIRI("http: IRI subjectId = VALUE_FACTORY.createIRI(ANON_USER); Mockito.verify(pdp).createRequest(subjectId, new HashMap<>(), resourceId, new HashMap<>(), actionId, new HashMap<>()); }
@Test public void userIsNotAnonymousTest() throws Exception { user = userFactory.createNew(VALUE_FACTORY.createIRI(MOBI_USER_IRI)); when(context.getProperty(AuthenticationProps.USERNAME)).thenReturn("tester"); when(engineManager.retrieveUser("tester")).thenReturn(Optional.of(user)); when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdStringClass.class.getDeclaredMethod("resourceIdString")); IRI actionId = VALUE_FACTORY.createIRI(Read.TYPE); IRI resourceId = VALUE_FACTORY.createIRI("http: IRI subjectId = VALUE_FACTORY.createIRI(MOBI_USER_IRI); filter.filter(context); Mockito.verify(pdp).createRequest(subjectId, new HashMap<>(), resourceId, new HashMap<>(), actionId, new HashMap<>()); }
@Test public void noResourceIdAnnotationTest() throws Exception { when(resourceInfo.getResourceMethod()).thenReturn(MockNoResourceIdClass.class.getDeclaredMethod("noResourceId")); filter.filter(context); Mockito.verify(pdp, never()).createRequest(any(), any(), any(), any(), any(), any()); }
@Test public void resourceIdQueryParamExistsNoDefaultTest() throws Exception { MultivaluedHashMap<String, String> queryParameters = new MultivaluedHashMap<>(); queryParameters.putSingle(QUERY_PARAM_KEY, QUERY_PARAM_VALUE); when(uriInfo.getQueryParameters()).thenReturn(queryParameters); when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdQueryParamClass.class.getDeclaredMethod("queryParamNoDefault")); IRI actionId = VALUE_FACTORY.createIRI(Read.TYPE); IRI resourceId = VALUE_FACTORY.createIRI(QUERY_PARAM_VALUE); IRI subjectId = VALUE_FACTORY.createIRI(ANON_USER); filter.filter(context); Mockito.verify(pdp).createRequest(subjectId, new HashMap<>(), resourceId, new HashMap<>(), actionId, new HashMap<>()); }
@Test public void resourceIdQueryParamExistsWithDefaultTest() throws Exception { MultivaluedHashMap<String, String> queryParameters = new MultivaluedHashMap<>(); queryParameters.putSingle(QUERY_PARAM_KEY, QUERY_PARAM_VALUE); when(uriInfo.getQueryParameters()).thenReturn(queryParameters); when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdQueryParamClass.class.getDeclaredMethod("queryParamWithDefault")); IRI actionId = VALUE_FACTORY.createIRI(Read.TYPE); IRI resourceId = VALUE_FACTORY.createIRI(QUERY_PARAM_VALUE); IRI subjectId = VALUE_FACTORY.createIRI(ANON_USER); filter.filter(context); Mockito.verify(pdp).createRequest(subjectId, new HashMap<>(), resourceId, new HashMap<>(), actionId, new HashMap<>()); }
@Test public void resourceIdMissingQueryParamNoDefaultTest() throws Exception { exceptionRule.expect(MobiWebException.class); exceptionRule.expectMessage("Query parameters do not contain testQueryParamKey"); MultivaluedHashMap<String, String> queryParameters = new MultivaluedHashMap<>(); when(uriInfo.getQueryParameters()).thenReturn(queryParameters); when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdQueryParamClass.class.getDeclaredMethod("queryParamNoDefault")); filter.filter(context); }
@Test public void resourceIdMissingQueryParamWithDefaultTest() throws Exception { MultivaluedHashMap<String, String> queryParameters = new MultivaluedHashMap<>(); when(uriInfo.getQueryParameters()).thenReturn(queryParameters); when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdQueryParamClass.class.getDeclaredMethod("queryParamWithDefault")); IRI actionId = VALUE_FACTORY.createIRI(Read.TYPE); IRI resourceId = VALUE_FACTORY.createIRI(DEFAULT_RESOURCE_ID_IRI); IRI subjectId = VALUE_FACTORY.createIRI(ANON_USER); filter.filter(context); Mockito.verify(pdp).createRequest(subjectId, new HashMap<>(), resourceId, new HashMap<>(), actionId, new HashMap<>()); }
@Test public void resourceIdMissingQueryParamWithDefaultNotExistsTest() throws Exception { exceptionRule.expect(MobiWebException.class); exceptionRule.expectMessage("Query parameters do not contain testQueryParamTwoKey"); MultivaluedHashMap<String, String> queryParameters = new MultivaluedHashMap<>(); when(uriInfo.getQueryParameters()).thenReturn(queryParameters); when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdQueryParamClass.class.getDeclaredMethod("queryParamWithDefaultNotExists")); filter.filter(context); }
@Test public void resourceIdPathParamExistsNoDefaultTest() throws Exception { MultivaluedHashMap<String, String> pathParameters = new MultivaluedHashMap<>(); pathParameters.putSingle(PATH_PARAM_KEY, PATH_PARAM_VALUE); when(uriInfo.getPathParameters()).thenReturn(pathParameters); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdPathParamClass.class.getDeclaredMethod("pathParamNoDefault")); IRI actionId = VALUE_FACTORY.createIRI(Read.TYPE); IRI resourceId = VALUE_FACTORY.createIRI(PATH_PARAM_VALUE); IRI subjectId = VALUE_FACTORY.createIRI(ANON_USER); filter.filter(context); Mockito.verify(pdp).createRequest(subjectId, new HashMap<>(), resourceId, new HashMap<>(), actionId, new HashMap<>()); }
@Test public void resourceIdPathParamExistsWithDefaultTest() throws Exception { MultivaluedHashMap<String, String> pathParameters = new MultivaluedHashMap<>(); pathParameters.putSingle(PATH_PARAM_KEY, PATH_PARAM_VALUE); when(uriInfo.getPathParameters()).thenReturn(pathParameters); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdPathParamClass.class.getDeclaredMethod("pathParamWithDefault")); IRI actionId = VALUE_FACTORY.createIRI(Read.TYPE); IRI resourceId = VALUE_FACTORY.createIRI(PATH_PARAM_VALUE); IRI subjectId = VALUE_FACTORY.createIRI(ANON_USER); filter.filter(context); Mockito.verify(pdp).createRequest(subjectId, new HashMap<>(), resourceId, new HashMap<>(), actionId, new HashMap<>()); }
@Test public void resourceIdMissingPathParamNoDefaultTest() throws Exception { exceptionRule.expect(MobiWebException.class); exceptionRule.expectMessage("Path does not contain parameter testPathParamKey"); MultivaluedHashMap<String, String> pathParameters = new MultivaluedHashMap<>(); when(uriInfo.getPathParameters()).thenReturn(pathParameters); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdPathParamClass.class.getDeclaredMethod("pathParamNoDefault")); filter.filter(context); }
@Test public void resourceIdMissingPathParamWithDefaultTest() throws Exception { MultivaluedHashMap<String, String> pathParameters = new MultivaluedHashMap<>(); when(uriInfo.getPathParameters()).thenReturn(pathParameters); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdPathParamClass.class.getDeclaredMethod("pathParamWithDefault")); IRI actionId = VALUE_FACTORY.createIRI(Read.TYPE); IRI resourceId = VALUE_FACTORY.createIRI(DEFAULT_RESOURCE_ID_IRI); IRI subjectId = VALUE_FACTORY.createIRI(ANON_USER); filter.filter(context); Mockito.verify(pdp).createRequest(subjectId, new HashMap<>(), resourceId, new HashMap<>(), actionId, new HashMap<>()); }
@Test public void resourceIdMissingPathParamWithDefaultNotExistsTest() throws Exception { exceptionRule.expect(MobiWebException.class); exceptionRule.expectMessage("Path does not contain parameter testPathParamTwoKey"); MultivaluedHashMap<String, String> pathParameters = new MultivaluedHashMap<>(); when(uriInfo.getPathParameters()).thenReturn(pathParameters); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdPathParamClass.class.getDeclaredMethod("pathParamWithDefaultNotExists")); filter.filter(context); }
@Test public void resourceIdFormDataExistsNoDefaultTest() throws Exception { FormDataMultiPart formPart = new FormDataMultiPart(); formPart.field(FORM_DATA_FIELD, FORM_DATA_VALUE); when(context.readEntity(FormDataMultiPart.class)).thenReturn(formPart); when(context.hasEntity()).thenReturn(true); when(context.getMediaType()).thenReturn(MediaType.MULTIPART_FORM_DATA_TYPE); when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdFormDataClass.class.getDeclaredMethod("formDataNoDefault")); IRI actionId = VALUE_FACTORY.createIRI(Read.TYPE); IRI resourceId = VALUE_FACTORY.createIRI(FORM_DATA_VALUE); IRI subjectId = VALUE_FACTORY.createIRI(ANON_USER); filter.filter(context); Mockito.verify(pdp).createRequest(subjectId, new HashMap<>(), resourceId, new HashMap<>(), actionId, new HashMap<>()); }
@Test public void resourceIdFormDataExistsWithDefaultTest() throws Exception { FormDataMultiPart formPart = new FormDataMultiPart(); formPart.field(FORM_DATA_FIELD, FORM_DATA_VALUE); when(context.readEntity(FormDataMultiPart.class)).thenReturn(formPart); when(context.hasEntity()).thenReturn(true); when(context.getMediaType()).thenReturn(MediaType.MULTIPART_FORM_DATA_TYPE); when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdFormDataClass.class.getDeclaredMethod("formDataWithDefault")); IRI actionId = VALUE_FACTORY.createIRI(Read.TYPE); IRI resourceId = VALUE_FACTORY.createIRI(FORM_DATA_VALUE); IRI subjectId = VALUE_FACTORY.createIRI(ANON_USER); filter.filter(context); Mockito.verify(pdp).createRequest(subjectId, new HashMap<>(), resourceId, new HashMap<>(), actionId, new HashMap<>()); }
@Test public void resourceIdEmptyFormDataNoDefaultTest() throws Exception { exceptionRule.expect(MobiWebException.class); exceptionRule.expectMessage("Form parameters do not contain testFormDataField"); FormDataMultiPart formPart = new FormDataMultiPart(); when(context.readEntity(FormDataMultiPart.class)).thenReturn(formPart); when(context.hasEntity()).thenReturn(true); when(context.getMediaType()).thenReturn(MediaType.MULTIPART_FORM_DATA_TYPE); when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdFormDataClass.class.getDeclaredMethod("formDataNoDefault")); filter.filter(context); }
@Test public void resourceIdEmptyFormDataWithDefaultTest() throws Exception { FormDataMultiPart formPart = new FormDataMultiPart(); when(context.readEntity(FormDataMultiPart.class)).thenReturn(formPart); when(context.hasEntity()).thenReturn(true); when(context.getMediaType()).thenReturn(MediaType.MULTIPART_FORM_DATA_TYPE); when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdFormDataClass.class.getDeclaredMethod("formDataWithDefault")); IRI actionId = VALUE_FACTORY.createIRI(Read.TYPE); IRI resourceId = VALUE_FACTORY.createIRI(DEFAULT_RESOURCE_ID_IRI); IRI subjectId = VALUE_FACTORY.createIRI(ANON_USER); filter.filter(context); Mockito.verify(pdp).createRequest(subjectId, new HashMap<>(), resourceId, new HashMap<>(), actionId, new HashMap<>()); }
@Test public void resourceIdEmptyFormDataWithDefaultNotExistsTest() throws Exception { exceptionRule.expect(MobiWebException.class); exceptionRule.expectMessage("Form parameters do not contain testFormDataTwoField"); FormDataMultiPart formPart = new FormDataMultiPart(); when(context.readEntity(FormDataMultiPart.class)).thenReturn(formPart); when(context.hasEntity()).thenReturn(true); when(context.getMediaType()).thenReturn(MediaType.MULTIPART_FORM_DATA_TYPE); when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdFormDataClass.class.getDeclaredMethod("formDataWithDefaultNotExists")); filter.filter(context); }
@Test public void resourceIdMissingFormDataNoDefaultTest() throws Exception { exceptionRule.expect(MobiWebException.class); exceptionRule.expectMessage("Expected Request to have form data"); FormDataMultiPart formPart = new FormDataMultiPart(); when(context.readEntity(FormDataMultiPart.class)).thenReturn(formPart); when(context.hasEntity()).thenReturn(false); when(context.getMediaType()).thenReturn(MediaType.MULTIPART_FORM_DATA_TYPE); when(uriInfo.getPathParameters()).thenReturn(new MultivaluedHashMap<>()); when(uriInfo.getQueryParameters()).thenReturn(new MultivaluedHashMap<>()); when(resourceInfo.getResourceMethod()).thenReturn(MockResourceIdFormDataClass.class.getDeclaredMethod("formDataNoDefault")); filter.filter(context); }