Categories
Azure Logic Apps

The Backup Safeguard

One of my customers is using AvePoint Cloud Backup to backup all his Teams in Microsoft365.

The tool has been implemented months ago by another supplier and I have now been asked to take a look into the backup job logs, since most of the Teams backups keep failing.

The error message in the logs was always the same:

"TeamXYZ" does not have any members or owners. AvePoint Cloud Backup does not protect Groups or Teams with no owners or members.

While doing some research I quickly came across the fact, that the service account (which is used by AvePoint Cloud Backup) needs to be an Owner of the Team, otherwise the backup of this Team will fail.

To double-check this, I’ve added the service account to one Team and checked the logs again afterwards: the backup was now successful for this Team.

Now we needed a way to add this service account to all existing Teams (300+) in his tenant.

Furthermore, we also needed a solution which makes sure, the backup account will be re-added to the Teams if someone mistakenly removes the account.

This is where the cloud magic comes in: Azure Logic Apps!

In this post I will share some insights on how to create a Logic App in Azure which loops through all existing Teams in a tenant and adds a specified user account as Owner to each Team.

Preliminaries:

  • Microsoft 365 Tenant
  • Azure Subscription
  • Global Administrator account

Implementation:

Go to https://portal.azure.com and search for “Logic Apps” via the search bar.

From there you can create a new Logic App via the “Add” button.

You may need to create a new Resource Group, or use an existing one and also need to provide a name and location for your Logic App.

After hitting the “Review + Create” button, your deployment to Azure should start immediately.

After the deployment was successful, you can go to the new resource either via the “Go to Resource” button, or by navigating to Logic Apps via the blades on the left side.

Now, we can start to put some logic in our Logic App. Just open the Logic App designer from the Development Tools blade on the left.

First of all, we need to create a trigger. In my case, the recurrence trigger is already sufficient, since the customer just wants this Logic App to run periodically.

We then need to create the actions this trigger will call. The first thing we need is an actual list of all Teams in the tenant. We will accomplish this via Graph API.

I’ve used the following query to get a list of all Teams IDs:

https://graph.microsoft.com/beta/groups?$select=id&$filter=resourceProvisioningOptions/Any(x:x eq 'Team')

Unfortunately, the HTTP action in Logic App doesn’t like this URI because of the special characters in it, so we need to tweak around this by initializing a variable before.

Then we can use this variable in our URI in the HTTP connector.

The Logic App should look like this now.

We now need to provide an authentication method for our HTTP connector against the Graph API.

Therefore, hit “Add new parameter” and select the “Authentication” checkbox.

The connector will provide you now some authentication types. Here we need to select “Active Directory OAuth”.

To authenticate with Active Diretory OAuth, we need to perform an App Registration in our tenant and add the appropriate permissions to use the Graph API.

Open a new tab in your browser and navigate to https://aad.portal.azure.com, there you can register a new Application via “App Registrations” in your tenant.

After successful registering the new Application, we need to grant the API permissions. Therefore just open the Application, jump to “API permissions” and grant the permission to read all groups.

To do so, hit “Add a permission” and select “Microsoft Graph”.

Here you can now grant the necessary permission.

Don’t forget to grant admin consent, after adding the permission. The status column should show you a green checkmark.

Now we need to create a Client Secret, which we can use in our HTTP connector. To create one, click the “Certificate & Secrets” blade and hit “+ New client secret”. Please note down the value immediately, since it can’t be retrieved from here again, after leaving the page.

The last thing we now need is the Application (client) ID of the application, which can be found via “Overview”.

That’s all. Now we can switch back to our Logic App Designer.

Since we don’t want to store our credentials in plain-text within the code, we will use parameters here.

I have defined the following parameters in this logic app:

  • Audience as String: just enter the URI-reference here, in our case its https://graph.microsoft.com
  • Backupuser AAD ID as String: the AAD object ID of the service account we want to add to each Team
  • Application/Client ID as String: the Application ID of our newly registered App
  • Client Secret as Secure String: the Client Secret of our newly registered App

Provide those details now in each Parameter value field and save your Logic App.

Now we can use those parameters in our HTTP connector.

Re-cap: until now, we have created a Logic App which is triggered every hour. We do have initialized a variable which contains our filter clause and use this variable in our HTTP connector against the Graph API.

If everything has been set up correct, our Graph API call will return a JSON contain the Group IDs of all Teams in our tenant.

The returned JSON should now look like this:

{
    "@odata.context": "https://graph.microsoft.com/beta/$metadata#groups(id)",
    "value": [
        {
            "id": "3b54d34b-544e-4a48-8bc4-b41d3193760f"
        },
        {
            "id": "5daf9b2a-48c1-484a-8e06-ae370c36ee45"
        },
        {
            "id": "4a642e25-3bb5-4e96-8e4b-4e3a6c7af1a6"
        },
        {
            "id": "01a8ceee-9c27-4e32-b319-59a254d0f25d"
        },
        {
            "id": "14a9b470-6683-4f48-b94f-36ee55c54bdd"
        },
        {
            "id": "8bce3e51-3398-4a43-b645-c65a2268e190"
        }
    ]
}

We can extract the IDs and parse them into variable by using the “Parse JSON” item.

The content here is the “Body” of your HTTP response. To create a proper schema, just the schema generator provided below and upload the sample payload as provided above.

Since we can now use all the retrieved Group IDs, we have to loop through them with the “For each” item. Just add the item and put in the “value” output from the “Parse JSON” item. Then create a new action within the “For each” item and use the “Add a member to team” item from the Teams connector.

Here we just need to use the “ID” values as input value for “Team” and use our “Backupser AAD ID” parameter in this connector. I’m my case, I also had to add the option, to add the member as “Owner” to the each Teams.

You can now run the Logic App in the designer and check the result.

For testing the Logic App, you can now create a new Team with some random user as Team Owner, trigger the Logic App manually (or wait for one hour) and see if the expected user account has been added to this team as Owner as well.

If you have any questions or feedback about this implementation, feel free to comment this post or get in touch with me via my contact details.

That’s it for today and thanks for reading!