Monday 6 August 2018

Sync Azure AD profile properties to SharePoint User Profiles using Azure Durable Functions

Recently, a client had asked us to synchronise user properties from their Azure AD profile to custom properties in their SharePoint UserProfile. This had to be a scheduled process as the data had to be kept up to date as well as it had to cater for any new profiles created in Azure AD/SharePoint.

We decided to use Azure Functions for this given the ease of configuring a timer triggered function (to run on schedule) and also the fact that functions run on a consumption based billing plan. This means that the client would get charged only for when the function executes (oh and also, the first million executions are free every month)

The main challenge we had to overcome was the limitation that an Azure Function has a default timeout of 5 minutes (which can be increased up to 10 minutes at the time of this writing) This means that if we were using a single Azure Function to update SharePoint UserProfile Properties for thousands of users, we were going to hit the timeout sooner or later. 

Fortunately, Durable Functions went GA recently which means that we have a way of managing state in the traditionally "state-less" Azure Functions. With durable functions, we can create an "activity" function to update the SharePoint User Profile properties for a single user. This function can be called in a loop for each user from an "orchestrator" function. Each run of the activity function is treated as a single execution and can be finished in the 5 minute default timeout.

So let's see how this can be done! We are using precompiled C# functions and Visual Studio 2017 to achieve this. Also make sure to have the Durable Functions nuget package installed in your Azure Functions project:
https://www.nuget.org/packages/Microsoft.Azure.WebJobs.Extensions.DurableTask/

The Durable Function workflow can be categorised into three different types of functions:


1) Client Function


These are standard Azure Functions which can be triggered by external events like timers, HTTP requests, queues etc. The only difference being they have an OrchestrationClient binding which is required to start orchestrations.

In our case, the Client Function is a simple timer triggered function which uses the OrchestrationClient to start a new Orchestration Function with the name O_SyncProfileProperties


2) Orchestrator Function


As the name suggests, the Orchestrator function acts as a coordinator of the Durable Functions workflow. It does the job of starting, stopping and waiting for activity functions and is also in charge of passing data (or state) in between them.

In our case, it calls the A_GetUsersToSync activity function to get the user profiles from Azure AD (using the Microsoft Graph API which is out of scope for this article) and then loops through the users to call the A_UpdateSharePointProfile function for each user


3) Activity Functions


As you might have guessed by now the Activity function is the one which actually does all the heavy lifting. For example, the actual CSOM code which will update the SharePoint UserProfile properties will live in the A_UpdateSharePointProfile activity function:

And that's it! In 3 simple steps, we have a Durable Functions Orchestration set up. For more information on Durable Functions including dos and don'ts, please see the documentation: https://docs.microsoft.com/en-us/azure/azure-functions/durable-functions-overview

Hope you found this post useful!

2 comments:

Veeralaxminarayana Induvasi said...

Good one!

Unknown said...

Great post! It actually shed some light to the project I'm developing :)
I'm trying to achieve something similar with Azure Durable Functions and Microsoft Graph, but I'm quite lost in how to create an activity that contains a Microsoft Graph call. I know it's not part of the scope of this article, but could you please give me some recommendations?
I know the common way to create an AF calling MS Graph API is by using an httpTrigger function type but since we are talking about Durable Functions, the functions we want to execute should be activityTrigger type.
In this case how should I call the Graph API endpoint inside the run.csx file?