This topic explains how to use method invocation authorizers in VMware Tanzu GemFire.
When the SecurityManager
is enabled, by default Tanzu 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 Tanzu GemFire member’s classpath could impact the integrity of the data and the system on which Tanzu GemFire is running. 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 Tanzu 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
Tanzu GemFire provides four authorizers by default, each one designed and implemented for a specific use case in mind. VMware recommends that you 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 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).
The default MethodInvocationAuthorizer
used by 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 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 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 |
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.
NoteUsage 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.
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:
is
or get
.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.
NoteUsage 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.
A fully flexible MethodInvocationAuthorizer
that allows methods to be invoked during the query execution only if the the following conditions are met:
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.
CautionThis 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. Usage of this authorizer implementation is recommended only 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.
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 GemFire in runtime during the actual query execution.
Complete these items to implement a custom method authorizer.
initialize
method of the MethodInvocationAuthorizer
interface to fully configure your implementation, based on the resources needed to execute the authorization.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.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:
MethodInvocationAuthorizer
is changed will use the newly configured authorizer.MethodInvocationAuthorizer
and will use it until the execution finishes.MethodInvocationAuthorizer
will be marked as invalid the next time a mapping is added or removed from the index.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
.NoteIn 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 GemFire deactivates the usage of this optimization until the member is restarted or the query is registered again.