Using PowerApps to streamline Support Agent common tasks
Before starting, the purpose with this article is that you hopefully can get some ideas of how to automate some common tasks and how we have implemented it
Introduction
Daniel Wellington is a Swedish brand founded in 2011. Since its inception, it has sold over 11 million watches and established itself as one of the fastest growing and most beloved brands in the watch industry.
Most people know how influencer marketing helped us become a global company, but what many don’t know is how our use of technology made that possible.
The first system we developed enabled us to reach influencers across the globe at scale. Then, we created our own e-commerce platform to be able to speak to our customers the way we wanted, and we built a complex ecosystem with B2B, B2C, and marketing channels working together.
We develop our services and applications on the AWS cloud platform and make extensive use of all of its amazing serverless features, neatly matched with microservice based architectures.
Our design principle is serverless first. If serverless is not available or practical, containers are recommended, EC2 is legacy. JavaScript, PHP, and Go are some of our languages of choice.
As a global tech-company that has disrupted an entire industry, we are constantly learning and finding our own way of doing business. Our latest venture is to try and removing rdp and streamline our support agents experiences using PowerApps / PowerAutomate.
My own role in the company is Cloud Operations / System Administrator where I and my colleagues have a few different workloads such as
- AWS workloads
- Infrastructure for our ERP systems (Dynamics NAV / Business Central)
- Our On-premise AD / Azure AD
- ADFS
- Windows workloads
- Automations and security features in O365 / Azure
Regarding MFA and the former Global Admin requirement
For quite some time our company has been on the verge of requiring MFA for all of our “Office 365” users. However with a roll out of that magnitude, 2k+ users, there are some problems that becomes blockers. The biggest for us?
The requirement of a Global Admin role to enable, disable and reset MFA
Now you might have been following various user voices on this subject like these
(In the plans)
https://office365.uservoice.com/forums/273493-office-365-admin/suggestions/17429305-delegate-permissions-for-managing-mfa
However if your main objective with reading this article is to find a solution to that, I can tell you right now that there are indeed two roles for this purpose which we will be using.
Authentication Admin
Priviliged Authentication Admin
The former allows password resets and more but can’t handle authentication for Global Admins
The latter can’t reset passwords but can reset and handle multifactor authentication even for Global Admins
So by assigning these roles (directly or through PIM) you should be good to go
Why did we decide to go with PowerApps / Power Automate?
Simply because it gives us means to gather various common tasks in one place. Our support Agents are managing multiple systems. We can connect the app both to our “on-prem” solutions in AWS by using On-Premise Data Gateway connector but also to Azure. I will touch on the On-prem connectors in the end of this article
We have looked into Windows Admin Center (WAC) which was promising but didn’t quite deliver what we needed
We used to (well we still do to many things) use bot commands to send various request from Microsoft teams into AWS. But as the requests became more complex so did the commands which increased user error rates.
Also in the beginning of the COVID19 outbreak, our bot stopped being able to respond through the bot framework API back to teams (note this has been fixed though). The functions worked but it was hard for the agents to understand if things worked or not. It increased the demand for another management type.
So the first thing we actually did was migrating our On-Prem MFA reset to Power Apps. But as I said, more on that later.
It was time to create a possibility to manage MFA using Power Apps.
All things I will write about here can be found around the internet to some extent. It may not be exactly this which is why I will summerize how we do it and what sources I have found that should be credited
Let’s get started!
Manage O365 / Azure MFA Using Automations, Power Automate and PowerApps
There is an excellent guide (allthough a little outdated) that I had as a guide when starting to look into this
https://ezcloudinfo.com/2019/02/01/delegate-resetting-azure-mfa-for-helpdesk-through-azure-automation-run-book-and-microsoft-flow/
End-Flow, sort of:
Prequisities:
- You need to create a new Automations Accounts in the Azure portal. For this you need a Azure Subscription. When Setting this up you will need to have rights to set-up Azure Run As accounts which means you will need to be App Administrator. You will also need Owner or Contributor on the Resource group
https://docs.microsoft.com/sv-se/azure/automation/manage-runas-account
It may be required to be Global Admin at some point - You need to create an account that has Priviliged Auth Admin and/or Authentication Admin
Create the Azure Automation Account
First of all, coming from AWS I would compare Automation Accounts to Systems Manager. It may not be a complete 1 to 1 but they share a lot of features
- Go to https://portal.azure.com and choose Automation Accounts
- Choose Add
- Enter the information
Name: This is the Name of the Automation Account
Subscription: What subscription in Azure you are using
Resource Group: Either choose one or create a new
Location: Location of the Automation account
Make sure to activatie Create Azure Run As Account
- Add Msol Module to the Automation Accounts (using second link you can deploy it straight from gallery)
https://docs.microsoft.com/sv-se/azure/automation/shared-resources/modules
https://www.powershellgallery.com/packages/MSOnline/1.1.183.57 - Add Credentials to the Automation Account for the user with Priviliged Auth Admin rights under shared resources
- Create a new runbook with Powershell as type
- Now you can do this in various way. Either you split it into multiple runbooks, or you create a bigger one with split functions. I’ll leave that up to you. Here is an example of a PS script to “Reset-MFA” for a user
- You can ofcourse use this to Disable or Enable MFA for users or get status etc.
- In order for the Support Agent to be able to run the job, the agent should atleast have the Automation Job Operator Role in the Authentication Account. You can changes this in the Access control (IAM)
Some things to consider before moving on
At the moment you can, with the Run As Account, connect to your subscription. It would have been awesome to add possibility to use this to connect to msol and reset that way but it just isn’t
You are left with an account without MFA to run the command. Now what you could / should do is atleast put in some credential swapping. You can do this within the automation account on a schedule
I looked at this when setting it up
https://www.itprotoday.com/iaaspaas/handling-passwords-azure-automation-service-accounts
Here is the script we ended up with which runs on a weekly schedule
Likewise you should look into cert renewal for the Automation Run As Account
PowerAutomate and PowerApps
Ok so now that we have set up the automation account and applied proper permissions, let’s head over to Power Automate and PowerApps
In order to get all the outputs we need atleast three flows
- A flow to invoke/create the Automation Jobs
- A flow to get the status of the Automation Job
- A flow to get the output of a Automation Job
I say atleast because it depends on how you construct your runbooks. If you have one runbook for all functions you are interested in, you are fine with three. Otherwise you will need additional flows for each function runbook (status and output can be the same).
Why do we need seperate flows for status and output you might ask. Flow supports waiting for Job to finish!
The way Automation job works is that if you trigger a job, that job will end up in an Automation Que. It can sit there for quite some time before starting. This means that the response to PowerApps may time-out before the command is executed / completed
To avoid request timeouts, we can use a timer inside powerapps and poll job status / job output (Asynchronus request) with a timer
If you are not using Powerapps then you could use Wait for job to finish.
Credit where credit is due. I looked at this great guide when looking into Asynchronus request and it’s almost identical to what we will be using below
https://www.lieben.nu/liebensraum/2019/11/using-runbooks-interactively-in-powerapps/
- Create a new flow in Power Automate. You can use Instant from Blank option
- Give it a Name and choose Power App as trigger
- Add a new step and Choose Create Job (Azure Automation)
- Input the information needed such as subscription, resource group, automation account, runbook name and choose wait for job — no
Add parameters as values with Ask in PowerApps
- Finally add a Respond to PowerApps (In this case we only respond with JobId)
- The flows for Status and Output are very similiar but instead of runbook with parameters you input the jobid which will be requested in PowerApps
Now that we have our flows, let’s head over to PowerApps
You can build your app from a template style like for mobile or set-up dimensions yourself. Whatever meets your preferences.
For this example. You will need the following items
- An input field (for user email to manage)
- Button(s) to trigger request(s)
- A Status label
- A timer
- An output “label”
To give you an idea, this is what ours currently look like (not really DW UX approved yet :) )
So as for what the different elements do then
On screen visible we reset some contexts
UpdateContext({UserEmailReset: true}); ← ResetEmailTextBox when swapping between screens
UpdateContext({UserEmailReset: false});
UpdateContext({mgmtType: true}); ← Reset Management selector dropdown
UpdateContext({mgmtType: false});
Set(runbookOutput,Blank()); ← Reset Output variable
Set(runbookJobId,Blank()); ← Reset Jobid variable
Set(runbookActive,false); ← Set Runbookactive to false
Set(runbookResult,Blank()) ← Reset Results
The button(s) has a visible validation which checks if the input is an email format or not. Like this
If(IsMatch(NameofEmailTextBox.Text,Match.Email),true,false)
The OnSelect for the buttons looks like this
Set(runbookResult,Blank());
Set(runbookOutput,Blank());
Set(runbookJobId,Blank());
Set(runbookActive,true);
Set(runbookJobId,NameOfPowerAppFlowCreateJob.Run(NameofEmailTextBox.Text,User().Email).jobid); ← Creating job and saving the jobid
UpdateContext({StartTimer:true}) ← Starts timer
The Status label has the following text (Gives user some feedback on what is happening)
If(IsBlank(runbookResult) && runbookActive = false,”Status”,If(runbookActive,”Please wait for request to complete…”,runbookResult))
The timer has the following OnTimerStart (Try to fetch Job Output)
If(runbookActive && Len(runbookJobId) > 5,Set(runbookOutput,NameOfPowerAppFlowGetJobOutput.Run(runbookJobId).joboutput))
It has the following OnTimerEnd (Fetching job status if it’s ongoing etc)
If(runbookActive && Len(runbookJobId) > 5,Set(runbookResult,NameOfPowerAppFlowGetJobStatus.Run(runbookJobId).jobstatus));If(runbookResult = “Completed” Or runbookResult = “Suspended” Or runbookResult = “Stopped”,Set(runbookActive,false))
The Output label simply references the runbookOutput
And that is it for the PowerApp. Now all you need to do is adding users that are allowed to use the app. Do note that they need the Job Operator role as previously explained
In our case we have it as an additional Tab within Teams aswell for quicker access.
Manage On-Prem resources in AWS using On-Prem Data Gateway, ALB, Lambda, SSM etc
In the beginning of this article, I mentioned that we are also using the management app to manage some “On-Prem” AD stuff like our On-Prem Azure MFA server and management of our different Navision instances and our AD users ofcourse.
We learned that we could use On-Prem Data Gateway to trigger internal ALBs (Application Load Balancer) in AWS while testing some Automations for our Navision instances. Because of this we can attach a lambda function to that ALB that handles all the inputs and responds to the app.
As you will see below we use SSM to do the remote powershell sessions in AWS side.
Overview “On-Premise” flow
Going forward
There is always good to have some improvements to think of looking ahead. Somethings I/we would want to solve are
- The account used for resets. Even though we are swapping passwords, the best thing would be to be able to use an account temporary or adding an MFA element to the request to protect it. AFAIK it is not supported in Graph either and is even more limited.
It might work with an application password but I have not found any command that allows passing that parameter in any connection string - On prem we can require MFA for requests, it would be nice to be able to do that through graph etc. Perhaps some PS coder out there knows how to do this in Azure
- All our code is in CloudFormation in AWS, It would be nice to do the same in Azure Resource Templates (ARM) if possible but I do not know that much about it at the time of writing this