Last active
November 17, 2018 21:53
-
-
Save darrenjrobinson/96a25eb5ad0b0c8dfc76fbbd014f52fb to your computer and use it in GitHub Desktop.
PowerShell Management Agent for Azure AD Import Script. Supporting blog post is located here https://blog.darrenjrobinson.com/how-to-create-an-azuread-microsoft-identity-manager-management-agent-using-the-ms-graphapi-and-differential-queries/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param ( | |
$Username, | |
$Password, | |
$Credentials, | |
$OperationType, | |
[bool] $usepagedimport, | |
$pagesize | |
) | |
$DebugFilePath = "C:\PROGRA~1\MICROS~4\2010\SYNCHR~1\EXTENS~2\AzureAD\Debug\AADImport.txt" | |
if(!(Test-Path $DebugFilePath)) | |
{ | |
$DebugFile = New-Item -Path $DebugFilePath -ItemType File | |
} | |
else | |
{ | |
$DebugFile = Get-Item -Path $DebugFilePath | |
} | |
"Starting Import as : " + $OperationType + (Get-Date) | Out-File $DebugFile -Append | |
# Adding the AD library to your PowerShell Session. | |
Add-Type -Path 'C:\Program Files\WindowsPowerShell\Modules\AzureADPreview\2.0.0.50\Microsoft.IdentityModel.Clients.ActiveDirectory.dll' | |
# This is the tenant id of you Azure AD. You can use tenant name instead if you want. | |
$tenantID = "customer.com.au" | |
$authString = "https://login.microsoftonline.com/$tenantID" | |
# The resource URI for your token. | |
$resource = "https://graph.windows.net/" | |
# This is the common client id. | |
$client_id = "1950a258-227b-4e31-a9cf-717495945fc2" | |
# ************** Differential Sync Settings ************************ | |
# What Objects are we interested in. I'm expliciting calling User for this MA. Other options are Group and Contact | |
#$Searchfilter ="`$filter=isof('Microsoft.DirectoryServices.User') or isof('Microsoft.DirectoryServices.Group') or isof('Microsoft.DirectoryServices.Contact')" | |
$Searchfilter ="`$filter=isof('Microsoft.DirectoryServices.User')" | |
# Object Type (eg. users, groups, contacts, directoryObjects) | |
$object = "users" | |
# Output Directory and file for Differential Cookie | |
$downloadDirectory = "C:\PROGRA~1\MICROS~4\2010\SYNCHR~1\EXTENS~2\AzureAD" | |
$cookieFile = "\AADDeltaCookie.txt" | |
$cookiefilepath = $downloadDirectory +$cookieFile | |
# Reset results variable | |
$query = $null | |
# Read in Delta Cookie if it exists, if not create the file for storing the cookie | |
if(!(Test-Path $cookiefilepath)) | |
{ | |
$cookie = New-Item -Path $cookiefilepath -ItemType File | |
"Creating new Cookie File" | Out-File $DebugFile -Append | |
} | |
else | |
{ | |
$cookie = Get-Item -Path $cookiefilepath | |
"Cookie File present" | Out-File $DebugFile -Append | |
} | |
# ****************************************************************** | |
# ********************** Authentication to Azure *************************** | |
# The username must be MFA disabled user (and an Admin if writing back to AzureAD) at least, and must not be a live id. | |
# Create a client credential with the above common client id, username and password from the Connectivity tab on the MA. | |
$creds = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential" ` | |
-ArgumentList $Username,$Password | |
# Create a authentication context with the above authentication string. | |
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" ` | |
-ArgumentList $authString | |
# Acquire access token from server. | |
$authenticationResult = $authContext.AcquireToken($resource,$client_id,$creds) | |
# Use the access token to setup headers for your http request. | |
$authHeader = $authenticationResult.AccessTokenType + " " + $authenticationResult.AccessToken | |
$headers = @{"Authorization"=$authHeader; "Content-Type"="application/json"} | |
# ************************************************************** | |
# Delta or Full Sync based on Run Type and Cookie File ? | |
if((Get-Item $cookie).length -gt 0kb -and $OperationType -eq "Delta"){ | |
# Delta cookie value exists. Get it | |
$url = Get-Content $cookie.FullName | |
$url += '&ocp-aad-dq-include-only-changed-properties=true&api-version=1.6' -f $authenticationResult.TenantId | |
"Delta Import" | Out-File $DebugFile -Append | |
} | |
else | |
{ | |
# no Delta Cookie, so first run OR Full Sync so return everything | |
$url = "https://graph.windows.net/{0}/$($object)?&$($Searchfilter)&api-version=1.6&deltaLink=" | |
"Full Import" | Out-File $DebugFile -Append | |
} | |
# *********************** IMPORT ********************************** | |
# Get first set of results | |
$users = Invoke-RestMethod -Method Get -Headers @{ | |
Authorization = $authenticationResult.CreateAuthorizationHeader() | |
'Content-Type' = "application/json" | |
} -Uri ($url -f $authenticationResult.TenantId) | |
"Retrieved Users " + $users.value.Count | Out-File $DebugFile -Append | |
# An Array for the retuned objects to go into | |
$tenantObjects = @() | |
# Add in our first batch of objects | |
$tenantObjects += $users.value | |
$moreObjects = $users | |
$tenantObjects.count | |
# Get all the remaining objects in batches | |
if ($users.'aad.nextLink'){ | |
$moreObjects.'aad.nextLink' = $users.'aad.nextLink' | |
do | |
{ | |
$moreObjects = Invoke-RestMethod -Method Get -Headers @{ | |
Authorization = $authenticationResult.CreateAuthorizationHeader() | |
'Content-Type' = "application/json" | |
} -Uri ($moreObjects.'aad.nextLink'+'&api-version=1.6' -f $authenticationResult.TenantId) | |
"Retrieved Users " + $moreObjects.value.count | Out-File $DebugFile -Append | |
$tenantObjects += $moreObjects.value | |
} while ($moreObjects.'aad.nextLink') | |
} | |
"Total Users " + $tenantObjects.count | Out-File $DebugFile -Append | |
# store the DeltaLink in a file for next time we run the MA | |
$moreObjects.'aad.deltaLink' | Out-File $cookie | |
# ********************* Process users into the MA ******************* | |
ForEach($user in $tenantObjects) | |
{ | |
if (!$user.'aad.isDeleted' -and ($user.userType -eq "Member" -or !$user.userType ) -and $user.'odata.type' -eq "Microsoft.DirectoryServices.User") | |
{ | |
$obj = @{} | |
$obj.Add("ID", $user.objectId) | |
$obj.Add("objectID", $user.objectId) | |
$obj.Add("objectClass", "AADUser") | |
$obj.Add("AADUserPrincipalName",$user.userPrincipalName) | |
$obj.Add("AADAccountEnabled",$user.accountEnabled) | |
$obj.Add("AADDirSyncEnabled",$user.dirSyncEnabled) | |
$obj.Add("AADDisplayName",$user.displayName) | |
$obj.Add("AADGivenName",$user.givenName) | |
$obj.Add("AADImmutableId",$user.immutableId) | |
$obj.Add("AADLastDirSyncTime",$user.lastDirSyncTime) | |
$obj.Add("AADMail",$user.mail) | |
$obj.Add("AADMailNickname",$user.mailNickname) | |
$obj.Add("AADonPremiseSID",$user.onPremisesSecurityIdentifier) | |
if ($user.proxyAddresses) | |
{ | |
$proxyAddresses = @() | |
foreach($address in $user.proxyAddresses) { | |
$proxyAddresses += $address | |
} | |
$obj.Add("AADProxyAddresses",($proxyAddresses)) | |
} | |
$obj.Add("AADSurname",$user.surname) | |
$obj.Add("AADTelephoneNumber",$user.telephoneNumber) | |
$obj.Add("AADPasswordPolicies",$user.passwordPolicies) | |
if ($user.showInAddressList){$obj.Add("AADShowInAddressList",$user.showInAddressList)} | |
$obj.Add("AADCompanyName",$user.companyName) | |
$obj.Add("AADCountry",$user.country) | |
$obj.Add("AADPhysicalDeliveryOfficeName",$user.physicalDeliveryOfficeName) | |
$obj.Add("AADUsageLocation",$user.usageLocation) | |
$obj.Add("AADJobTitle",$user.jobTitle) | |
$obj.Add("AADMobile",$user.mobile) | |
$obj.Add("AADSipProxyAddress",$user.sipProxyAddress) | |
if ($user.otherMails) | |
{ | |
$otherMails = @() | |
foreach($otheraddress in $user.otherMails) { | |
$otherMails += $otheraddress | |
} | |
$obj.Add("AADOtherMails",($otherMails)) | |
} | |
$obj.Add("AADCity",$user.city) | |
# Pass the User Object to the MA | |
$obj | |
} | |
} | |
# *********************************************************** | |
"Finished Import as : " + $OperationType + (Get-Date) | Out-File $DebugFile -Append | |
#endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment