DEV Community

hediyeh kianmehr
hediyeh kianmehr

Posted on • Edited on

Active Directory User Sync

Overview:

Synchronization is the process of creating users from Active Directory in OpenIAM.


In this document we cover these topics.

1.Active Directory User Sync

1.1 How to access the synchronization settings?
1.2 Validation Rule
1.3 Where is the log location of println?
1.4 Viewing the Log in Real-Time
1.5 Transformation Rule
1.6 Viewing Synchronization History
1.7 Troubleshooting Sync Issues
1.8 Successful Synchronization
1.9 Editing the Active Directory Connector Script


1.Active Directory User Sync

How to find users in Active Directory machine?

Accessing Active Directory Users and Computers

Login to your Active Directory machine.

Press Windows + R .

Type dsa.msc and press Enter.

This opens the Active Directory Users and Computers console.

Please navigate to your domain
based on our setup:Saeigroup.local is our domain

Then, navigate to your Organizational Unit
based on our setup: SaeiUsers is our Organizational Unit

note:
All users have a first name, last name, telephone number, and email address as an attribute.

To proceed, we need to import them into OpenIAM and then perform a one-way synchronization.


1.1 How to access the synchronization settings?

To access the synchronization settings

  • navigate to the provisioning tab

  • select synchronization

Synchronization occurred with the Managed System, and this managed system is referred to as the PowerShell Managed System.

  • In the Managed System column, we select AD PowerShell Managed System.

Choose Synchronization Type

And there are two options available: syncing either group or user.

  • We selected the AD PowerShell USER Example and proceeded to click on the edit option.


Configure the fields

Name: please enter the desired name

Records count in one Branch: 1000

Active checkbox: ticked


Provision to target system

Provision to target system? (checkbox) : Unticked

note:
If we didn't tick this checkbox, it would be one way, and it's from Active Directory users going to create in OpenIAM

note:
But if we want to have it two-way, we can tick the checkbox.


Managed System: AD PowerShell Managed System
synchronize Object: user


Synch Type: Complete
Synch Frequency: Execute once on exact data
Run on: select data that you want to sync executed


1.2 Validation Rule

Validation Rule: /sync/User/ad/ADPowerShellValidationgroovy

When you click on Edit, you can view the script.

The validation script checks whether the user retrieved from Active Directory is valid or not.

if it's not valid it is going to println it is not valid

1.3 Where is the log location of println?

note:
The println is logged in the file located at this path on the OpenIAM machine: /user/local/openIAM/logs.

Steps to Access the Log File:

  • Login to your OpenIAm machine.

  • Press Windows + R on your keyboard.

  • Type cmd and press Enter

  • In this path /user/local/openIAM/logs Type ls press Enter

you should see synchronization.log


1.4 Viewing the Log in Real-Time

If you type tail -f synchronization.log you would see validation script in your OpenIAm machine

tail -f synchronization.log
Enter fullscreen mode Exit fullscreen mode

note:

You can identify errors in the script by using println to debug. Additionally, you can check the log of OpenIAm machine in synchronization.log, file which is located in the path /user/local/openIAM/logs.

this the log from OpenIAm machine for syncronization


1.5 Transformation Rule:

/sync/User/ad/ADPowerShellTransformationgroovy

After successful validation, user data sourced from Active Directory is transformed into an attribute in OpenIAm machine.

When you click on Edit, you can view the script.

Some Attributes Not Synced by Default

Issue

The transformation script did not automatically sync all attributes because it was designed to transform only a limited set of attributes.

Solution

To address this issue, we have added a function to the script that enables the synchronization of additional attributes, including phone numbers.

Now we want to make some changes in the ADPowerShellTransformationgroovy script

Now we want to mention some changes in the ADPowerShellTransformationgroovy script as follows.

logging functionality

This script includes logging functionality.

            def lg = new Login()
                lg.operation = AttributeOperationEnum.ADD
                lg.login = attrVal.value
                lg.managedSysId = "0"
                lg.setActive(true)
                pUser.principalList.add(lg)

                /*Login lg2 = new Login()
                lg2.operation = AttributeOperationEnum.ADD
                lg2.login = attrVal.value
                lg2.managedSysId = config.getManagedSysId()
                lg2.setActive(true)
                pUser.principalList.add(lg2)*/

            }
        }
Enter fullscreen mode Exit fullscreen mode

eliminate the space

In this part of the code, we eliminate the space in the surname to prevent errors that occur when such a space exists. This ensures that if you search for a username in the search bar, it will appear correctly without that space.


        attrVal = columnMap.get("Surname")
        if (attrVal) {
            pUser.lastName = attrVal.value?.replaceAll("\\s", "")//empty space check
        }

Enter fullscreen mode Exit fullscreen mode

Handling Telephone Numbers in the Transformation Script

        def telAttr = columnMap.get("telephoneNumber")
        if (telAttr && StringUtils.isNotEmpty(telAttr.value)) {
            def phoneNumber = telAttr.value.trim()
            println("Preparing phone number for user: ${phoneNumber}")

            def areaCd = ""
            def countryCd = ""

            // Detect if phone number starts with 0
            if (phoneNumber.startsWith("0")) {
                areaCd = "021"    // Tehran example
                countryCd = "+98" // Iran code
                println("Detected local Iranian number, setting area and country codes.")
            } else {
                areaCd = "?"    
                countryCd = "?" 
                println("International or unknown format, no area/country codes assigned.")
            }
Enter fullscreen mode Exit fullscreen mode

In this part of the transformation script, the telephoneNumber is retrieved from Active Directory. The script then prepares to assign values for the Area code and Country code.

By default, both the Area code and Country code are left empty. The script then checks if the phoneNumber starts with 0—which is typical for Iranian phoneNumbers.

If the number starts with 0, the script:

Sets the Area code to 021

Sets the Country code to +98

Logs a message: Detected local Iranian number, setting area and country codes.

As a result, you can see that the user sync is functioning properly, and both the area code and country code are set correctly.

If the number does not start with 0, the script:

Sets both the Area code and Country code to ? as placeholders

Logs a message:Phone number not found on user — adding new phone.

note:
To avoid errors, it sets both the Area code and Country code to ? as placeholders when they are not explicitly defined.


           // Check if phone already exists for user
            boolean phoneExists = pUser.phones?.any { it.phoneNbr == phoneNumber }
            if (phoneExists) {
                println("Phone number already exists on user — skipping addition.")
            } else {
                println("Phone number not found on user — adding new phone.")
Enter fullscreen mode Exit fullscreen mode

If a phone number already exists, the script:

  • Skips adding it again

  • Logs the message: Phone number already exists on user — skipping addition.

If no phone number is found, the script:

  • Proceeds to add the new phone number

  • Logs the message: Phone number not found on user — adding new phone.


Handling Missing Phone Numbers

If the phone number is null or missing, the script assigns a placeholder value of # to the phone number.


import org.openiam.idm.srvc.continfo.dto.Phone //phone

                def phone = new Phone()
                phone.mdTypeId = "CELL_PHONE"
                phone.phoneNbr = phoneNumber
                phone.areaCd = areaCd
                phone.countryCd = countryCd
                phone.active = true
                phone.default = false
                phone.operation = AttributeOperationEnum.ADD

                if (pUser.phones == null) {
                    pUser.phones = new HashSet<Phone>()
                }
                pUser.phones.add(phone)
                println("Phone added successfully:")
            }
        }

Enter fullscreen mode Exit fullscreen mode

In this section of the script, several mandatory attributes are being set for the phone entry. All of these fields are required by OpenIAM. If any one of them is missing, an error will occur during processing.

If the phone number is null or missing, it assigns a placeholder value of # to Phone number.

note:
After all these changes, all attributes synced.
including phone numbers.


You can see the all log messages here (1.3 Where is the log location of println? )


SQL Query/Directory Filter

In this part we say which users should call to sync and with which attributes.

SQL Query/Directory Filter: Get-AllUser-Filter *
"OU=SaeiUsers,DC=Saeigroup,DC=local".Propertises *

You should replace each of these with the appropriate values from your Active Directory Users and Computers console.

OU = Your Organizational Unit
DC = Your Domain Component
DC = Your Network

Example (based on our setup):
OU=SaeiUsers,DC=Saeigroup,DC=local

The query says which users should call to sync it.
Additionally, we have no filter.
And search it base on OU = Our Organizational Unit user(SaeiUsers), DC = Our Domain Component(Saeigroup), Our Network(local).
And it is getting all the attributes.


Source attribute names

it refer to what attribute name and what is the source of it?

Source attribute names: /sync/User/ad/ADPowerShellAttributes groovy

When you click on Edit, you can view the script.


import org.openiam.sync.service.AttributesScript


class ADPowerShellAttributes implements AttributesScript {
    @Override
    String[] getAttributes() {
        return [
        "SamAccountName",
        "DisplayName",
        "EmailAddress", 
        "memberOf",
        "GivenName", 
        "Name", 
        "Surname",
        "UserPrincipalName",
        "telephoneNumber",
        ] as String[];
    }

}

Enter fullscreen mode Exit fullscreen mode

note:
We’ve added the telephoneNumber attribute to the Attributes script this is the only change made. However, you can add more attributes if needed, based on your requirements


  • We check the connection first, so click on Test Connection

  • and then click on Save

  • click on Sync Now


1.6 Viewing Synchronization History

  • Navigate to synchronization history

  • you can see the history of sync that you make.

1.7 Troubleshooting Sync Issues

The reason the sync might not happen could be because the transformation doesn't occur correctly.

if clicking on edit resolves the issue.

  • the system displays New User instead of the actual name of the user from Active Directory.

  • the result column shows failure

note:
The request body contains all attributes retrieved from Active Directory

if you click on New User

You would see the error displayed in the user interface as well as in the log we included in the TransportationGroovy script. You can access the log from here(1.3 Where is the log location of println?) to identify and resolve the issue.

For example:
The telephone number was not present in the request body. This indicates that the request did not retrieve it from the active directory. Therefore, we configure the query with properties to include both mandatory attributes and optional ones together in the SQL Query/Directory Filter.


1.8 Successful Synchronization

When synced correctly, you will see all the users who have been successfully synced.

And there is no error in here

Additionally, you will see a column map where you can view all the attributes associated with the user.

_Congratulations! You have successfully synchronized the user from Active Directory to OpenIAM.


1.9 Editing the Active Directory Connector Script

Login to your Active Directory machine.

locate this path: This PC> Local Disk C > ADConnector>Connector

  • Then click on Edit with Notepad

note:
Open the file it contains a script that manages updating user, retrieving user data, and sending user details.

note:
We will implement changes to the script and create a log file. This log file will include information such as messages like user not found or details like the username and telephone number of users

note:
If you check the log file created by the script, you'll find details about the user synchronized with their telephone number and other related information printed within the script.

Top comments (1)

Collapse
 
rourou profile image
Aaron Nim

Hi, I encountered an error with a message saying:

Exception at Program.RequestHandler at invoking PowerShell - ' System.Management.Automation.RuntimeException: Cannot run user creation as calculated path attribute ('OU=Switzerland,OU=Users,dc=dmfiam,dc=ch') either does not exist or is not of container or OU type (or not a root DC location)

AD Path:
Image description

Image description

After importing a user using a csv file