Table of Contents

Entra ID Directory Extensions

Haben Sie schon einmal Informationen in Entra ID speichern wollen, konnten aber kein passendes Attribut finden, um Ihre Daten zu abzulegen?
Zum Beispiel, um den Spitznamen einer Person auf eine nutzbare Weise zu hinterlegen? Oder benötigen Sie ein spezifisches Attribut aus Ihrer Personalverwaltungssoftware für Single Sign-On oder Autorisierung? Oder für dynamische Gruppen?

Wenn Sie Active Directory-Attribute synchronisiert haben, die standardmäßig nicht in Entra ID verfügbar sind, haben Sie möglicherweise unbewusst Directory Extensions erstellt – und jetzt müssen Sie diese Werte auslesen.

Diese Informationen sind in der Entra ID GUI (Stand Dezember 2023) nicht verfügbar, daher bleibt Ihnen nur die Graph API – meine persönliche Schnittstelle der Wahl ist PowerShell. Und da der Microsoft Dokumentation einige Snippets fehlen, dachte ich, es könnte interesant sein, meinen Ausflug niederzuschreiben.


Ich verwende eine separate JSON-Datei, um Informationen zu speichern, die ich nicht unbedingt im Internet teilen möchte:
tenantId : GUID des Entra ID Tenant
clientID : App ID meiner App Registration / Enterprise App
thumb : Fingerabdruck des Zertifikats, das ich zur Authentifizierung als App-Registrierung verwende
exampleUser : Benutzer-UPN meines Demo-Benutzers, Objekt-ID funktioniert genauso
extensionAppOID : OID – Object ID ! der App-Registration, mit der ich meine Directory Extension verknüpfen möchte


Verbindungsaufbau:

$graphConfig = ConvertFrom-Json $(Get-Content -Raw $hiddenValuesPath)
Connect-MgGraph -TenantId $graphConfig.tenantID -ClientId $graphConfig.clientID -CertificateThumbprint $graphConfig.thumb


Directory Extensions finden und lesen

  • Find-MgGraphCommand "CmdLet" liefert die API Uri, die vom CmdLet genutzt wird, so bekommt man bessere Dokumentation sowie die notwendigen Rechte
  • Get-MgUser / Die Graph API wird nur die Properties liefern nach denen man Fragt 😉


# Speichern der Directory Extension die ich ansehen will, da der volle Name etwas unhandlich ist
$extension  = Get-MgDirectoryObjectAvailableExtensionProperty  | where Name -match "exampleExtension"

# "Ich versuche so wenig Microsoft.Graph Module wie möglich zu nutzen weil Updates sonst ewig dauern"
# $extension = (Invoke-MgGraphRequest POST "/v1.0/directoryObjects/getAvailableExtensionProperties" -OutputType PSObject).Value | Where-Object Name -match "exampleExtension"

# Wert für einen einzelnen Benutzer auslesen
$user = Get-MgUser -UserId $graphConfig.exampleUser -Property Displayname, Id, UserPrincipalName, $extension.Name 

# Definieren einer Calculated Property für Select-Object, um die Verschachtelung in AdditionalProperties aufzulösen
$extensionValueExpr = @{Name = "$($extension.Name)"; Expression = {$_.AdditionalProperties.$($extension.Name)}}
$user | Select-Object Displayname, Id, UserPrincipalName, $extensionValueExpr | Format-Table

Ergebnis:

Exemple Result 1


Alternativ können wir nach den Extension Attributen Filtern:

$extension  = Get-MgDirectoryObjectAvailableExtensionProperty  | where Name -match "nickName"
$users = Get-MgUser -Filter "startswith($($extension.Name),'I')" -Property Displayname, Id, UserPrincipalName, $extension.Name 

# Definieren einer Calculated Property für Select-Object, um die Verschachtelung in AdditionalProperties aufzulösen
$extensionValueExpr = @{Name = "nickName"; Expression = {$_.AdditionalProperties.$($extension.Name)}}
$users | Select-Object Displayname, Id, UserPrincipalName, $extensionValueExpr | Format-Table

Ergebnis:

Example Result 2


Eine eigene Extension erstellen

! Dies sollte nicht für die von Entra ID Connect Sync verwendeten Extensions versucht werden – die Quelle für diese Attribute sollte On-Premises bleiben
Verwenden Sie den Entra ID Connect Sync-Assistenten, um Erweiterungen hinzuzufügen


# Es muss immer eine zugewiesene Applikation geben, ansonsten können die Attribute aber sehr breit genutzt werden
$oid = $graphConfig.extensionAppOID
$params = @{
    name = "freshExtension"
    dataType = "String"
    targetObjects = @("User")
}
New-MgApplicationExtensionProperty -ApplicationId $oid @params

# Wenn ich die App ID meiner Registration nutzen will müsste ich die Objekt ID von der Graph IP holen:
# $oid = (Get-MgApplication -Filter $("AppId eq '{0}'" -f $graphConfig.clientID)).Id

# Weniger Module, gleiche Params:
# Invoke-MgGraphRequest POST "/v1.0/applications/$oid/extensionProperties" -Body $params

Ergebnis:

Example Result 3


Extension auf einem Benutzer setzen

! Dies sollte nicht für die von Entra ID Connect Sync verwendeten Extensions versucht werden – die Quelle für diese Attribute sollte On-Premises bleiben
Nutzen sie OnPrem Management lösungen für diese Eigenschaften (Set-ADUser, IAM, etc.)

$extension  = Get-MgDirectoryObjectAvailableExtensionProperty  | where Name -match "freshExtension"

# Wir könnten mehrere Eigenschaften mit einem Request setzen, dann müsste man sie aber alle benennen :)
$params = @{
    "$($extension.Name)" = "Hello, this is a fresh value"
}
Update-MgUser -UserId $graphConfig.exampleUser -BodyParameter $params

# User Updates liefern kein Output bei Erfolg, schauen wir also nach
$user = Get-MgUser -UserId $graphConfig.exampleUser -Property Displayname, Id, UserPrincipalName, $extension.Name 

# Definieren einer Calculated Property für Select-Object, um die Verschachtelung in AdditionalProperties aufzulösen
$extensionValueExpr = @{Name = "freshExtension"; Expression = {$_.AdditionalProperties.$($extension.Name)}}
$user | Select-Object Displayname, Id, UserPrincipalName, $extensionValueExpr | Format-Table

Result:
Example Result 4


Alle Extension Attribute lesen

Wenn wir alle Extension Attibute sehen wollen wird es etwas komplizierter – lasst es mich bitte wissen wenn ihr einen besseren Weg kennt 😉

# Alle Extension Attribute auslesen - wird dieses Script regelmäßig ausgeführt könnte man diese Cachen.
$extensions = Get-MgDirectoryObjectAvailableExtensionProperty

# Standard Benutzereigenschaften die wir auslesen möchten
$properties = @("Displayname", "Id", "UserPrincipalName") 

# Auslesen aller Benutzer mit allen Extension Properties
$users = Get-MgUser -All -Property ($properties + $extensions.Name)

$allUsersParsed = [System.Collections.Arraylist]::new()

# Auflösen der Verschachtelung in der Hashtabelle
# Filtert auch unnötige Eigenschaften aus dem Graph Schema, die wir nicht angefragt haben
Foreach ($u in $users){
    $userParsed = @{}
    Foreach ($prop in $properties) {
        $userParsed.$prop = $u.$prop
    }
    $userParsed += $u.AdditionalProperties
    $allUsersParsed.Add([pscustomobject]$userParsed) | Out-Null
}

$allUsersParsed | Format-Table ($properties + $extensions.Name)

Ergebnis:

Example Result 5


Abschließende Worte

Wir können also jetzt Verzeichniserweiterungen lesen und erstellen – sehr cool. Aber wie geht es weiter? Ich habe es zum Spaß gemacht, aber lassen Sie mich wissen, wofür Sie dieses Wissen sinnvoll eingesetzt haben 😁


Ich werde keine Kommentare moderieren und möchte Ihre E-Mail-Adresse nicht; bitte beteiligen Sie sich an der Diskussion über meinen Zugehörigen LinkedIn Post.


Wenn sie an den Dingen interessiert sind die ich tue folgen sie mir auf LinkedIn.


Übersetzung unterstützt durch ChatGPT


Mehr Informationen



Updates:

  1. 08.12.23 – Verbessern der Codeklarheit rund um Select-Object
Zuletzt bearbeitet: 5. Januar 2024