Before You Begin
This 15-minute tutorial shows you how to configure the ForkJoin Workflow Element with Oracle Unified Directory 12c (OUD) to aggregate data from two remote data sources in real time.
This tutorial is part of the Oracle Virtual Directory 11g to Oracle Unified Directory 12c Transition Series.
Background
The ForkJoin workflow element solves the problem of split-directory configuration where the user data is split across two repositories. The ForkJoin workflow element can have one primary participant and one secondary participant, each of which is a workflow element of any type. The ForkJoin workflow element allows you to search (search filter) against the primary participant, the secondary participant, or both the primary and the secondary participant.
Consider a scenario, where user data resides in two identity
stores, fjoinA
and fjoinB
. Assume, fjoinA
is configured as the primary participant and fjoinB
is configured as the secondary participant. The primary participant
and the secondary participant namespace is dc=example,dc=com
.
The attributes, givenname
, telephonenumber
,
manager
, sn
, cn
, description
,
and departmentNumber
are stored in fjoinA
.
However, the attributes, title
, sn
,
cn
are stored in fjoinB
. The join rule
is cn=cn
and the secondary-only-attributes
parameter is set to title
. Now, with the ForkJoin
workflow element configured, when an LDAP-enabled application
queries the user data based on title
or sn
or both then OUD retrieves user entries that satisfies the
filter and includes data from both fjoinA
and fjoinB
.
In other words, you can aggregate data from two data sources fjoinA
and fjoinB
in real time.
What Do You Need?
- A basic understanding of Linux
- An environment with at least 16 GB of physical memory and Oracle Enterprise Linux 6.6 or later
- Two standalone OUD 12c instances running on
oud.example.com
. The following assumptions are made for this OBE:- The first standalone OUD instance,
fjoinA
, is running on LDAP port1389
and LDAP administration port4444
- The second standalone OUD instance,
fjoinB
, is running on LDAP port2389
and LDAP administration port2444
- The Proxy OUD instance,
fjoinP
, is running on LDAP port3389
and LDAP administration port3444
- The first standalone OUD instance,
- The LDIF files, fjoinA.ldif and fjoinB.ldif containing the sample data to be loaded into the respective OUD instances.
- The file
~/pwd.txt
exists, containing the password for the Directory Administrator - During the installation and configuration process, this
tutorial assumes the following directory locations:
OUD_ORACLE_HOME=/u01/app/oracle/product/oud/oud
OUD_INSTANCES=/u01/app/oracle/config/oud_instances
Prepare For ForkJoin Workflow Element Configuration
To deploy a ForkJoin workflow element configuration, you first
need to set up two OUD Directory Server instances, fjoinA
and fjoinB
.
- Navigate to the
$OUD_ORACLE_HOME
directory. - Run the
oud-setup
command to create the first OUD instance,fjoinA
../oud-setup \ --cli \ --no-prompt \ --hostname oud.example.com \ --ldapPort 1389 \ --adminConnectorPort 1444 \ --baseDN dc=example,dc=com \ --addBaseEntry \ --rootUserDN "cn=Directory Manager" \ --rootUserPasswordFile ~/pwd.txt \ --instancePath /u01/app/oracle/config/oud_instances/fjoinA \ --noPropertiesFile
The output should look similar to this:
Oracle Unified Directory 12.2.1.4.0 Please wait while the setup program initializes... Creating instance directory /u01/app/oracle/config/oud_instances/fjoinA .....Done. See /u01/app/oracle/config/oud_instances/fjoinA/logs/oud-setup for a detailed log of this operation. To see basic server configuration status and configuration you can launch /u01/app/oracle/config/oud_instances/fjoinA/bin/status
- Navigate to the
$OUD_INSTANCES/fjoinA/bin
directory. - Run the
ldapmodify
command to populate thefjoinA
directory server instance with sample entries from the fjoinA.ldif file../ldapmodify \ --hostname oud.example.com \ --port 1389 \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --defaultAdd --filename ~/fjoinA.ldif
The output should look similar to this:
Processing ADD request for ou=People,dc=example,dc=com ADD operation successful for DN ou=People,dc=example,dc=com Processing ADD request for cn=Rock,ou=People,dc=example,dc=com ADD operation successful for DN cn=Rock,ou=People,dc=example,dc=com Processing ADD request for cn=Sandy,ou=People,dc=example,dc=com ADD operation successful for DN cn=Sandy,ou=People,dc=example,dc=com Processing ADD request for cn=Rivry,ou=People,dc=example,dc=com ADD operation successful for DN cn=Rivry,ou=People,dc=example,dc=com Processing ADD request for cn=Woods,ou=People,dc=example,dc=com ADD operation successful for DN cn=Woods,ou=People,dc=example,dc=com
- Navigate to the
$OUD_ORACLE_HOME
directory. - Run the oud-setup command to create the second OUD instance,
fjoinB
, as follows:./oud-setup \ --cli \ --no-prompt \ --hostname oud.example.com \ --ldapPort 2389 \ --adminConnectorPort 2444 \ --baseDN dc=example,dc=com \ --addBaseEntry \ --rootUserDN "cn=Directory Manager" \ --rootUserPasswordFile ~/pwd.txt \ --instancePath /u01/app/oracle/config/oud_instances/fjoinB \ --noPropertiesFile
The output should look similar to this:
Oracle Unified Directory 12.2.1.4.0 Please wait while the setup program initializes... Creating instance directory /u01/app/oracle/config/oud_instances/fjoinB .....Done. See /u01/app/oracle/config/oud_instances/fjoinB/logs/oud-setup for a detailed log of this operation. To see basic server configuration status and configuration you can launch /u01/app/oracle/config/oud_instances/fjoinB/bin/status
- Navigate to the
$OUD_INSTANCES/fjoinB/bin
directory. - Run the
ldapmodify
command to populate thefjoinB
directory server instance with sample entries from the fjoinB.ldif file../ldapmodify \ --hostname oud.example.com \ --port 2389 \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --defaultAdd --filename ~/fjoinB.ldif
The output should look similar to this:
Processing ADD request for ou=People,dc=example,dc=com ADD operation successful for DN ou=People,dc=example,dc=com Processing ADD request for cn=Rock,ou=People,dc=example,dc=com ADD operation successful for DN cn=Rock,ou=People,dc=example,dc=com Processing ADD request for cn=Sandy,ou=People,dc=example,dc=com ADD operation successful for DN cn=Sandy,ou=People,dc=example,dc=com Processing ADD request for cn=Rivry,ou=People,dc=example,dc=com ADD operation successful for DN cn=Rivry,ou=People,dc=example,dc=com Processing ADD request for cn=Mounty,ou=People,dc=example,dc=com ADD operation successful for DN cn=Mounty,ou=People,dc=example,dc=com
Configure the OUD Proxy Server
Set up an OUD Proxy Server instance fjoinP
in front
of the data sources fjoinA
and fjoinB
that you want to join. In addition, to connect to a remote LDAP
directory server, the OUD proxy needs LDAP server extension and
LDAP proxy workflow elements configured. LDAP Server extensions are the
properties required to connect from OUD Proxy fjoinP
to the remote LDAP servers (fjoinA
and fjoinB
).
- Navigate to the
$OUD_ORACLE_HOME
directory. - Run the
oud-proxy-setup
command to create a proxy server instance,fjoinP
, as follows:./oud-proxy-setup \ --cli \ --no-prompt \ --hostname oud.example.com \ --ldapPort 3389 \ --adminConnectorPort 3444 \ --rootUserDN "cn=Directory Manager" \ --rootUserPasswordFile ~/pwd.txt \ --instancePath /u01/app/oracle/config/oud_instances/fjoinP \ --noPropertiesFile
The output should look similar to this:
Successfully wrote the updated Directory Server configuration Starting the Server : /u01/app/oracle/config/oud_instances/fjoinP/bin/start-ds --timeout 0 [15/Feb/2019:00:06:07 -0800] category=CORE severity=INFORMATION msgID=132 msg=The Directory Server is beginning the configuration bootstrapping process --- --- org.opends.server.DirectoryServerStarted, alert ID 458887): The Directory Server has started successfully
- Navigate to the
bin
directory of the OUD proxy server instance,$OUD_INSTANCES/fjoinP/bin
. - Create an LDAP Server Extension,
LDAPExtfjoinA
that provides details of the host and port required to connect tofjoinA
../dsconfig \ --hostname oud.example.com \ --port 3444 \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --trustAll \ --no-prompt \ create-extension \ --set enabled:true \ --type ldap-server \ --extension-name LDAPExtfjoinA \ --set remote-ldap-server-address:oud.example.com \ --set remote-ldap-server-port:1389
- Create an LDAP Proxy workflow element,
ProxyLDAPWFEfjoinA
, that sets the bind mode forfjoinA
../dsconfig \ --hostname oud.example.com \ --port 3444 \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --trustAll \ --no-prompt \ create-workflow-element \ --set enabled:true \ --type proxy-ldap \ --element-name ProxyLDAPWFEfjoinA \ --set ldap-server-extension:LDAPExtfjoinA \ --set client-cred-mode:use-client-identity
- Create an LDAP Server Extension,
LDAPExtfjoinB
that provides details of the host and port required to connect tofjoinB
../dsconfig \ --hostname oud.example.com \ --port 3444 \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --trustAll \ --no-prompt \ create-extension \ --set enabled:true \ --type ldap-server \ --extension-name LDAPExtfjoinB \ --set remote-ldap-server-address:oud.example.com \ --set remote-ldap-server-port:2389
- Create an LDAP Proxy workflow element,
ProxyLDAPWFEfjoinB
, that sets the bind mode forfjoinB
../dsconfig \ --hostname oud.example.com \ --port 3444 \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --trustAll \ --no-prompt \ create-workflow-element \ --set enabled:true \ --type proxy-ldap \ --element-name ProxyLDAPWFEfjoinB \ --set ldap-server-extension:LDAPExtfjoinB \ --set client-cred-mode:use-client-identity
Create ForkJoin Workflow Element
To aggregate data from two data sources, you create a Forkjoin Workflow.
- Create workflow element of type
fork-join
for join-suffixdc=forkjoin
../dsconfig \ --hostname oud.example.com \ --port 3444 \ --portProtocol LDAP \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --trustAll \ --no-prompt \ create-workflow-element \ --set enabled:true \ --set join-suffix:dc=forkjoin \ --set populate-joinedentrydn:true \ --set secondary-only-attributes:title \ --type fork-join \ --element-name fjwe1
- Create a workflow of type
generic
for join-suffixdc=forkjoin
../dsconfig \ --hostname oud.example.com \ --port 3444 \ --portProtocol LDAP \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --trustAll \ --no-prompt \ create-workflow \ --set base-dn:dc=forkjoin \ --set enabled:true \ --set workflow-element:fjwe1 \ --type generic \ --workflow-name forkjoinwf
Configure the ForkJoin Workflow Element
- Create the Primary ForkJoin participant that is the link
between the ForkJoin workflow element and
fjoinA
../dsconfig \ --hostname oud.example.com \ --port 3444 \ --portProtocol LDAP \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --trustAll \ --no-prompt \ create-primary-fork-join-participant \ --element-name fjwe1 \ --set participant-dn:dc=example,dc=com \ --set participating-workflow-element:ProxyLDAPWFEfjoinA \ --type generic
- Create the Secondary ForkJoin participant that is the link
between the ForkJoin workflow element and
fjoinB
../dsconfig \ --hostname oud.example.com \ --port 3444 \ --portProtocol LDAP \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --trustAll \ --no-prompt \ create-secondary-fork-join-participant \ --element-name fjwe1 \ --set participant-dn:dc=example,dc=com \ --set participating-workflow-element:ProxyLDAPWFEfjoinB \ --set participants-join-rule:cn=cn \ --type generic
- Attach the ForkJoin Workflow,
forkjoinwf
, to the network group../dsconfig \ --hostname oud.example.com \ --port 3444 \ --portProtocol LDAP \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --trustAll \ --no-prompt \ set-network-group-prop \ --group-name network-group \ --set workflow:forkjoinwf
- Restart the OUD Proxy Server
fjoinP
../stop-ds ./start-ds
Configure standard-join
Join policy and validate.
A standard-join
Join policy returns all entries that satisfy the search filter in the primary participant (fjoinA) after joining corresponding entries in the secondary participant (fjoinB). In this case the join is made (cn=cn
) between the two participants, allowing the secondary only attribute title
to be returned from fjoinB, and then the search filter "|(sn=*e*)(title=*e*)"
is applied to fjoinA, returning the entries shown below.
- Set the Join policy to
standard-join
usingdsconfig
../dsconfig \ --hostname oud.example.com \ --port 3444 \ --portProtocol LDAP \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --trustAll \ --no-prompt \ set-secondary-fork-join-participant-prop \ --element-name fjwe1 \ --set join-policy:standard-join
- Test using
ldapsearch
../ldapsearch \ --hostname oud.example.com \ --port 3389 \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --baseDN "dc=forkjoin" \ --searchScope sub "|(sn=*e*)(title=*e*)" sn cn title
- Output should look like this:
dn: cn=Rock,ou=People,dc=forkjoin sn: Anne title: Manager cn: Rock dn: cn=Sandy,ou=People,dc=forkjoin sn: Ketty title: SMTS cn: Sandy dn: cn=Woods,ou=People,dc=forkjoin sn: Tent cn: Woods
Note: Only entries from the primary participant (fjoinA) that have the letter 'e' in the
sn
attribute are returned. Where a match exists with the secondary participant (fjoinB) thetitle
attribute is also returned with the entry.
Configure left-outer-join
Join policy and validate.
A left-outer-join
Join policy returns the entries in the primary participant after joining with corresponding entries in secondary participant (standard-join
), and returns entries from the secondary participant that satisfy the join condition and which have a corresponding match in primary participant. This is the equivalent to Left Outer Join in database terminology.
- Set the Join policy to
left-outer-join
usingdsconfig
../dsconfig \ --hostname oud.example.com \ --port 3444 \ --portProtocol LDAP \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --trustAll \ --no-prompt \ set-secondary-fork-join-participant-prop \ --element-name fjwe1 \ --set join-policy:left-outer-join
- Test using
ldapsearch
../ldapsearch \ --hostname oud.example.com \ --port 3389 \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --baseDN "dc=forkjoin" \ --searchScope sub "|(sn=*e*)(title=*e*)" sn cn title
- Output should look like this:
dn: cn=Rock,ou=People,dc=forkjoin sn: Anne title: Manager cn: Rock dn: cn=Sandy,ou=People,dc=forkjoin sn: Ketty title: SMTS cn: Sandy dn: cn=Woods,ou=People,dc=forkjoin sn: Tent cn: Woods dn: cn=Rivry,ou=People,dc=forkjoin sn: Rod title: Trainee cn: Rivry
Note: In this case you are running the same
ldapsearch
as the previous step, but an additional entry is returned. The secondary participant (fjoinB) has an entry,dn: cn=Rivry,dc=example,dc=com
, which matches the search filter ((title=*e*)
) and matches the join condition with the primary participant (fjoinA),cn=cn
.
Configure full-outer-join
Join policy and validate.
A full-outer-join
Join policy returns all the entries in the primary participant after joining with corresponding entries in secondary participant (standard-join
); returns entries from the secondary participant that satisfy the join condition and which have a corresponding match in primary participant (left-outer-join
); and returns entries from the secondary participant that satisfy the search filter but do not have a matching entry in primary participant. This is the equivalent to Left Outer Join + Right Outer Join in database terminology.
- Set the Join policy to
full-outer-join
usingdsconfig
../dsconfig \ --hostname oud.example.com \ --port 3444 \ --portProtocol LDAP \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --trustAll \ --no-prompt \ set-secondary-fork-join-participant-prop \ --element-name fjwe1 \ --set join-policy:full-outer-join
- Test using
ldapsearch
../ldapsearch \ --hostname oud.example.com \ --port 3389 \ --bindDN "cn=Directory Manager" \ --bindPasswordFile ~/pwd.txt \ --baseDN "dc=forkjoin" \ --searchScope sub "|(sn=*e*)(title=*e*)" sn cn title
- Output should look like this:
dn: cn=Rock,ou=People,dc=forkjoin sn: Anne title: Manager cn: Rock dn: cn=Sandy,ou=People,dc=forkjoin sn: Ketty title: SMTS cn: Sandy dn: cn=Woods,ou=People,dc=forkjoin sn: Tent cn: Woods dn: cn=Rivry,ou=People,dc=forkjoin sn: Rod title: Trainee cn: Rivry dn: cn=Mounty,ou=People,dc=forkjoin sn: Ret title: MTS - dept_sec cn: Mounty
Note: In this case an additional entry is returned from the secondary participant as it matches the search filter (
(title=*e*)
) while the entry does not have a match with the join condition,cn=cn
.
Want to Learn More?
Feedback
To provide feedback on this tutorial, please contact Identity Management User Assistance.