Add multi-geo capabilities to Orchestry using a webhook and an Azure Automation Runbook

#Powershell #Azure #Teams

A company I'm working with is located in multiple countries and has added Multi-Geo licenses for Microsoft 365. Recently, we rolled out Orchestry to streamline requests and approvals for creating new Teams on behalf of staff.

Currently, one of the shortcomings of Orchestry is the lack of support for Microsoft's multi-geo capabilities. If you have a tenant spanning more than one location, you will need to manually move Teams that were provisioned in Orchestry after they've been created. The lack of multi-geo support is not great—a SharePoint Administrator is required to run PowerShell commands to manually move the site to bring it under compliance with any GDPR or other data governance requirements.

This post will detail the steps for a workflow that allows you to provision Teams in Orchestry and have them automatically moved to the correct location using a webhook and an Azure Automation Runbook.

Before starting, you will need an account with the following roles:

Let's begin by creating some checkboxes in the Teams request form in Orchestry that will allow users to indicate whether the Team should be in a different geo location.

First, log in to Teams and open the Orchestry app.

Navigate to the Orchestry Management tab, then navigate to Workspaces > Metadata:

Click the “New Metadata” button at the top right.

For this example, I'm going to add a simple checkbox for Yes/No to indicate if the Team is intended to be in the secondary geo location.

Use the following options for your metadata, then click the “Save” button:

Now that the field is ready, you will need to add it into the Teams request form template.

Inside the Orchestry Management tab, navigate to Workspaces > Templates:

Create a new template or edit an existing one. I'm going to create a “Test” template for this example. Before exiting the template, navigate to the “Configuration” tab. We need to tell Orchestry to add the metadata field to the template.

I've checked Subset of Enabled Metadata and selected my Test Metadata field:

Now, we need to create the Azure Automation Runbook and prep it so that it's ready to ingest a webhook from Orchestry.

Open a new browser tab, log in to the Azure dashboard, and create a Resource Group and an Automation Account.

Once it's finished provisioning, we are ready to add a runbook (script) to the Automation Account so that Azure can run it when requested.

Navigate to the Automation Account and open the “Runbooks” blade. Click the “Create a runbook” button:

In the wizard, select the following options:

Once created, we need to add the code that will run when a webhook is triggered. Once provisioned, Orchestry will send some data to the webhook URL that the Runbook will ingest to perform the move.

Navigate back to the Azure dashboard and open the “Runbooks” blade again on your Automation Account. Select the runbook you just created and select Edit > Edit in portal:

Paste in the following code, changing the XXDOMAINXX to your tenant name in the Connect-SPOService command.

    [Parameter(Mandatory = $false)]
    [object] $WebhookData

$jsonString = $WebhookData.RequestBody -replace '^"|"$'
$data = ConvertFrom-Json $jsonString

Import-Module -Name Microsoft.Online.SharePoint.PowerShell -DisableNameChecking -Force
Import-Module Orchestrator.AssetManagement.Cmdlets -ErrorAction SilentlyContinue
$StoredCredential = Get-AutomationPSCredential -Name 'OrchestryServiceAccount'
$userName = $StoredCredential.UserName
$password = $StoredCredential.Password
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $userName, $password
$connection = Connect-SPOService -Url '' -Credential $cred

foreach ($item in $data.RequestCustomMetadata) {
    if (($item.Name -eq 'XXXWill this workspace contain data for an EU based customerXXX' -and $item.Values -eq 'Yes') -or ($item.Name -eq 'XXXFor People Ops workspaces- will this team contain data for EU based employeesXXX' -and $item.Values -eq 'Yes')) {
        Write-Output "Site marked as multi-geo: $($data.URL)"
        $group = $data.URL -replace '', ''
        Set-SPOUnifiedGroup -GroupAlias $group -PreferredDataLocation 'DEU' 
        $status = Start-SPOUnifiedGroupMove -GroupAlias $group -DestinationDataLocation 'DEU'
if ($status) {
    Write-Output "Site move started with MoveJobId: $($status.MoveJobId) "
else {
    Write-Output "Site $($data.URL) is not being moved to DEU datacenters"

Note the lines: ($item.Name -eq 'XXXWill this workspace contain data for an EU based customerXXX' -and $item.Values -eq 'Yes') and ($item.Name -eq 'XXXFor People Ops workspaces- will this team contain data for EU based employeesXXX' -and $item.Values -eq 'Yes')

Be sure to change this $item.Name field to the exact wording of your custom metadata field in Orchestry:

Once you add the code, click “Save” and then “Publish”.

Now, we need to add the SharePoint Online PowerShell module to the Automation Account so that the Runbook can run the Start-SPOSiteContentMove command.

Navigate back to the Azure dashboard and open the “Modules” blade on your Automation Account. Click the “Browse Gallery” button and search for “SharePoint Online”. Select the “SharePoint Online Management Shell” module.

In the “Add a module” wizard, click “Select” to move to the next step. Set Runtime Version to 5.1 and click the “Import” button:

Now that we have the code and modules added, we need to add the Webhook object.

Navigate back to the Automation Account and click on the “Webhook” blade. Click the “Add webhook” button.

Click the “Create new webhook” button:

In the wizard, add a name and set an expiration date for the webhook. Be sure to copy the webhook URL to the clipboard before clicking the “Create” button, as it will disappear after you close the wizard:

Now, navigate back to the Orchestry Management tab, open the template, and navigate to Workspaces > Integrations. Paste the webhook URL into the “Webhook URL” field and click the “Save” button at the top right:

Now that the code and packages have been added, you will need to create a Service Account and grant permissions so that it can make changes in your Sharepoint tenant.

Create a regular user in Azure AD/Entra ID by navigating to Users > New User > Create new user. Make sure to note the username and password for the next step:

Add the role of “SharePoint Administrator” under the “Assigned roles” blade:

Note: Be sure to exclude this account from any Conditional Access policies that may block it from logging in like a block on MFA and Legacy Authentication.

After you've granted permissions, navigate back to the Automation Account and open the “Credentials” blade. Click “Add a credential” and paste in the username and password for the service account you just created:

Now, you're ready for testing.

Open the Orchestry app again from Teams and navigate to the “Request” tab. Select the template that you created or edited earlier, fill out some basic information, then check the box on your Test Metadata field:

After creation, your site will begin moving behind the scenes.

You can check on the status and outputs of the Runbook by navigating to the Runbook within your Automation Account and opening the “Jobs” blade:

You can check the progress of the move with the following PowerShell commands, just change the XXXDOMAINXXX and XXXTEST TEAMXXX values to match your tenant and Team name:

Import-module Microsoft.Online.SharePoint.PowerShell
Connect-SPOService -Url ''

Get-SPOUnifiedGroupMoveState -GroupAlias 'XXXTEST TEAMXXX'

As a side note, Microsoft doesn't have a full answer on how long it takes to move a Team or Sharepoint site between geographies. A rep on a recent MS Partner call says that most moves are completed within 24 hours. You can expect to see your new Team/SharePoint site appear in the new location with a new tenant name (e.g. and Users can still access the Team/SharePoint site using the original URL and will be redirected to the new location.

Another side note, the Orchestry webhook only fires after the Team has been created. This makes the runbook compatible with any approval workflows you may have setup within Orchestry, since it does not trigger until all of the necessary parts are done first.

If this workflow completed successfully, you can now provision Teams in Orchestry and automate the move to the correct geo-location. Hopefully, Orchestry will implement this functionality natively in the future, but for now this workaround should do the trick.