Azure Functions: Managed Identity, Microsoft Graph, and Roles to Read Security Events

It may be necessary to automate processing of Security Alerts from Microsoft Graph through an Azure Function. In order to do this, the Azure Function needs to have the role permissions to read Security Events in Microsoft Graph.

To accomplish this, you’ll need to create a Managed Identity for the Azure Function. Once that has been created, we’ll use PowerShell to assign the permissions to that Managed Identity in Azure.

$msi = Get-AzureADServicePrincipal -ObjectId <Managed Identity GUID>
$graph = Get-AzureADServicePrincipal -Filter “AppId eq ‘00000003-0000-0000-c000-000000000000′”
$role = $graph.AppRoles | Where{$_.Value -eq “SecurityEvents.Read.All”}
New-AzureADServiceAppRoleAssignment -ObjectId $msi.ObjectId -PrincipalId $msi.ObjectId -Id $role.Id -ResourceId $graph.ObjectId

Now that the permission has been assigned, your Azure Function should be able to read the Security Events from Microsoft Graph. This is because the AzureServiceTokenProvider automatically leverages the managed identity when you use it to obtain an Access Token for Microsoft Graph.

Happy dev’ing!

Azure: Enabling Function Apps to Access Microsoft Graph

With Azure Functions, it’s even easier to code to Azure; however, with such portability comes a little bit of pain to the growing processes. It used to be (and still is, frankly) that you had to register a full-blown application in Azure Active Directory to grant your application read access to other resources, such as Microsoft Graph. However, with these new features, we can bypass a lot of the old-school red-tape to get what we need to do up and running.

The first thing that you’ll want to do in your Azure Function App is to enable it’s Managed Identity. Keep in mind that all of the functions within your Azure Function App resource will have this shared managed identity, so this could present security implications, as you roll-out more functions in a shared space.

In the Azure Portal, go your Azure Function App, pick the specific Function App in question, go to Platform Features, select Identity, and then – under System assigned – toggle the Status to On. Save it. Wait for the execution to complete and then Refresh the page. Save the ObjectId, as we’ll be using that to grant our Functions within the Function App access to the Microsoft Graph.


Now that we have a service principal (via managed identity), we need to grant it permissions to the Graph Application, itself, at the tenant level.

Unfortunately, we can’t – at present – do this via the Azure Portal, so to do so, we’ll need to use the Azure Active Directory PowerShell Snap-In and we need to decide which permissions that we want to grant to our Azure Function App.

Connect as you normally would in your tenant and then run the following commands, replacing the redacted object id value with the one that you copied from the portal in the steps above and changing the target role value to be whichever roles in Graph that you want to assign (remember: this is at the Function App level and not individualised for specific functions within the Function App). In this case, I’m after reading the Security Alerts from Microsoft Graph, so this is the only role that I’ll be targeting. YMMV.

$objectId = [REDACTED]
$graph = Get-AzureADServicePrincipal -Filter “AppId eq ‘00000003-0000-0000-c000-000000000000′”
$targetRole = $graph.AppRoles | Where{$_.Value -like “*SecurityEvents.Read.All*”}
$msp = Get-AzureADServicePrincipal -ObjectId $objectId
New-AzureADServiceAppRoleAssignment -Id $targetRole.Id -PrincipalId $msp.ObjectId -ObjectId $msp.ObjectId -ResourceId $graph.ObjectId

If all goes according to plan, then you should see output similar to the below.

ObjectId ResourceDisplayName PrincipalDisplayName
——– ——————- ——————–
ibpZvR05qk2N7TMPftyjXxh14LgZiq1Fo41w-kdjaYA Microsoft Graph [REDACTED]

Now, you can leverage Microsoft Graph in the Functions contained within your Azure Function App for whichever permission[s] that you just granted the Azure Functions App.

Happy dev’ing! 🙂