Applying Intune tags with a Function App

By | October 26, 2020

Apply an Intune Scope Tag to a group of devices based on the device owner attributes.

Please note this OVERWRITES current tags.

In order to provide administrative isolation in Intune Microsoft use the concept of Tags. Tags apply to policies, app assignments, profiles and devices and an administrator with the appropriate role can only see and manage objects with those tags. This is all very useful for the profiles and policies as the tag is attached as you create them in the admin console.

Devices however is a bit of a pain, the enroll with the “Default tag and then either need to be manually changed or can pick up a tag based on group membership. This is start of something useful as you can use a dynamic device group to make all devices automatically pick up a tag HOWEVER its extraordinarily limited as its rarely a device property you want to drive the tagging, but rather the user property.

Hence this script.

What we are going to do is create an security group with assigned membership, apply our automated tag to that group then use a function app with some powershell scripting to add devices to that group based on the properties of the user rather than the device. In this case I am using the UPN suffix but it should be pretty obvious how to drag in other properties.

1. Create Group

First Create the group to contain the devices we want to tag.

2. Function App Code

First we create a powershell function app. This is based on my template function app which I detail on many posts and am not going to go through again.

If you go through the posts 365 Powershell in Azure Functions and 365 Azure Functions Graph and AzureAD you should be good to go (although I recommend looking through the rest detailing the build of the template app as they are excellent works of genius.*)

You will need to give your app registration the api permissions DeviceManagementManagedDevices.ReadWrite.All

The complete code for the function app is: (You will need to fill in $appID, $CertThumbprint, $TenantID and $GroupID)

# Input bindings are passed in via param block.
param($Timer)

$AppID="Your App ID"
$CertThumbprint="Your Certificate Thumbprint"
$tenantid = "Your Tenant ID"    

Function ConnectGraph($GraphURI, $Body, $Method) {

    Import-Module "D:\home\site\wwwroot\MSAL\MSAL.PS.psd1"
    $cert = Get-Item "Cert:\CurrentUser\My\$($CertThumbprint)"
    $MSALToken = Get-MsalToken -ClientId $appID -TenantId $tenantID -ClientCertificate $cert
    If (!$Body -and $Method -eq "Get"){
        (Invoke-RestMethod -Headers @{Authorization = "Bearer $($MSALToken.AccessToken)" } -Uri $GraphURI -Method Get)
    }
    ElseIf ($Body -and $Method -eq "Post") {

        (Invoke-RestMethod -Headers @{Authorization = "Bearer $($MSALToken.AccessToken)";'Content-type'="application/json" } -Uri $GraphURI -Method Post -Body $Body)

    }
}

#Get ALL MDM Devices
$MDMDevicesResponse = ConnectGraph -GraphURI "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices" -Method "Get"
$MDMDevices = $MDMDevicesResponse.Value
$NextLink = $MDMDevicesResponse.'@odata.nextLink'

While ($NextLink -ne $null) {
    $MDMDevicesResponse = ConnectGraph -GraphURI $NextLink -Method "Get"
    $NextLink = $MDMDevicesResponse.'@odata.nextLink'
    $MDMDevices += $MDMDevicesResponse.Value
}

#Enterprise ---------------------------------------------------------------------------------------------
$GroupID = "<<Your Group ID>>"

$TargettedDevices  = $MDMDevices | where {$_.operatingsystem -like "*android*" -and $_.UserPrincipalName -like "*enterprise.starfleet.com"}
ForEach ($TargettedDevice in $TargettedDevices) {

    #Getdirectory ID for Device
    $DeviceID = $TargettedDevice.AzureADDeviceID
    $uri = "https://graph.microsoft.com/v1.0/devices?`$filter=deviceID eq '"+$DeviceID+"'"
    $DirID = (ConnectGraph -GraphURI $uri -Method "Get").value.id
    $addmemberuri = "https://graph.microsoft.com/v1.0/groups/"+$GroupID+"/members/`$ref"
    $body = "{`"@odata.id`":`"https://graph.microsoft.com/v1.0/directoryObjects/"+$DirID+"`"}"
    ConnectGraph -graphuri $addmemberuri -method "Post" -Body $body
}

Lets go through each bit and see what it does!

So First off I’ve chopped out most of the template – I only need the ConnectGraph function in this case.

First step is to grab all the MDM managed devices via graph using the ConnectGraph function.

$MDMDevicesResponse = ConnectGraph -GraphURI "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices" -Method "Get"
$MDMDevices = $MDMDevicesResponse.Value

Note in the function itself I’ve made a change from the template by not specifying it should return the .value attribute – I need to keep the outer attributes specifically the ‘@odata.nextLink’. You can see the next thing I do is dump the current .value into a variable MDMDevices, then run a While loop to rerun the query with the next value for ‘@odata.nextLink’ until it is null – this grabs all of the paginated results as graph will only return 1000 at a time

While ($NextLink -ne $null) {
    $MDMDevicesResponse = ConnectGraph -GraphURI $NextLink -Method "Get"
    $NextLink = $MDMDevicesResponse.'@odata.nextLink'
    $MDMDevices += $MDMDevicesResponse.Value
}

Now I’ve got a variable with all of the managed devices I can do what I want with them. In this case I want to find all of those that are android devices and assigned to a user with the upn suffix “enterprise.starfleet.com”. The Group ID is specified down here as you will likely want to use the one script to add devices to multiple groups.

#Enterprise ---------------------------------------------------------------------------------------------
$GroupID = "<<your GroupID>>"

$TargettedDevices = $MDMDevices | where {$_.operatingsystem -like "*android*" -and $_.UserPrincipalName -like "*enterprise.starfleet.com"}

So now we have the devices we want to get into our group and can loop through them, but there’s a minor issue in that the Add Member mechanism in Graph wants a resource id for the object we want to add but that is not returned by the ManagedDevices API function. We need to use the AzureADDeviceID to query the Devices API function which DOES return the required resource id as the attribute “id” which we will dump into a variable $DirID

ForEach ($TargettedDevice in $TargettedDevices) {

    #Getdirectory ID for Device
    $DeviceID = $TargettedDevice.AzureADDeviceID
    $uri = "https://graph.microsoft.com/v1.0/devices?`$filter=deviceID eq '"+$DeviceID+"'"
    $DirID = (ConnectGraph -GraphURI $uri -Method "Get").value.id

Now we can continue the loop using this variable and the add memebrs api function which is on the URI https://graph.microsoft.com/v1.0/groups/{group-id}/members/$ref and accepts a link to the resource directory object URI for the object we want to add contained in JSON (e.g { “@odata.id”: “https://graph.microsoft.com/v1.0/directoryObjects/{id}” } )

    $addmemberuri = "https://graph.microsoft.com/v1.0/groups/"+$GroupID+"/members/`$ref"
    $body = "{`"@odata.id`":`"https://graph.microsoft.com/v1.0/directoryObjects/"+$DirID+"`"}"
    ConnectGraph -graphuri $addmemberuri -method "Post" -Body $body

So this loops through and adds every targeted device into the group. Obviously you are mainly going to get errors as after the initial run the majority of objects will already be in the group but we dont really care. (We could grab the group membership and check for the device then only run the add if it isn’t there but that seems a lot of work to hide some red text)

3. Function

Now we have our code working just create a new function within your admin function app (if you have been playing along at home and followed my other posts, otherwise create a Function app, add a certificate for an app with relevant API permisisons then create a new Function in it)

Once it creates, jump into the Code+ Test blade and copy the code in, replacing whats there. Populate the variables for teantna nd App/Client ID, Certificate Thumbprint and GroupID then give it a test run.

Once it executes your devices will be added to your group (have a look on the azure portal if you dont believe me!)

4. Add Tag to the Group

Now we just need to set Intune to apply a tag to any member of the group. Pop along to https://endpoint.microsoft.com/ and go to Tenant Administration | Roles | Scope (Tags) and find the scope tag you want to apply.

Once in the tag page just click Edit next to assignments and add your group.

It may take a couple of minutes to update but once it does the tags will be overwritten. You can assign manual tags now and they will be added to the group tag.

*Not a guarantee

Loading

Leave a Reply

Your email address will not be published. Required fields are marked *