Skip Headers
Oracle® Coherence Developer's Guide
Release 3.6.1

Part Number E15723-03
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

30 Securing Coherence

This chapter describes the following security features:

Using the Access Controller

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 following topics are included in this section:

Overview of the Access Controller

The Access Controller manages access to clustered resources, such as clustered services and caches and controls operations that include (but are not limited to) the following:

  • creating a new clustered cache or service

  • joining an existing clustered cache or service

  • destroying an existing clustered cache

The Access Controller serves three purposes:

  • grant or deny access to a protected clustered resource based on the caller's permissions

  • encrypt outgoing communications based on the caller's private credentials

  • decrypt incoming communications based on the caller's public credentials

Coherence uses a local Login Module (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, tangosol-coherence.xml. The specified class must 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. See"Enabling the Default Access Controller Implementation".

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 by using nonstandard 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 or other application binaries), modifying classes on-the-fly using custom class loader(s) and so on. Alternatively, a cluster node that never attempts to gain unauthorized access to clustered resources by using nonstandard 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 by using the 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 to consider:

  • A malicious node surpasses the local access check and attempts to join a clustered service or gain access to a clustered resource controlled by a trusted node

  • A malicious node creates a clustered service or clustered resource becoming its controller

To prevent either of these two scenarios from occurring Coherence uses two-way 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.

Proof of Identity

In the case of an active Access Controller, the client code can use the following construct to authenticate the caller and perform 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
        ...
        }
    };
Security.runAs(subject, action);

During the login call, Coherence uses 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:

  • Determine whether the local caller has sufficient rights to access the protected clustered resource (local access check)

  • Encrypt the outgoing communications regarding the access to the resource with the caller's private credentials retrieved during the authentication phase

  • Decrypt the result of the remote check using the requester's public credentials

  • In the case that access is granted verify whether the responder had sufficient rights to do so

The encrypt step (above) serves the 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 Java EE 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.

Proof of Trustworthiness

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:

  • Decrypt the incoming communication using the remote caller's public credentials

  • Encrypt the response of access check using the private credentials of the service

  • Determine whether the remote caller has sufficient rights to access the protected clustered resource (remote access check)

Since the requester will accept the response as valid only after decrypting it, the last step in this cycle serves a role of the proof of trustworthiness for the requester preventing a malicious node pretending to be a valid service senior.

Enabling the Default Access Controller Implementation

Coherence ships with a default Access Controller implementation that uses a standard Java keystore. The implementation class is the com.tangosol.net.security.DefaultController class and is configured in the Coherence operational deployment descriptor.

<security-config>
  <enabled system-property="tangosol.coherence.security">false</enabled>
  <login-module-name>Coherence</login-module-name>
  <access-controller>
    <class-name>com.tangosol.net.security.DefaultController</class-name>
    <init-params>
      <init-param id="1">
        <param-type>java.io.File</param-type>
        <param-value>./keystore.jks</param-value>
      </init-param>
      <init-param id="2">
        <param-type>java.io.File</param-type>
        <param-value>./permissions.xml</param-value>
      </init-param>
    </init-params>
  </access-controller>
  <callback-handler>
    <class-name/>
  </callback-handler>
</security-config>

The default access controller implementation is not enabled by default. To enable the default implementation, override the <enabled> element within the <security-config> node in an operational override file and set it to true. For example:

<coherence>
   <security-config>
      <enabled>true</enabled>
   </security-config>
</coherence>

The default access controller implementation can also by enabled by setting the tangosol.coherence.security system property to true.

Note:

When Coherence security is enabled, every call to the CacheFactory.getCache() or ConfigurableCacheFactory.ensureCache() API causes a security check. This can negatively impact an application's performance if these calls are made very frequently. The best practice is for the application to hold on to the cache reference and re-use it so that the security check is only performed on the initial call. When using this approach, it is the application's responsibility to ensure that those references are only used in an authorized way.

The <login-module-name> element serves as the application name in a login configuration file (see JAAS Reference Guide 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:

// LoginModule Configuration for Oracle Coherence(TM)
Coherence {
    com.tangosol.security.KeystoreLogin required
      keyStorePath="${user.dir}${/}keystore.jks";
};

The <access-controller> element defines the Access Controller 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:

  1. Create a keystore with necessary principals.

  2. 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:

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

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:

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

Working in Applications with Installed Security Manager

Complete the following steps when working in applications with the installed security manager.

  1. Enter the minimum set of privileges in the policy file.

    The minimum set of privileges required for Coherence to function are specified in the security.policy file which is included as part of the Coherence installation. This file can be found in COHERENCE_HOME/lib/security/security.policy.

    The policy file format is fully described in Java SE Security Guide. See

    http://java.sun.com/j2se/1.4.2/docs/guide/security/spec/security-spec.doc3.html#20128

    For example:

    grant codeBase "file:${coherence.home}/lib/coherence.jar"
        {
                permission java.security.AllPermission;
        };
    
  2. Sign the binaries using the JDK jarsigner tool, for example:

    jarsigner -keystore ./keystore.jks -storepass password coherence.jar admin
    

    and then additionally protected in the policy file:

    grant SignedBy "admin" codeBase "file:${coherence.home}/lib/coherence.jar"
        {
                permission java.security.AllPermission;
        };
    
  3. Use operating system mechanisms to protect all relevant files such as policy format, coherence binaries, and permissions from malicious modifications.

Using SSL in Coherence

Coherence provides a Secure Socket Layer (SSL) implementation that can be used to secure TCMP communication between cluster nodes as well as the TCP communication between Coherence*Extend clients and proxies. Coherence supports the Transport Layer Security (TLS) 1.0 protocol which is the next version of the SSL 3.0 protocol; however, the term SSL is used in this documentation since it is the more widely recognized term.

The following topics are included in this section:

Note:

This section only contains instructions for using SSL for TCMP between cluster nodes. For detailed instructions on SSL with Coherence*Extend, see "Using SSL to Secure Client Communication" in Oracle Coherence Client Guide.

Overview of SSL

This section provides a brief overview of common SSL concepts that are used in this documentation and is not intended to be a complete guide to SSL. Those new to SSL should refer to the formal specification maintained at http://www.ietf.org as well as the Java SE Security resources located at http://java.sun.com/javase/technologies/security/index.jsp. Those familiar with SSL can skip this section.

SSL is a security protocol that is used to secure communication between entities (typically, clients and servers) over a network. SSL works by authenticating clients and servers using digital certificates and by encrypting/decrypting communication using unique keys that are associated with authenticated clients and servers.

Establishing Identity and Trust

An entity's identity is established using a digital certificate together with a public and private encryption key. The digital certificate contains general information about the entity and also contains the public encryption key embedded within it. A digital certificate is verified by a Certificate Authority (CA) and signed using the CA's digital certificate. The CA's digital certificate establishes trust that the entity is authentic.

Encrypting and Decrypting Data

An entity's digital certificate contains a public encryption key that is paired with the entity's private encryption key. Certificates are passed between entities during an initial connection. Data is then encrypted using the public key. Data that is encrypted using an entity's public key can only be decrypted by the entity's private key. This ensures that only the entity that owns the public encryption key can decrypt the data.

Using One-Way Authentication Versus Two-Way Authentication

SSL communication between clients and servers can be set up using either one-way or two-way authentication. With one-way authentication, a server is required to identify itself to a client by sending its digital certificate for authentication. The client is not required to send the server a digital certificate and remains anonymous to the server. Two-Way authentication requires both the client and the server to send their respective digital certificates to each other for mutual authentication. Two-way authentication provides stronger security by assuring that the identity on both sides of the communication are known.

Generating SSL Artifacts

The Java keytool utility that is located in the JDK_HOME/bin directory can be used to generate and manage SSL artifacts. This includes: creating a key store; generating a unique public/private key pair; creating a self-signed digital certificate that includes the public key, associating the certificate with the private key; and storing these artifacts in the key store.

The following example creates a key store named server.jks that is located in the /test directory. A public and private key pair are generated for the entity identified by the -dname value ("cn=administrator, ou=Coherence, o=Oracle, c=US"). A self-signed certificate is created that includes the public key and identity information. The certificate is valid for 180 days and is associated with the private key in a key store entry referred to by the alias (admin). Passwords must be entered for both the key store and private key.

keytool -genkeypair -dname "cn=administrator, ou=Coherence, o=Oracle, c=US" 
-alias admin -keypass password -keystore /test/server -storepass password 
-validity 180

The certificate generated by this command is adequate for development purposes. However, certificates are typically verified by a trusted CA (such as VeriSign). To have the certificate verified, use the keytool utility to generate a Certificate Signing Request (CSR) file:

keytool -certreq -file admin.csr

This CSR file must be sent to the CA, which will return a signed certificate. Use the keytool utility to import the returned certificate which will replace the self-signed certificate in the key store:

keytool -importcert -trustcacerts -file signed_admin.cer

Lastly, the keytool utility is used to create a second key store that acts as a trust store. The trust store contains digital certificates of trusted CAs. Certificates that have been verified by a CA are only considered trusted if the CA's certificate is also found in the trust store. For example, in a typical one-way authentication scenario, a client must have a trust store that contains a digital certificate of the CA that signed the server's certificate. For development purposes, a self-signed certificate can be used for both identity and trust; moreover, a single keystore can be used as both the identity store and the trust store.

Configuring SSL for TCMP

A Coherence cluster can be configured to use SSL with TCMP. Coherence supports both one-way and two-way authentication. Two-Way authentication is typically used more often than one-way authentication, which has fewer use cases in a cluster environment. In addition, it is important to realize that TCMP is a peer-to-peer protocol that generally runs in trusted environments where many cluster nodes are expected to remain connected with each other. The implications of SSL on administration and performance should be carefully considered.

Defining a SSL Socket Provider

SSL for TCMP is configured in an operational override file by overriding the <socket-provider> element within the <unicast-listener> element. The preferred approach is to use the <socket-provider> element to reference a SSL socket provider configuration that is defined within a <socket-providers> node. The <socket-provider> element can also be used to define a full configuration within the <unicast-listener> element. Both approaches are demonstrated below. See "socket-provider" for a detailed reference of the <socket-provider> element.

Note:

A cluster must be configured to use well known addresses in order to use SSL with TCMP.

Example 30-1 demonstrates a SSL two-way authentication setup and requires both an identity store and trust store to be located on each node in the cluster. The example uses the default values for the <protocol> and <algorithm> element (TLS and SunX509, respectively). These are shown for completeness but may be left out when using the default values. The example uses the preferred approach where the SSL socket provider is defined within the <socket-providers> node and referred to from within the <unicast-listener> element.

Example 30-1 Sample SSL Configuration for TCMP Communication

<coherence>
   <cluster-config>
      <unicast-listener>
         <well-known-addresses>
            <socket-address id="1">
               <address>198.168.1.5</address>
               <port>8088</port>
            </socket-address>
         </well-known-addresses>
         <socket-provider>mySSLConfig</socket-provider>
      </unicast-listener>

      <socket-providers>
         <socket-provider id="mySSLConfig">
            <ssl>
               <protocol>TLS</protocol>
               <identity-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:server.jks</url>
                     <password>password</password>
                     <type>JKS</type>
                  </key-store>
                  <password>password</password>
               </identity-manager>
               <trust-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:trust.jks</url>
                     <password>password</password>
                     <type>JKS</type>
                  </key-store>
               </trust-manager>
            </ssl>
         </socket-provider>
      </socket-providers>
   </cluster-config>
</coherence>

As an alternative, the SSL socket provider can also be directly defined in the <unicast-listener> element as shown below:

<coherence>
   <cluster-config>
      <unicast-listener>
         <well-known-addresses>
            <socket-address id="1">
               <address>198.168.1.5</address>
               <port>8088</port>
            </socket-address>
         </well-known-addresses>
         <socket-provider>
            <ssl>
               <protocol>TLS</protocol>
               <identity-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:server.jks</url>
                     <password>password</password>
                     <type>JKS</type>
                  </key-store>
                  <password>password</password>
               </identity-manager>
               <trust-manager>
                  <algorithm>SunX509</algorithm>
                  <key-store>
                     <url>file:trust.jks</url>
                     <password>password</password>
                     <type>JKS</type>
                  </key-store>
               </trust-manager>
            </ssl>
         </socket-provider>
      </unicast-listener>
   </cluster-config>
</coherence>

Using the Pre-Defined SSL Socket Provider

Out-of-box, a pre-defined SSL socket provider is included that allows for configuration of two-way SSL connections that is based on peer trust where every trusted peer resides within a single JKS key store. The proprietary peer trust algorithm (PeerX509) works by assuming trust (and only trust) of the certificates that are in the key store. The peer algorithm can increase the performance of SSL by leveraging the fact that TCMP is a peer-to-peer protocol.

The pre-defined SSL socket provider is located within the <socket-providers> element in the operational deployment descriptor:

...
<socket-providers>
   ...
   <socket-provider id="ssl">
      <ssl>
         <identity-manager>
            <key-store>
               <url system-property="tangosol.coherence.security.keystore">
                  file:keystore.jks
               </url>
               <password system-property="tangosol.coherence.security.password"/>
            </key-store>
            <password system-property="tangosol.coherence.security.password"/>
         </identity-manager>
         <trust-manager>
            <algorithm>PeerX509</algorithm>
            <key-store>
               <url system-property="tangosol.coherence.security.keystore">
                  file:keystore.jks
               </url>
               <password system-property="tangosol.coherence.security.password"/>
            </key-store>
         </trust-manager>
      </ssl>
   </socket-provider>
</socket-providers>
...

As configured, the pre-defined SSL socket provider requires a Java key store named keystore.jks that is found on the classpath. This name can be overridden using the tangosol.coherence.security.keystore system property to specify a different key store. In addition, the tangosol.coherence.security.password system property can be used to specify the required password for the key store and certificate. As an alternative, an operational override file may be used to modify the pre-defined SSL socket provider definition as required.

Note:

Ensure that certificates for all nodes in the cluster have been imported into the key store.

To use the pre-defined SSL socket provider, override the <socket-provider> element in the <unicast-listener> configuration and reference the SSL socket provider using it's id attribute. The following example configures a unicast listener to use the pre-defined SSL socket provider.

<coherence>
   <cluster-config>
      <unicast-listener>
         <well-known-addresses>
            <socket-address id="1">
               <address>198.168.1.5</address>
               <port>8088</port>
            </socket-address>
         </well-known-addresses>
         <socket-provider>ssl</socket-provider>
      </unicast-listener>
   </cluster-config>
</coherence>