2 Enabling General Security Measures

You can use general security measures to help protect against unauthorized use of Oracle Coherence APIs, system resources, and cluster connections. General security measures are often enabled as a first step when securing Coherence solutions.

This chapter includes the following sections:

2.1 Using the Java Security Manager

You can control which system resources Coherence accesses and uses by enabling the Java security manager. The security manager uses a policy file that explicitly grants permissions for each resource. The COHERENCE_HOME/lib/security/security.policy policy configuration file specifies a minimum set of permissions that are required for Coherence. Use the file as provided, or modify the file to set additional permissions. A set of local (non-clustered) permissions is also provided.

The section includes the following topics:

2.1.1 Enable the Java Security Manager

To enable the Java security manager and use the COHERENCE_HOME/lib/security/security.policy file, set the following properties on a cluster member:

  1. Set the java.security.manager property to enable the Java security manager. For example:
    -Djava.security.manager
    
  2. Set the java.security.policy property to the location of the policy file. For example:
    -Djava.security.manager
    -Djava.security.policy=/coherence/lib/security/security.policy
    
  3. Set the coherence.home system property to COHERENCE_HOME. For example:
    -Djava.security.manager
    -Djava.security.policy=/coherence/lib/security/security.policy
    -Dcoherence.home=/coherence
    

Note:

The security policy file assumes that the default Java Runtime Environment (JRE) security permissions have been granted. Therefore, you must be careful to use a single equal sign (=) and not two equal signs (==) when setting the java.security.policy system property.

2.1.2 Specify Permissions

Modify the COHERENCE_HOME/lib/security/security.policy file to include additional permissions as required. See Permissions in the Java Development Kit (JDK) in Java SE Security.

To specify additional permissions in the security.policy file:

  1. Edit the security.policy file and add a permission for a resource. For example, the following permission grants access to the coherence.jar library:
    grant codeBase "file:${coherence.home}/lib/coherence.jar"
        {
                permission java.security.AllPermission;
        };
    
  2. When you declare binaries, sign the binaries using the JDK jarsigner tool. The following example signs the coherence.jar resource declared in the previous step:
    jarsigner -keystore ./keystore.jks -storepass password coherence.jar admin
    

    Add the signer in the permission declaration. For example, modify the original permission as follows to add the admin signer.

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

2.1.3 Programmatically Specifying Local Permissions

The com.tangosol.net.security.LocalPermission class provides a way to set permissions for local (non-clustered) Coherence API operations. Clients are either allowed or not allowed to perform the declared operations (referred to as targets). For example:

LocalPermission lp = new LocalPermission("Cluster.shutdown");

To use local permissions, the Java security manager must be enabled. See Enable the Java Security Manager.

Table 2-1 lists and describes the target names that can be declared.

Table 2-1 Local Permission Targets

Target Name Description

CacheFactory.setCacheFactoryBuilder

Protects the programmatic installation of a custom cache factory builder. Special consideration should be given when granting this permission. Granting this permission allows code to set a cache factory builder and intercept any access or mutation requests to any caches and also allows access to any data that flows into and from those caches.

Cluster.shutdown

Protects all services from being shutdown. Granting this permission allows code to programmatically shutdown the cluster node.

BackingMapManagerContext.getBackingMap

Protects direct access to backing maps. Special consideration should be given when granting this permission. Granting this permission allows code to get a reference to the backing map and access any stored data without any additional security checks.

BackingMapManagerContext.setClassLoader

Protect changes to class loaders used for storage. The class loader is used by the cache service to load application classes that might not exist in the system class loader. Granting this permission allows code to change which class loader is used for a particular service.

Service.getInternalService

Protects access to an internal service, cluster or cache reference. Granting this permission allows code to obtain direct access to the underlying service, cluster or cache storage implementation.

Service.registerResource

Protects service registries. Granting this permission allows code to re-register or unregister various resources associated with the service.

Service.registerEventInterceptor

Protects the programmatic installation of interceptors. Special consideration should be given when granting this permission. Granting this permission allows code to change or remove event interceptors associated with the cache service thus either getting access to underlying data or removing live events that are designed to protect the data integrity.

2.2 Using Host-Based Authorization

Host-based authorization is a type of access control that allows you to specify which hosts (based on host name or IP address) can connect to a cluster. The feature is available for both cluster member connections and extend client connections.

This section includes the following topics:

2.2.1 Overview of Host-Based Authorization

Host-based authorization uses the host name and IP address of a cluster member or extend client to determine whether a connection to the cluster is allowed. Specific host names, addresses, and address ranges can be defined. For custom processing, a custom filter can be created to validate hosts.

Host-based authorization is ideal for environments where known hosts with relatively static network addresses are joining or accessing the cluster. In dynamic environments, or when updating a DNS server, IP addresses can change and cause a cluster member or extend client to fail authorization. Cache operations may not complete if cluster members or extend clients are no longer authorized. Extend clients are more likely to have access problems because of their transient nature.

When using host-based authorization, consider the dynamic nature of the network environment. The need to reconfigure the list of authorized hosts may become impractical. If possible, always use a range of IP addresses instead of using a specific host name. Or, create a custom filter that is capable of resolving address that have changed. If host-based authorization becomes impractical, consider using extend client identity tokens or SSL. See Using Identity Tokens to Restrict Client Connections and Using SSL to Secure Communication, respectively.

2.2.2 Specify Cluster Member Authorized Hosts

The default behavior of a cluster allows any host to connect to the cluster and become a cluster member. Host-based authorization changes this behavior to allow only hosts with specific host names or IP addresses to connect to the cluster.

Configure authorized hosts in an operational override file using the <authorized-hosts> element within the <cluster-config> element. Enter specific addresses using the <host-address> element or a range of addresses using the <host-range> element. The <host-address> and <host-range> elements support an id attribute for uniquely identifying multiple elements.

The following example configures a cluster to accept only cluster members 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 and 192.168.0.30 to 192.168.0.40.

<?xml version='1.0'?>

<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
   xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config
   coherence-operational-config.xsd">
   <cluster-config>
      <authorized-hosts>
         <host-address id="1">192.168.0.5</host-address>
         <host-address id="2">192.168.0.6</host-address>
         <host-range id="1">
            <from-address>192.168.0.10</from-address>
            <to-address>192.168.0.20</to-address>
         </host-range>
         <host-range id="2">
            <from-address>192.168.0.30</from-address>
            <to-address>192.168.0.40</to-address>
         </host-range>
      </authorized-hosts>
   </cluster-config>
</coherence>

2.2.3 Specify Extend Client Authorized Hosts

The default behavior of an extend proxy server allows any extend client to connect to the cluster. Host-based authorization changes this behavior to allow only hosts with specific host names or IP addresses to connect to the cluster.

Configure authorized hosts in a cache configuration file using the <authorized-hosts> element within the <tcp-acceptor> element of a proxy scheme definition. Enter specific addresses using the <host-address> element or a range of addresses using the <host-range> element. The <host-address> and <host-range> elements support an id attribute for uniquely identifying multiple elements.

The following example configures an extend proxy to accept only client connections from clients 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 and 192.168.0.30 to 192.168.0.40.

<proxy-scheme>
   <service-name>ExtendTcpProxyService</service-name>
   <thread-count>5</thread-count>
   <acceptor-config>
      <tcp-acceptor>
         ...
         <authorized-hosts>
            <host-address id="1">192.168.0.5</host-address>
            <host-address id="2">192.168.0.6</host-address>
            <host-range id="1">
               <from-address>192.168.0.10</from-address>
               <to-address>192.168.0.20</to-address>
            </host-range>
            <host-range id="2">
               <from-address>192.168.0.30</from-address>
               <to-address>192.168.0.40</to-address>
            </host-range>
         </authorized-hosts>
         ...
      </tcp-acceptor>
   </acceptor-config>
   <autostart>true</autostart>
</proxy-scheme>

2.2.4 Use a Filter Class to Determine Authorization

A filter class determines whether to accept a particular host connection. Both extend client connections and cluster member connections support using filter classes. A filter class must implement the com.tangosol.util.Filter interface. The evaluate() method of the interface is passed the java.net.InetAddress of the host. Implementations should return true to accept the connection.

To enable a filter class, enter a fully qualified class name using the <class-name> element within the <host-filter> element. Set initialization parameters using the <init-params> element.

The following example configures a filter named MyFilter, which determines if a host connection is allowed.

<authorized-hosts>
   <host-address id="1">192.168.0.5</host-address>
   <host-address id="2">192.168.0.6</host-address>
   <host-range id="1">
      <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-hosts>

2.3 Managing Rogue Clients

You can use the suspect protocol to safeguard against rogue extend clients that operate outside of acceptable limits. Rogue clients are slow-to-respond clients or abusive clients that attempt to overuse a proxy— as is the case with denial of service attacks. In both cases, the potential exists for a proxy to run out of memory and become unresponsive.

The suspect algorithm monitors client connections looking for abnormally slow or abusive clients. When a rogue client connection is detected, the algorithm closes the connection 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 determine when a client is suspect, when it returns to normal, or when it is considered rogue.

Configure the suspect protocol within the <tcp-acceptor> element of a proxy scheme definition. See tcp-acceptor in Developing Applications with Oracle Coherence. 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 95 MB or 60000 messages, then the client is considered unsafe and the proxy closes the connection.

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