Chapter 1. Configuring Data Grid Authorization
Authorization restricts the ability to perform operations with Data Grid and access data. You assign users with roles that have different permission levels.
1.1. Data Grid Authorization
Data Grid lets you configure authorization to secure Cache Managers and cache instances. When user applications or clients attempt to perform an operation on secured Cached Managers and caches, they must provide an identity with a role that has sufficient permissions to perform that operation.
For example, you configure authorization on a specific cache instance so that invoking Cache.get()
requires an identity to be assigned a role with read permission while Cache.put()
requires a role with write permission.
In this scenario, if a user application or client with the reader
role attempts to write an entry, Data Grid denies the request and throws a security exception. If a user application or client with the writer
role sends a write request, Data Grid validates authorization and issues a token for subsequent operations.
Identity to Role Mapping
Identities are security Principals of type java.security.Principal
. Subjects, implemented with the javax.security.auth.Subject
class, represent a group of security Principals. In other words, a Subject represents a user and all groups to which it belongs.
Data Grid uses role mappers so that security principals correspond to roles, which represent one or more permissions.
The following image illustrates how security principals map to roles:
1.1.1. Permissions
Permissions control access to Cache Managers and caches by restricting the actions that you can perform. Permissions can also apply to specific entities such as named caches.
Permission | Function | Description |
---|---|---|
CONFIGURATION |
| Defines new cache configurations. |
LISTEN |
| Registers listeners against a Cache Manager. |
LIFECYCLE |
| Stops the Cache Manager. |
ALL | - | Includes all Cache Manager permissions. |
Permission | Function | Description |
---|---|---|
|
| Retrieves entries from a cache. |
WRITE |
| Writes, replaces, removes, evicts data in a cache. |
EXEC |
| Allows code execution against a cache. |
LISTEN |
| Registers listeners against a cache. |
BULK_READ |
| Executes bulk retrieve operations. |
BULK_WRITE |
| Executes bulk write operations. |
LIFECYCLE |
| Starts and stops a cache. |
ADMIN |
| Allows access to underlying components and internal structures. |
ALL | - | Includes all cache permissions. |
ALL_READ | - | Combines the READ and BULK_READ permissions. |
ALL_WRITE | - | Combines the WRITE and BULK_WRITE permissions. |
Combining permissions
You might need to combine permissions so that they are useful. For example, to allow "supervisors" to run stream operations but restrict "standard" users to puts and gets only, you can define the following mappings:
<role name="standard" permission="READ WRITE" /> <role name="supervisors" permission="READ WRITE EXEC BULK"/>
Reference
1.1.2. Role Mappers
Data Grid includes a PrincipalRoleMapper
API that maps security Principals in a Subject to authorization roles. There are two role mappers available by default:
- IdentityRoleMapper
Uses the Principal name as the role name.
-
Java class:
org.infinispan.security.mappers.IdentityRoleMapper
-
Declarative configuration:
<identity-role-mapper />
-
Java class:
- CommonNameRoleMapper
Uses the Common Name (CN) as the role name if the Principal name is a Distinguished Name (DN). For example the
cn=managers,ou=people,dc=example,dc=com
DN maps to themanagers
role.-
Java class:
org.infinispan.security.mappers.CommonRoleMapper
-
Declarative configuration:
<common-name-role-mapper />
-
Java class:
You can also use custom role mappers that implement the org.infinispan.security.PrincipalRoleMapper
interface. To configure custom role mappers declaratively, use: <custom-role-mapper class="my.custom.RoleMapper" />
1.2. Programmatically Configuring Authorization
When using Data Grid as an embedded library, you can configure authorization with the GlobalSecurityConfigurationBuilder
and ConfigurationBuilder
classes.
Procedure
Construct a
GlobalConfigurationBuilder
that enables authorization, specifies a role mapper, and defines a set of roles and permissions.GlobalConfigurationBuilder global = new GlobalConfigurationBuilder(); global .security() .authorization().enable() 1 .principalRoleMapper(new IdentityRoleMapper()) 2 .role("admin") 3 .permission(AuthorizationPermission.ALL) .role("reader") .permission(AuthorizationPermission.READ) .role("writer") .permission(AuthorizationPermission.WRITE) .role("supervisor") .permission(AuthorizationPermission.READ) .permission(AuthorizationPermission.WRITE) .permission(AuthorizationPermission.EXEC);
Enable authorization in the
ConfigurationBuilder
for caches to restrict access based on user roles.ConfigurationBuilder config = new ConfigurationBuilder(); config .security() .authorization() .enable(); 1
- 1
- Implicitly adds all roles from the global configuration.
If you do not want to apply all roles to a cache, explicitly define the roles that are authorized for caches as follows:
ConfigurationBuilder config = new ConfigurationBuilder(); config .security() .authorization() .enable() .role("admin") 1 .role("supervisor") .role("reader");
- 1
- Defines authorized roles for the cache. In this example, users who have the
writer
role only are not authorized for the "secured" cache. Data Grid denies any access requests from those users.
1.3. Declaratively Configuring Authorization
Configure authorization in your infinispan.xml
file.
Procedure
-
Configure the global authorization settings in the
cache-container
that specify a role mapper, and define a set of roles and permissions. Configure authorization for caches to restrict access based on user roles.
<infinispan> <cache-container default-cache="secured" name="secured"> <security> <authorization> 1 <identity-role-mapper /> 2 <role name="admin" permissions="ALL" /> 3 <role name="reader" permissions="READ" /> <role name="writer" permissions="WRITE" /> <role name="supervisor" permissions="READ WRITE EXEC"/> </authorization> </security> <local-cache name="secured"> <security> <authorization/> 4 </security> </local-cache> </cache-container> </infinispan>
If you do not want to apply all roles to a cache, explicitly define the roles that are authorized for caches as follows:
<infinispan> <cache-container default-cache="secured" name="secured"> <security> <authorization> <identity-role-mapper /> <role name="admin" permissions="ALL" /> <role name="reader" permissions="READ" /> <role name="writer" permissions="WRITE" /> <role name="supervisor" permissions="READ WRITE EXEC"/> </authorization> </security> <local-cache name="secured"> <security> <authorization roles="admin supervisor reader"/> 1 </security> </local-cache> </cache-container> </infinispan>
- 1
- Defines authorized roles for the cache. In this example, users who have the
writer
role only are not authorized for the "secured" cache. Data Grid denies any access requests from those users.
Reference
1.4. Code Execution with Secure Caches
When you configure Data Grid authorization and then construct a DefaultCacheManager
, it returns a SecureCache
that checks the security context before invoking any operations on the underlying caches. A SecureCache
also ensures that applications cannot retrieve lower-level insecure objects such as DataContainer
. For this reason, you must execute code with an identity that has the required authorization.
In Java, executing code with a specific identity usually means wrapping the code to be executed within a PrivilegedAction
as follows:
import org.infinispan.security.Security; Security.doAs(subject, new PrivilegedExceptionAction<Void>() { public Void run() throws Exception { cache.put("key", "value"); } });
With Java 8, you can simplify the preceding call as follows:
Security.doAs(mySubject, PrivilegedAction<String>() -> cache.put("key", "value"));
The preceding call uses the Security.doAs()
method instead of Subject.doAs()
. You can use either method with Data Grid, however Security.doAs()
provides better performance.
If you need the current Subject, use the following call to retrieve it from the Data Grid context or from the AccessControlContext:
Security.getSubject();