5 Securing Coherence*Extend

Coherence*Extend includes a set of features that are used to secure communication between extend clients and extend proxies. The features provide varying levels of security and can be implemented as required. For general Coherence security, see "Securing Coherence" in Oracle Coherence Developer's Guide.

The following sections are included in this chapter:

Restricting Client Connections

The extend proxy's default behavior is to accept all extend client connections. This behavior can be changed to only allow client connections based on their host name or IP address. A customized filter can also be created to determine whether or not to accept a particular client. This type of access control is ideal for environments were the clients that are accessing the cluster are known in advance.

The <authorized-host> element is used to enter the host name or IP address of the clients that are allowed to access the cluster. Specific addresses are entered using the <host-address> element. A range of address can be defined using the <host-range> element.

The following example configures an extend proxy to only accept client connections from client's whose IP address is either 192.168.0.5, 192.168.0.6, or within the range of 192.168.0.10 to 192.168.0.20:

<proxy-scheme>
   <service-name>ExtendTcpProxyService</service-name>
   <thread-count>5</thread-count>
   <acceptor-config>
      <tcp-acceptor>
         ...
         <authorized-host>
            <host-address>192.168.0.5</host-address>
            <host-address>192.168.0.6</host-address>
            <host-range>
               <from-address>192.168.0.10</from-address>
               <to-address>192.168.0.20</to-address>
            </host-range>
         </authorized-host>
         ...
      </tcp-acceptor>
   </acceptor-config>
   <autostart>true</autostart>
</proxy-scheme>

A filter class can also be used to determine whether or not to accept a particular client. the class must implement the com.tangosol.util.Filter interface. The evaluate() method of the interface is passed the java.net.InetAddress of the client. Implementations should return true to allow the client to connect. To enable a filter, enter a fully qualified class name using the <class-name> element within the <host-filter> element. Initialization parameters for the implementation class can also be set using the <init-params> element.

The following example configures a filter named MyFilter, which is used to determine if a client is allowed to connect to the cluster.

<proxy-scheme>
   <service-name>ExtendTcpProxyService</service-name>
   <thread-count>5</thread-count>
   <acceptor-config>
      <tcp-acceptor>
         ...
         <authorized-host>
            <host-address>192.168.0.5</host-address>
            <host-address>192.168.0.6</host-address>
            <host-range>
               <from-address>192.168.0.10</from-address>
               <to-address>192.168.0.20</to-address>
            </host-range>
            <host-filter>
               <class-name>package.MyFilter</class-name>
               <init-params>
                  <init-param>
                     <param-name>sPolicy</param-name>
                     <param-value>strict</param-value>
                  </init-param>
               </init-params>
            </host-filter>
         </authorized-host>
         ...
      </tcp-acceptor>
   </acceptor-config>
   <autostart>true</autostart>
</proxy-scheme>

Using Identity Tokens to Restrict Client Connections

Extend client can be restricted from accessing a cluster by using an identity token. The token is sent between extend clients and extend proxies whenever a connection is attempted. Only extend clients that pass a valid identity token are allowed to access the cluster.

On the extend client, identity tokens are created by an identity transformer and sent as part of the connection request. On the cluster side, an identity asserter is used to validate the identity token before the connection is accepted. Coherence*Extend includes a default identity transformer (DefaultIdentityTransformer) and identity asserter (DefaultIdentityAsserter) that use the Subject (Java) or Principal (.NET) for the identity token. The default behavior can be overridden by providing custom identity transformer and identity asserter implementations and enabling them in the Coherence operational override file.

Note:

  • The identity transformer and identity asserter implementation classes must be located on both the extend client's and the extend proxy server's classpath at run time.

  • See "Using Custom Security Types" for more information on using security object types other than the types that are predefined in POF.

The following topics are included in this section:

Creating a Custom Identity Transformer

An identity transformer is a client-side component that converts a Subject, or Principal, into an identity token that can be passed to an extend proxy. The identity token can be any type of object useful for identity validation; it is not required to be a well-known security type. At run time, the token is serialized and sent as part of the extend connection request.

Note:

Identity tokens that are of a type that Coherence can serialize are automatically serialized. For .NET and C++ clients, the type must be a POF type. See "Using Custom Security Types" for more information on using security object types other than the types that are predefined in POF.

For Java and C++, the identity transformer must implement the IdentityTransformer interface. C# clients implement the IIdentityTransformer interface.

Example 5-1 is a Java implementation that restricts client access by requiring a client to supply a password to access the proxy. The IdentityTransformer gets a password from a system property on the client and returns it as an identity token.

Example 5-1 A Sample Identity Transformer Implementation

import com.tangosol.net.security.IdentityTransformer;
import javax.security.auth.Subject;
 
public class PasswordIdentityTransformer 
        implements IdentityTransformer
    {
    public Object transformIdentity(Subject subject)
            throws SecurityException
        {
        return System.getProperty("mySecretPassword");
        }
    }

If client authentication is already being done, a new Principal could be added to the Subject, with the Principal name as the password. The password Principal could be added to the Subject during JAAS authentication by modifying an existing JAAS login module or by adding an additional required login module that would add the password Principal. JAAS allows multiple login modules each of which can modify the Subject. Similarly, in .NET a password identity could be added to the Principal. The asserter on the cluster-side would then validate the "normal" Principals plus validate the password Principal. See "Creating a Custom Identity Asserter" below.

Enabling a Custom Identity Transformer

An identity transformer implementation is enabled in the client-side tangosol-coherence-override.xml file using the <identity-transformer> element within the <security-config> node. The element must include the full name of the implementation class. For example:

<coherence>
   <security-config>
      <identity-transformer>
        <class-name>com.my.PasswordIdentityTransformer</class-name>
      </identity-transformer>
   </security-config>
</coherence>

Creating a Custom Identity Asserter

An identity asserter is a cluster-side component that resides on the cache server that is hosting an extend proxy service. The asserter validates an identity token that is created by an identity transformer on the extend client. The token gets passed when an extend client initiates a connection. If the validation fails, the connection is refused and a security exception is thrown. The transformer and asserter are also invoked when a new channel within an existing connection is created. For Java and C++, the identity asserter must implement the IdentityAsserter interface. C# clients implement the IIdentityAsserter interface.

Example 5-2 is a Java implementation that checks a security token to ensure a valid password is given. In this case, the password is checked against a system property on the cache server. This asserter implementation is used for the identity transformer sample in Example 5-1.

Example 5-2 A Sample Identity Asserter Implementation

import com.tangosol.net.security.IdentityAsserter;
import javax.security.auth.Subject;
 
 
public class PasswordIdentityAsserter 
        implements IdentityAsserter
    {
    public Subject assertIdentity(Object oToken)
            throws SecurityException
        {
        if (oToken instanceof String)
            {
            if (((String) oToken).equals(System.getProperty("mySecretPassword")))
                {
                return null;
                }
            }
        throw new SecurityException("Access denied");
        }
    }

There are many possible variations when creating an identity asserter. For example, the asserter could reject connections based on a list of Principals, check role Principals, validate signed Principal name, and so on. The asserter can block any connection attempt that doesn't prove the correct identity.

Enabling a Custom Identity Asserter

An identity asserter implementation is enabled in the cluster-side tangosol-coherence-override.xml file using the <identity-asserter> element within the <security-config> node. The element must include the full name of the implementation class. For example:

<coherence>
   <security-config>
      <identity-asserter>
        <class-name>com.my.PasswordIdentityAsserter</class-name>
      </identity-asserter>
   </security-config>
</coherence>

Using Custom Security Types

Security objects are automatically serialized/deserialized using Portable Object Format (POF) when they are passed between extend clients and extend proxies. Security objects of types that are predefined in POF can be used without any configuration or programming changes. Security objects of custom types that are not predefined in POF (for example, when using Kerberos authentication) causes an error.

For custom security types, an application can choose to either convert the custom type or define the type in POF:

Convert the Type

In this approach, a custom identity transformer converts a custom security object type to a type that is predefined for POF such as a character array or string before returning it as an object token. On the proxy server, a custom identity asserter would convert it back (after validation) to a subject.

For example, a subject may contain credentials that will not be serialized. The identity transformer would extract the credential and convert it to a character array, returning that array as the token. On the proxy server, the identity asserter would convert the character array to the proper credential type, validate it, and then construct a subject to return.

Define the Custom Type in POF

In this approach, custom security types are defined in a POF configuration file. The type must be defined in both the client's POF configuration file as well as the POF configuration file on the proxy server.

For detailed information on using POF with Java, see "Using Portable Object Format" in the Oracle Coherence Developer's Guide. For more information on using POF with C++ and C#, see Chapter 11, "Building Integration Objects for C++ Clients," and Chapter 20, "Building Integration Objects for .NET Clients," respectively.

Understanding Custom Identity Token Interoperability

Solutions that choose to use a custom identity token must always consider what tokens may be sent by an extend client and what tokens may be received by an extend proxy. This is particularly important during rolling upgrades as well as when rolling out a custom identity token solution.

Coherence Upgrades

Interoperability issues may occur during the process of upgrading Coherence. In this scenario, there may be different client versions that interoperate with different proxy server versions. In particular:

  • When a 3.5 extend client is connecting to a 3.6 extend proxy, the custom identity asserter that is implemented on the extend proxy must be able to handle identity tokens sent by the 3.5 extend client. A 3.5 extend client will send either a null token or a Subject. The custom identity asserter must be prepared to handle those token types in addition to any custom tokens originating from a 3.6 extend client.

  • Conversely, when a 3.6 extend client is connecting to a 3.5 extend proxy, the client must not use a custom identity transformer that sends a token that the 3.5 extend proxy cannot handle. The client must send either a null token or a Subject.

Custom Identity Token Rollout

Interoperability issues may occur between extend clients and extend proxies when rolling out a custom identity token solution. In this scenario, as extend proxies are migrated to use a custom identity asserter, there will be proxies that continue to use the default asserter until the roll out is completed. Likewise, as extend clients are migrated to use a custom identity transformer, there will be clients that continue to use the default transformer until the roll out is completed. In both cases, the extend clients and extend proxies must be able to handle a null token or a Subject until the rollout is complete.

A possible strategy for such scenarios may be to have a custom identity asserter that accepts null or Subject tokens temporarily as clients are updated. The identity asserter could check an external source for a policy that indicates whether or not those tokens are accepted. Once all clients have been updated to use a custom token, the policy could be changed and the identity asserter will no longer accept those tokens.

Associating Identities with Extend Services

Subject scoping allows remote cache and remote invocation service references that are returned to a client to be associated with the identity from the current security context. Clients use their platform-specific authentication APIs to establish a security context. A subject or principal is obtained from the current security context whenever a client creates a NamedCache and InvocationService instance. All requests are then made in the context of the established subject or principal.

Note:

See "Using Custom Security Types" for more information on using security object types other than the types that are predefined in POF.

For example, if the "trader" user calls CacheFactory.getCache("trade-cache") and the "manager" user calls CacheFactory.getCache("trade-cache"), each user gets a different remote cache reference object. Since an identity will be associated with that remote cache reference, authorization decisions can be made based on the identity of the caller. See "Implementing Authorization" below for details on implementing authorization.

Subject scoping is not enabled by default. This feature is enabled in the client-side tangosol-coherence-override.xml file using the <subject-scope> element within the <security-config> node. The following example enables subject scoping and ensures each subject gets a unique remote cache and remote invocation service reference.

<coherence>
   <security-config>
      <subject-scope>true<subject-scope>
   </security-config>
</coherence>

Implementing Authorization

Authorization is used to control which actions a particular user is able to perform based on their access control rights. In Coherence*Extend, authorization is implemented through the use of interceptor classes. An extend proxy calls the interceptor classes before a client accesses a proxied resource (cache, cache service, invocation service). Interceptor classes are implementation specific and must provide the necessary authorization logic before passing the request to the proxied resources.

The following topics are included in this section:

The code samples in this section are based on the Java authorization example, which is included in the Coherence examples that are delivered as part of the documentation library. The example demonstrates a basic authorization implementation that uses the Principal obtained from a client request and a role-based policy to determine whether or not to allow operations on the requested service. Download the examples for the complete implementation.

Creating Authorization Interceptor Classes

An interceptor class can be created for both a proxied cache service and a proxied invocation service by implementing the CacheService and InvocationService interfaces, respectively. However, a set of wrapper classes are typically extended when implementing authorization: com.tangosol.net.WrapperCacheService (together with com.tangosol.net.cache.WrapperNamedCache) and com.tangosol.net.WrapperInvocationService. The wrapper classes delegate to their respective interfaces and provide a convenient way to create interceptor classes that apply access control to the wrapped interface methods.

Example 5-3 is taken from the Coherence examples and demonstrates creating an authorization interceptor class for a proxied cache service by extending WrapperCacheService. It wraps all CacheService methods on the proxy and applies access controls based on the Subject passed from an extend client. The implementation only allows a Principal with the specified role to access the wrapped CacheService.

Example 5-3 Extending the WrapperCacheService Class for Authorization

public class EntitledCacheService
   extends WrapperCacheService
   {
   public EntitledCacheService(CacheService service)
       {
       super(service);
       }

   public NamedCache ensureCache(String sName, ClassLoader loader)
      {
      SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_READER);
      return new EntitledNamedCache(super.ensureCache(sName, loader));
      }

   public void releaseCache(NamedCache map)
      {
      if (map instanceof EntitledNamedCache)
         {
         EntitledNamedCache cache =  (EntitledNamedCache) map;
         SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_READER);
         map = cache.getNamedCache();
         }
      super.releaseCache(map);
      }

   public void destroyCache(NamedCache map)
      {
      if (map instanceof EntitledNamedCache)
         {
         EntitledNamedCache cache =  (EntitledNamedCache) map;
         SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_ADMIN);
         map = cache.getNamedCache();
         }
      super.destroyCache(map);
      }
}

Notice that this class requires a named cache implementation. For this example, the WrapperNamedCache class is extended and wraps each method of the NamedCache instance. This allows access controls to be applied to different cache operations. Example 5-4 is a code excerpt taken from the Coherence examples that demonstrates overriding the NamedCache methods and applying access checks before allowing the method to be executed. See the Coherence examples for the complete class.

Example 5-4 Extending the WrapperNamedCache Class for Authorization

public class EntitledNamedCache
   extends WrapperNamedCache
   {
   public EntitledNamedCache(NamedCache cache)
      {
       super(cache, cache.getCacheName());
      }

   public Object put(Object oKey, Object oValue, long cMillis)
      {
      SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_WRITER);      return super.put(oKey, oValue, cMillis);
      }

   public Object get(Object oKey)
      {
      SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_READER);
      return super.get(oKey);
      }

   public void destroy()
      {
      SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_ADMIN);
      super.destroy();
      }
...

Example 5-5 is taken from the Coherence examples and demonstrates creating an authorization interceptor class for a proxied invocation service by extending WrapperInvocationService. It wraps all InvocationService methods on the proxy and applies access controls based on the Subject passed from an extend client. The implementation only allows Principals with a specified role name to access the wrapped InvocationService.

Example 5-5 Extending the WrapperInvocationService Class for Authorization

public class EntitledInvocationService
   extends WrapperInvocationService
   {
   public EntitledInvocationService(InvocationService service)
      {
      super(service);
      }

   public void execute(Invocable task, Set setMembers, InvocationObserver 
      observer)
      {
      SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_WRITER)
      super.execute(task, setMembers, observer);
      }

   public Map query(Invocable task, Set setMembers)
      {
      SecurityExampleHelper.checkAccess(SecurityExampleHelper.ROLE_WRITER)
      return super.query(task, setMembers);
      }
}

When a client attempts to use a remote invocation service, the proxy calls the query() method on the EntitledInvocationService class, rather than on the proxied InvocationService instance. The EntitledInvocationService class decides to allow or deny the call. If the call is allowed, it then calls the query() method on the proxied InvocationService instance.

Enabling Authorization Interceptor Classes

Interceptor classes for a proxied cache service and a proxied invocation service are enabled in a proxy scheme definition within the <cache-service-proxy> element and <invocation-service-proxy> element, respectively. The <class-name> element is used to enter the fully qualified name of the interceptor class. Initialization parameters required by the class can be specified using the <init-params> element. See "cache-service-proxy" and "invocation-service-proxy" in Oracle Coherence Developer's Guide for detailed information on using these elements.

The following example demonstrates enabling both a proxied cache service and proxied invocation service interceptor class. The example uses the interceptor classes that were created in Example 5-3 and Example 5-5.

<proxy-scheme>
   ...
   <proxy-config>
      <cache-service-proxy>
         <class-name>
            com.tangosol.examples.security.EntitledCacheService
         </class-name>
         <init-params>
            <init-param>
               <param-type>com.tangosol.net.CacheService</param-type>
               <param-value>{service}</param-value>
            </init-param>
         </init-params>
      </cache-service-proxy>
      <invocation-service-proxy>
      <class-name>
         com.tangosol.examples.security.EntitledInvocationService
      </class-name>
      <init-params>
         <init-param>
            <param-type>com.tangosol.net.InvocationService</param-type>
            <param-value>{service}</param-value>
         </init-param>
      </init-params>
   </invocation-service-proxy>
</proxy-config>

Using SSL to Secure Client Communication

Communication between extend clients and extend proxies can be secured using SSL. SSL requires configuration on both the client side as well as the cluster side. SSL is supported for both Java and .NET clients but not for C++ clients. For those new to SSL, see "Using SSL in Coherence" in Oracle Coherence Developer's Guide, which provides a brief overview of common SSL concepts as well as links to more detailed SSL resources.

The configuration examples in this section assume that valid digital certificates for all clients and servers have been created as required and that the certificates have been signed by a Certificate Authority (CA). The digital certificates must be found in an identity store, and the trust store must include the signing CA's digital certificate. Self-Signed certificates may be used during development as needed.

The following topics are included in this section:

Configuring a Cluster-Side SSL Socket Provider

SSL is configured in the cluster-side cache configuration file by defining a SSL socket provider for a proxy service. There are two options for configuring a SSL socket provider depending on the level of granularity that is required:

  • Per Proxy Service – Each proxy service defines a SSL socket provider configuration or references a pre-defined configuration that is included in the operational configuration file.

  • All Proxy Services – All proxy services use the same global SSL socket provider configuration. Proxy services that provide their own configuration override the global configuration. The global configuration can also reference a predefined configuration that is included in the operational configuration file.

Configure a SSL Socket Provider Per Proxy Service

To configure a SSL socket provider for a proxy service, add a <socket-provider> element within the <tcp-acceptor> element of each <proxy-scheme> definition. See "socket-provider" in Oracle Coherence Developer's Guide for a detailed reference of the <socket-provider> element.

Example 5-6 demonstrates a proxy scheme that configures a SSL socket provider that 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.

Example 5-6 configures both an identity key store (server.jks) and a trust key store (trust.jks). This is typical of two-way SSL authentication where both the client and proxy must exchange their digital certificate and confirm each other's identity. For one-way SSL authentication, the proxy server configuration must include an identity key store but need not include a trust key store.

Example 5-6 Sample Cluster-Side SSL Configuration

...
<caching-schemes>
   ...
   <proxy-scheme>
      <service-name>ExtendTcpSSLProxyService</service-name>
      <acceptor-config>
         <tcp-acceptor>
            <local-address>
               <address>192.168.1.5</address>
               <port>9099</port>
            </local-address>
            <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>
         </tcp-acceptor>
      </acceptor-config>
      <autostart>true</autostart>
   </proxy-scheme>
   ...
</caching-schemes>
...

The following example references a SSL socket provider configuration that is defined in the <socket-providers> node of the operational deployment descriptor by specifying the configuration's id attribute (ssl). See "socket-providers" in Oracle Coherence Developer's Guide for a detailed reference of the <socket-providers> element.

Note:

Out-of-box, a pre-defined SSL socket provider is included in the operational deployment descriptor and is named ssl. The pre-defined SSL socket provider is configured for two-way SSL connections and is based on peer trust where every trusted peer resides within a single JKS key store. See "Using the Pre-Defined SSL Socket Provider" in Oracle Coherence Developer's Guide for more information on using the pre-defined SSL socket provider. To configure a different SSL socket provider, use an operational override file to modify the pre-defined SSL socket provider or to create a new socket provider configuration as required.
...
<caching-schemes>
   ...
   <proxy-scheme>
      <service-name>ExtendTcpSSLProxyService</service-name>
      <acceptor-config>
         <tcp-acceptor>
            <local-address>
               <address>192.168.1.5</address>
               <port>9099</port>
            </local-address>
            <socket-provider>ssl</socket-provider>
         </tcp-acceptor>
      </acceptor-config>
      <autostart>true</autostart>
   </proxy-scheme>
</caching-schemes>
...

Configure a SSL Socket Provider for All Proxy Services

To configure a global SSL socket provider for use by all proxy services, use a <socket-provider> element within the <defaults> element of the cache configuration file. With this approach, no additional configuration is required within a proxy scheme definition. See "defaults" in Oracle Coherence Developer's Guide for a detailed reference of the <default> element.

The following example uses the same SSL socket provider configuration from Example 5-6 and configures it for all proxy services:

<cache-config>
   <defaults>
      <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>
   </defaults>
   ...

The following example configures a global SSL socket provider by referencing a SSL socket provider configuration that is defined in the operational deployment descriptor:

<cache-config>
   <defaults>
      <socket-provider>ssl</socket-provider>
   </defaults>
   ...

Configure a Java Client-Side SSL Socket Provider

SSL is configured in the client-side cache configuration file by defining a SSL socket provider for a remote cache scheme and, if required, for a remote invocation scheme. There are two options for configuring a SSL socket provider depending on the level of granularity that is required:

  • Per Remote Service – Each remote service defines a SSL socket provider configuration or references a pre-defined configuration that is included in the operational configuration file.

  • All Remote Services – All remote services use the same global SSL socket provider configuration. Remote services that provide their own configuration override the global configuration. The global configuration can also reference a predefined configuration that is included in the operational configuration file.

Configure a SSL Socket Provider Per Remote Service

To configure a SSL socket provider for a remote service, add a <socket-provider> element within the <tcp-initiator> element of a remote scheme definition. See "socket-provider" in Oracle Coherence Developer's Guide for a detailed reference of the <socket-provider> element.

Example 5-7 demonstrates a remote cache scheme that configures a socket provider that uses SSL. 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.

Example 5-7 configures both an identity key store (server.jks) and a trust key store (trust.jks). This is typical of two-way SSL authentication where both the client and proxy must exchange their digital certificate and confirm each other's identity. For one-way SSL authentication, the client configuration must include a trust key store but need not include an identity key store, which indicates the client will not exchange its digital certificate to the proxy and remains anonymous. The client's trust key store must includes the CA's digital certificate that was used to sign the proxy's digital certificate.

Example 5-7 Sample Java Client-Side SSL Configuration

<?xml version="1.0"?>
<!DOCTYPE cache-config SYSTEM "cache-config.dtd">
<cache-config>
   <caching-scheme-mapping>
      <cache-mapping>
         <cache-name>dist-extend</cache-name>
         <scheme-name>extend-dist</scheme-name>
      </cache-mapping>
   </caching-scheme-mapping>

   <caching-schemes>
      <remote-cache-scheme>
         <scheme-name>extend-dist</scheme-name>
         <service-name>ExtendTcpSSLCacheService</service-name>
         <initiator-config>
            <tcp-initiator>
               <remote-addresses>
                  <socket-address>
                     <address>198.168.1.5</address>
                     <port>9099</port>
                  </socket-address>
               </remote-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>
               <connect-timeout>10s</connect-timeout>
            </tcp-initiator>
            <outgoing-message-handler>
               <request-timeout>5s</request-timeout>
            </outgoing-message-handler>
         </initiator-config>
      </remote-cache-scheme>
   </caching-schemes>
</cache-config>

The following example references a SSL socket provider configuration that is defined in the <socket-providers> node of the operational deployment descriptor by specifying the configuration's id attribute (ssl). See "socket-providers" in Oracle Coherence Developer's Guide for a detailed reference of the <socket-providers> element.

Note:

Out-of-box, a pre-defined SSL socket provider is included in the operational deployment descriptor and is named ssl. The pre-defined SSL socket provider is configured for two-way SSL connections and is based on peer trust where every trusted peer resides within a single JKS key store. See "Using the Pre-Defined SSL Socket Provider" in Oracle Coherence Developer's Guide for more information on using the pre-defined SSL socket provider. To configure a different SSL socket provider, use an operational override file to modify the pre-defined SSL socket provider or to create a new socket provider configuration as required.
<?xml version="1.0"?>
<!DOCTYPE cache-config SYSTEM "cache-config.dtd">
<cache-config>
   <caching-scheme-mapping>
      <cache-mapping>
         <cache-name>dist-extend</cache-name>
         <scheme-name>extend-dist</scheme-name>
      </cache-mapping>
   </caching-scheme-mapping>

   <caching-schemes>
      <remote-cache-scheme>
         <scheme-name>extend-dist</scheme-name>
         <service-name>ExtendTcpSSLCacheService</service-name>
         <initiator-config>
            <tcp-initiator>
               <remote-addresses>
                  <socket-address>
                     <address>198.168.1.5</address>
                     <port>9099</port>
                  </socket-address>
               </remote-addresses>
               <socket-provider>ssl</socket-provider>
               <connect-timeout>10s</connect-timeout>
            </tcp-initiator>
            <outgoing-message-handler>
               <request-timeout>5s</request-timeout>
            </outgoing-message-handler>
         </initiator-config>
      </remote-cache-scheme>
   </caching-schemes>
</cache-config>

Configure a SSL Socket Provider for All Remote Services

To configure a global SSL socket provider for use by all remote services, use a <socket-provider> element within the <defaults> element of the cache configuration file. With this approach, no additional configuration is required within a remote scheme definition. See "defaults" in Oracle Coherence Developer's Guide for a detailed reference of the <default> element.

The following example uses the same SSL socket provider configuration from Example 5-7 and configures it for all remote services:

<cache-config>
   <defaults>
      <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>
   </defaults>
   ...

The following example configures a global SSL socket provider by referencing a SSL socket provider configuration that is defined in the operational deployment descriptor:

<cache-config>
   <defaults>
      <socket-provider>ssl</socket-provider>
   </defaults>
   ...

Configure a .NET Client-Side Stream Provider

SSL is configured in the .NET client-side cache configuration file by defining an SSL stream provider for remote serviceS. The SSL stream provider is is defined using the <stream-provider> element within the <tcp-initiator> element.

Note:

Certificates are managed on Window servers at the OS level using the Certificate Manager. The sample configuration assumes that the extend proxy's certificate is included in the Certificate Manager and that the CA's certificate that was used to sign the proxy's certificate is included as a trusted certificate authority. For more information on managing certificates, see http://technet.microsoft.com/en-us/library/cc782338(WS.10).aspx.

Example 5-8 demonstrates a remote cache scheme that configures a SSL stream provider. Refer to the cache configuration XML schema (INSTALL_DIR\config\cache-config.xsd) for details on the elements used to configure a SSL stream provider.

Example 5-8 Sample .NET Client-Side SSL Configuration

<?xml version="1.0"?>
<!DOCTYPE cache-config SYSTEM "cache-config.dtd">
<cache-config>
   <caching-scheme-mapping>
      <cache-mapping>
         <cache-name>dist-extend</cache-name>
         <scheme-name>extend-dist</scheme-name>
      </cache-mapping>
   </caching-scheme-mapping>

   <caching-schemes>
      <remote-cache-scheme>
         <scheme-name>extend-dist</scheme-name>
         <service-name>ExtendTcpSSLCacheService</service-name>
         <initiator-config>
            <tcp-initiator>
               <stream-provider>
                  <ssl>
                     <protocol>Tls</protocol>
                     <local-certificates>
                        <certificate>
                           <url>C:\</url>
                           <password>password</password>
                           <flags>DefaultKeySet</flags>
                        </certificate>
                     </local-certificates>
                  </ssl>
               </stream-provider>
               <remote-addresses>
                  <socket-address>
                     <address>198.168.1.5</address>
                     <port>9099</port>
                  </socket-address>
               </remote-addresses>
               <connect-timeout>10s</connect-timeout>
            </tcp-initiator>
            <outgoing-message-handler>
               <request-timeout>5s</request-timeout>
            </outgoing-message-handler>
         </initiator-config>
      </remote-cache-scheme>
   </caching-schemes>
</cache-config>

Managing Rogue Clients

Extend clients that operate outside of acceptable limits are considered rogue clients. Rogue clients can be slow responding clients or abusive clients that attempt to overuse a proxy— as is the case with denial of service attacks. In both cases, the proxy could run out of memory and become unresponsive.

The suspect protocol is used to safeguard against such abuses. The suspect algorithm monitors client connections looking for abnormally slow or abusive clients. When a rouge client connection is detected, the algorithm closes the connection in order to protect the proxy server from running out of memory. The protocol works by monitoring both the size (in bytes) and length (in messages) of the outgoing connection buffer backlog for a client. Different levels are set to determine when a client is suspect, when it has returned to normal, or when it is considered rogue.

The suspect protocol is configured within the <tcp-acceptor> element of a proxy scheme definition. See "tcp-acceptor" in the Oracle Coherence Developer's Guide for details on using the <tcp-acceptor> element. The suspect protocol is enabled by default.

The following example demonstrates configuring the suspect protocol and is similar to the default settings. When the outgoing connection buffer backlog for a client reaches 10 MB or 10000 messages, the client is considered suspect and is monitored. If the connection buffer backlog for a client returns to 2 MB or 2000 messages, then the client is considered safe and the client is no longer monitored. If the connection buffer backlog for a client reaches the 95 MB or 60000 messages, then the client is considered unsafe and the connection with the client is closed:

<proxy-scheme>
   <service-name>ExtendTcpProxyService</service-name>
   <thread-count>5</thread-count>
   <acceptor-config>
      <tcp-acceptor>
         ...
         <suspect-protocol-enabled>true</suspect-protocol-enabled>
         <suspect-buffer-size>10M<suspect-buffer-size>
         <suspect-buffer-length>10000<suspect-buffer-length>
         <nominal-buffer-size>2M<nominal-buffer-size>
         <nominal-buffer-length>2000<nominal-buffer-length>
         <limit-buffer-size>95M<limit-buffer-size>
         <limit-buffer-length>60000<limit-buffer-length>
         ...
      </tcp-acceptor>
   </acceptor-config>
   <autostart>true</autostart>
</proxy-scheme>