Intro-

Intune offers the ability to manually rename Android Enterprise devices using the Intune portal, but no automated out of box solution.  The “Bulk Rename” process still requires the administrator to manually perform the function on a schedule.  The automated rename solution outlined below eliminates the need for manual administration, standardizes Android Enterprise naming, and uses “Managed Identities” to remove the need for individual user elevated permissions.  Also, by including the custom attributes in the device name, you can create Dynamic Azure Security Groups based off criterial not natively available in Azure AD.

Prerequisites–

How To-

Step 1 – Create Azure Monitor Alert / Log Analytics Kusto query

For this step you have 2 options when alerting from an Android MDM event (which appear in the Azure AD audit log).  Option 1 query the “Azure AD shared device mode” registration event, or if you are not using “Azure AD shared device mode” you can query for Android Enterprise enrollment registration event.

When Selecting “Log Analytics Workspace” make sure to select the one collecting the Intune Audit logs.

Create “Custom Log” with the following Kusto query (depending on which event you want to trigger from)

Option 1: Azure AD shared device mode registration event:

AuditLogs
| where OperationName == "Register device"
| where AADOperationType == "Add"
| where AdditionalDetails has "Shared"
| where AdditionalDetails has "Android"
| parse AdditionalDetails with * "Device Id" deviceid

Option 2: Intune Android Add Device event:

AuditLogs
| where OperationName == "Add device"
| where parse_json(tostring(parse_json(tostring(TargetResources[0].modifiedProperties))[8].newValue))[0] == "Android"

Intune enrollment of previously enrolled devices will show up as “OperationName: Update Device” instead of Add device.  This can cause confusion and the automation to fail.  Option 1 also eliminates parsing which can later break with future schema updates.  A few reasons why option 1 is the better choice.

For Measurement Aggregation granularity and Frequency of evaluation I find 15 minutes the sweet spot.

Select the Logic App created from the prerequisites.  Since we are not passing information from the alert to Logic App don’t worry about custom attributes and schema.  We simply run the query again in the Logic App later*

Step 2 – Grant Managed Identity Graph Permissions

Select the Logic App previous created and select “Identity”

Now we need to grant the Managed Identity Graph API permissions.  The only way of adding the required permissions is utilizing the Azure AD cmdlet:

Connect-AzureAD
# Your tenant id (in Azure Portal, under Azure Active Directory -> Overview )
$TenantID="XXX"
# Microsoft Graph App ID (DON'T CHANGE SAME FOR ALL TENANTS)
$GraphAppId = "00000003-0000-0000-c000-000000000000"
# Name of the manage identity (same as the Logic App name)
$DisplayNameOfMSI="logic-xxx" 
# Check the Microsoft Graph documentation for the permission you need for the operation
#$PermissionName = "Domain.Read.All"
#$PermissionName = "Directory.Read.All"
#$PermissionName = "Device.Read.All"
#$PermissionName = "DeviceManagementManagedDevices.Read.All"
$PermissionName = "Device.ReadWrite.All"
#$PermissionName = "DeviceManagementApps.Read.All"
#$PermissionName = "DeviceManagementApps.ReadWrite.All"
#$PermissionName = "DeviceManagementManagedDevices.ReadWrite.All"
#$PermissionName = "DeviceManagementConfiguration.ReadWrite.All"
#$PermissionName = "DeviceManagementManagedDevices.PrivilegedOperations.All"
$PermissionName = "DeviceManagementConfiguration.Read.All"
#$PermissionName = "WindowsUpdates.ReadWrite.All"
#$PermissionName = "Directory.AccessAsUser.All"

# Install the module (You need admin on the machine)
#Install-Module AzureAD 

#Connect-AzureAD -TenantId $TenantID 
$MSI = (Get-AzureADServicePrincipal -Filter "displayName eq '$DisplayNameOfMSI'")
Start-Sleep -Seconds 10
$GraphServicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '$GraphAppId'"
$AppRole = $GraphServicePrincipal.AppRoles | `
Where-Object {$_.Value -eq $PermissionName -and $_.AllowedMemberTypes -contains "Application"}
New-AzureAdServiceAppRoleAssignment -ObjectId $MSI.ObjectId -PrincipalId $MSI.ObjectId `
-ResourceId $GraphServicePrincipal.ObjectId -Id $AppRole.Id

This is my accumulation of Graph permissions I commonly use.  For this automated task “Device.ReadWrite.All” (Azure AD permission) and “DeviceManagementConfiguration.Read.All” (Intune permission) are required.  Notice the comment on the GrapphAppID which is universal on any tenant.

To validate the permission was correctly applied view the Enterprise Application in Azure Active Directory

Here you can see all the permission assigned to the Enterprise Application / Managed Identity

Step 3 – Design the Logic App

Here are the is what the Logic App looks like when completed:

Logic App Action 1- “When HTTP request is received”

This is OOB configuration with custom configuration

Logic App Action 2- “LA Query AAD New Device Registration”

Since we are not passing or parsing any information from the Azure Monitor Alert, we execute Azure Monitor Logs – Run query and list results

Unfortunately, as of writing this you cannot use the Managed Identity to query the Log Analytics Workspace. Instead, you need to create a SPN and assign Access Control Role “Log Analytics Reader” and use this as your connection.  Do not use your User Credentials since you will need to update this connection every password rotation.

Here is the query used for the Azure AD Shared Device Enrollment event from Step 1.  Notice there is parsing performed to return only the “deviceID” and Time Range 1 hour.  The reason for the extended Time Range is to capture devices that take longer to provision.  Because of the conditions in this Logic App extending beyond the initial alert is fine since we filter out devices that have already been renamed further down.

AuditLogs
| where OperationName == "Register device"
| where AADOperationType == "Add"
| where AdditionalDetails has "Shared"
| where AdditionalDetails has "Android"
| parse AdditionalDetails with * "Device Id" deviceid
| parse deviceid with * "value" value1
| parse value1 with eq ":" value2
| extend value3=replace(@'}', @'', value2)
| extend value4=replace(@'"', @'', value3)
| extend deviceid=replace(@']', @'', value4)
| project deviceid

Logic App Action 3- “Data Operations- Compose”

Select deviceid from the previous step “LA Query AAD New Device Registration”.  Notice after you select this value you the “Compose” will be nested in a “For Each” action automatically.

Logic App Action 4- “HTTP GET Device Info Intune”

Query Intune device information using the Device ID from the Log Analytics output.

Notice that the v1.0 and not BETA Graph is being utilized.  BETA is not supported as a production workload by Microsoft due to potential changes, and the Graph API service is not always available and will return constant timeouts if you are performing routine renames which will break the automation*

https://graph.microsoft.com/v1.0/deviceManagement/managedDevices?$filter=azureADDeviceId eq 'xxxOutputsxxx'

Logic App Action 5- “Parse Device Info Intune” 

Intune and Azure AD device information will be required in future steps, so we will need to parse the results from “HTTP Get Device Info Intune”.  Use the below sample or generate schema from running the LogicApp now.

Sample Schema

{
    "properties": {
        "@@odata.context": {
            "type": "string"
        },
        "@@odata.count": {
            "type": "integer"
        },
        "value": {
            "items": {
                "properties": {
                    "activationLockBypassCode": {},
                    "androidSecurityPatchLevel": {
                        "type": "string"
                    },
                    "azureADDeviceId": {
                        "type": "string"
                    },
                    "azureADRegistered": {
                        "type": "boolean"
                    },
                    "complianceGracePeriodExpirationDateTime": {
                        "type": "string"
                    },
                    "complianceState": {
                        "type": "string"
                    },
                    "configurationManagerClientEnabledFeatures": {},
                    "deviceActionResults": {
                        "type": "array"
                    },
                    "deviceCategoryDisplayName": {
                        "type": "string"
                    },
                    "deviceEnrollmentType": {
                        "type": "string"
                    },
                    "deviceHealthAttestationState": {},
                    "deviceName": {
                        "type": "string"
                    },
                    "deviceRegistrationState": {
                        "type": "string"
                    },
                    "easActivated": {
                        "type": "boolean"
                    },
                    "easActivationDateTime": {
                        "type": "string"
                    },
                    "easDeviceId": {
                        "type": "string"
                    },
                    "emailAddress": {
                        "type": "string"
                    },
                    "enrolledDateTime": {
                        "type": "string"
                    },
                    "ethernetMacAddress": {},
                    "exchangeAccessState": {
                        "type": "string"
                    },
                    "exchangeAccessStateReason": {
                        "type": "string"
                    },
                    "exchangeLastSuccessfulSyncDateTime": {
                        "type": "string"
                    },
                    "freeStorageSpaceInBytes": {
                        "type": "integer"
                    },
                    "iccid": {},
                    "id": {
                        "type": "string"
                    },
                    "imei": {
                        "type": "string"
                    },
                    "isEncrypted": {
                        "type": "boolean"
                    },
                    "isSupervised": {
                        "type": "boolean"
                    },
                    "jailBroken": {
                        "type": "string"
                    },
                    "lastSyncDateTime": {
                        "type": "string"
                    },
                    "managedDeviceName": {
                        "type": "string"
                    },
                    "managedDeviceOwnerType": {
                        "type": "string"
                    },
                    "managementAgent": {
                        "type": "string"
                    },
                    "managementCertificateExpirationDate": {
                        "type": "string"
                    },
                    "manufacturer": {
                        "type": "string"
                    },
                    "meid": {
                        "type": "string"
                    },
                    "model": {
                        "type": "string"
                    },
                    "notes": {},
                    "operatingSystem": {
                        "type": "string"
                    },
                    "osVersion": {
                        "type": "string"
                    },
                    "partnerReportedThreatState": {
                        "type": "string"
                    },
                    "phoneNumber": {
                        "type": "string"
                    },
                    "physicalMemoryInBytes": {
                        "type": "integer"
                    },
                    "remoteAssistanceSessionErrorDetails": {},
                    "remoteAssistanceSessionUrl": {},
                    "requireUserEnrollmentApproval": {},
                    "serialNumber": {
                        "type": "string"
                    },
                    "subscriberCarrier": {
                        "type": "string"
                    },
                    "totalStorageSpaceInBytes": {
                        "type": "integer"
                    },
                    "udid": {},
                    "userDisplayName": {
                        "type": "string"
                    },
                    "userId": {
                        "type": "string"
                    },
                    "userPrincipalName": {
                        "type": "string"
                    },
                    "wiFiMacAddress": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "userId",
                    "deviceName",
                    "managedDeviceOwnerType",
                    "enrolledDateTime",
                    "lastSyncDateTime",
                    "operatingSystem",
                    "complianceState",
                    "jailBroken",
                    "managementAgent",
                    "osVersion",
                    "easActivated",
                    "easDeviceId",
                    "easActivationDateTime",
                    "azureADRegistered",
                    "deviceEnrollmentType",
                    "activationLockBypassCode",
                    "emailAddress",
                    "azureADDeviceId",
                    "deviceRegistrationState",
                    "deviceCategoryDisplayName",
                    "isSupervised",
                    "exchangeLastSuccessfulSyncDateTime",
                    "exchangeAccessState",
                    "exchangeAccessStateReason",
                    "remoteAssistanceSessionUrl",
                    "remoteAssistanceSessionErrorDetails",
                    "isEncrypted",
                    "userPrincipalName",
                    "model",
                    "manufacturer",
                    "imei",
                    "complianceGracePeriodExpirationDateTime",
                    "serialNumber",
                    "phoneNumber",
                    "androidSecurityPatchLevel",
                    "userDisplayName",
                    "configurationManagerClientEnabledFeatures",
                    "wiFiMacAddress",
                    "deviceHealthAttestationState",
                    "subscriberCarrier",
                    "meid",
                    "totalStorageSpaceInBytes",
                    "freeStorageSpaceInBytes",
                    "managedDeviceName",
                    "partnerReportedThreatState",
                    "requireUserEnrollmentApproval",
                    "managementCertificateExpirationDate",
                    "iccid",
                    "udid",
                    "notes",
                    "ethernetMacAddress",
                    "physicalMemoryInBytes",
                    "deviceActionResults"
                ],
                "type": "object"
            },
            "type": "array"
        }
    },
    "type": "object"
}

Logic App Action 6- “HTTP Get Device Info Azure AD”

Query Intune device information using the Device ID from the Log Analytics output.

Logic App Action 7- “Parse Device Infor Azure AD”

Azure AD device information will be required in future steps, so we will need to parse the results from “HTTP Get Device Info Azure AD”.  Use the below sample or generate schema from running the Logic App now.

Sample Schema

{
    "properties": {
        "@@odata.context": {
            "type": "string"
        },
        "value": {
            "items": {
                "properties": {
                    "accountEnabled": {
                        "type": "boolean"
                    },
                    "alternativeSecurityIds": {
                        "items": {
                            "properties": {
                                "identityProvider": {},
                                "key": {
                                    "type": "string"
                                },
                                "type": {
                                    "type": "integer"
                                }
                            },
                            "required": [
                                "type",
                                "identityProvider",
                                "key"
                            ],
                            "type": "object"
                        },
                        "type": "array"
                    },
                    "approximateLastSignInDateTime": {
                        "type": "string"
                    },
                    "complianceExpirationDateTime": {},
                    "createdDateTime": {
                        "type": "string"
                    },
                    "deletedDateTime": {},
                    "deviceCategory": {},
                    "deviceId": {
                        "type": "string"
                    },
                    "deviceMetadata": {},
                    "deviceOwnership": {
                        "type": "string"
                    },
                    "deviceVersion": {
                        "type": "integer"
                    },
                    "displayName": {
                        "type": "string"
                    },
                    "domainName": {},
                    "enrollmentProfileName": {
                        "type": "string"
                    },
                    "enrollmentType": {
                        "type": "string"
                    },
                    "extensionAttributes": {
                        "properties": {
                            "extensionAttribute1": {},
                            "extensionAttribute10": {},
                            "extensionAttribute11": {},
                            "extensionAttribute12": {},
                            "extensionAttribute13": {},
                            "extensionAttribute14": {},
                            "extensionAttribute15": {},
                            "extensionAttribute2": {},
                            "extensionAttribute3": {},
                            "extensionAttribute4": {},
                            "extensionAttribute5": {},
                            "extensionAttribute6": {},
                            "extensionAttribute7": {},
                            "extensionAttribute8": {},
                            "extensionAttribute9": {}
                        },
                        "type": "object"
                    },
                    "externalSourceName": {},
                    "id": {
                        "type": "string"
                    },
                    "isCompliant": {
                        "type": "boolean"
                    },
                    "isManaged": {
                        "type": "boolean"
                    },
                    "isRooted": {
                        "type": "boolean"
                    },
                    "managementType": {
                        "type": "string"
                    },
                    "manufacturer": {
                        "type": "string"
                    },
                    "mdmAppId": {},
                    "model": {
                        "type": "string"
                    },
                    "onPremisesLastSyncDateTime": {},
                    "onPremisesSyncEnabled": {},
                    "operatingSystem": {
                        "type": "string"
                    },
                    "operatingSystemVersion": {
                        "type": "string"
                    },
                    "physicalIds": {
                        "items": {
                            "type": "string"
                        },
                        "type": "array"
                    },
                    "profileType": {
                        "type": "string"
                    },
                    "registrationDateTime": {
                        "type": "string"
                    },
                    "sourceType": {},
                    "systemLabels": {
                        "items": {
                            "type": "string"
                        },
                        "type": "array"
                    },
                    "trustType": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "deletedDateTime",
                    "accountEnabled",
                    "approximateLastSignInDateTime",
                    "complianceExpirationDateTime",
                    "createdDateTime",
                    "deviceCategory",
                    "deviceId",
                    "deviceMetadata",
                    "deviceOwnership",
                    "deviceVersion",
                    "displayName",
                    "domainName",
                    "enrollmentProfileName",
                    "enrollmentType",
                    "externalSourceName",
                    "isCompliant",
                    "isManaged",
                    "isRooted",
                    "managementType",
                    "manufacturer",
                    "mdmAppId",
                    "model",
                    "onPremisesLastSyncDateTime",
                    "onPremisesSyncEnabled",
                    "operatingSystem",
                    "operatingSystemVersion",
                    "physicalIds",
                    "profileType",
                    "registrationDateTime",
                    "sourceType",
                    "systemLabels",
                    "trustType",
                    "extensionAttributes",
                    "alternativeSecurityIds"
                ],
                "type": "object"
            },
            "type": "array"
        }
    },
    "type": "object"
}

Logic App Action 8- “Condition” in Validate and Rename Device

I use multiple conditions to ensure the device is the intended device to rename, such as deviceName, operatingSystem, and managedBy.

Logic App Action 9- “True” Rename Device Values Intune

Logic App Action 10- “HTTP Rename Device”

This is where the device rename occurs using Graph. 

Id in the URI comes from the value from Action 7- “Parse Device Infor Azure AD”

It’s important to add some unique identifier on each device name.  In the event you have stale devices, or the directory has not updated using a unique device name is crucial or the automation will fail.  I like to stamp each device with the date using a date expression:

utcNow('yyMMdd')

Logic App Action 9 thru 12- Post results into Teams

You need to insert at least a 5 minute delay between the POST rename step and GET new device name step allowing Graph time to update the new device name.  If you do not have this pause you will have the old name even when initiating a new HTTP Get from graph because not enough time has passed for the new name to be available.

The Teams Post and Rename:

LL&P – Popich

Advertisement