RegExMethodAuthorizer implements MethodInvocationAuthorizer { @Override public boolean authorize(Method method, Object target) { if (restrictedMethodAuthorizer.isPermanentlyForbiddenMethod(method, target)) { return false; } if (target.getClass().getPackage().getName().startsWith(GEODE_BASE_PACKAGE)) { return restrictedMethodAuthorizer.isAllowedGeodeMethod(method, target); } String fullyQualifiedMethodName = target.getClass().getName() + "." + method.getName(); if (compiledPatterns.stream() .anyMatch(pattern -> pattern.matcher(fullyQualifiedMethodName).matches())) { return true; } return restrictedMethodAuthorizer.authorize(method, target); } RegExMethodAuthorizer(Cache cache, Set<String> allowedPatterns);  RegExMethodAuthorizer(RestrictedMethodAuthorizer restrictedMethodAuthorizer,
      Set<String> allowedPatterns); Set<String> getAllowedPatterns(); @Override boolean authorize(Method method, Object target);  }
@Test public void authorizeShouldReturnFalseForKnownDangerousMethods() throws Exception { TestBean testBean = new TestBean(); List<Method> dangerousMethods = new ArrayList<>(); dangerousMethods.add(TestBean.class.getMethod("getClass")); dangerousMethods.add(TestBean.class.getMethod("readResolve")); dangerousMethods.add(TestBean.class.getMethod("readObjectNoData")); dangerousMethods.add(TestBean.class.getMethod("readObject", ObjectInputStream.class)); dangerousMethods.add(TestBean.class.getMethod("writeReplace")); dangerousMethods.add(TestBean.class.getMethod("writeObject", ObjectOutputStream.class)); dangerousMethods.forEach(method -> assertThat( geodeRegExMatchingMethodAuthorizer.authorize(method, testBean)).isFalse()); }
@Test public void authorizeShouldReturnFalseForGeodeMethodsThatAreNotConsideredSafeEvenIfTheyMatchTheUserRegEx() throws Exception { Set<Pair<Method, Object>> methods = new HashSet<>(); methods.add(new Pair<>(TestBean.class.getMethod("accessor"), new TestBean())); methods.add(new Pair<>(TestBean.class.getMethod("mutator"), new TestBean())); methods.add(new Pair<>(BucketDump.class.getMethod("getValues"), mock(BucketDump.class))); methods.add(new Pair<>(RegionConfig.class.getMethod("getEntries"), mock(RegionConfig.class))); methods.add(new Pair<>(EntryEvent.class.getMethod("getKey"), mock(EntryEvent.class))); methods.add(new Pair<>(Valuable.class.getMethod("getValue"), mock(Valuable.class))); methods.add(new Pair<>(HAContainerMap.class.getMethod("containsKey", Object.class), mock(HAContainerMap.class))); methods.add(new Pair<>(HAContainerMap.class.getMethod("entrySet"), mock(HAContainerMap.class))); methods.add(new Pair<>(HAContainerMap.class.getMethod("get", Object.class), mock(HAContainerMap.class))); methods.add(new Pair<>(HAContainerMap.class.getMethod("keySet"), mock(HAContainerMap.class))); methods.add(new Pair<>(HAContainerMap.class.getMethod("values"), mock(HAContainerMap.class))); methods.forEach( pair -> assertThat(geodeRegExMatchingMethodAuthorizer.authorize(pair.getX(), pair.getY())) .as("For method: " + pair.getX().getName()).isFalse()); }
@Test public void authorizeShouldReturnFalseWheneverTheSecurityServiceDoesNotAllowOperationsOnTheRegion() throws Exception { Region region = mock(Region.class); Region localRegion = mock(LocalRegion.class); Region partitionedRegion = mock(PartitionedRegion.class); when(region.getName()).thenReturn("testRegion"); when(localRegion.getName()).thenReturn("testRegion"); when(partitionedRegion.getName()).thenReturn("testRegion"); doThrow(new NotAuthorizedException("Mock Exception")).when(mockSecurityService).authorize( ResourcePermission.Resource.DATA, ResourcePermission.Operation.READ, "testRegion"); List<Method> methods = new ArrayList<>(); methods.add(Map.class.getMethod("containsKey", Object.class)); methods.add(Map.class.getMethod("entrySet")); methods.add(Map.class.getMethod("get", Object.class)); methods.add(Map.class.getMethod("keySet")); methods.add(Map.class.getMethod("values")); methods.forEach(method -> { assertThat(geodeRegExMatchingMethodAuthorizer.authorize(method, region)).isFalse(); assertThat(geodeRegExMatchingMethodAuthorizer.authorize(method, localRegion)).isFalse(); assertThat(geodeRegExMatchingMethodAuthorizer.authorize(method, partitionedRegion)).isFalse(); }); }
@Test public void authorizeShouldReturnTrueForMapMethodsOnRegionInstancesWheneverTheSecurityServiceAllowsOperationsOnTheRegion() throws Exception { Region region = mock(Region.class); Region localRegion = mock(LocalRegion.class); Region partitionedRegion = mock(PartitionedRegion.class); List<Method> methods = new ArrayList<>(); methods.add(Map.class.getMethod("containsKey", Object.class)); methods.add(Map.class.getMethod("entrySet")); methods.add(Map.class.getMethod("get", Object.class)); methods.add(Map.class.getMethod("keySet")); methods.add(Map.class.getMethod("values")); methods.forEach(method -> { assertThat(geodeRegExMatchingMethodAuthorizer.authorize(method, region)).isTrue(); assertThat(geodeRegExMatchingMethodAuthorizer.authorize(method, localRegion)).isTrue(); assertThat(geodeRegExMatchingMethodAuthorizer.authorize(method, partitionedRegion)).isTrue(); }); }
@Test public void authorizeShouldReturnTrueForNonMatchingMethodsConsideredSafeByDefault() throws Exception { Set<Pair<Method, Object>> someSafeMethods = new HashSet<>(); someSafeMethods.add(new Pair<>(Object.class.getMethod("toString"), new Object())); someSafeMethods.add(new Pair<>(Object.class.getMethod("equals", Object.class), new Object())); someSafeMethods.add( new Pair<>(Comparable.class.getMethod("compareTo", Object.class), mock(Comparable.class))); someSafeMethods.add(new Pair<>(Number.class.getMethod("byteValue"), new Integer("0"))); someSafeMethods.add(new Pair<>(Date.class.getMethod("after", Date.class), new Date())); someSafeMethods.add(new Pair<>(String.class.getMethod("indexOf", int.class), "")); someSafeMethods.add(new Pair<>(Map.Entry.class.getMethod("getKey"), mock(Map.Entry.class))); someSafeMethods .add(new Pair<>(Map.class.getMethod("get", Object.class), Collections.emptyMap())); RegExMethodAuthorizer authorizer = new RegExMethodAuthorizer( new RestrictedMethodAuthorizer(mockCache), Collections.emptySet()); someSafeMethods.forEach(pair -> assertThat(authorizer.authorize(pair.getX(), pair.getY())) .as("For method: " + pair.getX().getName()).isTrue()); }
@Test public void authorizeShouldReturnFalseForNonMatchingMethodsThatAreNotConsideredSafeByDefault() throws Exception { Set<Pair<Method, Object>> someNonSafeMethods = new HashSet<>(); someNonSafeMethods.add(new Pair<>(Object.class.getMethod("wait"), new Object())); someNonSafeMethods.add(new Pair<>(Number.class.getMethod("notify"), new Integer("0"))); someNonSafeMethods.add(new Pair<>(Date.class.getMethod("setYear", int.class), new Date())); someNonSafeMethods.add(new Pair<>(Set.class.getMethod("add", Object.class), new HashSet<>())); someNonSafeMethods.add( new Pair<>(Map.Entry.class.getMethod("setValue", Object.class), mock(Map.Entry.class))); someNonSafeMethods.add( new Pair<>(Map.class.getMethod("put", Object.class, Object.class), Collections.emptyMap())); RegExMethodAuthorizer authorizer = new RegExMethodAuthorizer( new RestrictedMethodAuthorizer(mockCache), Collections.emptySet()); someNonSafeMethods.forEach(pair -> assertThat(authorizer.authorize(pair.getX(), pair.getY())) .as("For method: " + pair.getX().getName()).isFalse()); }
@Test public void authorizeShouldReturnTrueForMatchingMethods() throws Exception { RestrictedMethodAuthorizer defaultAuthorizer = new RestrictedMethodAuthorizer(mockCache); Set<String> regularExpressions = new HashSet<>(Arrays.asList("^java\\.lang\\..*\\.(?:wait|notify)", "^java\\.util\\..*\\.(?:set|put|add).*", ".*MockitoMock.*")); RegExMethodAuthorizer customAuthorizer = new RegExMethodAuthorizer(defaultAuthorizer, regularExpressions); Set<Pair<Method, Object>> someNonSafeMethods = new HashSet<>(); someNonSafeMethods.add(new Pair<>(Object.class.getMethod("wait"), new Object())); someNonSafeMethods.add(new Pair<>(Number.class.getMethod("notify"), new Integer("0"))); someNonSafeMethods.add(new Pair<>(Date.class.getMethod("setYear", int.class), new Date())); someNonSafeMethods.add(new Pair<>(Set.class.getMethod("add", Object.class), new HashSet<>())); someNonSafeMethods.add( new Pair<>(Map.Entry.class.getMethod("setValue", Object.class), mock(Map.Entry.class))); someNonSafeMethods .add(new Pair<>(Map.class.getMethod("put", Object.class, Object.class), new HashMap<>())); someNonSafeMethods .forEach(pair -> assertThat(customAuthorizer.authorize(pair.getX(), pair.getY())) .as("For method: " + pair.getX().getName()).isTrue()); }