# Synchronization

OpenIAM sends a query to the connector with the list of attributes it expects. The connector executes the query against AD, forms key-value pairs from the results, and returns matching attribute values to OpenIAM. Unmatched attributes are returned as null. Key matching is case-insensitive.

All queries are evaluated on the connector side and converted to PowerShell commands. The service account credentials stored in the managed system configuration are used for authentication.

{% hint style="warning" %}
Do not specify `Server` or `Credential` parameters in your queries — the connector handles the connection itself.
{% endhint %}

Running synchronization is very similar to performing PowerShell queries targeted to AD. In most cases it leverages functionality of [Get-ADUpoweser](https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-aduser), [Get-ADGroup](https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-adgroup) or [Get-ADComputer](https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-adcomputer) cmdlets.

#### General query execution logic <a href="#generalqueryexecutionlogic" id="generalqueryexecutionlogic"></a>

OpenIAM sends the query to the connector to execute the list of attributes it expects to receive. The query result on the connector side is being treated as a key-values pair. When this key-values pair is formed, the connector makes a match between attributes that were requested from OpenIAM and keys available. If the key is matched ( case-insensitive) the value(s) will be returned to OpenIAM. If the key is not found, but attribute was requested the attribute value will be returned as null.

While running search requests the connector should be authenticated against AD using service account. Therefore, the query, even being almost identical to PowerShell queries, is being evaluated on the connector side and modified to real PowerShell commands. The connector leaves your ability to run pure PowerShell requests, but also offers simplified syntax that is described below.

In all examples below we will use [Get-ADUser](https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-aduser) cmdlet, however same examples could be used with replacement of [Get-ADUser](https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-aduser) to [Get-ADGroup](https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-adgroup) or [Get-ADComputer](https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-adcomputer).

#### Returned attributes <a href="#returnedattributes" id="returnedattributes"></a>

If query does not contain -Properties parameter, the basic attributes that connector will get from AD are:

* DistinguishedName
* Enabled
* GivenName
* Name
* ObjectClass
* ObjectGUID
* SamAccountName
* SID
* Surname
* UserPrincipalName

**Getting extra attributes**. To add extra attributes you need to specify *'-Properties X,Y,Z'* or *'-Properties \*'* parameter where X, Y, Z are required attributes in a comma separated list. If you need all attributes to be returned, you can specify *instead of specifying particular attributes. But you should note that querying all attributes using* significantly decreases performance and there are not a lot of use cases when you really need everything from the user profile. So, it is recommended to always specify only those attributes that you need.

A full query example would look like:

```powershell
Get-ADUser -Filter * -Properties Mail,WhenCreated
```

The query above would search for all users inside AD (or inside SearchBaseDN) and will be able to get a basic set of attributes (described above) + Mail and WhenCreated.

```powershell
Get-ADUser -Filter * -Properties *
```

The query above would search for all users inside AD (or inside SearchBaseDN) and will be able to get all attributes from user profile. This could be very slow and RAM consuming if there are lots of users in AD.

#### Query syntax <a href="#querysyntax" id="querysyntax"></a>

You can run a direct query using syntax described at [Get-ADUser](https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-aduser), [Get-ADGroup](https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-adgroup) or [Get-ADComputer](https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-adcomputer) cmdlets.

**Please note** that you do not need to specify *'Server'* and *'Credential'* parameters because the connector already handles connection himself.

If you specify the 'Filter' parameter and do not specify 'SearchBase', the 'SearchBase' value will be set to ' SearchBaseDN' setting inside your managed system page.

Query examples:

```powershell
Get-ADUser -Filter *
```

Query above gets all users from AD, but if SearchBaseDN is set - the scope will be limited to SearchBaseDN like described above.

```powershell
Get-ADUser -Identity 'SamAccountName or SID, GUID or DN' -Properties *
```

Sometimes it is good to synchronize a single user - this scenario is usually being used to test sync processes, for demonstrations and validating functionality. In this case the query could be used like above.

```powershell
Get-ADUser -Filter {Surname -eq 'Potter'}
```

The query above would select all users with surname 'Potter'. Search would be limited to SearchBaseDN, because we have not specified it *AND* the search query contains -Filter parameter. We could override SearchBaseDN by setting the SearchBase parameter. If we do it, query would look like:

```powershell
Get-ADUser -Filter {Surname -eq 'Potter'} -SearchBase 'DC=openiamtest,DC=local'
```

If you run other queries than having 'Filter' parameter inside, you will not be limited to SearchBaseDN.

For example, one common scenario is filtering users that were modified after a certain date:

```powershell
Get-ADUser -LDAPFilter '(whenChanged>=20200726000000.0Z)' -Properties whenChanged
```

Here the whenChanged attribute is specified in YYYYMMDD (+hours, min), so the query would return all users that were modified after the 26th of July 2020.

Sometimes it could be useful to sync user objects only from certain locations inside AD. -Search base parameter accepts only one location, but you can add filtering inside your query.

{% code overflow="wrap" %}

```powershell
Get-ADUser -Filter * -Properties property1,property2 | Where-Object {$_.DistinguishedName -like '*OU=SomeOU1,DC=openiamtest,DC=local' -or $_.DistinguishedName -like '*OU=SomeOU2,DC=openiamtest,DC=local'}
```

{% endcode %}

Such request would get all users inside AD, but will filter and return only users whose DistinguishedName ends with given locations. So, it will also include child locations. Some of you may say that for pure PowerShell the query above does not look optimal, and it would be optimal to pass the required location to the pipeline and run Get-ADUser for those locations only. But the connector does some modifications for the queries before the run, so that method would not be possible. At the same time, filtering will help reach your aim.

## Synchronizing users

{% hint style="info" %}
User synchronization uses `Get-ADUser`.
{% endhint %}

**Default returned attributes** (when `-Properties` is not specified):\
DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName.

To retrieve additional attributes, add `-Properties X,Y,Z`. Using `-Properties *` returns everything but significantly reduces performance on large directories — always specify only the attributes you need.

**Query examples:**

{% code expandable="true" %}

```powershell
# All users (limited to SearchBaseDN if configured)
Get-ADUser -Filter *

# All users with specific extra attributes
Get-ADUser -Filter * -Properties Mail,WhenCreated

# Single user by identity
Get-ADUser -Identity 'SamAccountName or SID, GUID or DN' -Properties *

# Filter by attribute
Get-ADUser -Filter {Surname -eq 'Potter'}

# Filter with explicit SearchBase (overrides SearchBaseDN)
Get-ADUser -Filter {Surname -eq 'Potter'} -SearchBase 'DC=openiamtest,DC=local'

# Users in specific OUs
Get-ADUser -Filter * -Properties property1,property2 | Where-Object {
  $_.DistinguishedName -like '*OU=SomeOU1,DC=openiamtest,DC=local' -or
  $_.DistinguishedName -like '*OU=SomeOU2,DC=openiamtest,DC=local'
}
```

{% endcode %}

### Synchronizing Group memberships

Include `memberOf` in the `-Properties` list to sync a user's group memberships:

```powershell
Get-ADUser -Filter * -Properties memberOf
```

AD does not include primary group membership in `memberOf` (it is usually "Domain Users"). To sync primary group membership explicitly:

```powershell
Get-ADUser -Filter * -Properties memberOf,PrimaryGroup
```

OpenIAM ships an out-of-the-box sync configuration named **AD PowerShell USER Example**.

## Synchronizing groups

Group synchronization uses `Get-ADGroup` and follows the same principles as user sync.

{% code overflow="wrap" expandable="true" %}

```powershell
# All distribution groups
Get-ADGroup -Filter 'groupcategory -eq "Distribution"'

# Security groups in a specific location
Get-ADGroup -Filter 'groupcategory -eq "Security"' -SearchBase 'CN=Users,DC=openiamtest,DC=local'

# All security groups with specific extra attributes
Get-ADGroup -Filter 'groupcategory -eq "Security"' -Properties cn,whenCreated
```

{% endcode %}

**Default returned attributes for groups:**\
DistinguishedName, GroupCategory, GroupScope, Name, ObjectClass, ObjectGUID, SamAccountName, SID.

**Additional requestable attributes:**\
CanonicalName, Created, createTimeStamp, Deleted, Description, HomePage, isCriticalSystemObject, isDeleted, LastKnownParent, ManagedBy, MemberOf, Members, Modified, modifyTimeStamp, ProtectedFromAccidentalDeletion, whenChanged, whenCreated.

OpenIAM ships an out-of-the-box sync configuration named **AD PowerShell GROUP Example**.

## Synchronizing file shares

The AD connector connects to each Windows file share server directly using PowerShell remoting.

```powershell
# Sync file shares from specific servers
Get-SmbSharesInfo -ComputerNames 'server1','server2'

# Sync all file shares in a domain
# (queries domain controller for all computers, then connects to each)
Get-SmbSharesInfo -DomainController 'yourDCHostname'
```

To collect permissions for each file share, include `Permissions` in the **Attribute names lookup** field of the synchronization configuration. If omitted, permission collection is skipped.

## Incremental synchronization

Use the `Modified` property to retrieve only objects changed since the last sync:

```powershell
Get-ADUser -Filter "Modified -gt '$((Get-Date '?').ToUniversalTime())'"
```

OpenIAM replaces `?` at runtime with the actual last-sync date value.

<figure><img src="/files/vWTVPqMtUNPBPC0nArxM" alt=""><figcaption></figcaption></figure>

The date format must be agreed between OpenIAM and the connector via the `DateTimeStringFormat` parameter in the request metadata. This is configured in the Managed System settings.

## Urgent queues

If certain messages require prioritized processing over regular traffic, you can configure an urgent queue:

1. Open `Connector.config` in the connector folder.

<figure><img src="/files/Oh9H9q3YsbU1KrQiJ58e" alt=""><figcaption></figcaption></figure>

2. In the `RabbitMQQueues` array, duplicate the existing record.
3. In the new record, prepend `URGENT_` to both the `*ReceiveQueue` and `*ResponseQueue` property names, as shown below.

<figure><img src="/files/sRWHMXCSEKwFEiMVC9JF" alt=""><figcaption></figcaption></figure>

Concurrency values can be tuned independently for the normal and urgent queues.

## Cron expressions

To run synchronization automatically on a schedule, set a Cron expression in the **Synch Frequency** field of the synchronization configuration.

| Frequency          | Cron Expression |
| ------------------ | --------------- |
| Every day at 23:00 | `0 0 23 * * ?`  |
| Every 1 hour       | `0 0 * * * ?`   |
| Every 15 minutes   | `0 /15 * * * ?` |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs-beta.openiam.com/application-onboarding/connectors/active-directory-powershell-connector/synchronization.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
