3 Using an Access Controller
This chapter includes the following sections:
- Overview of Using an Access Controller
Coherence includes an access controller that is used to secure access to cluster resources and operations. A local login module is used to authenticate a caller, and an access controller on one or more cluster nodes verifies the access rights of the caller. - Using the Default Access Controller Implementation
Coherence includes a default access controller implementation that uses a standard Java keystore for authentication. - Using a Custom Access Controller Implementation
You can create a custom access controller implementation if you have specific security requirements that are not addressed by the default implementation.
Overview of Using an Access Controller
An access controller:
-
Grants or denies access to a protected clustered resource based on the caller's permissions
-
Encrypts outgoing communications based on the caller's private credentials
-
Decrypts incoming communications based on the caller's public credentials
A default access controller implementation is provided. The implementation is based on the key management infrastructure that ships as a standard part of the HotSpot JDK. See Using the Default Access Controller Implementation.
Figure 3-1 shows a conceptual view of securing two cluster members using access controllers.
Figure 3-1 Conceptual View of Access Controller Security
![Description of Figure 3-1 follows Description of Figure 3-1 follows](img/access_controller.png)
Description of "Figure 3-1 Conceptual View of Access Controller Security"
Understanding the Security Context
Each clustered service maintains the concept of a senior service member that serves as a controlling agent for a particular service. The senior member does not consult with other members when accessing a clustered resource. However, juniors member that want to join a service must request and receive a confirmation from the senior member. The senior member notifies all other cluster members about the joining member.
The security subsystem is designed to operate in a partially hostile environment because data is distributed among cluster members. Every member is considered to be a malicious member. That is, members are assumed to lack sufficient credentials to join a clustered service or obtain access to a clustered resource.
File system mechanisms and standard Java security policies guarantee the trustworthiness of a single node. However, there are two scenarios to consider with member communication:
-
A malicious node surpasses the local access check and attempts to join a clustered service or gain access to a clustered resource that a trusted node controls.
-
A malicious node creates a clustered service or clustered resource and becomes its controller.
The security subsystem uses a two-way encryption algorithm to prevent either of these two scenarios from occurring. All client requests must establish proof of identity, and all service responses must establish proof of trustworthiness.
Proof of Identity
The following client code sample authenticates a caller and performs necessary actions:
import com.tangosol.net.security.Security; import java.security.PrivilegedAction; import javax.security.auth.Subject; ... Subject subject = Security.login(sName, acPassword); PrivilegedAction action = new PrivilegedAction() { public Object run() { // all processing here is taking place with access // rights assigned to the corresponding Subject // for example: CacheFactory.getCache().put(key, value); ... } }; Security.runAs(subject, action);
The caller is authenticated using JAAS on the caller's node during the login
call. If the authentication is successful, the local access controller:
-
Determines whether the local caller has sufficient rights to access the protected clustered resource (local access check)
-
Encrypts the outgoing communications regarding the access to the resource with the caller's private credentials retrieved during the authentication phase
-
Decrypts the result of the remote check using the requester's public credentials
-
Verifies whether the responder has sufficient rights to be granted access
The encryption step provides proof of identity for the responder and blocks a malicious node that pretends to pass the local access check phase.
There are two additional ways to provide the client authentication information. First, pass a reference to a CallbackHandler
class instead of the user name and password. Second, use a previously authenticated Subject
. The latter approach is ideal when a Java EE application uses Oracle Coherence and retrieves an authenticated Subject
from the application container.
If a caller's request does not include any authentication context, a CallbackHandler
implementation is instantiated and called. The implementation is declared in an operational override file and retrieves the appropriate credentials. However, this lazy approach is much less efficient, because without an externally defined call scope every access to a protected clustered resource forces repetitive authentication calls.
Proof of Trustworthiness
Cluster members use explicit API calls to create clustered resources. The senior service member retains the private credentials that are presented during a call as a proof of trustworthiness. When the senior service member receives an access request to a protected clustered resource, the local access controller:
-
Decrypts the incoming communication using the remote caller's public credentials
-
Encrypts the access check response using the private credentials of the service.
-
Determines whether the remote caller has sufficient rights to access the protected clustered resource (remote access check).
Parent topic: Using an Access Controller
Using the Default Access Controller Implementation
com.tangosol.net.security.DefaultController
class. It is configured within the <security-config>
element in the operational deployment descriptor. See security-config in Developing Applications with Oracle Coherence.
This section includes the following topics:
- Enable the Access Controller
- Create a Keystore
- Include the Login Module
- Create a Permissions File
- Create an Authentication Callback Handler
- Enable Security Audit Logs
Parent topic: Using an Access Controller
Enable the Access Controller
To enable the default access controller implementation within the <security-config>
element, add an <enabled>
element that is set to true
. For example:
<security-config> <enabled system-property="coherence.security">true</enabled> </security-config>
The coherence.security
system property also enables the access controller. For example:
-Dcoherence.security=true
Note:
When access controller security is enabled, every call to the CacheFactory.getCache()
or ConfigurableCacheFactory.ensureCache()
API causes a security check. This negatively affects an application's performance if these calls are made frequently. The best practice is for the application to hold on to the cache reference and reuse it so that the security check is performed only on the initial call. With this approach, ensure that your application only uses the references in an authorized way.
Parent topic: Using the Default Access Controller Implementation
Create a Keystore
An access controller requires a keystore that is used by both the controller and login module. Create a keystore with necessary principals using the Java keytool
utility. Ensure that the keystore is found on the classpath at runtime, or use the coherence.security.keystore
system property to explicitly enter the name and location of the keystore. For example:
-Dcoherence.security.keystore=keystore.jks
The following example creates three principals: admin
(to be used by the Java Security framework), manager
, and worker
(to be used by Oracle Coherence).
keytool -genkey -v -keystore ./keystore.jks -storepass password -alias admin -keypass password -dname CN=Administrator,O=MyCompany,L=MyCity,ST=MyState keytool -genkey -v -keystore ./keystore.jks -storepass password -alias manager -keypass password -dname CN=Manager,OU=MyUnit keytool -genkey -v -keystore ./keystore.jks -storepass password -alias worker -keypass password -dname CN=Worker,OU=MyUnit
Parent topic: Using the Default Access Controller Implementation
Include the Login Module
Oracle Coherence includes the COHERENCE_HOME
/lib/security/
coherence-login.jar
Java keystore (JKS) login module, which depends only on standard Java run-time classes. Place the library in the JRE lib/ext
(standard extension) directory. The name in the <login-module-name>
element, within the <security-config>
element, serves as the application name in the COHERENCE_HOME
/lib/security/login.config
login module file. The login module declaration contains the path to the keystore. Change the keyStorePath
variable to the location of the keystore.
// LoginModule Configuration for Oracle Coherence Coherence { com.tangosol.security.KeystoreLogin required keyStorePath="${user.dir}${/}security${/}keystore.jks"; };
Parent topic: Using the Default Access Controller Implementation
Create a Permissions File
An access controller requires a permissions.xml
file that declares access rights for principals. See the COHERENCE_HOME
/lib/security/permissions.xsd
schema for the syntax of the permissions file. Ensure that the file is found on the classpath at runtime, or use the coherence.security.permissions
system property to explicitly enter the name and location of the permissions file. For example:
-Dcoherence.security.permissions=permissions.xml
The following example 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
.
<?xml version='1.0'?> <permissions> <grant> <principal> <class>javax.security.auth.x500.X500Principal</class> <name>CN=Manager,OU=MyUnit</name> </principal> <permission> <target>*</target> <action>all</action> </permission> </grant> <grant> <principal> <class>javax.security.auth.x500.X500Principal</class> <name>CN=Worker,OU=MyUnit</name> </principal> <permission> <target>cache=common*</target> <action>join</action> </permission> <permission> <target>service=invocation</target> <action>all</action> </permission> </grant> </permissions>
Parent topic: Using the Default Access Controller Implementation
Create an Authentication Callback Handler
An access controller uses an authentication callback handler to authenticate a client when all other authentication methods have been unsuccessful. To create a callback handler, implement the javax.security.auth.callback.CallbackHandler
interface.
Note:
the handler approach is much less efficient since without an externally defined call scope every access to a protected clustered resource forces repetitive authentication calls.
To configure a custom callback handler within the <security-config>
element, add a <callback-handler>
element that includes the fully qualified name of the implementation class. The following example configures a callback handler named MyCallbackHandler
.
<security-config> <callback-handler> <class-name>package.MyCallbackHandler</class-name> </callback-handler> </security-config>
Parent topic: Using the Default Access Controller Implementation
Enable Security Audit Logs
Security audit logs are used to track the cluster operations that are being performed by each user. Each operation results in a log message being emitted. For example:
"Destroy" action for cache "Accounts" has been permitted for the user "CN=Bob, OU=Accounting".
Security audit logs are not enabled by default. To enable audit logs within the <security-config>
element, override the security log initialization parameter within the <access-controller>
element and set the parameter value to true
. For example,
<security-config> <access-controller> <init-params> <init-param id="3"> <param-type>boolean</param-type> <param-value system-property="coherence.security.log"> true</param-value> </init-param> </init-params> </access-controller> </security-config>
The coherence.security.log
system property also enables security audit logs. For example:
-Dcoherence.security.log=true
Parent topic: Using the Default Access Controller Implementation
Using a Custom Access Controller Implementation
com.tangosol.net.security.AccessController
interface.
To configure a custom access controller within the <security-config>
element, add an <access-controller>
element that includes the fully qualified name of the implementation class. The following example configures a custom access controller called MyAccessController
.
<security-config> <enabled system-property="coherence.security">true</enabled> <access-controller> <class-name>package.MyAccessController</class-name> </access-controller> </security-config>
Specify any required initialization parameters by using the <init-params>
element. The following example includes parameters to pass the MyAccessController
class a keystore and a permissions file.
<security-config> <enabled system-property="coherence.security">true</enabled> <access-controller> <class-name>package.MyAccessController</class-name> <init-params> <init-param> <param-type>java.io.File</param-type> <param-value>./keystore.jks</param-value> </init-param> <init-param> <param-type>java.io.File</param-type> <param-value>./permissions.xml</param-value> </init-param> </init-params> </access-controller> </security-config>
Parent topic: Using an Access Controller