Pages

Monday, April 3, 2023

Using Microsoft Forms and Logic App to create an automated submissions and approval process for Azure AD User Creation

Being an architect usually means that I do not usually take part in ongoing operational activities when an environment has gone live and therefore the days where I handle requests for new Azure AD account creations are supposed to be behind me but most of my fellow colleagues may know that this isn’t usually the case as there are plenty of scenarios where we still need to roll up our sleeves and perform activities such as provision accounts. Account provisioning should be managed by a proper ticketing system, but it may not be available for new greenfield environment builds that has not been transitioned to operations. What I’ve found over the years is that large projects that last upwards of a year or more can have a large volume of new account requests and a large set of unidentified accounts when it is ready to be transitioned from the project to sustainment team.

One of the ways I’ve tried to better manage, and track Azure AD accounts is through the use of Microsoft Forms and a Logic App that automates the process of creating user accounts through an approval process. Microsoft Forms provides an easy way to create a secure form for requestors to fill out and track the submissions, while Logic App allows me to create a flow that sends approval to a group of administrators, automates the creation of accounts, and sends notifications. I’ve found that this temporary solution has served very well for situations where I do not have a ticketing system and I only have access to Microsoft Azure and 365 licenses.

This blog post serves to provide steps for how to create the form and the automation, and I hope it will help others who might need an interim solution for account creation and management.

Create an Automation Account Runbook to Generate a Random Password

While it is possible to have the Azure AD step generate a password when creating an account, most of the environments I’ve worked in has had more stringent requirements so we will need to create an Automation Account Runbook to randomly generate a password to be used when creating the Azure AD account. I won’t be providing too prescriptive steps for creating the Automation Account Runbook but would like to provide enough information for its creation.

Create an Automation Account or reuse one that is already available. For this example, I am reusing an Automation Account to host the runbook that will generate a random password and return it back to, in our case, a Logic App:

image

The runbook code that generates the password can be found at my following GitHub repository: https://github.com/terenceluk/Azure/blob/main/PowerShell/Generate-Random-Password.ps1

image

To lock down the Automation Account so that it can only be access by the Logic App, we’ll turn on the System assigned identity in the Identity blade, which will allow us to grant permissions to the Logic App:

image

Creating the Microsoft Form

There are various ways to create a Microsoft Form such as navigating to https://forms.office.com or directly in Teams. For this example, I’ll be creating the form directly in a Teams team that I created for IT Requests as shown in the screenshot below.

image

Begin by clicking on the + sign, search for Forms, and then click on the Forms icon:

image

Provide a name for the form and click the Save button:

image

The new form will be displayed in the Teams tab. Proceed to edit the for and add the attributes you would like to collect. The form I created consists of the following fields:

  • Authorizing Manager – For placing an entry into Microsoft Form’s record as to who authorized this account creation
  • Requestor - For placing an entry into Microsoft Form’s record as to who requested this account creation (the submitter may not be the requestor)
  • First Name – Will be used for the Display Name and Given Name in the Create user azure ad action.
  • Last Name – Will be used for the Display Name and Surname Name in the Create user azure ad action.
  • Location – Will be used for the Office Location in the Create user azure ad action.
  • Job Title – Will be used for the Job Title in the Create user azure ad action.
  • Department – Will be used for the Department in the Create user azure ad action.
  • Company Name – For placing an entry into Microsoft Form’s record
  • Office 365 License – For determining whether this user requires an Office 365 license
  • Power BI License – For determining whether this user requires an Power BI license
  • DevOps Access – For determining whether to grant this user to DevOps
  • Date Required – For determining when this user account is required
  • Start Date – For determining when this user starts
  • End Date – For determining when this user account should expire
  • New User Contact Email – For determining what email address should be used to contact this user
  • New User Contact Number – For determining what phone number should be used to contact this user
  • Requestor's Email Address (approved and denied notifications) – For determining email address the new account details such as login name and temporary password should be sent to
image

You can preview the form by clicking on the Preview button:

image

With the form created, proceed to close the form in editing mode by click on the Edit | <Form name> and click on the Remove option:

image

The message can be a bit misleading but the reason why we’re removing it is because it is currently in edit mode:

image

With the form removed, proceed to click on the + sign in the tab again:

image

Click on the form icon again:

image

We will now use the Add an existing form option to add the form we had just created:

image

The form will now be in Fill mode (non editing):

image

The form can be accessed via the Teams channel or directly through a link (both require authentication by default). To obtain the link, simply navigate to https://forms.office.com and sign-in to locate the form:

image

Open the form and click on Collect Responses:

image

You can configure the permissions for accessing the form as well as shortening the URL:

image

Obtain the Form ID

Our Logic App will be triggered when a form has been submitted and the way it identifies the form is through its From ID. To find this unique string, navigate to www.office.com, click on the top left corner tile button and then Forms:

image

The most recent for we created will be displayed but if the recent list contains other documents you have worked on that has pushed the form off the list then we can navigate to it by clicking on the team under My Groups:

image

Proceed to open the form by clicking on it then with the form displayed in the browser, copy the URL and locate the string after the id= string and copy it:

https://forms.office.com/pages/designpagev2.aspx?origin=OfficeDotCom&lang=en-US&route=GroupForms&subpage=design&id=C0f0hB4_iUiflasPUUMCT_1a5E1qzx9IgJMuQa0Fbb9UME5RSlhYWFNLODdDQ1lVUzhINlRVRzBNNiQlQCN0PWcu

image

We’ll be using this form ID shortly so save it somewhere that can easily retrieved.

Logic App Flow

Before I begin, I would like to go through the flow of the submission, approval, processing, and notification flow of the Logic App as shown in the following screenshot.

image

The flow of the Logic App goes as such:

Approval Process

  1. The Logic App starts when a response is submitted through the Microsoft Forms
  2. The next step is to retrieve the values of each parameter in the submitted response so we can use it in the later actions
  3. The Initialize Variable is used for generating HTML code that will be used to generate an email as Send an email (V2) no longer accepts HTML code
  4. An approval email is sent to the desired approvers

Approved Process

If the one of approvers has approved the new account request then:

  1. An automated account runbook that generates a random password will be started to generate a random password
  2. When the password is generated, the password will be retrieved
  3. An Azure AD account will be created with the form submission values and the password generated

If Account Creation is Successful

If the Azure AD account creation is successful then:

  1. Set the initialized variable at the beginning of the workflow to contain the contents of the email to be sent out
  2. Send the email with the accounts detail to:
    1. The person who authenticated and submitted the form
    2. The email address provided in the field: Requestor's Email Address (approved and denied notifications)
    3. The infrastructure team

If Account Creation is Unsuccessful

If the Azure AD account creation is unsuccessful then:

  1. Set the initialized variable at the beginning of the workflow to contain the contents of the email to be sent out
  2. Send a friendly email with the accounts detail to the person who authenticated and submitted the form and the email address provided in the field: Requestor's Email Address (approved and denied notifications)
  3. Send a failure email with the accounts detail to the the infrastructure team
  4. Terminate the job and set the status as failed so the logic app run will be label as failed rather than success so it is easier to troubleshoot

Denied Process

If the one of approvers has rejected the new account request then:

  1. Set the initialized variable at the beginning of the workflow to contain the contents of the email to be sent out
  2. Send a friendly email with the accounts detail to the person who authenticated and submitted the form and the email address provided in the field: Requestor's Email Address (approved and denied notifications)

Create the Logic App

Now that we gone through the flow of the Logic App at a high level and have the form to collect the user input created, proceed to create a new Logic App:

image

With the Logic App created, proceed to navigate to the Logic app designer:

image

Scroll down to the Templates section and create a Blank Logic App:

image

A new blank template will be discovered for steps to be configured:

image

Type in Microsoft Forms in the search field and click on When a new response is submitted:

image

image

Sign into the tenant to create a connection to Microsoft Forms:

image

Select Enter custom Value for the Form Id:

image

Paste in the form ID we copied previously:

C0f0hB4_iUiflasPUUMCT_1a5E1qzx9IgJMuQa0Fbb9UME5RSlhYWFNLODdDQ1lVUzhINlRVRzBNNiQlQCN0PWcu

Proceed to create a new step, type in Get response details Microsoft forms in the search field and select the action:

image

image

Paste in the previously copied form Id into the Form Id field and select List of response notifications Response ID for the Response ID field:

image

The next step is to create an Initialize variable step to create a variable that will store our HTML code so we can use it to generate a properly formatted email out to notify the recipient about the status of the account creation. Add a new step, search for Initialize variable and select it under Actions:

image

Provide the following for the variable:

Name: NotificationEmailBody
Type: String
Value: <Blank>

image

Proceed to create a new step, type in Send approval email in the search field and select the action:

image

Fill in email address for approval.

One of the differences between Send approval email and Send an email (V2) is that the Body will treat the content as HTML code so paste in the code that will generate an email with HTML content:

image

The email template I used for this notification was taken from Sandro Pereira’s blog post here: https://blog.sandro-pereira.com/2020/01/26/logic-apps-how-to-send-a-well-formatted-html-email-notification-with-office-365-outlook-connector/

I made some changes to it as I only needed the table for the report. The modified HTML code can be found at my following GitHub repo: https://github.com/terenceluk/Microsoft-365/blob/main/HTML/ApprovalEmail.html

Note that you will need to update the body with the parameters submitted in the form by using the Dynamic content:

image

The following is a sample of the approval email that will be sent to the approvers:

image

With the approval email step completed, we will now create a condition that will determine whether the request has been approved or rejected. Proceed to create a new step, select Built-in and type in condition in the search field and select the action:

image

On the Condition box, click inside the Choose a value box.

image

From the dynamic content list that appears, under Send approval email, select the SelectedOption property.

image

In the middle comparison box, select the is equal to operator.

On the condition's right side, in the Choose a value box, enter the text, Approve.

When you're done, the condition looks like this example:

image

With the condition configured, we’ll be configuring the flow where the account creation is approved so proceed to navigate to the True block, add an action, search for Create job, and select Create Job Automation Account:

image

Fill in the required fields:

Subscription: <Select the subscription containing the Automation Account>
Resource Group: <Manually enter Resource Group containing Automation Account>
Automation Account: <Select the Automation Account containing the Runbook>
Runbook name: <Select the Runbook with the PowerShell script that generates the password>
Wait for Job: Yes
Managed identity: System-assigned managed identity

image

At this point, we’ll need to configure the required permissions so that the Logic App requires to authenticate to execute the Automation Runbook. Open another browser tab so you do not lose the Logic App step configuration, navigate to the Identity blade and turn on System-assigned:

image

Next, navigate to the Automation Account, open the Access control (IAM) blade, click on Role assignments, click Add, Add role assignment:

image

Search for the Automation Operator role:

image

Select the Members tab, click on Managed identity and select the Logic App for the Azure AD user creation:

image

Successfully assigning the permissions will display the following in the IAM blade:

image

With the permissions assigned to the Logic App so it can successfully execute the runbook, we can now add a step to retrieve the generated password from the runbook. Proceed to create an action, search for Get job output and select Get job output Azure Automation:

image

Fill in the required fields:

Subscription: <Select the subscription containing the Automation Account>
Resource Group: <Manually enter Resource Group containing Automation Account>
Automation Account: <Select the Automation Account containing the Runbook>
Job ID: <Use the Dynamic content feature to add the Job ID>

image

Create a new step, type in Create user azure ad in the search field and select the action:

image

Sign in to create the connection to Azure AD, grant the permissions request for the Logic App:

image

The available attributes are available:

  • Account Enabled
  • Display Name
  • Mail Nickname
  • Password
  • User Principal Name
  • Given Name
  • Surname
image

The fields from the form should be available as dynamic content to use:

image

A few customizations that will need to be added to the fields are as follow:

Mail Nickname: To maintain consistency, I prefer to have this value all in lower case

Password: This is provided by the previously executed runbook but I’ve noticed that the output adds \r\n to the password which would cause this step to fail so we need to remove the undesired characters

User Principal Name: As with the Mail Nickname, I prefer to have this value all in lower case

With the above identified, we’ll be using expression functions (https://learn.microsoft.com/en-us/azure/logic-apps/workflow-definition-language-functions-reference) to adjust the values for these parameters. Switch over to the Code view for the Logic App:

image

Edit the lines as highlighted in the screenshot below:

image

Mail Nickname:
"mailNickname": "@{toLower(body('Get_response_details')?['r9b9abc58c2fb468181b916528b9b97ad'])}.@{toLower(body('Get_response_details')?['r17ea325b22b044c2ba26346a3e98c787'])}",

Password:
"password": "@{replace(body('Get_job_output'),'\r\n','')}"

User Principal Name:
"userPrincipalName": "@{toLower(body('Get_response_details')?['r9b9abc58c2fb468181b916528b9b97ad'])}.@{toLower(body('Get_response_details')?['r17ea325b22b044c2ba26346a3e98c787'])}@contoso.onmicrosoft.com"

With the adjustments made, this is what the step would look like:

image

The next step will now fork out to two different paths as the Create user step can succeed or fail and we want to handle both. To create these two different paths, add two Set variable steps and configure one to should run after as being is successful and the other as has timed out and has failed:

image

When the step succeeds, we want to set the variable that we defined earlier with the body of the email we’ll send out to confirm the account has created and when it fails, repeat the same but with different content.

image

The success email will include a username, the temporary password, and with a table containing the form submission data:

image

The next step will use the Send an email from a shared mailbox (V2) to send a confirmation to the desired recipients:

image

You may notice that the variable for the failed user creation is a bit different than the success as it does not include the welcome message and I intentionally did this because we will be sending two different emails (one user friendly and one for IT) where the first part of the email is different:

image

With the body configured, proceed to create the email notifications to be sent out to the user and the IT team:

image

The last step is to add a Terminate action to set the status as failed because we this is not done then the Logic App run history will state the process as being successful:

image

The last part of the Logic App is to handle the process when the approval is rejected. Proceed to use the Set variable action to create the body of the email:

image

Lastly, create an action to send a denied notification email to the desired recipients:

image

This has been a very long post but I hope this can provide start of how you can set up an automated process with approval to create Azure AD accounts. I can think of many other improvements I’ll be adding in for the future and a few of them include:

  1. Using Microsoft Purview Message Encryption to encrypt the email with the password by using a keyword trigger
  2. Using PowerShell cmdlets to set attributes not configuration with the Create AD User step
  3. Adding user to a group that assigns licenses

Hope this has been helpful.

2 comments:

Anonymous said...

This was very helpful and was trying to follow this guide but as soon as i approve a request, the workflow runs and stops at "Get job output" step and throwing errors saying code: 404, message: "The response is not in a JSON format". InnerError: Cannot read server response. Will be great for any guidance on how to resolve this.

Craig said...

Thanks so much Terence, a great in-depth guide, using this to automate the marking and approvals of Microsoft Forms Quizzes.