1. Infinispan Security
Infinispan provides security for components as well as data across different layers:
-
Within the core library to provide role-based access control (RBAC) to CacheManagers, Cache instances, and stored data.
-
Over remote protocols to authenticate client requests and encrypt network traffic.
-
Across nodes in clusters to authenticate new cluster members and encrypt the cluster transport.
The Infinispan core library uses standard Java security libraries such as JAAS, JSSE, JCA, JCE, and SASL to ease integration and improve compatibility with custom applications and container environments. For this reason, the Infinispan core library provides only interfaces and a set of basic implementations.
Infinispan servers support a wide range of security standards and mechanisms to readily integrate with enterprise-level security frameworks.
2. Configuring Infinispan Authorization
Authorization restricts the ability to perform operations with Infinispan and access data. You assign users with roles that have different permission levels.
2.1. Infinispan Authorization
Infinispan 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, Infinispan denies the request and throws a
security exception. If a user application or client with the writer
role
sends a write request, Infinispan validates authorization and issues a token
for subsequent operations.
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.
Infinispan 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:
2.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. |
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"/>
2.1.2. Role Mappers
Infinispan 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 />
-
- 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 />
-
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" />
2.2. Programmatically Configuring Authorization
When using Infinispan as an embedded library, you can configure authorization
with the GlobalSecurityConfigurationBuilder
and ConfigurationBuilder
classes.
-
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);
1 Enables Infinispan authorization for the Cache Manager. 2 Specifies an implementation of PrincipalRoleMapper
that maps Principals to roles.3 Defines roles and their associated permissions. -
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. Infinispan denies any access requests from those users.
2.3. Declaratively Configuring Authorization
Configure authorization in your infinispan.xml
file.
-
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>
1 Enables Infinispan authorization for the Cache Manager. 2 Specifies an implementation of PrincipalRoleMapper
that maps Principals to roles.3 Defines roles and their associated permissions. 4 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:
<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. Infinispan denies any access requests from those users.
2.4. Code Execution with Secure Caches
When you configure Infinispan 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 Infinispan, however
Security.doAs()
provides better performance.
If you need the current Subject, use the following call to retrieve it from the Infinispan context or from the AccessControlContext:
Security.getSubject();
3. Encrypting Cluster Transport
Secure cluster transport so that nodes communicate with encrypted messages. You can also configure Infinispan clusters to perform certificate authentication so that only nodes with valid identities can join.
3.1. Infinispan Cluster Security
To secure cluster traffic, you configure Infinispan nodes to encrypt JGroups message payloads with secret keys.
Infinispan nodes can obtain secret keys from either:
-
The coordinator node (asymmetric encryption).
-
A shared keystore (symmetric encryption).
You configure asymmetric encryption by adding the ASYM_ENCRYPT
protocol to a JGroups stack in your Infinispan configuration.
This allows Infinispan clusters to generate and distribute secret keys.
When using asymmetric encryption, you should also provide keystores so that nodes can perform certificate authentication and securely exchange secret keys. This protects your cluster from man-in-the-middle (MitM) attacks. |
Asymmetric encryption secures cluster traffic as follows:
-
The first node in the Infinispan cluster, the coordinator node, generates a secret key.
-
A joining node performs certificate authentication with the coordinator to mutually verify identity.
-
The joining node requests the secret key from the coordinator node. That request includes the public key for the joining node.
-
The coordinator node encrypts the secret key with the public key and returns it to the joining node.
-
The joining node decrypts and installs the secret key.
-
The node joins the cluster, encrypting and decrypting messages with the secret key.
You configure symmetric encryption by adding the SYM_ENCRYPT
protocol to a JGroups stack in your Infinispan configuration.
This allows Infinispan clusters to obtain secret keys from keystores that you provide.
-
Nodes install the secret key from a keystore on the Infinispan classpath at startup.
-
Node join clusters, encrypting and decrypting messages with the secret key.
ASYM_ENCRYPT
with certificate authentication provides an additional layer of encryption in comparison with SYM_ENCRYPT
.
You provide keystores that encrypt the requests to coordinator nodes for the secret key.
Infinispan automatically generates that secret key and handles cluster traffic, while letting you specify when to generate secret keys.
For example, you can configure clusters to generate new secret keys when nodes leave.
This ensures that nodes cannot bypass certificate authentication and join with old keys.
SYM_ENCRYPT
, on the other hand, is faster than ASYM_ENCRYPT
because nodes do not need to exchange keys with the cluster coordinator.
A potential drawback to SYM_ENCRYPT
is that there is no configuration to automatically generate new secret keys when cluster membership changes.
Users are responsible for generating and distributing the secret keys that nodes use to encrypt cluster traffic.
3.2. Configuring Cluster Transport with Asymmetric Encryption
Configure Infinispan clusters to generate and distribute secret keys that encrypt JGroups messages.
-
Create a keystore with certificate chains that enables Infinispan to verify node identity.
-
Place the keystore on the classpath for each node in the cluster.
For Infinispan Server, you put the keystore in the $ISPN_HOME directory.
-
Add the
SSL_KEY_EXCHANGE
andASYM_ENCRYPT
protocols to a JGroups stack in your Infinispan configuration, as in the following example:<infinispan> <jgroups> <stack name="encrypt-tcp" extends="tcp"> (1) <SSL_KEY_EXCHANGE keystore_name="mykeystore.jks" (2) keystore_password="changeit" (3) stack.combine="INSERT_AFTER" stack.position="VERIFY_SUSPECT"/> (4) <ASYM_ENCRYPT asym_keylength="2048" (5) asym_algorithm="RSA" (6) change_key_on_coord_leave = "false" (7) change_key_on_leave = "false" (8) use_external_key_exchange = "true" (9) stack.combine="INSERT_AFTER" stack.position="SSL_KEY_EXCHANGE"/> (10) </stack> </jgroups> <cache-container name="default" statistics="true"> <transport cluster="${infinispan.cluster.name}" stack="encrypt-tcp" (11) node-name="${infinispan.node.name:}"/> </cache-container> </infinispan>
1 Creates a secure JGroups stack named "encrypt-tcp" that extends the default TCP stack for Infinispan. 2 Names the keystore that nodes use to perform certificate authentication. 3 Specifies the keystore password. 4 Uses the stack.combine
andstack.position
attributes to insertSSL_KEY_EXCHANGE
into the default TCP stack after theVERIFY_SUSPECT
protocol.5 Specifies the length of the secret key that the coordinator node generates. The default value is 2048
.6 Specifies the cipher engine the coordinator node uses to generate secret keys. The default value is RSA
.7 Configures Infinispan to generate and distribute a new secret key when the coordinator node changes. 8 Configures Infinispan to generate and distribute a new secret key when nodes leave. 9 Configures Infinispan nodes to use the SSL_KEY_EXCHANGE
protocol for certificate authentication.10 Uses the stack.combine
andstack.position
attributes to insertASYM_ENCRYPT
into the default TCP stack after theSSL_KEY_EXCHANGE
protocol.11 Configures the Infinispan cluster to use the secure JGroups stack.
When you start your Infinispan cluster, the following log message indicates that the cluster is using the secure JGroups stack:
[org.infinispan.CLUSTER] ISPN000078: Starting JGroups channel cluster with stack <encrypted_stack_name>
Infinispan nodes can join the cluster only if they use ASYM_ENCRYPT
and can obtain the secret key from the coordinator node.
Otherwise the following message is written to Infinispan logs:
[org.jgroups.protocols.ASYM_ENCRYPT] <hostname>: received message without encrypt header from <hostname>; dropping it
The example ASYM_ENCRYPT
configuration in this procedure shows commonly used parameters.
Refer to JGroups documentation for the full set of available parameters.
3.3. Configuring Cluster Transport with Symmetric Encryption
Configure Infinispan clusters to encrypt JGroups messages with secret keys from keystores that you provide.
-
Create a keystore that contains a secret key.
-
Place the keystore on the classpath for each node in the cluster.
For Infinispan Server, you put the keystore in the $ISPN_HOME directory.
-
Add the
SYM_ENCRYPT
protocol to a JGroups stack in your Infinispan configuration, as in the following example:<infinispan> <jgroups> <stack name="encrypt-tcp" extends="tcp"> (1) <SYM_ENCRYPT keystore_name="myKeystore.p12" (2) keystore_type="PKCS12" (3) store_password="changeit" (4) key_password="changeit" (5) alias="myKey" (6) stack.combine="INSERT_AFTER" stack.position="VERIFY_SUSPECT"/> (7) </stack> </jgroups> <cache-container name="default" statistics="true"> <transport cluster="${infinispan.cluster.name}" stack="encrypt-tcp" (8) node-name="${infinispan.node.name:}"/> </cache-container> </infinispan>
1 Creates a secure JGroups stack named "encrypt-tcp" that extends the default TCP stack for Infinispan. 2 Names the keystore from which nodes obtain secret keys. 3 Specifies the keystore type. JGroups uses JCEKS by default. 4 Specifies the keystore password. 5 Specifies the secret key password. 6 Specifies the secret key alias. 7 Uses the stack.combine
andstack.position
attributes to insertSYM_ENCRYPT
into the default TCP stack after theVERIFY_SUSPECT
protocol.8 Configures the Infinispan cluster to use the secure JGroups stack.
When you start your Infinispan cluster, the following log message indicates that the cluster is using the secure JGroups stack:
[org.infinispan.CLUSTER] ISPN000078: Starting JGroups channel cluster with stack <encrypted_stack_name>
Infinispan nodes can join the cluster only if they use SYM_ENCRYPT
and can obtain the secret key from the shared keystore.
Otherwise the following message is written to Infinispan logs:
[org.jgroups.protocols.SYM_ENCRYPT] <hostname>: received message without encrypt header from <hostname>; dropping it
The example SYM_ENCRYPT
configuration in this procedure shows commonly used parameters.
Refer to JGroups documentation for the full set of available parameters.
4. Infinispan Ports and Protocols
As Infinispan distributes data across your network and can establish connections for external client requests, you should be aware of the ports and protocols that Infinispan uses to handle network traffic.
If run Infinispan as a remote server then you might need to allow remote clients through your firewall. Likewise, you should adjust ports that Infinispan nodes use for cluster communication to prevent conflicts or network issues.
4.1. Infinispan Server Ports and Protocols
Infinispan Server exposes endpoints on your network for remote client access.
Port | Protocol | Description |
---|---|---|
|
TCP |
Hot Rod and REST endpoint |
|
TCP |
Memcached endpoint, which is disabled by default. |
4.1.1. Configuring Network Firewalls for Remote Connections
Adjust any firewall rules to allow traffic between the server and external clients.
On Red Hat Enterprise Linux (RHEL) workstations, for example, you can allow
traffic to port 11222
with firewalld as follows:
# firewall-cmd --add-port=11222/tcp --permanent
success
# firewall-cmd --list-ports | grep 11222
11222/tcp
To configure firewall rules that apply across a network, you can use the nftables utility.
4.2. TCP and UDP Ports for Cluster Traffic
Infinispan uses the following ports for cluster transport messages:
Default Port | Protocol | Description |
---|---|---|
|
TCP/UDP |
JGroups cluster bind port |
|
UDP |
JGroups multicast |
Cross-Site Replication
Infinispan uses the following ports for the JGroups RELAY2 protocol:
7900
-
For Infinispan clusters running on Kubernetes.
7800
-
If using UDP for traffic between nodes and TCP for traffic between clusters.
7801
-
If using TCP for traffic between nodes and TCP for traffic between clusters.