Thursday Jul 19, 2012

Dynamic Authorised Hosts

A simple way to help secure a Coherence cluster is to configure the authorised hosts that can be part of the cluster. If a Coherence application tries to join a cluster and its not running on a server in the authorised host it will be rejected. To setup authorised hosts the cluster host names or IP addresses can be explicitly added to the authorised hosts section of the tangosol-coherence-override.xml file, as shown below:

  <authorized-hosts>
    <host-address id="1">192.168.56.101</host-address>
    <host-address id="2">192.168.56.1</host-address>
  </authorized-hosts>

But what happens when your cluster needs to grow and you need to add another server that is not in the authorised host list or your cluster topology needs to change that and this includes a hostnames or IP address of the server not in the list?

Sometimes a full cluster restart with a different configuration is an option but in other cases this is not. Fortunately there are a couple of solutions to this problem - apart from a complete cluster re-start. 

The first is to perform a rolling-restart (shutting down each node in turn, changing its configuration and restarting it). But this operation will impact cluster performance as cache data will need to be recovered and re-balanced. Another option is to specify a range of authorised hosts rather than explicitly name them. This approach balances the need to secure your cluster with the need to change the configuration at some point in the future. A range of hosts that con join a cluster can be specified as follows:

  <authorized-hosts>
    <host-range>
      <from-address>192.168.56.101</from-address>
      <to-address>192.168.56.190</to-address>
    </host-range>
  </authorized-hosts>

A third option is to use a Coherence filter to determine which hosts are authorised to join the cluster. This allows for a more dynamic configuration as a custom filter can access a separate file with a list of hosts, LDAP server or database. By using a filter its possible to specify exactly which hosts can run cluster members while at the same time allowing this lit to be changed dynamically.

A filter to determine authorised hosts can be added to a cluster configuration (tangosol-coherence-override.xml file) as shown below:

  <authorized-hosts>
    <host-filter>
      <!-- Custom Filter to perform authorised host check -->
      <class-name>com.oracle.coherence.test.AuthroizedHostsFilter</class-name>
      <init-params>
        <!-- URL for authorised host list -->
        <init-param>
          <param-type>String</param-type>
          <param-value>

            file:/Users/Dave/workspace/CoherenceAuthorizedHostsTest/hosts.txt

          </param-value>
        </init-param>
        <!-- Time in ms between re-reading authorised hosts -->
        <init-param>
          <param-type>Int</param-type>
          <param-value>10000</param-value>
        </init-param>
      </init-params>
    </host-filter>
  </authorized-hosts>

And an example custom filter that periodically checks a list of hosts at a URL could look like this:

/**
 * File: AuthorizedHostFilter.java
 * 
 * Copyright (c) 2012. All Rights Reserved. Oracle Corporation.
 * 
 * Oracle is a registered trademark of Oracle Corporation and/or its affiliates.
 * 
 * This software is the confidential and proprietary information of Oracle
 * Corporation. You shall not disclose such confidential and proprietary
 * information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Oracle Corporation.
 * 
 * Oracle Corporation makes no representations or warranties about the
 * suitability of the software, either express or implied, including but not
 * limited to the implied warranties of merchantability, fitness for a
 * particular purpose, or non-infringement. Oracle Corporation shall not be
 * liable for any damages suffered by licensee as a result of using, modifying
 * or distributing this software or its derivatives.
 * 
 * This notice may not be removed or altered.
 */
package com.oracle.coherence.test;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import com.tangosol.net.CacheFactory;
import com.tangosol.util.Filter;

/**
 * Simple filter to check if a host is in an authoirsed host list
 * Note: this implementation checks the IP address of a host not the hostname
 * 
 * @author Dave Felcey
 */
public class AuthroizedHostsFilter implements Filter {
  /**
   * List of authorised hosts. Thi list is synchronised in case an update and check are being 
   * perform at the same time
   */
  private List hosts = Collections.synchronizedList(new ArrayList());
  /**
   * URL where authorised host list is located
   */
  private String hostsFileUrl;
  /**
   * Timer use to re-read authorised hosts
   */
  private Timer timer = new Timer();
  
  /**
   * Constructor for AuthroizedHostsFilter
   * @param hostsFileUrl the URL where authorised hosts list is located
   * @param reLoadInterval interval in ms at which authorised hosts list is re-read
   */
  public AuthroizedHostsFilter(String hostsFileUrl, int reLoadInterval) {
    this.hostsFileUrl = hostsFileUrl;
    
    // Load values
    load();
    
    // Schedule periodic reload
    timer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
          CacheFactory.log("About to refresh host list");
          load();
        }
    }, reLoadInterval, reLoadInterval);
  }

  /**
   * Loads authorised host list
   */
  private void load() {
    try {
      CacheFactory.log("Curent dir: " + System.getProperty("user.dir"), CacheFactory.LOG_DEBUG);
      CacheFactory.log("Loading hosts file from URL: " + hostsFileUrl, CacheFactory.LOG_DEBUG);
      URL url = new URL(hostsFileUrl);
      BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));

      String inputLine;
      while ((inputLine = in.readLine()) != null) {
          CacheFactory.log("Host IP address: " + inputLine, CacheFactory.LOG_DEBUG);
          hosts.add(inputLine);
      }
      in.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  @Override
  public boolean evaluate(Object host) {
    String h = host.toString();   
    h = h.substring(h.indexOf('/') + 1);
    
    CacheFactory.log("Validating host IP address: " + host + "(" + h + "), " + hosts.contains(h), CacheFactory.LOG_DEBUG);
    return hosts.contains(h);
  }
}

The dynamic lookup in the example above could be secured further by requiring some kind of credentials for the lookup or instead of polling the resource some kind of change notification could be used to tell the filter when to re-read the authorised hosts. However, in many cases the above approach should be adequate. A full example of the above filter is available from here.

About

Views and ideas about Oracle Coherence and other software

Search

Categories
Archives
« July 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
       
Today