This chapter provides instructions for enabling an access controller to help protect against unauthorized use of cluster resources. The default access controller implementation is based on the key management infrastructure that is part of the HotSpot JDK. This implementation uses Java Authentication and Authorization Service (JAAS) for authentication.
Note:
This chapter does not discuss SSL. See Chapter 5, "Using SSL to Secure Communication," for detailed SSL instructions.
This chapter includes the following sections:
An access controller secures 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 a caller's access rights. See the JAAS Reference Guide for details on login modules.
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
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.
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.
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).
A default access controller implementation is provided that uses a standard Java keystore. The implementation class is the com.tangosol.net.security.DefaultController
class. It is configured within the <security-config>
element in the operational deployment descriptor. See Developing Applications with Oracle Coherence for details on the <security-config>
element and its subelements. To use the default access controller, complete the topics in this section.
This section includes the following topics:
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="tangosol.coherence.security">true</enabled> </security-config>
The tangosol.coherence.security
system property also enables the access controller. For example:
-Dtangosol.coherence.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.
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 tangosol.coherence.security.keystore
system property to explicitly enter the name and location of the keystore. For example:
-Dtangosol.coherence.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
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"; };
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 tangosol.coherence.security.permissions
system property to explicitly enter the name and location of the permissions file. For example:
-Dtangosol.coherence.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>
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>
Custom access controllers must implement the com.tangosol.net.security.AccessController
interface. See the Java API Reference for Oracle Coherence for details on using this API. 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="tangosol.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="tangosol.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>