Updated: Nov 26, 2021
Automation is all about efficiency. The end goal is being able to eliminate repetitive tasks prone to human error, build standards and save costs. With the Power Platform or Logic Apps in Azure, you can build powerful low-code workflows, but if you want them to run fully on application permissions and not be attached to a user account... Then I'm afraid you have already been googling for quite some time before you found this post.
I will start with the background for my last completed automation mission where this was dealt with. The client is a large organization that is continuously growing in size, and with that comes more resources and people to manage. They decided to invest in the future: time saving and streamlining repetitive tasks. They wanted to grant and easily gain insight into who has access to what.
This client, as many others, outsource their IT division, meaning that it would be in their best interest to have an easy-to-maintain solution. I wanted to bring the action to the involved, and not make it necessary to log into the Azure portal and navigate around to find information about what is going on. Visibility, reusability, simplicity and security, was the mantra.
The quest began with dealing with the internal users' application access. We wanted a system where one would leverage Azure AD security groups to manage access rights, standardize and delegate responsibilities where possible and audit in an easy to use, but yet powerful database tool with role base access control.
Azure Functions is a serverless, code-first solution in Azure to help you require less code, infrastructure maintenance and expenses. A Function App can host multiple Azure Functions which are integrated with Logic Apps.
Azure Logic Apps is a designer-first cloud service that you use to define a workflow, and it performs the given sequence of actions, when the trigger gets fired, such as when a certain event occurs.
You can view and edit the JSON code directly or in the portal GUI, where you can see how each step gets executed, one step triggering the next. Each step describing what it does in an understandable manner, with the ability of adding additional comments. You can place multiple related actions inside scopes (brown blocks) for error handling and maintaining overview.
There are a great number of things one can achieve without being a developer. For personal or team-based use within an organization, tools such as Power Automate which is a logic app residing outside of Azure, is a magnificent tool. Do your employees require approvals for different decisions, creating a productivity bottle neck? Do you want to be notified about certain events? Power Automate has what you need. Add some development skills and the opportunities are endless. We can help you roll out a customized solution using ARM templates, Bicep or Terraform. You choose. As consultants building a solution that could be leveraged org. wide and not just small scale, we made some calls regarding security and ALM as Flow has some limitations we had to address. One can argue, but in our opinion it was a matter of simplicity vs sustainability.
The vast majority of the connectors that perform the actions we needed, had to be connected to a user account. In Power Automate, this is even more challenging, as the flow can have multiple owners, but needs to be recreated, imported or sent as a copy (non-solution aware), to change “creator”, giving it certain rights. Such as assigning other owners. If a Power Automate flow is not shared and the owner leaves the firm, the flow becomes a ghost. The connections I mentioned, in both Logic Apps and Power Automate break upon password change.
MFA is not supposed to break connections, according to Microsoft, but for several power community users, it has broken connections. The connectors could only use the delegated permissions and if your organization uses PIM, the user would need to activate his or her role, in order for the flow to get the right authorization. Some organizations use a service account for this purpose. We decided that this was not good enough. What other options exist?
First of all: Not all actions or connectors prompt you into signing in with a user account. For instance, the Sendgrid communication platform, illustrated in the flow picture above, is a connector a that accepts an API key instead of user credentials.
There are a number of connectors that support managed identity and Service Principals. Unfortunately, the list is short. Microsoft Teams had it in preview for a while, but then removed it again.
Flow has premium connectors that make HTTP requests, leverage key vault, secure in- and outputs, but your flows will lose quite a bit of simplicity when you have to make multiple HTTP requests in each Logic App to first get an access token and then perform actions. The logic apps tend to grow huge.
Do some research and you will be persuaded that creating a custom connector is the way to go. Fine. Create a custom connector to perform your actions. This is basically an API wrapper, where you upon creation, set up either Oauth 2.0, basic or API key authentication, so it then seems that you have solved the problem with the user account dependency. However, the custom connector will, in November 2021, default to submitting calls “on behalf of user” as a Delegated API permissions call. This defaulting intellisense can be edited in the swagger editor, to "Application", but that runs into the problem that the Custom Connector doesn't provide anywhere to specify a Refresh URL or method through which you can either set or update the initial access token itself. I even experienced that the custom connector changed the value back to “accessCode”, after saving it.
We decided to build a network of Logic Apps to work as a framework for orchestrating workflows and call Azure Functions to perform the API calls that require authentication. This allowed us to leverage system based managed identity.
See Anders Julton's post about this topic here. The code blocks within Azure Functions could then be neatly stored in the backend, while the end user viewing the Logic App could focus on the results that the functions return.
The Logic Apps would trigger the functions as many times as needed, receive and make decisions based on the different status codes and responses. If an unwanted error occurred, the flow would call a dedicated "error notification child flow" that could receive calls from any parent flow.
This flow would post a Message Card to a teams channel with dynamic information and Flow Run URI and Id to view/resubmit the incident in the portal.
If you set up an incoming webhook to a Teams channel, you get a URI to post message cards to that don't require authentication. Therefore, this address should be treated as a secret .
The end user would not have to log into the portal to check, without such provocation. To view who had received access and to what, one would only have to do a look-up in the Sharepoint List.
The process initiating the flow could be run from anywhere the client would set it up, and we can control the endpoints that are allowed to call the initial Logic App. This all meant that we could now run flows performing actions involving Sharepoint, Microsoft Forms and Azure AD, through the Graph API.
We could do all this without a user account or delegated permissions, leveraging Managed Identity and a Sendgrid API key, through the combination of Logic Apps and Azure Functions.
If anyone stumbles across a different solution or the situation changes, please be in touch! I wish to simplify and empower my clients as much as possible. I am not worried to run out of tasks to automate. Also feel free if you'd like to have a conversation about which of your business processes I or we as a team could set up for you.
Thanks for reading!