Dit artikel beschrijft het inrichten en onderhouden van het Entra ID-profielsynchronisatiescript (versie 2.5 en hoger): de configuratiesecties, de veldmapping, groepslidmaatschap en wat je in de output en logs terugziet.
De documentatie bestaat uit twee delen:
- Deel 1: de eenmalige opzet - app-registratie, Azure Automation-account, runbook, testen en schedulen.
- Deel 2 (dit artikel): het inrichten en onderhouden van het script.
$additionalFields, $customProfileFields, $teamMemberships en $roleMemberships anders geconfigureerd Neem bij het upgraden je bestaande configuratie niet één-op-één over, maar zet deze vier opties om naar de nieuwe syntax (zie Veldmapping en Groepslidmaatschap). Alle overige instellingen kun je overnemen. De verbindingsgegevens staan voortaan bovenin het script in de CONNECT-sectie. Daarnaast is de module MSAL.PS niet meer nodig: het script authenticeert nu rechtstreeks via
Connect-MgGraph. Hiervoor is Microsoft.Graph.Authentication versie 2.0 of hoger vereist; werk deze module zo nodig bij in het Automation-account. MSAL.PS mag daarna verwijderd worden.Dit artikel bestaat uit de volgende secties:
- De configuratiesecties
- Veldmapping
- Groepslidmaatschap en rollen
- Output en logging
- Onderhoud: de client secret vervangen
- Troubleshoot
De configuratiesecties
Het script is opgedeeld in drie configuratiesecties:
- CONNECT - verbindingsgegevens en secrets.
- BASIC - de opties die elke klant minimaal invult.
- ADVANCED - optionele inrichting zoals groepslidmaatschap en custom velden.
SettingsUsed-regel (JSON) naar de console en de log geschreven. Secrets uit de CONNECT-sectie komen daar nooit in terecht. Zie Output en logging. Deze logging helpt Embrace support om sneller te kunnen troubleshooten.CONNECT
| Variabele | Omschrijving |
|---|---|
$azAppId$azTenantId$azSecret
|
De gegevens van de Azure app-registratie. Voor $azSecret kun je ook verwijzen naar een Automation-variabele: $azSecret = Get-AutomationVariable -Name "azureClientSecretValue"
|
$kcTenantId |
De tenantnaam. Deze waarde wordt verstrekt door Embrace. |
$authClientSecret |
De secret voor het versturen van gegevens. Deze waarde wordt verstrekt door Embrace. |
BASIC
| Variabele | Omschrijving |
|---|---|
$entraGroup |
De naam van de Entra ID-groep waarvan alle leden (recursief, dus inclusief geneste groepen) naar Embrace worden gesynchroniseerd. Heeft een gebruiker de disabled-status in Entra ID, dan zal de gebruiker als uitgeschakelde gebruiker worden getoond op Social |
$dryRun |
$true: het script toont alleen een voorbeeld van de output en verstuurt niets. $false: de gegevens worden daadwerkelijk naar Embrace verstuurd. Voor meer info, zie Output en logging
|
$dryRunSampleSize |
Het aantal gebruikers per groep dat tijdens een dry run wordt opgehaald en getoond. Tip: hoog het aantal gebruikers op als je geavanceerde instellingen zoals toegangsgroepen wilt toetsen. |
$syncManager |
$true synchroniseert ook het manager-veld. Dit kost een extra Graph-aanroep per gebruiker; alleen aanzetten als het manager-veld gebruikt wordt. |
$syncUPN |
$true synchroniseert ook de UserPrincipalName. |
$disableNonProvidedUsers |
$true: Embrace-gebruikers met een ExternalId die niet (meer) in de aangeleverde lijst zitten, worden gedeactiveerd. $false: Het uitschakelen van niet-aangeleverde accounts dient handmatig gedaan te worden |
$additionalFields |
De veldmapping van Entra ID naar Embrace-profielvelden. Hiermee koppel je specifieke Entra ID-velden aan Embrace profielvelden. Zie Veldmapping voor meer uitleg |
ADVANCED
| Variabele | Omschrijving |
|---|---|
$assignSocialGroups |
$true: gebruikers worden op basis van hun Entra ID UserType lid van Social's Members-groep (type Member) of Guests-groep (type Guest). |
$makeAllUsersSocialMembers |
$true: álle gesynchroniseerde gebruikers worden Member, ongeacht hun UserType. Werkt alleen als $assignSocialGroups = $true. |
$forcedGuestGroup |
Optioneel: de naam van een Entra ID-groep waarvan de leden áltijd Social Guest worden, ongeacht de twee opties hierboven. |
$syncExtensions |
$true maakt het synchroniseren van extensionAttributes mogelijk. Kost een extra Graph-aanroep per gebruiker. |
$customProfileFields |
Mapping naar custom Embrace-profielvelden (prefix x-user-attribute-custom-profile- in Keycloak). Zelfde syntax als $additionalFields. |
$teamMemberships |
Embrace-teamlidmaatschap op basis van Entra ID-groepslidmaatschap. Zie Groepslidmaatschap. |
$roleMemberships |
Embrace-rollidmaatschap op basis van Entra ID-groepslidmaatschap. |
$customMappings |
Team of rol toekennen op basis van de waarde van een Entra ID-property (bijv. iedereen met Department = Finance). |
Volgorde bij het bepalen van Member/Guest: $forcedGuestGroup gaat vóór $makeAllUsersSocialMembers, en die gaat vóór het UserType uit Entra ID.
Veldmapping ($additionalFields en $customProfileFields)
De mapping is een hashtable: 'Embrace-veldnaam' = 'Entra ID-veldnaam'. Elke regel staat op zichzelf. Je kunt regels vrij aan- en uitzetten met een # zonder dat de configuratie stukgaat.
$additionalFields = @{
'job-title' = 'jobTitle'
'company-name' = 'companyName'
'department' = 'department'
'displayname' = 'displayName'
'hire-date' = 'employeeHireDate'
'street-address' = 'streetAddress'
'office' = 'officeLocation'
'city' = 'city'
'country' = 'country'
'postal-code' = 'postalCode'
'office-phone' = 'businessPhones'
'mobile-phone' = 'mobilePhone'
}Meerdere Entra ID-velden combineren in één Embrace-veld doe je met een lijst als waarde:
'department' = 'company', 'department'
Verplichte velden
Deze velden staan vast in het script en zijn nodig voor een geldige synchronisatie. Ze hoeven (en mogen) niet in de mapping opgenomen te worden:
| Embrace | Entra ID |
|---|---|
| ExternalId | Id |
| FirstName | GivenName |
| LastName | Surname |
| AccountEnabled | AccountEnabled |
User extensions (extensionAttributes)
Entra ID biedt de mogelijkheid om eigen eigenschappen aan een gebruikersprofiel toe te voegen. Wil je een extensionAttribute in de mapping opnemen, zet dan $syncExtensions = $true (onder ADVANCED):
$additionalFields = @{
'profile-birth-date' = 'extension_f946aada8c064232b6753f91f2ca3bf4_BirthDate'
}Hetzelfde geldt voor custom Embrace-profielvelden:
$customProfileFields = @{
'hobbies' = 'extension_f946aada8c064232b6753f91f2ca3bf4_Hobbies'
'skills' = 'extensionAttribute1'
}$syncExtensions is alleen nodig wanneer je een extensionAttribute in de mapping gebruikt. Wil je een veld vullen met een vaste waarde of zelf conversies doen op bepaalde waarden, dan kan dat via de customFields-functie. Daarvoor hoeft $syncExtensions niet aan.Een beheerder van Entra ID kan de juiste namen van deze eigenschappen verstrekken. Je kunt de namen ook zelf uitlezen met de onderstaande PowerShell-snippet (vul een gebruikers-id in van een testgebruiker met extensions):
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Beta.Users
# General configuration for connecting to Microsoft Entra ID
$azureApplicationId = ''
$azureTenantId = ''
$azureClientSecretValue = ''
# userid of a test user with extensions:
$userId = ''
# connect to Graph (requires Microsoft.Graph.Authentication 2.0 or higher)
$clientSecretCredential = New-Object System.Management.Automation.PSCredential($azureApplicationId, (ConvertTo-SecureString -AsPlainText -Force $azureClientSecretValue))
Connect-MgGraph -TenantId $azureTenantId -ClientSecretCredential $clientSecretCredential -NoWelcome
$userProperties = Get-MgBetaUser -UserId $userId
Write-Host $userProperties.AdditionalPropertiesWaarden transformeren of vast vullen: de customFields-functie
Moet een waarde eerst bewerkt worden (bijvoorbeeld een datumconversie of taalcode), of wil je een veld vullen met een vaste waarde, gebruik dan de customFields-functie in het script. Deze functie wordt voor elke gebruiker aangeroepen en vereist geen $syncExtensions. Voorbeelden:
# Geboortedatum uit een extensionAttribute omzetten naar ISO-formaat:
if (![string]::IsNullOrEmpty($entraUser.ExtensionProperty['extension_..._BirthDate']))
{
$user.Attributes | Add-Member -type NoteProperty -name "profile-birth-date" -Value ([datetime]::ParseExact($entraUser.ExtensionProperty['extension_..._BirthDate'], 'dd-MM-yyyy', $null)).ToString("o") -Force
}
# Taal afleiden uit het land:
$lang = "nl"
switch ($entraUser.Country) {
"GB" { $lang = "en" }
"DE" { $lang = "de" }
}
$user.Attributes | Add-Member -type NoteProperty -name "language" -Value $lang -Force
# Veld vullen met een vaste waarde (hiervoor is geen $syncExtensions of mapping nodig):
$user.Attributes | Add-Member -type NoteProperty -name "profile-office" -Value 'Hoofdkantoor' -ForceGroepslidmaatschap en rollen
In het script kun je inregelen dat leden van een Entra ID-groep automatisch lid worden van een groep binnen Embrace. Dit kan een intranetgroep en/of een rechtengroep zijn.
Beide soorten groepen verwijzen naar Toegangsgroepen in Embrace. De intranetbeheerder (hier zijn specifieke rechten voor nodig) dient deze Toegangsgroepen aan te maken en de naamgeving te delen met de Entra ID-beheerder voor verdere verwerking in het script. Zie hiervoor Users - Rechten en rollen.
Teamlidmaatschap configureer je als hashtable: 'Embrace-team' = 'Entra ID-groepsnaam'. Gebruik / voor subgroep-paden. Meerdere Entra ID-groepen naar hetzelfde team kan met een lijst als waarde.
Intranetgroepen
Via Toegangsgroepen maakt de intranetbeheerder een mapping aan voor synchronisatie van Entra ID-groepen naar de Social intranetgroepen:
- Zorg dat Entra ID-groepen gesynchroniseerd mogen worden (toggle in Management > Groepsinstellingen)
- Maak een Toegangsgroep aan: Management > Users > Toegangsgroepen
- Koppel de Toegangsgroep: tabje Synchronisatie > zoek de Social intranetgroep
$teamMemberships = @{
'Embrace Suite/[Naam Embrace intranetgroep]' = '[Naam EntraID groep]'
}Rechtengroepen
Voor het toekennen van rollen is de best practice om een rechtengroep aan te maken en daar een rol aan te koppelen:
- Maak een rol aan: Management > Users > Rollen
- Maak een rechtengroep aan: Management > Users > Toegangsgroepen
- Koppel de aangemaakte rol(len) aan de toegangsgroep
$teamMemberships = @{
'Embrace Suite/[Naam Embrace rechtengroep]' = '[Naam EntraID groep]'
}Meerdere Entra ID-groepen samenvoegen in één Embrace-groep
Moeten de leden van twee (of meer) Entra ID-groepen in dezelfde Embrace-groep terechtkomen, geef dan een lijst op als waarde:
$teamMemberships = @{
'Embrace Suite/[Naam Embrace groep]' = '[Naam EntraID groep 1]', '[Naam EntraID groep 2]'
}De leden van beide Entra ID-groepen worden samengevoegd en ontdubbeld: een gebruiker die in beide Entra ID-groepen zit, wordt één keer lid van de Embrace-groep. Andersom mag dezelfde Entra ID-groep ook bij meerdere Embrace-groepen worden gebruikt.
Combineren
Intranetgroepen en rechtengroepen kun je combineren in één configuratie, en meerdere Entra ID-groepen kunnen naar hetzelfde team verwijzen:
$teamMemberships = @{
'Embrace Suite/Nieuws' = 'AD-Medewerkers'
'Embrace Suite/Redacteuren' = 'AD-Communicatie', 'AD-Marketing'
'Embrace Suite/Testers' = 'AD-Testgroep'
}Rollidmaatschap
Rollidmaatschap werkt hetzelfde; een client-rol geef je op als 'clientnaam/rolnaam':
$roleMemberships = @{
'Content Reader' = 'F_Finance_users'
'broker/read-token' = 'F_Sales_users'
}Custom mappings
Wil je een team of rol toekennen op basis van een Entra ID-property in plaats van groepslidmaatschap, gebruik dan $customMappings:
$customMappings = @(
[PropertyMapping]::new([Action]::Assign, [EmbraceType]::Group, 'Embrace Suite/Testers', 'jobTitle', 'Tester', $false)
[PropertyMapping]::new([Action]::Assign, [EmbraceType]::Group, 'Embrace Suite/Consultants', 'Department', 'Consultancy', $false)
)$false) geeft aan of de waarde als reguliere expressie behandeld moet worden. Met $true kun je bijvoorbeeld matchen op een deel van een e-maildomein.Output en logging
Wat doet een dry run precies?
- Er wordt niets naar Embrace verstuurd.
- Per groep wordt slechts een steekproef van
$dryRunSampleSizegebruikers opgehaald. Het getoonde aantal gevonden gebruikers is dus niet het werkelijke totaal. - De deactiveringsfase (
$disableNonProvidedUsers) wordt tijdens een dry run volledig overgeslagen: omdat maar een steekproef wordt opgehaald, zou een preview ten onrechte gebruikers tonen die buiten de steekproef vallen. - Alle meldingen zijn voorzien van het label
DRY RUN.
SettingsUsed
Bij de start van elke run schrijft het script één regel met de volledige actieve configuratie (JSON), zowel naar de console als naar de log:
SettingsUsed: {"scriptVersion":"2.5","dryRun":true,"entraGroup":"...","additionalFields":[...],...}Verbindingsgegevens en secrets uit de CONNECT-sectie staan hier uiteraard niet in. Gebruik deze regel om te controleren of de configuratie is wat je verwacht. Embrace kan deze informatie gebruiken bij het debuggen van issues
Samenvatting aan het einde van de run
Summary: 143 users created or updated, 2 skipped (missing first name, last name or email), 5 users disabled, duration 00:04:12Staat er een WARNING: ... sync calls failed achter, kijk dan hoger in de output naar de FAILURE-meldingen.
Onderhoud: de client secret vervangen
De client secret van de Azure app-registratie heeft een beperkte geldigheid (maximaal 24 maanden). Is de secret verlopen, dan faalt de synchronisatie direct bij de start met een Azure-foutmelding zoals AADSTS7000222: The provided client secret keys ... are expired.
Zo vervang je de secret:
- Ga in Azure (portal.azure.com) naar Microsoft Entra ID -> App registrations en open de app-registratie van de profielsynchronisatie.
- Ga naar Certificates & secrets en kies New client secret. Geef een herkenbare naam, kies een verlooptijd (bijvoorbeeld 24 maanden) en kies Add.
- Kopieer de secret value direct: deze wordt maar één keer getoond.
- Werk de waarde bij op de plek waar het script hem leest:
- Gebruik je een Automation-variabele (aanbevolen): werk de waarde van
azureClientSecretValuebij onder Shared Resources -> Variables in het Automation-account. Het script zelf hoeft dan niet aangepast te worden. - Staat de secret direct in het script: vervang de waarde van
$azSecretin de CONNECT-sectie van het runbook en publiceer het runbook opnieuw.
- Gebruik je een Automation-variabele (aanbevolen): werk de waarde van
- Verwijder de verlopen secret bij de app-registratie en controleer de synchronisatie met een dry run (
$dryRun = $true) of via de eerstvolgende geplande run.
De $authClientSecret (voor het versturen naar Embrace) verloopt niet op een vaste datum; die wordt door Embrace verstrekt en hoeft alleen vervangen te worden als Embrace daarom vraagt.
Troubleshoot
-
"$additionalFields must be configured as a hashtable ..."
Je gebruikt nog de configuratie-syntax van een scriptversie ouder dan 2.5. Zet de configuratie om naar de hashtable-syntax; zie Veldmapping. -
"ME-ID Group '...' not found (configured in $teamMemberships)"
De genoemde Entra ID-groep bestaat niet of is anders gespeld. De melding vermeldt in welke configuratie-optie de groep wordt gebruikt. -
"WARNING: First name, Last name and Email cannot be empty. Skipping user ..."
De gebruiker mist een verplicht veld in Entra ID en wordt overgeslagen. Vul het veld in Entra ID en draai de sync opnieuw. -
"AADSTS7000222: The provided client secret keys for app ... are expired"
De client secret van de Azure app-registratie is verlopen. Zie Onderhoud: de client secret vervangen. -
"The following required PowerShell modules are missing: ..." of "Microsoft.Graph.Authentication version ... 2.0 or higher is required"
Zie de troubleshoot-sectie van deel 1: de eenmalige opzet.
Foutmeldingen over de Azure-omgeving (modules, runtime, JWT) staan beschreven in deel 1: de eenmalige opzet.