MEM – Managing device groups and management names with Power Apps

Happy New Year everyone! 2020 was quite the year for many things including blog posts. Regarding posts, I posted quite a few blogs about utilizing Microsoft Endpoint Manager (MEM) and the Microsoft Power Platform to enhance admin tasks, end user updates, reporting, and more.

I’m starting off the New Year with a creative post and continuing the theme I begain in 2020 showing how flexible Power Apps and Power Automate can be when we find we need to provide pieces of MEM admin functionality without needing full access to the MEM console.

The Power App created for this post is great for admins, non-admins, service providers, educational instituations, etc. Feel free to utilize and expand on the ideas written in this and my other posts.

Continuing the Power Platform + MEM theme, essentially we can create our own UI to meet the needs of our business and IT operations and to interface with external services and other platforms all through Power Automate.

The app created for this post focuses on device grouping and utilizing the management name to tag devices with specific names to help identify them easier in the MEM Intune admin console. This app becomes really interesting when we want to group devices by serial number or other attributes, including management name, all by selecting devices from a list in Power Apps.

Think of this app as a one stop shop to manage device grouping and the management names. This app is especially helpful when managing userless devices such as rugged and/or firstline devices, or devices used in educational environments where they need to be grouped and tagged with a name, in Intune’s case, a management name.

For a review of app functionality I encourage you to watch the video below before proceeding:

Let’s get started

Requirements

  • Microsoft Azure
  • Azure Active Directory
  • Microsoft Graph
  • Microsoft Endpoint Manager – Intune
  • Power Apps
  • Power Automate

Note: there are a lot of details in this post, please reference video above to help with your learning and app details. Some of the code and fields I use are from prior posts so there shouldn’t be many surprises, however I do have some new ideas, code, fields I implemented to make this all work end-to-end.


Power Automate

For the entire app to function we need several Power Automate flows. Try not to be intimidated as most of these are simple flows making HTTP calls to Intune and Azure AD graph API:

  • Add devices to AAD group
  • Get device list from Intune
  • Add or update management name
  • Create AAD group
  • Get device group members
  • Delete devices from a group
  • Get Azure AD groups

Pro tips

  1. It’s best to build out the Power Automate flows before designing the Power App, however sometimes I find myself going back and forth when designing as it’s how I am able to visualize the app + automation.
  2. One thing to keep in mind, anytime a change is made in a Power Automate flow it’s helpful to delete and re-add Power Automate flow in your Power App (remember to copy the code for the button first), this essentially refreshes the connection and updates it so it can see the items in the flow. Do this by selecting the data connecter in the Power App, find the Power Automate flow, delete, then re-add it by selecting ACTION > Power Automate from the menu bar. Depending on what object is selected, you may have to re-add the code, e.g. OnVisible, OnSelect fields, etc..


Get and refresh Azure AD groups

I recommend starting with a “manually trigger flow” trigger instead of PowerApps trigger to make testing easier. I always replace the button trigger with the PowerApps trigger when the flow works end-to-end and all my testing is completed.

Identical to my previous post (and other posts) where I utilize a Azure AD groups to target actions to group, all we need to do here is copy and paste from existing apps, however if you haven’t created any apps from my posts, here’s how we get and refresh Azure AD groups in a dropdown list box.

Add an HTTP, Parse JSON, and Response actions. HTTP action will query graph, Parse JSON will read the data returned and parse out the data so it’s selectable in subsequent steps, and the Response action takes the array from the Parse JSON action to we can populate a collection in Power Apps. If you’ve followed my blogs, in previous posts I step through how to configure the steps for HTTP action configuration and custom connectors (if you prefer connectors). We’ll make a call to this Power Automate flow in Power Apps, more on this later.

URI is for HTTP action is:

https://graph.microsoft.com/v1.0/groups?$top=950&$select=id,displayName&$orderby=displayName

Parse JSON schema

{
    "type": "object",
    "properties": {
        "@@odata.context": {
            "type": "string"
        },
        "value": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "displayName": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "displayName"
                ]
            }
        }
    }
}

Response action schema (this is just a subset of the parse JSON code)

{
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "id": {
                "type": "string"
            },
            "displayName": {
                "type": "string"
            }
        }
    }
}

Create AAD group

We need a method to create an Azure AD group for convenance more than anything else since we can already create groups directly in the MEM admin center, however why not make it an all-in-one experience. Do this by creating a new Power Automate flow, add an initialize variable action and an HTTP action. Add and HTTP action and utilize Azure AD auth and the client/secret for the Azure AD registered app with appropriate API permissions.

Note: for creating a group the “mailNickname”, which is a required attribute, we need to remove all spaces from the displayName and I use the following formula to accomplish it:

replace(variables('varGroupName'),' ','')


Add devices to group

This is the most complex of the flows and I had to think on this one for a bit because essentially we need to match the devices in Intune with the device objects in Azure AD while reducing query performance impact.

When adding devices to a group we need to map the devices in Intune to device objects in Azure AD because using Graph to add objects to groups requires the Azure AD objectID. Unfortunately we can’t use the device ID in an Azure AD search query in Graph to add the device objects to an Azure AD group so we need to query for the name of the device in Azure AD as they’re identical to Intune device names. To do this we must query through all Azure AD device objects until we find a device name match as they’re identical in Azure AD and Intune. Then we need to reference the Azure AD object ID (“ID”) of the devices in a Graph POST call to add the devices to the group. For performance purposes we can use Graph to search for the name of the device in Azure AD and only return the devices checked from the list. This cuts down on pulling all device objects into Power Automate and having to do the work there.

You’re probably wondering why I didn’t just search by deviceID in Azure AD. Unfortunately Graph doesn’t allow searching on the Azure AD deviceID attribute like we can with Intune objects. Since Intune doesn’t store the Azure AD objectID I needed to search on the device name as the device name is identical in Azure AD and Intune.

Once a group and one or more device are selected we want to add them to the selected group using Power Automate (this is covered in the Power Apps section below).

Create a new Power Automate flow and add two variables, and one Parse JSON action. Name variables what you’d like and reference the image below to configure them.

For the Parse JSON action reference the varDeviceID schema below.

Now add an HTTP action and use the deviceName from the Parse JSON output in the dynamic content, this will create an apply to each action with the HTTP action which makes sense because we could have more than one device selected and is the whole point of the Power App. Here’s the query for this HTTP action:

https://graph.microsoft.com/v1.0/devices?$select=displayName,id,deviceid&$expand=registeredOwners&$filter=startswith(displayName,'deviceName from Parse JSON values')

Add another Parse JSON below the HTTP action in the apply to each action and utilize the second JSON schema below for get devices AAD query. Essentially we’re using the deviceName to make a call to Azure AD and return the device objectIDs to be utilized in the last HTTP action which adds the devices to the Azure AD group.

Add the final HTTP action outside of the apply to each action and when we reference the attributes from the dynamic content another apply to each action will be added automatically containing this HTTP action.


Pro Tip
Something you’ll notice when adding info to the body of an HTTP call, if we add one “@” before odata.id (@odata.id) we will not be able to save the flow. We must add another “@”, so it will look like “@@odata.id”, basically escaping the initial @ symbol.

Parse JSON schema for varDeviceID

{
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "deviceEnrollmentType": {
                "type": "string"
            },
            "deviceName": {
                "type": "string"
            },
            "id": {
                "type": "string"
            },
            "manufacturer": {
                "type": "string"
            },
            "model": {
                "type": "string"
            },
            "operatingSystem": {
                "type": "string"
            },
            "serialNumber": {
                "type": "string"
            }
        },
        "required": [
            "deviceEnrollmentType",
            "deviceName",
            "id",
            "manufacturer",
            "model",
            "operatingSystem",
            "serialNumber"
        ]
    }
}

Parse JSON schema get devices AAD query

{
    "type": "object",
    "properties": {
        "@@odata.context": {
            "type": "string"
        },
        "value": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "displayName": {
                        "type": "string"
                    },
                    "id": {
                        "type": "string"
                    },
                    "deviceId": {
                        "type": "string"
                    },
                    "registeredOwners": {
                        "type": "array"
                    }
                },
                "required": [
                    "displayName",
                    "id",
                    "deviceId",
                    "registeredOwners"
                ]
            }
        }
    }
}


Add/Update management name

To add and update the management name, create a new Power Automate flow and add two initialize variable actions, parse JSON action to Parse all the devices IDs sent over, and an HTTP action. The “Apply to each” action will auto-generate when the “id” attributes is selected from the Parse JSON list under dynamic content.

The Parse JSON array is as follows:

{
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "id": {
                "type": "string"
            }
        },
        "required": [
            "id"
        ]
    }
}

The HTTP action is straight forward so I won’t paste the code here as it’s visible in the HTTP action in the image below. varDeviceID will process all the device id’s sent from Power Apps and the varmgtName is the value of the management name added in Power Apps.


Get devices from Intune

For this flow, we need to return all devices from Intune to be populated in a Power Apps collection (i.e. a data table). If you prefer to only return certain devices such as Android and/or iOS, you’d modify the query below and the modify the JSON and response schemas.

HTTP action URI query:

https://graph.microsoft.com/v1.0/devicemanagement/manageddevices?$select=deviceName,id,operatingSystem,serialNumber,deviceEnrollmentType,manufacturer,model,managedDeviceName

Parse JSON

{
    "type": "object",
    "properties": {
        "@@odata.context": {
            "type": "string"
        },
        "@@odata.count": {
            "type": "integer"
        },
        "value": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "deviceName": {
                        "type": "string"
                    },
                    "id": {
                        "type": "string"
                    },
                    "operatingSystem": {
                        "type": "string"
                    },
                    "serialNumber": {
                        "type": "string"
                    },
                    "deviceEnrollmentType": {
                        "type": "string"
                    },
                    "manufacturer": {
                        "type": "string"
                    },
                    "model": {
                        "type": "string"
                    },
                    "managedDeviceName": {
                        "type": "string"
                    }
                },
                "required": [
                    "deviceName",
                    "operatingSystem",
                    "serialNumber",
                    "deviceEnrollmentType",
                    "manufacturer",
                    "model",
                    "managedDeviceName"
                ]
            }
        }
    }
}

Response action schema

{
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "deviceName": {
                "type": "string"
            },
            "id": {
                "type": "string"
            },
            "operatingSystem": {
                "type": "string"
            },
            "serialNumber": {
                "type": "string"
            },
            "deviceEnrollmentType": {
                "type": "string"
            },
            "manufacturer": {
                "type": "string"
            },
            "model": {
                "type": "string"
            },
            "managedDeviceName": {
                "type": "string"
            }
        }
    }
}


Delete devices from Azure AD group

This Power Automate flow is nearly identical to the Add devices to Azure AD group flow, in fact I selected “save as” and saved with a different name. There are a couple differences though:

I changed the variable names to keep me straight with the variables and the graph query to delete devices in the HTTP action needed to change from PATCH to DELETE with an updated URI:

https://graph.microsoft.com/v1.0/groups/{group-id}/members/{directory-object-id}/$ref

Otherwise, everything else remained the same.

Parse JSON

varDeleteDeviceID (renamed from varDeviceID) needed a schema update to include @odata.type:

{
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "manufacturer": {
                "type": "string"
            },
            "model": {
                "type": "string"
            },
            "operatingSystem": {
                "type": "string"
            },
            "@@odata.type": {
                "type": "string"
            },
            "deviceId": {
                "type": "string"
            },
            "displayName": {
                "type": "string"
            },
            "operatingSystemVersion": {
                "type": "string"
            }
        },
        "required": [
            "@@odata.type",
            "deviceId",
            "displayName",
            "manufacturer",
            "model",
            "operatingSystem",
            "operatingSystemVersion"
        ]
    }
}


Power Apps

The Power App consists of two screens the main screen is where the bulk of the work is accomplished while the second screen is a method to check and update the actions that occurred with device groups.

Pro tips

  1. Name the fields, button, labels, etc. appropriately to reduce guess work what field is what when troubleshooting.
  2. Adjusting screen orientation in settings will ultimately resize everything, use caution when using this feature. If more screen space is added it will shrink everything and you’ll need to resize all fields and fonts by hand.

Power Apps screen one


You’ll notice there are quite few things on the screen and I’ll go through each individually.

On screen one of the application add the following code to “OnVisible” under ACTION:

ClearCollect(AADGroupCollection,{displayName:""});Collect(AADGroupCollection, 'PowerApp->HTTP'.Run());Set(JSONVariable, JSON(AADGroupCollection, JSONFormat.IncludeBinaryData));ClearCollect(enrolledDevicescollection,'Getdevices-(MEMgroupdevicesapp)'.Run());Set(JSONVariable, JSON(enrolledDevicescollection,JSONFormat.IncludeBinaryData));Clear(deviceSelectionCollection)

What the code is doing is adding a blank value to the AAD group collection so the dropdown show’s a blank value, then Power Automate runs to pull the data into the collection. We also clear the collection for the Intune device query as well as clear the collection for device selections.

At this time you’ll need to switch the trigger to Power Apps in both get Intune devices and the Azure AD groups Power Automate flows.

Search items

Search items allows the user to search on any visible field, such as OS, management name, serial, etc. Search items supports partial input and it’s fast. The benefit of search is to narrow down devices to be selected and added to a group and/or adding/removing a management name.

Search items is just a text input box, no code needed here. Simply add a textinput field to the form and label it accordingly.

Device list gallery

dd a blank gallery to the screen and use the code below for the “Items” property:

SortByColumns(Search(enrolledDevicescollection,'Search gallery textbox'.Text,"deviceName","operatingSystem","manufacturer","model","serialNumber","managedDeviceName"),SortColumn, If(SortDecending,Ascending,Descending))

Add the get devices from Intune Power Automate flow to the gallery. To populate the fields in the query, select the gallery and add labels to represent the columns. Each label will return the column in the collection.

Pro Tip
Sometimes I add a button to test or refresh data in Power Apps, it’s super helpful when we need to test things out. So for this item, I would add a button and use the code above in the OnSelect action for the button.

Create AAD Group

Creating an AAD group provides the ability to create an AAD group in case we forgot to create one before hand. This is more for convenance than anything. Once a new group is created, select “Refresh AAD Groups” button and a Power Automate flow will run an update the list. Add a button an use the code below for the OnSelect action for the button:

Set(varGroupName,'AAD group name textbox_1'.Text);('CreateAADgroup(MEMgroupdevicesapp)'.Run(varGroupName))


Refresh AAD groups

When the app is launched it creates a collection of AAD groups (up to 950 as that’s the limit so you may want to filter your query if there are more than 950 AAD groups in your tenant). For the main screen in the Power App select “Action” from the menu bar and then select “Power Automate” and choose the AAD PA flow you’ve created.

Next under ACTION > OnVisible for the main screen add the following code:

ClearCollect(AADGroupCollection, THE NAME OF THE POWER AUTOMATE AAD GROUP FLOW); Set(JSONVariable, JSON(AADGroupCollection, JSONFormat.IncludeBinaryData))

The code above clears the existing collection (if there is one) then creates a new collection named “AADGroupCollection. The “Refresh AAD Groups” button calls the same JSON above add the code under ACTION > OnSelect for the button, copy and past the same code for the button OnSelect action.


Add devices to group

Once a group is chosen and devices selected from the list, select “Add devices to Group”. In the background a Power Automate flow will run and add the devices to the selected group. Go to screen two of the app to view the devices in the group, more on this later. Create a button and utilize the code below for the add devices to group button:

Set(vargroupID,'AAD group ComboBox2'.Selected.id);'Adddevicestogroup(MEMgroupdevicesapp)'.Run(JSON(deviceSelectionCollection,JSONFormat.IndentFour),vargroupID)

Add/Update management name

Add the desired name to the text input box, select devices from the list to add the management name to and select “Add/Update management name” button. A Power Automate flow will run in the background and update the management name for each device selected.

To create this add a textinput box and a button. Use the following code for the button:

Set(varmgtName,'Mgt name TextInput'.Text);'Button->AddorUpdatemgtname'.Run(JSON(deviceSelectionCollection.id,JSONFormat.IndentFour),varmgtName)


Update device list

The device list does not update dynamically, although we could add an action to refresh periodically, however I chose a button as it’s more real-time. The update device list button refreshes the list by running a Power Automate flow.

ClearCollect(enrolledDevicescollection,'Getdevices-(MEMgroupdevicesapp)'.Run());Set(JSONVariable, JSON(enrolledDevicescollection,JSONFormat.IncludeBinaryData));Clear(deviceSelectionCollection);UpdateContext({ClearCheckbox:true});UpdateContext({ClearCheckbox:false})

Powe Apps screen two

The first screen is the bulk of the app, screen two provide the ability to select an AAD group and see the members of that group and also delete device objects from the group. Note: this does not replace Azure AD dynamic groups.

For screen two, I thought it would be nice to be able to view which devices are in which Azure AD groups. Screen two consists of a searchable device dropdown which is a copy and paste excise from the fields on screen one. We then add a blank gallery and map the table to the group collection created when the app is launched and/or AAD groups are refreshed. Finally a button to delete selected devices from the view if needed. This is all for convenance and all this can be accomplished in the MEM admin center if needed. However, this type of application is useful for non-admins and other scenarios.

The fields are identical to the fields on page one, just copy and paste the fields. I recommend creating different variables and collections though and this can be accomplished by renaming the variable and collections in the code. For the “Delete Devices” button, this is identical to Add Devices button code, however I renamed the variables and reference a different Power Automate flow:

Set(vargroupID_2,'AAD group ComboBox'.Selected.id);'Deletedevicesingroup(MEMgroupdevicesapp)'.Run(JSON(devfromGroupCollection,JSONFormat.IndentFour),vargroupID_2)

Conclusion

That’s it! I have to say this was one of my favorite apps to create as it provides a lot of options and ideas for the broader endpoint management community to build on.