Automated Intune Devices Report via Azure Automation with Managed Identity

Before I was using Niel's guide to set up the monthly Intune devices report via Azure Automation. Since Microsoft is retiring “run as ” account in September this year, I have to switch to managed identity. I have to say, there is not much documentation on how to set up the permissions for managed identity. And it is a pain to switch.

Here are some codes to setup permissions for managed identity, maybe in the future will be changed:

Connecting
# Connect to Microsoft Graph in Azure Automation
Connect-AzAccount -Identity
$AccessToken = Get-AzAccessToken -ResourceUrl "https://graph.microsoft.com"
# Connect to the Graph SDK with the acquired access token
Connect-Graph -AccessToken $AccessToken.Token -Scopes AppRoleAssignment.ReadWrite.All
#Define the desired graph endpoint
Select-MgProfile  Beta


# Connect to Microsoft Graph
Connect-MgGraph -Scopes "Application.Read.All","AppRoleAssignment.ReadWrite.All,RoleManagement.ReadWrite.Directory"

# Select beta profile
Select-MgProfile Beta


$ManagedIdentity = "xxx"
# We can also lookup the object id using the name of the managed identity:
$ManagedIdentity = (Get-MgServicePrincipal -Filter "displayName eq 'MobileDevice'").id



###  Assigning Teams permission  ###
# Fetch details of the Teams management app
$TeamsApp = Get-MgServicePrincipal -Filter "AppId eq '48ac35b8-9aa8-4d74-927d-1f4a14a0b239'"  
$AppPermission = $TeamsApp.AppRoles | Where-Object {$_.DisplayName -eq "Application_access"} # Create the payload for the assignment
$AppRoleAssignment = @{
    "PrincipalId" = $ManagedIdentity
    "ResourceId" = $TeamsApp.Id
    "AppRoleId" = $AppPermission.Id }
# Assign the role to the service principal for the managed identity.
New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $ManagedIdentity -BodyParameter $AppRoleAssignment


###  Assigning Graph permission  ###
$GraphApp = Get-MgServicePrincipal -Filter "AppId eq '00000003-0000-0000-c000-000000000000'" # Microsoft Graph
$Role = $GraphApp.AppRoles | Where-Object {$_.Value -eq  'Device.Read.All'}
$AppRoleAssignment = @{
    "PrincipalId" = $ManagedIdentity
    "ResourceId" = $GraphApp.Id
    "AppRoleId" = $Role.Id }
# Assign the Graph permission
New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $ManagedIdentity -BodyParameter $AppRoleAssignment

###  Assigning Sharepoint permission  ###
# Add the correct 'Object (principal) ID' for the Managed Identity
$ManagedIdentity = "e8800382-610d-4761-9b15-873065e53227"

# Add the correct Graph scope to grant
$graphScope = "Sites.Selected"

Connect-MgGraph -Scope AppRoleAssignment.ReadWrite.All
$graph = Get-MgServicePrincipal -Filter "AppId eq '00000003-0000-0000-c000-000000000000'"
$graphAppRole = $graph.AppRoles | ? Value -eq $graphScope

$appRoleAssignment = @{
    "principalId" = $ManagedIdentity
    "resourceId"  = $graph.Id
    "appRoleId"   = $graphAppRole.Id
}

New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $ManagedIdentity -BodyParameter $appRoleAssignment | Format-List

###  Assigning Sharepoint permission for one specific site  ###
# Add the correct 'Application (client) ID' and 'displayName' for the Managed Identity
$application = @{
    id = "caddd31b-a690-4074-afce-22dd7b56dec4"
    displayName = "MobileDevice"
}

# Add the correct role to grant the Managed Identity (read or write)
$appRole = "write"

# Add the correct SharePoint Online tenant URL and site name
$spoTenant = "cariboubio.sharepoint.com"
$spoSite  = "Automation2"

# No need to change anything below
$spoSiteId = $spoTenant + ":/sites/" + $spoSite + ":"

Import-Module Microsoft.Graph.Sites
Connect-MgGraph -Scope Sites.FullControl.All

New-MgSitePermission -SiteId $spoSiteId -Roles $appRole -GrantedToIdentities @{ Application = $application }

### Sharepoint ###
Add-PnPAzureADServicePrincipalAppRole -Principal "your-objecet-id" -AppRole "Group.Read.All" -BuiltInType MicrosoftGraph
Add-PnPAzureADServicePrincipalAppRole -Principal "mymanagedidentity" -AppRole "Sites.FullControl.All" -BuiltInType SharePointOnline


###  Removing permission  ###
$ManagedIdentity = ""
$GraphApp = Get-MgServicePrincipal -Filter "AppId eq '00000003-0000-0000-c000-000000000000'" # Microsoft Graph
[Array]$SPPermissions = Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $ManagedIdentity
$Role = $GraphApp.AppRoles | Where-Object {$_.Value -eq "TeamWork.Migrate.All"}
$Assignment = $SpPermissions | Where-Object {$_.AppRoleId -eq $Role.Id}
Remove-MgServicePrincipalAppRoleAssignment -AppRoleAssignmentId $Assignment.Id -ServicePrincipalId $ManagedIdentity


### Connect to sharepoint interactively ###
Connect-PnPOnline xx.sharepoint.com -Interactive

Another code to assign managed identity permission:

<#
    .SYNOPSIS
    Adds a configurable role to a given Managed Identity (not currently possible through the Azure Portal)

    .NOTES
    filename: add-roleToManagedIdentity
    author: Jos Lieben / [email protected]
    copyright: Lieben Consultancy, free to use
    site: https://www.lieben.nu
    Updated: 27/08/2021
#>
Param(
    [Parameter(Mandatory=$true)][String]$displayName="we-naima-aa",
    [Parameter(Mandatory=$true)][String]$role="GroupMember.ReadWrite.All"
)
Connect-AzureAD 
$Msi = (Get-AzureADServicePrincipal -Filter "displayName eq '$displayName'")
Start-Sleep -Seconds 10
$baseSPN = Get-AzureADServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'"
$AppRole = $baseSPN.AppRoles | Where-Object {$_.Value -eq $role -and $_.AllowedMemberTypes -contains "Application"}
New-AzureAdServiceAppRoleAssignment -ObjectId $Msi.ObjectId -PrincipalId $Msi.ObjectId -ResourceId $baseSPN.ObjectId -Id $AppRole.Id

Here is my new code on Azure Automation to get the data from Intune, upload to SharePoint, and then send a notification to Teams.

##### Automated Intune Devices Report via Azure Automation with Managed Identity #####
##### Rui Qiu #####
##### v1.0 #####
##### 04262023 #####

### Get MS Graph Access Token using Managed Identity ###
$url = $env:IDENTITY_ENDPOINT  
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" 
$headers.Add("X-IDENTITY-HEADER", $env:IDENTITY_HEADER) 
$headers.Add("Metadata", "True") 
$body = @{resource='https://graph.microsoft.com/' } 
$accessToken = (Invoke-RestMethod $url -Method 'POST' -Headers $headers -ContentType 'application/x-www-form-urlencoded' -Body $body ).access_token
$authHeader = @{
    'Authorization' = "Bearer $accessToken"
}

#Connect to Azure 
Connect-AzAccount -Identity

### Pull data from Graph ###
$URI = "https://graph.microsoft.com/beta/deviceManagement/manageddevices"
$Response = Invoke-WebRequest -Uri $URI -Method Get -Headers $authHeader -UseBasicParsing 
$JsonResponse = $Response.Content | ConvertFrom-Json
$DeviceData = $JsonResponse.value
If ($JsonResponse.'@odata.nextLink')
{
    do {
        $URI = $JsonResponse.'@odata.nextLink'
        $Response = Invoke-WebRequest -Uri $URI -Method Get -Headers $authHeader -UseBasicParsing 
        $JsonResponse = $Response.Content | ConvertFrom-Json
        $DeviceData += $JsonResponse.value
    } until ($null -eq $JsonResponse.'@odata.nextLink')
}

### Data processing ###
$CurrentDate = Get-Date -Format "MMddyyyy"
Write-Output "Date is $CurrentDate"
$FilePath = "$env:temp\MobileDevices_$CurrentDate.csv"
Write-Output "File path is $FilePath"
$MobileDevices = $DeviceData | where {$_.operatingSystem -ne "Windows" -and $_.operatingSystem -ne "macOS"}
$MobileDevices | Select-Object DeviceName, emailAddress, EnrolledDateTime, lastSyncDateTime, operatingSystem | export-csv -Path $FilePath -Force -NoTypeInformation 
if (Test-path $FilePath){
	Write-Output "Export for Managed Devices Succeeded"
}

### Upload to Sharepoint ###
$conn = Connect-PnPOnline -Url "https://xxx.sharepoint.com/sites/xxx" -ManagedIdentity -ReturnConnection -Verbose
$addFile = Add-PnPFile -Path $FilePath -Folder "Shared Documents/Reports" -connection $conn


Import-Module PSTeams 
$TeamsWebhookURL = "https://xxx.webhook.office.com/xxx/"
$TeamsID = $TeamsWebhookURL
$Button1 = New-TeamsButton -Name 'View Intune Mobile Devices Report' -Link "https://xxx.sharepoint.com/sites/xxx/Shared%20Documents/xxx"
$Section = New-TeamsSection `
	-ActivityText "There are currently $(($MobileDevices.value).count) managed Mobile Devices"`
    -Buttons $Button1 
Send-TeamsMessage `
    -URI $TeamsID `
    -MessageTitle 'New Report' `
    -MessageText 'Managed Mobile Devices Report' `
    -Color DodgerBlue `
    -Sections $Section

And here is my code to do auto clean up :


# Connect to the Graph API as the automation account managed identity
Connect-MgGraph -Identity

# Get Zulu formatted time from 60 days ago for filter
$date = (Get-Date (Get-Date).AddDays(-60) -Format u).Replace(' ','T')

# Get devices that haven't signed in for more than 90 days
$devices = Get-MgDevice -All -Filter "ApproximateLastSignInDateTime le $date"

### Data processing ###
$CurrentDate = Get-Date -Format "MMddyyyy"
$FilePath = "$env:temp\Devices_$CurrentDate.csv"
Write-Output "File path is $FilePath"
#$MobileDevices | Select-Object DeviceName, emailAddress, EnrolledDateTime, lastSyncDateTime, operatingSystem | export-csv -Path $FilePath -Force -NoTypeInformation 
$devices | export-csv -Path $FilePath -Force
if (Test-path $FilePath){
	Write-Output "Export for Managed Devices Succeeded"
}
### Upload to Sharepoint ###
$conn = Connect-PnPOnline -Url "https://xxx.sharepoint.com/sites/xxx" -ManagedIdentity -ReturnConnection -Verbose
$addFile = Add-PnPFile -Path $FilePath -Folder "Shared Documents/DeviceCleanUP" -connection $conn

### Device Clean UP ###

$devices | ForEach-Object { 
    Write-Output "Deleting $($_.DisplayName),$($_.DeviceId)"
    Remove-MgDevice -DeviceId $_.Id
}

Write-Output "$(($devices.DeviceId).count) total devices"

### Teams Notification ###
Import-Module PSTeams 
$TeamsWebhookURL = "https://xxx.webhook.office.com/"
$TeamsID = $TeamsWebhookURL
$Button1 = New-TeamsButton -Name 'View Monthly Auto Device CleanUP Report' -Link "https://xxx.sharepoint.com/sites/xxx/Shared%20Documents/xxx"
$Section = New-TeamsSection `
	-ActivityText "There are currently $(($devices.DeviceId).count) managed Azure Devices have been removed."`
    -Buttons $Button1 
Send-TeamsMessage `
    -URI $TeamsID `
    -MessageTitle 'New Clean Up Report' `
    -MessageText 'Device Auto CleanUP Report' `
    -Color DodgerBlue `
    -Sections $Section

And here are references for read

https://practical365.com/managed-identity-powershell/
https://the-itguy.de/assign-microsoft-graph-permission-to-a-managed-identity/
https://docs.smsagent.blog/microsoft-endpoint-manager-reporting/managed-devices-report/grant-api-permissions
https://www.inthecloud247.com/configure-a-user-assigned-managed-identity-the-basics/
https://gotoguy.blog/2022/03/15/add-graph-application-permissions-to-managed-identity-using-graph-explorer/comment-page-1/
https://docs.smsagent.blog/microsoft-endpoint-manager-reporting/managed-devices-report/create-an-azure-automation-runbook
https://www.nielskok.tech/powershellautomation/intune-devices-report-via-graph-and-teams/
https://learningbydoing.cloud/blog/connecting-to-sharepoint-online-using-managed-identity-with-granular-access-permissions/
https://pivotalbi.com/copy-files-from-sharepoint-online-using-azure-data-factory-and-the-microsoft-graph-api/
https://oceanleaf.ch/intune-automation-enlightenment/
https://gregramsey.net/2020/04/07/how-to-use-logic-apps-to-query-intune-for-device-information/
https://github.com/pnp/PnP-PowerShell/issues/2360

https://pnp.github.io/powershell/articles/azureautomationrunbook.html#by-using-a-managed-identity

https://www.burgerhout.org/device-clean-up-in-azuread-intune/
https://blog.nathanmcnulty.com/azure-automation-device-cleanup-v2/

Leave a Comment