Today, I share a blog post on creating an approval flow to process user requests for a Windows 365 cloud PC. Such a flow allows an end-user to request a cloud PC, after which the user’s manager needs to approve or deny the request. When the request is approved, the cloud PC is automatically provisioned. This saves the IT admin time manually assigning a license/ cloud PC.
The solution is short
The solution consists of several parts. The end-user can enter a new request by filling in a form. The information from this form is stored on a SharePoint List. An Azure Logic Apps flow checks every few minutes if a new item is created on the SP List. If a new item is created, the flow starts to run and queries Microsoft Graph for some user information and the user`s manager.
A Teams adaptive card is sent to the manager that waits for a response from the manager. The manager can approve or deny the request via the Teams client. When the request is approved, the user is added to an Entra ID group to which a Windows 365 license is assigned. As last the user is informed via a Teams message if the request has been approved or denied.
I will soon publish a template for easy deployment of the flow to my GitHub repo.
Requirements
We have some requirements that need to be in place before we can use our Logic Apps flow.
We need to have the license assignment in place, which means Entra ID groups are assigned to the proper Windows 365 licenses. Besides that, we need to have provisioning policies in place and Entra ID groups assigned to the policies.
In this example, I have two different Windows 365 licenses, which the users can request in three different regions. Meaning I have 6 provisions policies and related Entra ID group.
As described, a form stores the requests in a SharePoint List, but besides that, I also store information on these 6 Entra ID groups in a SharePoint List. A requirement is to have those SharePoint Lists, but also a (service) account with access to those lists.
We use Microsoft Graph calls to query Microsoft Graph for information on the user and the manager and also add the user to a group. Authentication for this is done with a managed identity. As you can read in the documentation, we have the option to use a system-assigned and user-assigned managed identity. In my case, I use a system-assigned MI, as that is considered the most secure.
This Managed Identity needs to have (application) permissions to execute all the Graph calls we make.
This is the application permission needed for our flow;
User.Read.All
GroupMember.ReadWrite.All
As last, we need to have a (service) account with a Teams license, to send the approval message to the manager and to send a message to the end-user.
Setting up the SharePoint Lists
As described I make use of two SharePoint Lists. The List to which the Form writes it’s information is very basic. I hide the default Title column and add two new (required) columns: Geography and Performance Type. Both columns are of type choice and contain the choices the users have.
Directly from a SP List it’s easy to create a Form by just clicking on the Forms button.
From the pop-up windows select New form.
Uncheck Title and if needed add a description under selection boxes.
The second list contains information of the different Entra ID groups to which licenses and provisioning policies are assigned. I have three columns of type single line of text. Location and Type (which describes the location and type of the W365 cloud PC), Entra Group Name and Entra Group Object ID.
In this list, as an admin you enter all the related information.
Setting up the flow
When we have our requirements in place, we can start building the Azure Logic Apps flow.
Sign in to the Azure portal and open the Logic Apps service. Create a Logic App of type Consumption.
We need to select a subscription, resource group, and region, and enter the name of the flow before we can create the Logic Apps flow.
When the flow is created, click on the name of the flow at the top of the screen, and open the Identity section. On the System assigned tab, set the switch to On and confirm this by selecting Yes.
Make sure to assign the application permissions to the system-assigned manager identity.
Browse to the Overview tab and click on Edit.
The first thing we need to add to the flow is a Trigger. Click on Add a trigger and search for SharePoint. Select the trigger When an item is created.
First sign in with your service account with access to the SP List.
Next, select the Site Address where the SP List is located and select the List Name.
In case nothing is shown in the list, click on Enter custom value and paste the needed information.
Click on How often do you want to check for items. Here we select how often the flow checks for new items. It is up to you to configure this to your needs.
After the trigger, we add our first action by clicking on the plus button. We add an HTTP action with which we can query Microsoft Graph for the user’s information, like the User Principal Name.
Select GET as Method.
Next, select Authentication under Advanced parameters.
As Authentication type select Managed identity.
Select System-assigned managed identity from the list.
And add https://graph.microsoft.com as Audience.
Enter below URI:
https://graph.microsoft.com/v1.0/users/[EMAIL]?$select=id,displayName,mail,userPrincipalName
We need to replace [EMAIL] with information from the trigger. The trigger pulls in some data related to the SharePoint item, including who created it and the creator’s email. Via Dynamic content we can add this information in the URI. Dynamic content is added by clicking on the lightning button, after which we can search for content.
Search for email and select Created by Email.
This is the URI after adding the dynamic content item.
Next, we need to add a Parse JSON action, which is a Data operations action. We parse the output of the HTTP action, to be able to use the values later on in the flow.
Add the Parse JSON action to the flow.
In the Content field, we add Body, which is found as dynamic content of the HTTP action.
We don’t have to write the schema ourselves, we can generate it by adding a sample payload. We can get this example payload, by running the current flow and grabbing the output from the HTTP action.
Or run the same query in Microsoft grab explorer to retrieve the same output.
Select Use sample payload on the Parse JSON action and paste the information.
And we have configured the Parse JSON action.
We add a second HTTP Action to the flow, this time to query for the manager of the user.
Select GET as Method.
Next, select Authentication under Advanced parameters.
As Authentication type select Managed identity.
Select System-assigned managed identity from the list.
And add https://graph.microsoft.com as Audience.
Enter below URI:
https://graph.microsoft.com/v1.0/users/[EMAIL]/manager?$select=id,displayName,mail,userPrincipalName
Replace [EMAIL] again with the Created by email dynamic content.
Again, the HTTP action is followed by a Parse JSON action.
The next step is to add an action to send the Teams adaptive card. Let’s first have a look at how we can create such an adaptive card with the adaptive card designer.
On this website, we can create a design for our adaptive card.
We need to select the host app (1) which is Microsoft Teams.
We can drag different input fields (2) into the designer field (3), like Input.text fields.
By selecting such a field, we can add text into the field (4).
We can add a title and several lines of information.
Under the text fields, we add an Input.ChoiceSet field. With that field, we allow the manager to make a choice of approve or deny.
We need to enter an Id (1), add a Label (2) and enter a Placeholder (3) in the configuration of the ChoiceSet field.
Besides that, I want the field to be required, thus I select Required (1).
I enter an Error message (2) which shows up in case an error occurs when submitting the info. And as last I fill in the Choices (3). I enter Approve and Deny (twice). One to show in the Adaptive Card as an option in the list, and the second time it’s the info sent back to the Logic Apps flow.
Now we need to select the whole adaptive card, click Add an action and select Action.Submit.
When we select preview mode, we can see how the card looks like.
Copy all the information from the card payload editor field, which we need in the flow.
In the flow, add a Post adaptive card and wait for a response action.
We select Flow bot under Post as and Chat with Flow bot under Post In.
In the Recipient field, we need to add the variable mail from the manager. This mail item is dynamic content from the second Parse JSON action.
We paste the designer’s card payload information in the Teams action’s body field. We can complement that information with dynamic content, like the display name of the manager, the requestor, and the requested information about the cloud PC.
We need to parse the response of the Teams action. The easiest way to do that is running the whole flow, including an approval from a manager. When the response is sent, the flow finishes until the Teams action. Then we can grab the Teams action’s output body to create the Paese JSON schema.
With the next action, we split up the flow in an approval and deny part, which is done with a Switch action. The responseselectionid in the Teams action contains the outcome of the approval; approve or deny. Add responseselectionid the dynamic content from the last Parse JSON action to the On field of the Switch.
Under the switch we add two cases, Approve and Deny.
Enter Approve in the Equals field of the approve case. Enter Deny in the deny case.
Under the approval case, we add a Get items action, which is a SharePoint action. With this action we will pull in the information from the SharePoint List that contains information of the Entra ID groups. But we only want to retrieve the group information of the group that corresponds to the requested cloud PC, therefore we use a Filter Query in the action.
Select the Site Address and SharePoint List.
Enter the following as Filter Query; LocationandType eq ‘ ‘
Between the quotation marks we add the SharePoint Values from the request, so that it corresponds with the related Entra Group as how it is stored in the SP List.
Add another HTTP action to the flow.
Select GET as Method.
Next, select Authentication under Advanced parameters.
As Authentication type select Managed identity.
Select System-assigned managed identity from the list.
And add https://graph.microsoft.com as Audience.
Enter below URI:
https://graph.microsoft.com/v1.0/groups/[ENTRAIDGROUPOBJECTID]/members/$ref
Replace [ENTRAIDGROUPOBJECTID] with the Group Object ID value retrieved with the Get items action.
Enter the below in the Body field;
{
"@@odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/[BODY ID]"
}
Replace [BODY ID] with the body ID from the Parse JSON action that retrieved the requestor information.
The HTTP action is automatically added to a For each action.
Next we add a Teams action to the flow to inform the user that the request has been approved. You can select a Post a message Teams action, but also an action to send an adaptive card again.
In the recipient field, add the requester’s mail and enter information to your needs in the message field.
Repeat this step under the Deny case.
The end result
The end result is that the user is provided with information about the outcome of the Windows 365 request.
And this all in an automated way so that no IT admin needs to take action when an end user needs a Windows 365 cloud PC.
You can also implement this automation to inform your end user when the cloud PC is provisioned.
Thanks for reading! And good luck implementing this solution.