Thursday, 27 August 2015

Oracle Unified Directory (OUD) Proxy Load Balancing and Transformation Configuration

1.     Introduction

Oracle Unified Directory Proxy (OUDP) is an LDAP v3 compliant server that stores no data but proxies requests from clients to other directories. There could be a number of scenarios where using a proxy can be useful. For a detailed description of these scenarios and proxy functionality, please refer to Oracle Unified Directory of the Oracle® Fusion MiddlewareAdministrator's Guide for Oracle Unified Directory 11g Release 2 (11.1.2)[1]

In this entry, the proxy configuration steps for setting up a directory topology as depicted in Figure 1 - Example Topology will be covered. In this diagram, OUDP1 and OUDP2 are two directory proxies that are proxying requests to two directory instances (OUDD1 and OUDD2).
Figure 1 - Example Topology (Click to enlarge)



The configuration steps covered include setting up the following:
  1. Load Balancing
  2. A Read Transformation to add an outbound attribute, and
  3. DN Renaming
A bash script for setting up the entire configuration in a single step is also provided.

2.     OUD Request Handling

A short summary of OUD request handling is in order before getting into the details. Any LDAP request that comes into OUD goes through the following processing:
  1. The relevant connection handler invokes the request handler which places the request in the work queue.
  2. A worker thread picks this up from the queue and routes this to a network group based on the QoS policies and criteria.The network group forwards the operation to a workflow based on the naming context. The operation is forwarded to the workflow that has the same naming context as the request base DN.
  3. The workflow then forwards this to the first workflow element defined in the workflow. For a proxy server, a workflow can be defined as a chain of workflow elements with each workflow element invoking the next workflow element in the chain after completing its processing.
All this is covered in more detail (including a nifty diagram) in Section 5.2, "Architecture of Oracle Unified Directory" of the Oracle® Fusion Middleware Administrator's Guide for Oracle Unified Directory 11g Release 2 (11.1.2).

3.     Implementation

In the example depicted in Figure 1 - Example Topology, the workflow elements that are chained together to form a request processing workflow are shaded in green.
  1. The first workflow element is a DN Renaming transformation. DN Renaming is used to transform the content of a DIT into another DIT with a different base DN. In this example, DN renaming will be used to transform all entries under ou=subsidiary,dc=company,dc=com on the server side to have a DN of dc=subsidiary,dc=com on the client side. DN Renaming applies to the entry DN as well as to any attributes that has DN (e.g. manager) or Name And Optional UIDs (e.g. uniquemember) syntax.
  2. The second workflow element is a Read Transformation. OUD Proxy supports a number of transformations. These are covered in detail in the product documentation. In this example, an Add Outbound Attribute transformation will be used to create a multi-valued virtual attribute called username and populate it with values from the uid and mail attributes.
  3. The third workflow element is a Load Balancing workflow element. Once again, there are a number of options around load balancing and distribution that is supported and a detailed description is available in the product documentation. In this example, Load Balancing with the Failover algorithm will be used. All requests coming into OUDP1 will be sent to OUDD1 (primary route). If OUDD1 is not available, then requests will be sent to OUDD2 (backup route). Similarly, all requests coming into OUDP2 will be sent to OUDD2 (primary route). If OUDD2 is not available, then requests will be sent to OUDD1 (backup route). Normally, after failover the backup route continues to handle requests even after the primary server that has failed becomes available. This default behavior will be changed by setting the switch-back property to true for the load balancing algorithm.
The configuration described above can be set up:
  • Using the OUD dsconfig CLI, or by
  • Using the Oracle Directory Services Manager (ODSM) web UI, or by
  • Using the oud-proxy-setup GUI (at the time of initial setup only)
This blog entry will describe using the OUD dsconfig CLI to set this up. Note the following about the dsconfig example commands given below:
  1. The commands are shown with line-breaks for readability. However, they should be entered in one line or with suitable terminators (e.g. \ on Linux).
  2.  Replace the variable references as follows:
  • $INSTANCE_HOME – OUD Proxy instance directory (e.g. /oracle/fmwhome/asinst_1/OUD)
  • $OUDP_ADMIN_PORT – OUD Proxy Administration Port (e.g. 4444)
  • $OUDP_HOST – OUD Proxy Hostname or IP Address
  • $OUDP_ADMIN_USER – Administrator User Bind DN (e.g. cn=Directory Manager)
  • $OUDP_ADMIN_PWD_FILE – Location of a text file containing the Administrator User password (e.g. /home/oracle/pwd-file)
  • $OUD1_HOST – Hostname or IP Address of OUDD1
  • $OUD1_PORT – LDAP listen port of OUDD1
  • $OUD1_SSL_PORT – LDAPS listen port of OUDD1
  • $OUD2_HOST – Hostname or IP Address of OUDD2
  • $OUD2_PORT – LDAP listen port of OUDD2
  • $OUD2_SSL_PORT – LDAPS listen port of OUDD2

3.1.                      Load Balancing


Detailed view of OUD Proxy Load Balancing Elements
Figure 2 - Load Balancing (Click to enlarge)
Figure 2 - Load Balancing depicts the elements that need to be setup in each OUD Proxy for realizing the load balancing requirements outlined earlier. These are:
  1. A Load Balancing workflow element (we-lb1 in Figure 2 - Load Balancing) that uses failover as the load balancing algorithm and has the switch-back property set to true. we-lb1 encapsulates the load balancing routes and will be the last workflow element in any workflow that has to transfer the request to the OUD Directory. This can be setup by executing the following commands against each OUD Proxy.
## Create load-balancing workflow element
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X create-workflow-element --element-name we-lb1 --type load-balancing --set enabled:true

## Create load-balancing algorithm
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X create-load-balancing-algorithm --type failover --element-name we-lb1

## Set switch-back true on load-balancing algorithm $INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X --advanced set-load-balancing-algorithm-prop --element-name we-lb1 --set switch-back:true
  1. LDAP Server Extensions (oud1 and oud2 in Figure 2 - Load Balancing) pointing to each OUD Directory. These elements can be setup by executing the following commands against each OUD Proxy.
## Create LDAP Server Extensions

$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X create-extension --extension-name oud1 --type ldap-server --set enabled:true --set remote-ldap-server-address:$OUDD1_HOST --set remote-ldap-server-port:$OUDD1_PORT --set remote-ldap-server-ssl-port:$OUDD1_SSL_PORT --set ssl-trust-all:true[2] --set remote-ldap-server-ssl-policy:user

$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X create-extension --extension-name oud2 --type ldap-server --set enabled:true --set remote-ldap-server-address:$OUDD2_HOST --set remote-ldap-server-port:$OUDD2_PORT --set remote-ldap-server-ssl-port:$OUDD2_SSL_PORT --set ssl-trust-all:true[3] --set remote-ldap-server-ssl-policy:user
  1. proxy-ldap workflow elements (we-ldap1 and we-ldap2 in Figure 2 - Load Balancing) for encapsulating each LDAP Server Extension. These elements can be setup by executing the following commands against each OUD Proxy.
## Create proxy-ldap workflow elements

$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X create-workflow-element --element-name we-ldap1 --type proxy-ldap --set enabled:true --set client-cred-mode:use-client-identity --set ldap-server-extension:oud1

$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X create-workflow-element --element-name we-ldap2 --type proxy-ldap --set enabled:true --set client-cred-mode:use-client-identity --set ldap-server-extension:oud2
  1. Load Balancing Routes (route1 and route2 in Figure 2 - Load Balancing) pointing to each proxy-ldap workflow element. route1 using we-ldap1 will be the primary route for all operations in OUDP1. route2 using we-ldap2 will be the primary route for all operations in OUDP2. The commands for setting this up on OUDP1 are:
## Create primary route
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X  create-load-balancing-route --route-name route1 --type failover --element-name we-lb1 --set workflow-element:we-ldap1 --set add-priority:1 --set bind-priority:1 --set compare-priority:1 --set delete-priority:1 --set extended-priority:1 --set modify-priority:1 --set modifydn-priority:1 --set search-priority:1

## Create backup route
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X  create-load-balancing-route --route-name route2 --type failover --element-name we-lb1 --set workflow-element:we-ldap2 --set add-priority:2 --set bind-priority:2 --set compare-priority:2 --set delete-priority:2 --set extended-priority:2 --set modify-priority:2 --set modifydn-priority:2 --set search-priority:2
The commands for setting this up on OUDP2 are:
## Create primary route
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X  create-load-balancing-route --route-name route1 --type failover --element-name we-lb1 --set workflow-element:we-ldap2 --set add-priority:1 --set bind-priority:1 --set compare-priority:1 --set delete-priority:1 --set extended-priority:1 --set modify-priority:1 --set modifydn-priority:1 --set search-priority:1

## Create backup route
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X  create-load-balancing-route --route-name route2 --type failover --element-name we-lb1 --set workflow-element:we-ldap1 --set add-priority:2 --set bind-priority:2 --set compare-priority:2 --set delete-priority:2 --set extended-priority:2--set modify-priority:2 --set modifydn-priority:2 --set search-priority:2

3.2.                      Transformation



Detailed view of OUD Proxy Transformation Elements
Figure 3 - Transformations (Click to enlarge)

Figure 3 - Transformation depicts the elements that need to be setup in each OUD Proxy for realizing the transformation requirements outlined earlier. These are:
  1. A transformation workflow element (we-username-transforms in Figure 3 - Transformations) that has one transformation(add-username in Figure 3 - Transformation) that creates a multi-valued virtual attribute called username and populates it with the values in the uid and mail directory attributes. This can be setup by executing the following commands against each OUD Proxy:
## Transformations - Create Add Outbound Attribute transformation
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X create-transformation --transformation-name add-username --type add-outbound-attribute --set client-attribute:username=%uid%=%mail% --set virtual-in-source:false

## Transformations - Create transformation workflow element
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X  create-workflow-element --element-name we-username-transforms --type transformations --set enabled:true --set transformation:add-username --set next-workflow-element:we-lb1

  1. A dn-renaming workflow element (we-dn-rename-to-subs in Figure 3 - Transformation). This can be setup by executing the following commands against each OUD Proxy:
## Transformations - Create DN Renaming workflow element
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X  create-workflow-element --element-name we-dn-rename-to-subs --type dn-renaming --set enabled:true --set client-base-dn:dc=subsidiary,dc=com --set source-base-dn:ou=subsidiary,dc=company,dc=com --set next-workflow-element:we-username-transforms

3.3.                      Putting it all together

The last piece in the puzzle is a workflow with that will invoke the first workflow element in the processing chain. This can be setup as outlined below:
  1. Create a new workflow. This can be done by executing the following commands against each OUD Proxy:
## Create Workflow
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X create-workflow --workflow-name "Subsidiary" --set base-dn:dc=subsidiary,dc=com --set enabled:true --set workflow-element:we-dn-rename-to-subs --type generic
  1.  Attach the workflow to a network group. In this example, the workflow will be attached to the network group called “network-group” that is available out of the box with OUD. This can be done by executing the following commands against each OUD Proxy:
## Add workflow to the OOTB "network-group" Network Group
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X set-network-group-prop --group-name network-group --set enabled:true --set priority:0 --add allowed-protocol:ldap --add allowed-protocol:ldaps --add workflow:"Subsidiary"

4.     Configuration Script

All the commands described in the previous sections are packaged as a single bash shell script below. This script can be used to create the whole configuration after making suitable changes to the environment specific variables. It needs to be run against each OUD Proxy in the topology. Please read the comments at the top of the script before attempting to execute it. This script has been tested only on a two node topology.
#!/bin/bash
## OUD Proxy config script
## INSTANCE_HOME should be set to the OUD Proxy instance directory
## Pass --no-prompt as argument to script when invoking for silent execution
## Begin editable env vars
## DEV1
OUD1_HOST=localhost
OUD1_PORT=1389
OUD1_SSL_PORT=1636
## Set value for OUD2_HOST only for HA envs
OUD2_HOST=localhost
OUD2_PORT=2389
OUD2_SSL_PORT=2636
## Node index of the OUDP that is being configured - used to determine routing.
## In a single node env, possible value is 1. In a two node env, possible values are 1 and 2.
## Even number of nodes in a topology is assumed. Testing done only on 2 node topology
OUDP_NODE_INDEX=1
OUDP_HOST=localhost
OUDP_ADMIN_PORT=6444
OUDP_ADMIN_USER=cn=oudadmin
OUDP_ADMIN_PWD_FILE=/home/oracle/pwd-file
NO_PROMPT=$1
## End editable env vars
if [ "x$INSTANCE_HOME" == "x" ]; then echo "INSTANCE_HOME should be set to the OUD Proxy instance directory"; exit 1; fi
function add_dir_for_lb {
    ## Create LDAP Server Extension
    $INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X $NO_PROMPT create-extension --extension-name oud$4 --type ldap-server --set enabled:true --set remote-ldap-server-address:$1 --set remote-ldap-server-port:$2 --set remote-ldap-server-ssl-port:$3 --set ssl-trust-all:true --set remote-ldap-server-ssl-policy:user
    ## Create proxy-ldap workflow element
    $INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X $NO_PROMPT  create-workflow-element --element-name we-ldap$4 --type proxy-ldap --set enabled:true --set client-cred-mode:use-client-identity --set ldap-server-extension:oud$4
    if [ "$4" -eq "$5" ]
            then
                    ## Create primary route
                    $INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X $NO_PROMPT  create-load-balancing-route --route-name route$4 --type failover --element-name we-lb1 --set workflow-element:we-ldap$4 --set add-priority:1 --set bind-priority:1 --set compare-priority:1 --set delete-priority:1 --set extended-priority:1 --set modify-priority:1 --set modifydn-priority:1 --set search-priority:1
            else
                    ## Create backup route
                    $INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X $NO_PROMPT  create-load-balancing-route --route-name route$4 --type failover --element-name we-lb1 --set workflow-element:we-ldap$4 --set add-priority:2 --set bind-priority:2 --set compare-priority:2 --set delete-priority:2 --set extended-priority:2 --set modify-priority:2 --set modifydn-priority:2 --set search-priority:2
    fi
}
## Load Balancing Configuration
## Create load-balancing workflow element
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X $NO_PROMPT  create-workflow-element --element-name we-lb1 --type load-balancing --set enabled:true
## Create load-balancing algorithm
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X $NO_PROMPT create-load-balancing-algorithm --type failover --element-name we-lb1
## Set switch-back true on load-balancing algorithm
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X $NO_PROMPT --advanced set-load-balancing-algorithm-prop --element-name we-lb1 --set switch-back:true
## Point to OUD1
add_dir_for_lb $OUD1_HOST $OUD1_PORT $OUD1_SSL_PORT 1 $OUDP_NODE_INDEX
## Point to OUD2
if [[ $OUD2_HOST ]]
    then
            add_dir_for_lb $OUD2_HOST $OUD2_PORT $OUD2_SSL_PORT 2 $OUDP_NODE_INDEX
fi
## Transformations - Create Add Outbound Attribute transformation
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X $NO_PROMPT create-transformation --transformation-name add-username --type add-outbound-attribute --set client-attribute:username=%uid%=%mail% --set virtual-in-source:false
## Transformations - Create transformation workflow element
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X $NO_PROMPT  create-workflow-element --element-name we-username-transforms --type transformations --set enabled:true --set transformation:add-username --set next-workflow-element:we-lb1
## Transformations - Create DN Renaming workflow element
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X $NO_PROMPT  create-workflow-element --element-name we-dn-rename-to-subs --type dn-renaming --set enabled:true --set client-base-dn:dc=subsidiary,dc=com --set source-base-dn:ou=subsidiary,dc=company,dc=com --set next-workflow-element:we-username-transforms
## Create Workflow
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X $NO_PROMPT create-workflow --workflow-name "Subsidiary" --set base-dn:dc=subsidiary,dc=com --set enabled:true --set workflow-element:we-dn-rename-to-subs --type generic
## Add workflow to the OOTB "network-group" Network Group
$INSTANCE_HOME/bin/dsconfig -p $OUDP_ADMIN_PORT -h $OUDP_HOST -D $OUDP_ADMIN_USER -j $OUDP_ADMIN_PWD_FILE -X $NO_PROMPT set-network-group-prop --group-name network-group --set enabled:true --set priority:0 --add allowed-protocol:ldap --add allowed-protocol:ldaps --add workflow:"Subsidiary"


[1] Note that this and all other links were current at the time of writing.
[2] For prod environments, it is recommended to set this to false and provide a ssl-trust-manager-provider instead.
[3] For prod environments, it is recommended to set this to false and provide a ssl-trust-manager-provider instead.