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 EnterIn this path
/user/local/openIAM/logs
Typels
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
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)*/
}
}
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
}
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.")
}
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.")
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:")
}
}
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[];
}
}
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)
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:

After importing a user using a csv file