/** * Returns true if the application user is authorized to the given namespace and has the given permissions. * * @param applicationUser the application user * @param namespace the namespace * @param permissions the permissions * * @return true if authorized, false otherwise */ private boolean isAuthorized(ApplicationUser applicationUser, String namespace, NamespacePermissionEnum... permissions) { if (applicationUser != null && applicationUser.getNamespaceAuthorizations() != null) { for (NamespaceAuthorization currentUserAuthorization : applicationUser.getNamespaceAuthorizations()) { List<NamespacePermissionEnum> currentUserNamespacePermissions = currentUserAuthorization.getNamespacePermissions(); if (currentUserNamespacePermissions == null) { currentUserNamespacePermissions = Collections.emptyList(); } if (StringUtils.equalsIgnoreCase(currentUserAuthorization.getNamespace(), namespace) && currentUserNamespacePermissions.stream().anyMatch(Arrays.asList(permissions)::contains)) { return true; } } } return false; }
/** * Returns true if the application user is authorized to the given namespace and has the given permissions. * * @param applicationUser the application user * @param namespace the namespace * @param permissions the permissions * * @return true if authorized, false otherwise */ private boolean isAuthorized(ApplicationUser applicationUser, String namespace, NamespacePermissionEnum... permissions) { if (applicationUser != null && applicationUser.getNamespaceAuthorizations() != null) { for (NamespaceAuthorization currentUserAuthorization : applicationUser.getNamespaceAuthorizations()) { List<NamespacePermissionEnum> currentUserNamespacePermissions = currentUserAuthorization.getNamespacePermissions(); if (currentUserNamespacePermissions == null) { currentUserNamespacePermissions = Collections.emptyList(); } if (StringUtils.equalsIgnoreCase(currentUserAuthorization.getNamespace(), namespace) && currentUserNamespacePermissions.stream().anyMatch(Arrays.asList(permissions)::contains)) { return true; } } } return false; }
/** * Gets a set of namespace codes which the current user is authorized for the given permissions. * * @param permissions List of permissions to query * * @return Set of namespace codes */ public Set<String> getAuthorizedNamespaces(NamespacePermissionEnum... permissions) { Set<String> namespaces = new HashSet<>(); if (SecurityContextHolder.getContext().getAuthentication() != null) { ApplicationUser applicationUser = getApplicationUser(); if (applicationUser != null) { for (NamespaceAuthorization namespaceAuthorization : applicationUser.getNamespaceAuthorizations()) { if (namespaceAuthorization.getNamespacePermissions().containsAll(Arrays.asList(permissions))) { namespaces.add(namespaceAuthorization.getNamespace()); } } } } return namespaces; }
/** * Gets a set of namespace codes which the current user is authorized for the given permissions. * * @param permissions List of permissions to query * * @return Set of namespace codes */ public Set<String> getAuthorizedNamespaces(NamespacePermissionEnum... permissions) { Set<String> namespaces = new HashSet<>(); if (SecurityContextHolder.getContext().getAuthentication() != null) { ApplicationUser applicationUser = getApplicationUser(); if (applicationUser != null) { for (NamespaceAuthorization namespaceAuthorization : applicationUser.getNamespaceAuthorizations()) { if (namespaceAuthorization.getNamespacePermissions().containsAll(Arrays.asList(permissions))) { namespaces.add(namespaceAuthorization.getNamespace()); } } } } return namespaces; }
@Override public UserAuthorizations getCurrentUser() { // Create the user authorizations. UserAuthorizations userAuthorizations = new UserAuthorizations(); // Get the application user. Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null) { SecurityUserWrapper securityUserWrapper = (SecurityUserWrapper) authentication.getPrincipal(); ApplicationUser applicationUser = securityUserWrapper.getApplicationUser(); userAuthorizations.setUserId(applicationUser.getUserId()); // If roles are present on the application user then filter the herd-specific security roles and add that information to the Current user. if (CollectionUtils.isNotEmpty(applicationUser.getRoles())) { userAuthorizations.setSecurityRoles(new ArrayList<>(getValidSecurityRoles(applicationUser.getRoles()))); } // Get all granted authorities for this user. Collection<GrantedAuthority> grantedAuthorities = securityUserWrapper.getAuthorities(); // Add relative security functions as per granted authorities, if any are present. if (CollectionUtils.isNotEmpty(grantedAuthorities)) { userAuthorizations.setSecurityFunctions( grantedAuthorities.stream().map(grantedAuthority -> new String(grantedAuthority.getAuthority())).collect(Collectors.toList())); } userAuthorizations.setNamespaceAuthorizations(new ArrayList<>(applicationUser.getNamespaceAuthorizations())); } return userAuthorizations; }
@Override public UserAuthorizations getCurrentUser() { // Create the user authorizations. UserAuthorizations userAuthorizations = new UserAuthorizations(); // Get the application user. Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null) { SecurityUserWrapper securityUserWrapper = (SecurityUserWrapper) authentication.getPrincipal(); ApplicationUser applicationUser = securityUserWrapper.getApplicationUser(); userAuthorizations.setUserId(applicationUser.getUserId()); // If roles are present on the application user then filter the herd-specific security roles and add that information to the Current user. if (CollectionUtils.isNotEmpty(applicationUser.getRoles())) { userAuthorizations.setSecurityRoles(new ArrayList<>(getValidSecurityRoles(applicationUser.getRoles()))); } // Get all granted authorities for this user. Collection<GrantedAuthority> grantedAuthorities = securityUserWrapper.getAuthorities(); // Add relative security functions as per granted authorities, if any are present. if (CollectionUtils.isNotEmpty(grantedAuthorities)) { userAuthorizations.setSecurityFunctions( grantedAuthorities.stream().map(grantedAuthority -> new String(grantedAuthority.getAuthority())).collect(Collectors.toList())); } userAuthorizations.setNamespaceAuthorizations(new ArrayList<>(applicationUser.getNamespaceAuthorizations())); } return userAuthorizations; }
@Test public void testBuildNamespaceAuthorizationsAssertWildcardEntityNotAddedIfMatchFails() { ApplicationUser applicationUser = new ApplicationUser(getClass()); String userId = "userId"; applicationUser.setUserId(userId); when(configurationHelper.getBooleanProperty(any())).thenReturn(true); List<UserNamespaceAuthorizationEntity> wildcardEntities = new ArrayList<>(); UserNamespaceAuthorizationEntity wildcardEntity = new UserNamespaceAuthorizationEntity(); wildcardEntity.setUserId("wildcardEntityUserId"); NamespaceEntity namespaceEntity = new NamespaceEntity(); namespaceEntity.setCode("namespace"); wildcardEntity.setNamespace(namespaceEntity); wildcardEntities.add(wildcardEntity); when(userNamespaceAuthorizationDao.getUserNamespaceAuthorizationsByUserIdStartsWith(any())).thenReturn(wildcardEntities); when(wildcardHelper.matches(any(), any())).thenReturn(false); userNamespaceAuthorizationHelper.buildNamespaceAuthorizations(applicationUser); assertEquals(0, applicationUser.getNamespaceAuthorizations().size()); verify(userNamespaceAuthorizationDao).getUserNamespaceAuthorizationsByUserId(eq(userId)); verify(userNamespaceAuthorizationDao).getUserNamespaceAuthorizationsByUserIdStartsWith(eq(WildcardHelper.WILDCARD_TOKEN)); verify(wildcardHelper).matches(eq(userId.toUpperCase()), eq(wildcardEntity.getUserId().toUpperCase())); verifyNoMoreInteractions(userNamespaceAuthorizationDao, wildcardHelper); } }
applicationUser.setUserId(userId); applicationUser.setNamespaceAuthorizations(new HashSet<>()); applicationUser.getNamespaceAuthorizations().add(new NamespaceAuthorization("foo", Arrays.asList(NamespacePermissionEnum.READ))); applicationUser.getNamespaceAuthorizations().add(new NamespaceAuthorization("bar", Arrays.asList(NamespacePermissionEnum.WRITE))); SecurityContextHolder.getContext().setAuthentication( new TestingAuthenticationToken(new SecurityUserWrapper(userId, "", false, false, false, false, Arrays.asList(), applicationUser), null));
@Test public void checkPermissionAssertAccessApprovedWhenUserRequiresMultiplePermissionsButIsMissingOne() throws Exception { // Mock a join point of the method call // mockMethodMultiplePermissions("foo"); JoinPoint joinPoint = mock(JoinPoint.class); MethodSignature methodSignature = mock(MethodSignature.class); Method method = NamespaceSecurityAdviceTest.class.getDeclaredMethod("mockMethodMultiplePermissions", String.class); when(methodSignature.getMethod()).thenReturn(method); when(methodSignature.getParameterNames()).thenReturn(new String[] {"namespace"}); when(joinPoint.getSignature()).thenReturn(methodSignature); when(joinPoint.getArgs()).thenReturn(new Object[] {"foo"}); String userId = "userId"; ApplicationUser applicationUser = new ApplicationUser(getClass()); applicationUser.setUserId(userId); applicationUser.setNamespaceAuthorizations(new HashSet<>()); // User requires both READ and WRITE, but only has READ // It works now as the permissions in the same space are treated using OR logic now applicationUser.getNamespaceAuthorizations().add(new NamespaceAuthorization("foo", Arrays.asList(NamespacePermissionEnum.READ))); SecurityContextHolder.getContext().setAuthentication( new TestingAuthenticationToken(new SecurityUserWrapper(userId, "", false, false, false, false, Arrays.asList(), applicationUser), null)); try { namespaceSecurityAdvice.checkPermission(joinPoint); } catch (Exception e) { fail(); } }
@Test public void checkPermissionAssertNoErrorWhenUserHasMultiplePermissions() throws Exception { // Mock a join point of the method call // mockMethod("foo"); JoinPoint joinPoint = mock(JoinPoint.class); MethodSignature methodSignature = mock(MethodSignature.class); Method method = NamespaceSecurityAdviceTest.class.getDeclaredMethod("mockMethod", String.class); when(methodSignature.getMethod()).thenReturn(method); when(methodSignature.getParameterNames()).thenReturn(new String[] {"namespace"}); when(joinPoint.getSignature()).thenReturn(methodSignature); when(joinPoint.getArgs()).thenReturn(new Object[] {"foo"}); String userId = "userId"; ApplicationUser applicationUser = new ApplicationUser(getClass()); applicationUser.setUserId(userId); applicationUser.setNamespaceAuthorizations(new HashSet<>()); applicationUser.getNamespaceAuthorizations() .add(new NamespaceAuthorization("foo", Arrays.asList(NamespacePermissionEnum.READ, NamespacePermissionEnum.WRITE))); SecurityContextHolder.getContext().setAuthentication( new TestingAuthenticationToken(new SecurityUserWrapper(userId, "", false, false, false, false, Arrays.asList(), applicationUser), null)); try { namespaceSecurityAdvice.checkPermission(joinPoint); } catch (AccessDeniedException e) { fail(); } }
@Test public void checkPermissionAssertNoExceptionWhenHasPermissionsNamespaceIgnoreCase() throws Exception { // Mock a join point of the method call // mockMethod("foo"); JoinPoint joinPoint = mock(JoinPoint.class); MethodSignature methodSignature = mock(MethodSignature.class); Method method = NamespaceSecurityAdviceTest.class.getDeclaredMethod("mockMethod", String.class); when(methodSignature.getParameterNames()).thenReturn(new String[] {"namespace"}); when(methodSignature.getMethod()).thenReturn(method); when(joinPoint.getSignature()).thenReturn(methodSignature); when(joinPoint.getArgs()).thenReturn(new Object[] {"foo"}); String userId = "userId"; ApplicationUser applicationUser = new ApplicationUser(getClass()); applicationUser.setUserId(userId); applicationUser.setNamespaceAuthorizations(new HashSet<>()); // user has permission to capital "FOO" and needs permission to lowercase "foo" applicationUser.getNamespaceAuthorizations().add(new NamespaceAuthorization("FOO", Arrays.asList(NamespacePermissionEnum.READ))); SecurityContextHolder.getContext().setAuthentication( new TestingAuthenticationToken(new SecurityUserWrapper(userId, "", false, false, false, false, Arrays.asList(), applicationUser), null)); try { namespaceSecurityAdvice.checkPermission(joinPoint); } catch (AccessDeniedException e) { fail(); } }
@Test public void checkPermissionAssertNoExceptionWhenHasPermissionsNamespaceTrimmed() throws Exception { // Mock a join point of the method call // mockMethod(" foo "); JoinPoint joinPoint = mock(JoinPoint.class); MethodSignature methodSignature = mock(MethodSignature.class); Method method = NamespaceSecurityAdviceTest.class.getDeclaredMethod("mockMethod", String.class); when(methodSignature.getParameterNames()).thenReturn(new String[] {"namespace"}); when(methodSignature.getMethod()).thenReturn(method); when(joinPoint.getSignature()).thenReturn(methodSignature); when(joinPoint.getArgs()).thenReturn(new Object[] {BLANK_TEXT + "foo" + BLANK_TEXT}); String userId = "userId"; ApplicationUser applicationUser = new ApplicationUser(getClass()); applicationUser.setUserId(userId); applicationUser.setNamespaceAuthorizations(new HashSet<>()); // User has permission to "foo" but the actual namespace given is " foo " applicationUser.getNamespaceAuthorizations().add(new NamespaceAuthorization("foo", Arrays.asList(NamespacePermissionEnum.READ))); SecurityContextHolder.getContext().setAuthentication( new TestingAuthenticationToken(new SecurityUserWrapper(userId, "", false, false, false, false, Arrays.asList(), applicationUser), null)); try { namespaceSecurityAdvice.checkPermission(joinPoint); } catch (AccessDeniedException e) { fail(); } }
@Test public void checkPermissionAssertAccessDeniedWhenCurrentUserHasNoAnyRequiredPermissions() throws Exception { // Mock a join point of the method call // mockMethod("foo"); JoinPoint joinPoint = mock(JoinPoint.class); MethodSignature methodSignature = mock(MethodSignature.class); Method method = NamespaceSecurityAdviceTest.class.getDeclaredMethod("mockMethodMultiplePermissions", String.class); when(methodSignature.getParameterNames()).thenReturn(new String[] {"namespace"}); when(methodSignature.getMethod()).thenReturn(method); when(joinPoint.getSignature()).thenReturn(methodSignature); when(joinPoint.getArgs()).thenReturn(new Object[] {"foo"}); String userId = "userId"; ApplicationUser applicationUser = new ApplicationUser(getClass()); applicationUser.setUserId(userId); applicationUser.setNamespaceAuthorizations(new HashSet<>()); applicationUser.getNamespaceAuthorizations().add(new NamespaceAuthorization("foo", Arrays.asList(NamespacePermissionEnum.WRITE_DESCRIPTIVE_CONTENT))); SecurityContextHolder.getContext().setAuthentication( new TestingAuthenticationToken(new SecurityUserWrapper(userId, "", false, false, false, false, Arrays.asList(), applicationUser), null)); try { namespaceSecurityAdvice.checkPermission(joinPoint); fail(); } catch (Exception e) { assertEquals(AccessDeniedException.class, e.getClass()); assertEquals(String.format("User \"%s\" does not have \"[READ OR WRITE]\" permission(s) to the namespace \"foo\"", userId), e.getMessage()); } }
applicationUser.setUserId(userId); applicationUser.setNamespaceAuthorizations(new HashSet<>()); applicationUser.getNamespaceAuthorizations().add(new NamespaceAuthorization("foo", Arrays.asList(NamespacePermissionEnum.READ))); SecurityContextHolder.getContext().setAuthentication( new TestingAuthenticationToken(new SecurityUserWrapper(userId, "", false, false, false, false, Arrays.asList(), applicationUser), null));
@Test public void testBuildNamespaceAuthorizationsAssertWildcardQueryExecuted() { ApplicationUser applicationUser = new ApplicationUser(getClass()); String userId = "userId"; applicationUser.setUserId(userId); when(configurationHelper.getBooleanProperty(any())).thenReturn(true); List<UserNamespaceAuthorizationEntity> wildcardEntities = new ArrayList<>(); UserNamespaceAuthorizationEntity wildcardEntity = new UserNamespaceAuthorizationEntity(); wildcardEntity.setUserId("wildcardEntityUserId"); NamespaceEntity namespaceEntity = new NamespaceEntity(); namespaceEntity.setCode("namespace"); wildcardEntity.setNamespace(namespaceEntity); wildcardEntities.add(wildcardEntity); when(userNamespaceAuthorizationDao.getUserNamespaceAuthorizationsByUserIdStartsWith(any())).thenReturn(wildcardEntities); when(wildcardHelper.matches(any(), any())).thenReturn(true); userNamespaceAuthorizationHelper.buildNamespaceAuthorizations(applicationUser); assertEquals(1, applicationUser.getNamespaceAuthorizations().size()); NamespaceAuthorization namespaceAuthorization = IterableUtils.get(applicationUser.getNamespaceAuthorizations(), 0); assertEquals(namespaceEntity.getCode(), namespaceAuthorization.getNamespace()); verify(userNamespaceAuthorizationDao).getUserNamespaceAuthorizationsByUserId(eq(userId)); verify(userNamespaceAuthorizationDao).getUserNamespaceAuthorizationsByUserIdStartsWith(eq(WildcardHelper.WILDCARD_TOKEN)); verify(wildcardHelper).matches(eq(userId.toUpperCase()), eq(wildcardEntity.getUserId().toUpperCase())); verifyNoMoreInteractions(userNamespaceAuthorizationDao, wildcardHelper); }
@Test public void checkPermissionAssertAccessDeniedWhenCurrentUserHasNullPermissions() throws Exception { // Mock a join point of the method call // mockMethod("foo"); JoinPoint joinPoint = mock(JoinPoint.class); MethodSignature methodSignature = mock(MethodSignature.class); Method method = NamespaceSecurityAdviceTest.class.getDeclaredMethod("mockMethod", String.class); when(methodSignature.getParameterNames()).thenReturn(new String[] {"namespace"}); when(methodSignature.getMethod()).thenReturn(method); when(joinPoint.getSignature()).thenReturn(methodSignature); when(joinPoint.getArgs()).thenReturn(new Object[] {"foo"}); String userId = "userId"; ApplicationUser applicationUser = new ApplicationUser(getClass()); applicationUser.setUserId(userId); applicationUser.setNamespaceAuthorizations(new HashSet<>()); applicationUser.getNamespaceAuthorizations().add(new NamespaceAuthorization("foo", null)); SecurityContextHolder.getContext().setAuthentication( new TestingAuthenticationToken(new SecurityUserWrapper(userId, "", false, false, false, false, Arrays.asList(), applicationUser), null)); try { namespaceSecurityAdvice.checkPermission(joinPoint); fail(); } catch (Exception e) { assertEquals(AccessDeniedException.class, e.getClass()); assertEquals(String.format("User \"%s\" does not have \"[READ]\" permission(s) to the namespace \"foo\"", userId), e.getMessage()); } }
@Test public void testBuildNamespaceAuthorizationsAssertAuthLookupByUserId() { ApplicationUser applicationUser = new ApplicationUser(getClass()); String userId = "userId"; applicationUser.setUserId(userId); when(configurationHelper.getBooleanProperty(any())).thenReturn(true); List<UserNamespaceAuthorizationEntity> userNamespaceAuthorizationEntities = new ArrayList<>(); UserNamespaceAuthorizationEntity userNamespaceAuthorizationEntity = new UserNamespaceAuthorizationEntity(); userNamespaceAuthorizationEntity.setUserId("userNamespaceAuthorizationEntityUserId"); NamespaceEntity namespaceEntity = new NamespaceEntity(); namespaceEntity.setCode("namespace"); userNamespaceAuthorizationEntity.setNamespace(namespaceEntity); userNamespaceAuthorizationEntities.add(userNamespaceAuthorizationEntity); when(userNamespaceAuthorizationDao.getUserNamespaceAuthorizationsByUserId(any())).thenReturn(userNamespaceAuthorizationEntities); userNamespaceAuthorizationHelper.buildNamespaceAuthorizations(applicationUser); assertEquals(1, applicationUser.getNamespaceAuthorizations().size()); NamespaceAuthorization namespaceAuthorization = IterableUtils.get(applicationUser.getNamespaceAuthorizations(), 0); assertEquals(namespaceEntity.getCode(), namespaceAuthorization.getNamespace()); verify(userNamespaceAuthorizationDao).getUserNamespaceAuthorizationsByUserId(eq(userId)); verify(userNamespaceAuthorizationDao).getUserNamespaceAuthorizationsByUserIdStartsWith(eq(WildcardHelper.WILDCARD_TOKEN)); verifyNoMoreInteractions(userNamespaceAuthorizationDao, wildcardHelper); }
@Test public void testGetJobAssertNoErrorGivenJobCompletedAndUserDoesHasPermissions() throws Exception { jobDefinitionServiceTestHelper.createJobDefinition(null); Job job = jobService.createAndStartJob(jobServiceTestHelper.createJobCreateRequest(TEST_ACTIVITI_NAMESPACE_CD, TEST_ACTIVITI_JOB_NAME)); String username = "username"; ApplicationUser applicationUser = new ApplicationUser(getClass()); applicationUser.setUserId(username); applicationUser.setNamespaceAuthorizations(new HashSet<>()); applicationUser.getNamespaceAuthorizations().add(new NamespaceAuthorization(TEST_ACTIVITI_NAMESPACE_CD, Arrays.asList(NamespacePermissionEnum.READ))); SecurityContextHolder.getContext().setAuthentication( new TestingAuthenticationToken(new SecurityUserWrapper(username, "password", false, false, false, false, Collections.emptyList(), applicationUser), null)); try { jobService.getJob(job.getId(), false); } catch (AccessDeniedException e) { fail(); } }
@Test public void testGetJobAssertNoErrorGivenJobRunningAndUserDoesHasPermissions() throws Exception { jobDefinitionServiceTestHelper.createJobDefinition(ACTIVITI_XML_TEST_USER_TASK_WITH_CLASSPATH); Job job = jobService.createAndStartJob(jobServiceTestHelper.createJobCreateRequest(TEST_ACTIVITI_NAMESPACE_CD, TEST_ACTIVITI_JOB_NAME)); String username = "username"; ApplicationUser applicationUser = new ApplicationUser(getClass()); applicationUser.setUserId(username); applicationUser.setNamespaceAuthorizations(new HashSet<>()); applicationUser.getNamespaceAuthorizations().add(new NamespaceAuthorization(TEST_ACTIVITI_NAMESPACE_CD, Arrays.asList(NamespacePermissionEnum.READ))); SecurityContextHolder.getContext().setAuthentication( new TestingAuthenticationToken(new SecurityUserWrapper(username, "password", false, false, false, false, Collections.emptyList(), applicationUser), null)); try { jobService.getJob(job.getId(), false); } catch (AccessDeniedException e) { fail(); } }
@Test public void testDeleteJobAssertNoErrorWhenUserHasPermissions() throws Exception { // Start a job that will wait in a receive task jobDefinitionServiceTestHelper.createJobDefinition(ACTIVITI_XML_TEST_RECEIVE_TASK_WITH_CLASSPATH); Job job = jobService.createAndStartJob(jobServiceTestHelper.createJobCreateRequest(TEST_ACTIVITI_NAMESPACE_CD, TEST_ACTIVITI_JOB_NAME)); String username = "username"; ApplicationUser applicationUser = new ApplicationUser(getClass()); applicationUser.setUserId(username); applicationUser.setNamespaceAuthorizations(new HashSet<>()); applicationUser.getNamespaceAuthorizations() .add(new NamespaceAuthorization(TEST_ACTIVITI_NAMESPACE_CD, Arrays.asList(NamespacePermissionEnum.EXECUTE))); SecurityContextHolder.getContext().setAuthentication( new TestingAuthenticationToken(new SecurityUserWrapper(username, "password", false, false, false, false, Collections.emptyList(), applicationUser), null)); try { jobService.deleteJob(job.getId(), new JobDeleteRequest("test delete reason")); } catch (AccessDeniedException e) { fail(); } }