3 Using an Access Controller

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 Using SSL to Secure Communication, for detailed SSL instructions.

This chapter includes the following sections:

3.1 Overview of Using an Access Controller

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

Description of Figure 3-1 follows
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).

3.2 Using the Default Access Controller Implementation

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:

3.2.1 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.

3.2.2 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

3.2.3 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";
};

3.2.4 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>

3.2.5 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>

3.2.6 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

3.3 Using a Custom Access Controller Implementation

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="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>