Method Invocation Authorizers

Overview

When the SecurityManager is enabled, by default VMware GemFire throws a NotAuthorizedException when a method within a query is invoked and does not belong to the list of default allowed methods, given in RestrictedMethodAuthorizer.

The MethodInvocationAuthorizer is used to determine whether a specific method invocation on a given object should be allowed or denied during the execution of a particular OQL query.

Allowing users to execute arbitrary methods on any object present within the VMware GemFire member’s classpath could impact the integrity of the data and the system on which VMware GemFire is running. In order to avoid this problem, it is always recommended to enable a SecurityManager at the cluster level, give users only the permissions they require, and configure a MethodInvocationAuthorizer that meets your needs.

The main threats to which a VMware GemFire cluster might be exposed without a MethodInvocationAuthorizer are highlighted below.

Java Reflection

Allows the user to do anything within the JVM.

SELECT * FROM /region r WHERE r.getClass().forName('java.lang.Runtime').getDeclaredMethods()[0].invoke()

Cache Modification

Allows the user to do anything with the Cache: close it, access other regions, etc.

SELECT * FROM /region.getCache().close()

Region Modification

Allows the user to destroy, add or invalidate the entire Region, or specific entries.

SELECT * FROM /region.destroyRegion()
SELECT * FROM /region.put('xyz','abc')
SELECT * FROM /region.invalidate('xyz')

Region Modification

Allows the user to mutate the state of specific entries.

`SELECT r.setName('newName') FROM /region r`                                                                                  |

VMware GemFire Authorizers

VMware GemFire provides four authorizers out of the box, each one designed and implemented for a specific use case in mind. It is recommended to always use one of these authorizers, and only implement your own if your use case needs are not already met by one of them.

All of the implementations provided by VMware GemFire are designed to prevent security problems and have been thoroughly tested. Extra care should be taken, however, when configuring the internals of some of the authorizers as an incorrect configuration might introduce security holes into the system.

The table below shows a summary of which security threats are fully addressed by each authorizer and which ones might be exploitable, depending on how they are configured (details are shown later for each implementation).

RestrictedMethodAuthorizer

The default MethodInvocationAuthorizer used by VMware GemFire to determine whether a method is allowed to be executed on a specific object instance or not.

The implementation forbids the invocation of all methods during a query execution, except for the ones shown below:

Class Allowed Methods
java.lang.Object equals, toString, compareTo
java.lang.Boolean booleanValue
java.lang.Number byteValue, intValue, doubleValue, floatValue, longValue, shortValue
java.util.Date after, before, getTime
java.sql.Timestamp getNanos
java.lang.String chartAt, codePointAt, codePointBefore, codePointCount, compareToIgnoreCase, concat, contains, contentEquals, endsWith, equalsIgnoreCase, getBytes, hashCode, indexOf, intern, isEmpty, lastIndexOf, length, matches, offsetByCodePoints, replace, replaceAll, replaceFirst, split, startsWith, substring, toCharArray, toLowerCase, toUpperCase, trim
java.util.Map.Entry, org.apache.geode.cache.Region.Entry getKey, getValue
java.util.Collection, java.util.Map, org.apache.geode.cache.Region get, entrySet, keySet, values, getEntries, getValues, containsKey

The authorizer also provides utilities that can be used by custom implementations to determine whether a method is permanently forbidden or, if the method belongs to VMware GemFire, whether it is considered safe to be used within a query execution.

The methods getClass, readObject, readResolve, readObjectNoData, writeObject and writeReplace are permanently forbidden.

The below table shows those methods that belong to VMware GemFire and are considered safe (for methods on org.apache.geode.cache.Region, the authorizer also verifies that the user has the DATA:READ:RegionName permission).

Class Allowed Methods
org.apache.geode.cache.Region.Entry getKey, getValue
org.apache.geode.cache.Region get, entrySet, keySet, values, getEntries, getValues, containsKey

UnrestrictedMethodAuthorizer

A less restrictive MethodInvocationAuthorizer that allows any method invocation during the query execution as long as the following conditions are met:

This authorizer implementation addresses only three of the four main security risks: Java Reflection, Cache Modification and Region Modification. The Region Entry Modification security risk still exists: users with the DATA:READ:RegionName permission will be able to execute ANY method (even those that mutate the object) on the entries stored within the region and on instances used as bind parameters of the query, so this authorizer implementation must be used with extreme care.

Note: Usage of this authorizer is recommended for secured clusters on which only trusted users and applications have access to the query engine. It might also be used on clusters on which all entries stored are immutable.

JavaBeanAccessorMethodAuthorizer

A more flexible MethodInvocationAuthorizer that allows methods to be invoked during a query execution if and only if all of the following conditions are met:

  • The method is not considered permanently forbidden by the RestrictedMethodAuthorizer.
  • The method does not belong to VMware GemFire, or does belong but is considered safe by the RestrictedMethodAuthorizer.
  • The method follows the design patterns for accessor methods described in the JavaBean Specification 1.01; that is, the method name begins with is or get.
  • The target object on which the method will be executed belongs to a set of pre-configured packages.

When used as intended, and assuming that all region entries and bind parameters follow the JavaBean Specification 1.01, this authorizer implementation addresses all four security risks: Java Reflection, Cache Modification, Region Modification and Region Entry Modification. It should be noted, however, that the Region Entry Modification security threat might be re-introduced: users with the DATA:READ:RegionName privilege will be able to execute any method whose name starts with is or get on the objects stored within the region and on instances used as bind parameters, providing they are in the pre-configured packages. If those methods do not fully follow the JavaBean Specification 1.01 in that accessors do not mutate the object state, then instances could be potentially modified in place.

Note: Usage of this authorizer is only recommended for secured clusters on which the user has full confidence in that all objects stored within the regions and used as bind parameters follow the JavaBean Specification 1.01. It might also be used on clusters on which all entries stored are immutable.

RegExMethodAuthorizer

A fully flexible MethodInvocationAuthorizer that allows methods to be invoked during the query execution only if the the following conditions are met:

  • The method is not considered permanently forbidden by the RestrictedMethodAuthorizer.
  • The method does not belong to VMware GemFire, or does belong but is considered safe by the RestrictedMethodAuthorizer.
  • The fully qualified method name matches at least one of the pre-configured regular expressions.

When correctly configured, this authorizer implementation addresses the four main security risks: Java Reflection, Cache Modification, Region Modification and Region Entry Modification.
For the statement to remain true, however, the regular expressions used must be correctly configured so no mutator methods ever match. If the regular expressions are not restrictive enough, the Region Entry Modification security risk might be potentially re-introduced: users with the DATA:READ:RegionName privilege will be able to execute methods (even those modifying the entry) on the objects stored within the region and on instances used as bind parameters of the query.

Note: This authorizer must be used with extreme care, it is the most powerful in terms of flexibility and versatility (full control through regular expressions regarding what to allow and what to forbid); but it is also the most dangerous as one small mistake in the configured regular expressions can unexpectedly allow a wide variety of non safe methods to be executed.

Note: Usage of this authorizer implementation is only recommended for scenarios in which the user knows exactly what code is deployed to the cluster, allowing a correct configuration of the regular expressions used. It might also be used on clusters on which all entries stored are immutable.

Custom Authorizers

How Authorization Works

It is important to note that the query engine does not have any information about the actual type of the objects while pre-processing or parsing the query itself, neither can it obtain these details before actually executing the query. The actual check to determine whether a method is allowed or not must be executed while the objects are being traversed by the query engine in runtime.

The query engine, however, remembers whether a specific method has been already authorized or not for the current query execution context, meaning that the authorization will be executed only once in the lifetime of a particular query for every new method seen while traversing the objects. Nevertheless, the authorizer implementation must be highly performant as it will be invoked by VMware GemFire in runtime during the actual query execution.

Implementing a Method Authorizer

Complete these items to implement a custom method authorizer.

  • Decide which methods from your domain model should be allowed to be invoked during a query execution.
  • Decide which resources, if any, you will need in order to determine whether a method can be invoked or not.
  • Implement the initialize method of the MethodInvocationAuthorizer interface to fully configure your implementation, based on the resources needed to execute the authorization.
  • Implement the authorize method of the MethodInvocationAuthorizer interface. It must determine whether a method is allowed to be executed on a particular object instance during a query execution. The implementation should be lightning fast and thread safe.

Changing the Method Authorizer

You can set the MethodInvocationAuthorizer to be used by the query engine through the gfsh command-line utility. In addition, you can modify the configured MethodInvocationAuthorizer while members are already running by using the alter query-service command. It is always advisable to make these changes during periods of low activity, though.

The following constraints apply when the MethodInvocationAuthorizer used by the cluster is changed in runtime:

  • Queries started after the MethodInvocationAuthorizer is changed will use the newly configured authorizer.
  • Queries in flight are not affected. Before the query starts, it picks up the already configured MethodInvocationAuthorizer and will use it until the execution finishes.
  • Indexes configured with an expression using methods forbidden by the newly configured MethodInvocationAuthorizer will be marked as invalid the next time a mapping is added or removed from the index.
  • Continuous queries already running will pick up the newly configured MethodInvocationAuthorizer the next time the CQ is processed upon the arrival of a cache event. If the CQ has methods forbidden by the newly configured MethodInvocationAuthorizer, any subsequent execution will result in an error during the CQ processing, and the onError method will be invoked for the associated CqListener.

Note: In order to improve performance, the continuous query engine uses an internal cache to avoid executing the query in scenarios for which the answer can be automatically inferred. These results might become invalid after applying the new security rules, so VMware GemFire disables the usage of this optimization until the member is restarted or the query is registered again.