Here is a script I created to load licensed Microsoft 365 users as contacts in ITFlow. I'm using a local server as my middleware. Client ID is manually defined in the script.
Comments/suggestions/edit ideas requested.
#Update/Create script with logic
#Pull 365 users with assigned licenses and create/update contact in ITFlow via Microsoft Graph
#Uses a Microsoft Azure App registration with a local certificate to authenticate with 365
$maximumfunctioncount = '32768'
# Import-Module -Name Microsoft.Graph
# API Key
$apiKey = "PUT your ITFlow API key here"
# Base site URL
$siteUrl = "https://yourITFlow_site"
# Define 365 identity parameters
$TenantId= "tenantid"
$clientId = "clientid"
# Create a certificate object
$cert = Get-childItem "Cert:\CurrentUser\My\$thumbprint" -dnsname "IT Flow"
$thumbprint = $cert.Thumbprint
#Connect to 365 powershell via certificate
Connect-MgGraph -TenantId $tenantId -ApplicationId $clientId -Certificatethumbprint $thumbprint -nowelcome
# Get all 365 users with assigned licenses
$users = Get-MgbetaUser -Filter 'assignedLicenses/$count ne 0' -ConsistencyLevel eventual -CountVariable licensedUserCount -all -Property DisplayName, UserPrincipalName, GivenName, SurName, BusinessPhones, OfficeLocation, Identities, Department | Select-object DisplayName, UserPrincipalName, GivenName, SurName, BusinessPhones, OfficeLocation, Department, Identities
# Get User Info
foreach ($user in $users) {
# Define variables
$contact_email = $user.UserPrincipalName
# Read Module
$read_module = "/api/v1/contacts/read.php"
$uri_read = $siteUrl + $read_module + "?api_key=" + $apikey + "&contact_email=$Contact_email"
# Check if contact exists in ITFlow database
$exists = Invoke-RestMethod -Method GET -Uri $uri_read
# If the contact exists update it, if not create it.
if ($exists.success -eq "False"){
$module = "/api/v1/contacts/create.php"
Write-Host $contact_email ("Contact does not exist - Creating contact...")
} else {
if ($exists.success -eq "True"){
$module = "/api/v1/contacts/update.php"
Write-Host $contact_email ("Contact already exists - Checking for updates")
} else {
Write-host "error"
}
}
# Define an array of locations to assign users to
# Department field used in this script to determine location
$locations =@(
[PSCustomObject]@{ Name = "AHR"; LocationID = "7" }
[PSCustomObject]@{ Name = "AP"; LocationID = "6" }
[PSCustomObject]@{ Name = "ASP"; LocationID = "1" }
[PSCustomObject]@{ Name = "BCH"; LocationID = "8" }
[PSCustomObject]@{ Name = "BP"; LocationID = "10" }
[PSCustomObject]@{ Name = "BRC"; LocationID = "9" }
[PSCustomObject]@{ Name = "CHR"; LocationID = "12" }
[PSCustomObject]@{ Name = "CMNR"; LocationID = "11" }
[PSCustomObject]@{ Name = "CNR"; LocationID = "14" }
[PSCustomObject]@{ Name = "CW"; LocationID = "13" }
[PSCustomObject]@{ Name = "ECNR"; LocationID = "15" }
[PSCustomObject]@{ Name = "EHR"; LocationID = "2" }
[PSCustomObject]@{ Name = "ELC"; LocationID = "16" }
[PSCustomObject]@{ Name = "GV"; LocationID = "18" }
[PSCustomObject]@{ Name = "GVTL"; LocationID = "17" }
[PSCustomObject]@{ Name = "HLC"; LocationID = "19" }
[PSCustomObject]@{ Name = "HSHR"; LocationID = "20" }
[PSCustomObject]@{ Name = "ICR"; LocationID = "41" }
[PSCustomObject]@{ Name = "JRN"; LocationID = "21" }
[PSCustomObject]@{ Name = "KP"; LocationID = "22" }
[PSCustomObject]@{ Name = "LM"; LocationID = "4" }
[PSCustomObject]@{ Name = "LTC"; LocationID = "42" }
[PSCustomObject]@{ Name = "MAP"; LocationID = "39" }
[PSCustomObject]@{ Name = "MM"; LocationID = "24" }
[PSCustomObject]@{ Name = "MSQ"; LocationID = "23" }
[PSCustomObject]@{ Name = "NHL"; LocationID = "25" }
[PSCustomObject]@{ Name = "NWA"; LocationID = "40" }
[PSCustomObject]@{ Name = "ORH"; LocationID = "26" }
[PSCustomObject]@{ Name = "PTL"; LocationID = "27" }
[PSCustomObject]@{ Name = "RCH"; LocationID = "5" }
[PSCustomObject]@{ Name = "RNR"; LocationID = "28" }
[PSCustomObject]@{ Name = "SFR"; LocationID = "30" }
[PSCustomObject]@{ Name = "SOH"; LocationID = "29" }
[PSCustomObject]@{ Name = "SPC"; LocationID = "31" }
[PSCustomObject]@{ Name = "STE"; LocationID = "32" }
[PSCustomObject]@{ Name = "SVNR"; LocationID = "3" }
[PSCustomObject]@{ Name = "TCR"; LocationID = "33" }
[PSCustomObject]@{ Name = "THR"; LocationID = "35" }
[PSCustomObject]@{ Name = "TLTL"; LocationID = "36" }
[PSCustomObject]@{ Name = "TMM"; LocationID = "34" }
[PSCustomObject]@{ Name = "WCH"; LocationID = "38" }
[PSCustomObject]@{ Name = "WWH"; LocationID = "37" }
)
# Define $Contact for IT Flow update/create
# Use 365 displayname if first/last name fields are blank
$contact_name = $user.GivenName + " " + $user.Surname
if ([string]::IsNullOrEmpty($user.GivenName + $user.Surname)) {
$Contact_name_itflow = $user.DisplayName
} else {
$Contact_name_itflow = $contact_name
}
# Define $Values for data array to write to ITFlow
$contact_title = $user.DisplayName
$contact_phone = $user.BusinessPhones[0]
$contact_mobile = $user.Identities | Where-Object { $_.Issuer -eq "phone" } | Select-Object -ExpandProperty "IssuerassignedID"
$contact_id = $exists.data.contact_id
# Select appropriate location from array using 365 Department field
$LocationID = $locations | Where-object { $_.Name -eq $user.Department }
# Select numeric location ID from chosen record
$contact_location_id = "$($LocationID.LocationID)"
$contact_extension = $user.Office
$contact_department = $user.Department
$body = @"
{
"api_key" : "$apiKey",
"contact_id" : "$contact_id",
"contact_name" : "$Contact_Name_itflow",
"contact_title" : "$contact_title",
"contact_department" : "$contact_department",
"contact_email" : "$Contact_Email",
"contact_phone" : "$contact_phone",
"contact_extension" : "$contact_extension",
"contact_mobile" : "$contact_mobile",
"contact_location_id" : "$contact_location_id",
"client_id" : "1"
}
"@
# Build URI from defined data
$uri = $siteUrl + $module
# Used to Display Output for testing
# write-host $body
# Write data to ITFlow!!!
Invoke-RestMethod -Method Post -Uri $uri -Body $body -ErrorVariable $a
}