Security Framework in Coherence is based on a concept of Clustered Access Controller, which can be turned on (activated) by a configurable parameter or command line attribute.
The Access Controller manages access to the "clustered resources", such as clustered services and caches and controls operations that include (but not limited to) the following:
The Access Controller serves three purposes:
Coherence uses a local LoginModule (see JAAS Reference Guide for details) to authenticate the caller and an Access Controller on one or more cluster nodes to verify the caller's access rights.
The Access Controller is a pluggable component that could be declared in the Coherence Deployment Descriptor. The specified class should implement the com.tangosol.net.security.AccessController interface.
Coherence provides a default Access Controller implementation that is based on the Key Management infrastructure that is shipped as a standard part of Sun's JDK.
Each clustered service in Coherence maintains a concept of a "senior" service member (cluster node), which serves as a controlling agent for a particular service. While the senior member does not have to consult anyone when accessing a clustered resource, any junior node willing to join that service has to request and receive a confirmation from the senior member, which in turn notifies all other cluster nodes about the joining node.
Since Coherence is a system providing distributed data management and computing, the security subsystem is designed to operate in a partially hostile environment. We assume that when there is data shared between two cluster nodes either node could be a malicious one - lacking sufficient credentials to join a clustered service or obtain access to a clustered resource.
Let's call a cluster node that may try to gain unauthorized access to clustered resources via non-standard means as a "malicious" node. The means of such an access could vary. They could range from attempts to get protected or private class data using reflection, replacing classes in the distribution (coherence.jar, tangosol.jar or other application binaries), modifying classes on-the-fly using custom ClassLoader(s) etc. Alternatively, a cluster node that never attempts to gain unauthorized access to clustered resources via non-standard means will be called a "trusted" node. It's important to note that even a trusted node may attempt to gain access to resources without having sufficient rights, but it does so in a standard way via exposed standard API.
File system mechanisms (the same that is used to protect the integrity of the Java runtime libraries) and standard Java security policy could be used to resolve an issue of guarantying the trustworthiness of a given single node. In a case of inter-node communications there are two dangers that we have to consider:
To prevent either of these two scenarios from occurring Coherence utilizes two-ways encryption algorithm: all client requests must be accompanied by the proof of identity and all service responses must be accompanied by the proof of trustworthiness.
In a case of an active Access Controller the client code could use the following construct to authenticate the caller and perform necessary actions:
During the "login" call Coherence utilizes JAAS that runs on the caller's node to authenticate the caller. In a case of successful authentication, it uses the local Access Controller to:
Step 2 in this cycle serves a role of the proof of identity for the responder preventing a malicious node pretending to pass the local access check phase.
There are two alternative ways to provide the client authentication information. First, a reference to a CallbackHandler could be passed instead of the user name and password. Second, a previously authenticated Subject could be used, which could become handy when Coherence is used by a J2EE application that could retrieve an authenticated Subject from the application container.
If a caller's request comes without any authentication context, Coherence will instantiate and call a CallbackHandler implementation declared in the Coherence operational descriptor to retrieve the appropriate credentials. However that "lazy" approach is much less efficient, since without externally defined call scope, every access to a protected clustered resource will force repetitive authentication calls.
Every clustered resource in Coherence is created by an explicit API call. A senior service member retains the private credentials that are presented during that call as a proof of trustworthiness. When the senior service member receives an access request to a protected clustered resource, it use the local Access Controller to:
Since the requestor will accept the response as valid only after decrypting it, step 3) in this cycle serves a role of the proof of trustworthiness for the requestor preventing a malicious node pretending to be a valid service senior.
Coherence is shipped with an Access Controller implementation that uses a standard Java KeyStore. The implementation class is com.tangosol.net.security.DefaultController and the corresponding part of the Coherence operational descriptor used to configure the default implementation looks like:
The "login-module-name" element serves as the application name in a login configuration file (see JAAS Reference Guide1 for complete details). Coherence is shipped with a Java keystore (JKS) based login module that is contained in the coherence-login.jar, which depends only on standard Java runtime classes and could be placed in the JRE's lib/ext (standard extension) directory. The corresponding login module declaration would look like:
The "access-controller" element defines the AccessController implementation that takes two parameters to instantiate. The first parameter is a path to the same keystore that will be used by both controller and login module. The second parameter is a path to the access permission file (see discussion below).
The "callback-handler" is an optional element that defines a custom implementation of the javax.security.auth.callback.CallbackHandler interface that would be instantiated and used by Coherence to authenticate the client when all other means are exhausted.
Two more steps have to be performed, to make the default Access Controller implementation usable in your application. First, we have to create a keystore with necessary principals. Then, we need to create the "permissions" file that would declare the access right for the corresponding principals.
Consider the following example that creates three principals: "admin" to be used by the Java Security framework; "manager" and "worker" to be used by Coherence:
Consider the following example that assigns all rights to the "Manager" principal, only "join" rights to the "Worker" principal for caches that have names prefixed by "common" and all rights to the "Worker" principal for the invocation service named "invocation":
1. The policy file format is fully described in J2SE Security Guide.
2. The binaries could be signed using the JDK jarsigner tool, for example:
and then additionally protected in the policy file:
3. All relevant files such as policy format, coherence binaries, and permissions should be protected by operating system mechanisms to prevent malicious modifications.