Oracle by Example brandingConfigure the ForkJoin Workflow Element with Oracle Unified Directory 12c

section 0Before 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 port 1389 and LDAP administration port 4444
    • The second standalone OUD instance, fjoinB, is running on LDAP port 2389 and LDAP administration port 2444
    • The Proxy OUD instance, fjoinP, is running on LDAP port 3389 and LDAP administration port 3444
  • 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

section 1Prepare 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.

  1. Navigate to the $OUD_ORACLE_HOME directory.
  2. 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
  3. Navigate to the $OUD_INSTANCES/fjoinA/bin directory.
  4. Run the ldapmodify command to populate the fjoinA 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
  5. Navigate to the $OUD_ORACLE_HOME directory.
  6. 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
  7. Navigate to the $OUD_INSTANCES/fjoinB/bin directory.
  8. Run the ldapmodify command to populate the fjoinB 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

section 2Configure 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).

  1. Navigate to the $OUD_ORACLE_HOME directory.
  2. 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
    
  3. Navigate to the bin directory of the OUD proxy server instance, $OUD_INSTANCES/fjoinP/bin.
  4. Create an LDAP Server Extension, LDAPExtfjoinA that provides details of the host and port required to connect to fjoinA.
    ./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 
  5. Create an LDAP Proxy workflow element, ProxyLDAPWFEfjoinA, that sets the bind mode for fjoinA.
    ./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
  6. Create an LDAP Server Extension, LDAPExtfjoinB that provides details of the host and port required to connect to fjoinB.
    ./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 
  7. Create an LDAP Proxy workflow element, ProxyLDAPWFEfjoinB, that sets the bind mode for fjoinB.
    ./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

section 3Create ForkJoin Workflow Element

To aggregate data from two data sources, you create a Forkjoin Workflow.

  1. Create workflow element of type fork-join for join-suffix dc=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
  2. Create a workflow of type generic for join-suffix dc=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

section 4Configure the ForkJoin Workflow Element

  1. 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
  2. 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
  3. 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
  4. Restart the OUD Proxy Server fjoinP.
    ./stop-ds
    ./start-ds

section 5Configure 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.

  1. Set the Join policy to standard-join using dsconfig.
    ./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
  2. 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
  3. 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) the title attribute is also returned with the entry.


section 6Configure 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.

  1. Set the Join policy to left-outer-join using dsconfig.
    ./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
  2. 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
  3. 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.


section 7Configure 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.

  1. Set the Join policy to full-outer-join using dsconfig.
    ./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
  2. 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
  3. 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.


more informationWant to Learn More?

feedbackFeedback

To provide feedback on this tutorial, please contact Identity Management User Assistance.