One-Click Recovery for Compromised M365 Tenant : Get your M365 tenant Back in no Time

If a hacker manages to compromise a global admin account, the first thing he’ll do is block sign-in for all the other global admins, including the break glass account. This will make it almost impossible to recover the tenant (you’ll have to go through Microsoft, and that will take a lot of time).

In this article, we’ll look at how to recover the M365 tenant by creating a break glass account after the tenant has been compromised. we’ll discuss how to use Azure automation and PowerShell for easy one-click recovery of your tenant in case it’s compromised.

The idea is to create an Azure Automation Account, then create a Runbook with a PowerShell script to create a Global Administrator account, then generate a Webhook with a unique WEB link. Once the tenant has been compromised, simply send HTTP request through PowerShell command that will Create the Break Glass Account on the spot and allow you to retrieve your tenant instantly.

I’ve already explained in my previous article (👉 (1) Microsoft Azure automation — Runbooks & Webhooks : A Technical Guide | LinkedIn) how to do the daily housekeeping of the resources deployed in your Azure test tenant to avoid oversights and unpleasant billing surprises, and I’m going to continue in azure automation today with Runbooks and Webhooks to show you how to recover a compromised tenant in a single click.


At the end of this article, you will get one HTTPS link with Global Admin Login/Password , you should store them securely to be able to use them in case your tenant is compromised. (In my case, I’m thinking about using USB flash drive or external Password Keeper)


I – What is Break Glass Account and Why is it essential ?

A “Break Glass” account (or emergency account) in Azure is an administrative account with elevated privileges, designed to be used only in an emergency or when all other means of access have failed, particularly due to a large-scale account compromise.

Why is it essential ?

  • Last resort : If all other administrative accounts have been locked out, the “Break Glass” account can be used to regain control of the Azure environment and take corrective action.
  • Privilege separation : By isolating this account from the rest of the administrative accounts, you limit the risk of compromise and reduce the attack surface.
  • Strict access control : By imposing strict access rules on this account (mandatory multi-factor authentication, geographical access restrictions, etc.), you ensure that it can only be used by authorized persons and in exceptional circumstances.
  • Audit : All activities linked to this account must be rigorously audited in order to detect any unauthorized use, and to investigate if necessary.

What’s make this article special, the Break Glass Account will be created remotely after tenant is compromised.

II – What is Azure Automation ?

Azure Automation is a cloud-based automation service that enables developers and system administrators to manage configuration and automation tasks in Azure and in external environments. It offers a variety of features, including update management, configuration management, change tracking and inventory, as well as process automation.

1 – Azure Automation Runbooks :

Runbooks are PowerShell scripts, Python or graphical workflows that can be run to automate tasks. They can be triggered in a variety of ways, including by :

  • A calendar
  • A webhook
  • An Azure alert
  • Another Azure Automation action

Runbooks can be used to automate a wide range of tasks, such as :

  • Automated resource deployment and management
  • Scheduled maintenance tasks
  • Response to monitoring alerts
  • Software and application configuration
  • Data collection and analysis
  • Notification of administrators in the event of problems

Runbooks types :

  • PowerShell Runbooks
  • PowerShell Workflow Runbooks
  • Python Runbooks
  • Graphical Runbooks

2 – Azure Automation Webhooks :

Webhooks are a way of triggering a Runbook from an external event. For example, you can use a webhook to trigger a runbook when a new e-mail arrives in a specific inbox, or when a ticket is created in an incident tracking system.

Webhooks are created using a unique URL that can be called up from any system or application. When the URL is called, the associated Runbook is triggered and the call data is transmitted to the Runbook.

3 – Advantages of using Runbooks and Webhooks :

The use of Runbooks and Webhooks offers a number of advantages :

  • Increased efficiency : Runbooks and Webhooks can automate manual tasks, saving time and improving productivity.
  • Reduced errors : Runbooks and Webhooks can automate error-prone tasks, which can reduce the number of human errors.
  • Improved consistency : Runbooks and Webhooks ensure that tasks are carried out in the same way every time, which can improve the consistency and quality of results.
  • Increased agility : Runbooks and Webhooks can be used to create flexible workflows that can be easily adapted to changing needs.

III – Pricing :

Azure Automation is billed according to two main components :

  • Process Automation : charged per minute of job execution. This means you pay according to how long your scripts and runbooks take to run.
  • Configuration Management : charged per node managed. A node generally represents a machine or service instance that you manage using Azure Automation.

Here is an example for process automation :

  • 500 minutes of process automation and 744 hours of watchers are free each month for process automation.

IV – Mindmap to Create Runbook and webhook :

  • Select “+ Create
  • Fill in the required information, such as subscription, resource group, Automation account name and region, then click “Review + Create“.
  • Click create to finish Account creation.

2 – Assign appropriate Rights to your Automation Account :

After creating Automation account we should Assign it with the right permissions to be able to be executed, because every script need level of rights as you know.

The easy way is to assign Global Admin Role, but to avoid that Automation Account appear with global admin Account list and to be blocked by the hacker with the ather Global Admin Accounts, we will divide Global Admin Role in two sub roles :

  • User Administrator (To Create user)
  • Privileged Role Administrator (To Assign Global Admin Right)

To do this this :

  • Go to Entra admin portal : https://entra.microsoft.com/
  • select “Roles & admins” from the left menu bar.
  • Select “All roles” panel.
  • type “User Administrator” in the search bar
  • Select “User Administrator
  • Click “Add Assignments
  • type your Atomation Account Name then select it.
  • Click “Add
  • Here is User Admin role added for our automation account.
  • Do the same thing with “Privileged Role Administrator” :

3 – Create Runbook :

After Creating Automation Account, we will proceed to Runbook creation, for this :

  • Access to the new Automation Account.
  • Go to “Runbooks” in the left menu bar.
  • Select “+ Create a Runbook” to start new runbook creation.
  • Fill in the required information, Name, Runbook Type (PowerShell, Python, PowerShell Workflow, Graphical PowerShell, Graphical PowerShell Workflow) , Runtime version, and description, then click “Review + Create“.
  • Click Create.
  • you will beredirected automatically to PowerShell Editor :

The following script will create new Global Admin User on request.

Paste the following PowerShell Script (You need to change userUPN, userDisplayName and Password values in the script , with (first section #To be changed as comment))

The following script is tested and working properly, you only need to change your Global Admin login password.

# ------------------------------------- To be Changed ----------------------------
# Define variables
$userUPN = "BreakGlass@globalitnow.onmicrosoft.com"
$userDisplayName = "BG Global Admin"
$password = "P@ssw0rd123!"
#------------------------------------------------------------------------------------

try {
    # Logging in to Azure ...
    Connect-AzAccount -Identity
}
catch {
    Write-Error -Message $_.Exception
    throw $_.Exception
}

# Import necessary modules
Import-Module Az.Accounts
Import-Module Az.Resources

# Get Azure AD token
$context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$token = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.microsoft.com").AccessToken

# Create the new user
$uri = "https://graph.microsoft.com/v1.0/users"
$body = @{
    accountEnabled = $true
    displayName = $userDisplayName
    mailNickname = ($userUPN -split '@')[0]
    userPrincipalName = $userUPN
    passwordProfile = @{
        password = $password
        forceChangePasswordNextSignIn = $true
    }
} | ConvertTo-Json

$newUser = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Bearer $token"} -Method Post -Body $body -ContentType "application/json"

# Get Global Administrator role
$uri = "https://graph.microsoft.com/v1.0/directoryRoles"
$roles = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Bearer $token"} -Method Get
$globalAdminRole = $roles.value | Where-Object { $_.displayName -eq 'Global Administrator' }

# Assign Global Administrator role to the new user
$uri = "https://graph.microsoft.com/v1.0/directoryRoles/$($globalAdminRole.id)/members/`$ref"
$body = @{
    "@odata.id" = "https://graph.microsoft.com/v1.0/directoryObjects/$($newUser.id)"
} | ConvertTo-Json

Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Bearer $token"} -Method Post -Body $body -ContentType "application/json"

Write-Output "New Global Administrator user created successfully: $userUPN"

After pasting the script and making essantial changes (login/password), we need to :

  1. Save the script
  2. Publish the script
  • Our Runbook is Published now.

After Runbook is created, we will generate https web link to be used in the future to create remotely Global Admin account, as I said no need for authentication with this web link.

4 – Explanation of the concept : Starting a runbook from a webhook :

A webhook allows an external service to start a particular runbook in Azure Automation through a single HTTP request. External services include Azure DevOps Services, GitHub, Azure Monitor logs, and custom applications. Such a service can use a webhook to start a runbook without implementing the full Azure Automation API.

Here are some important properties of a webhook in Azure Automation:

  • Name : Name of the webhook. It is only used to identify the runbook in Azure Automation.
  • URL : Webhook URL. This is the unique address that a client calls with an HTTP POST method to start the runbook linked to the webhook.
  • Expiration date : Expiration date of the webhook, after which it can no longer be used.
  • Enabled : Parameter indicating whether the webhook should be enabled by default when it is created.

A webhook can be used to pass parameters that will be used for Runbook execution (for more details).

keep in mind client requirements for TLS 1.2 or higher with webhooks.

5 – Create a webhook :

  • Open your runbook (Create-Break-Glass-Account in my case)
  • Select “Webhooks” from the left menu bar
  • Select “+ Webhook” to start webhook creation
  • Select create new webhook
  • Fill in the required information, Name, Enabled and expiration date…etc
  • Copy https URL in secure place (keep in mind you will never be able to get the link after selecting OK buton)
  • Click “OK“.

6 – Test the webhook :

here is the link I have copied from webhook (it’s a fake link 😂).

Copy paste this Powershell script in your PC (Dont forget to replace the fake link) and execute it :

$webhookURI = "https://2c848b7a-f51f-4113-8aa2-37e8b4fa3716.webhook.eus.azure-automation.net/webhooks?token=vPFDWuRtvzBssdfsxSX13aUPxVr14s5sdEeCSUYXoSVE"

$response = Invoke-WebRequest -Method Post -Uri $webhookURI

$response

here is execution results, we can see StatusCode equal 202 that’s mean script Accepted and execution is started on Microsoft Azure.

Here is script Execution result, as you can see here new Global Admin user created as expected.

  • User created with Global Admin role.

Keep in Mind script execution in cloud can take more time than local scripts, so you need to wait couple of minutes to be able to connect with new global admin account.

7 – Test Connection with new global Admin User :

VI – Conclusion :

In conclusion, automation in Microsoft Azure, in particular the use of Runbooks and Webhooks, offers a wealth of possibilities for improving efficiency and productivity. This guide aims to provide you with the knowledge and skills you need to make the most of these tools. By following the instructions and tips provided in this guide, you’ll be able to transform the way you work with Azure.

Aymen EL JAZIRI (Microsoft MVP)
Aymen EL JAZIRI (Microsoft MVP)

Hi, I’m Aymen El Jaziri , a passionate System Administrator and Microsoft MVP, with years of hands-on experience in managing and securing modern IT infrastructures.
This blog is where I share technical guides, automation scripts, product reviews, and real-world solutions that help IT professionals simplify their day-to-day work and stay ahead in a fast-evolving cloud ecosystem.
Whether you’re here to troubleshoot an issue, improve your automation game, or learn new best practices , welcome in my blog !
Let’s build a stronger, smarter IT community together.
Feel free to connect with me on LinkedIn for more content, discussions, or collaboration opportunities.

Thanks

Aymen

Articles: 154