In my last post I covered how to monitor the GOD Mode in Azure (Coined by the great John Savill). While visibility and monitoring are great capabilities, there’s a big issue: the permanent nature of the access. - Let's fix that!

The way Elevated Access currently works, there’s no built-in way to manage, or restrict it—not through PIM for time- and approval-based access, not with access reviews, and not with entitlement management either.
Once access is enabled for a user, it stays available until manually removed.
That doesn’t feel quite right, does it?
Luckily, by building on the logs we’re already collecting from Entra (as covered in my last post), we can fix this. Using an Azure Automation Account and an Azure Logic App, we’ll make elevated access time-restricted, providing a way for us to Restrict Elevated Access in Entra!
Table of Content
Overview of the Solution
The solution is build with the following resources across Microsoft Entra & Azure:
Azure Automation Account
Authenticating via Managed Identity provided following permissions:
User Access Administrator at root scope in Azure
Directory Reader in Entra
Logic App
Authenticating via Managed Identity provided following permissions:
RBAC Reader to the resource group of the log analytic workspace & automation account
RBAC Automation Job Operator to the automation account
RBAC Log Analytic Reader to the log analytic workspace
Connection between the Logic App & Automation Account.
Virtual Network
Private Endpoints
Private DNS Zone
Visual solution flow

Once the Logic App runs successfully—removing access and collecting the job output—you can extend its functionality. For example, you might send a notification to an admin, ideally using plus addressing.
Step-by-Step Guide: Setting Up the Automation and Logic App Infrastructure
Step 1: Configuring the Azure Virtual Network
To ensure secure internal access to the Automation Account, we’ll start by setting up a Virtual Network (VNET) with a private endpoint.
If your environment already has a suitable VNET, you can use that instead.
Steps
Access the Azure portal, search for and access Virtual Network
Choose Create and fill out the basic information
Skip Security Settings—these aren’t needed for this setup.
On the IP addresses page, remove the default subnet, and choose to Add a subnet. Fill the basic information of the subnet.
Enable Private Endpoint Network Policy for Network Security Groups. This is required for the Private Link setup later.
Review + Create the Virtual Network
Step 2: Creating the Azure Automation Account
With the VNET ready, the next step is setting up the Automation Account, including the Private Endpoint and Private DNS Zone.
Steps
Search for and access Automation Accounts in the Azure portal
Choose Create and fill out the basic info for the Automation Account
Under Managed Identity, choose:
System Assigned (single service), OR
User Assigned (multi-service)
This guide uses System Assigned.
In Networking Settings, set Connectivity Configuration to Private Access.
In the Networking settings page, change the Connectivity configuration to Private access.
Create a private endpoint fill out the default information. Make sure the Target sub-resource is set to Webhook.
Enable Integrate with Private DNS Zone and either:
Choose an existing zone, OR
Allow Azure to create a new zone.
Review + Create the Automation account
Step 2.5: Automation Account Post-Creation Configuration
With the Automation Account created, we now configure:
Runbook setup
RBAC Permissions
Entra ID Permissions
Configuring RBAC for the Managed Identity
Navigate to the Identity menu in the Automation Account.
Copy the Managed Identity Object ID
Run the following PowerShell snippet to assign User Access Administrator permissions
# Parameters
$ManagedIdentityId = "<ManagedIdentityObjectID" # Replace with the Object ID of the managed identity
$RoleID = "18d7d88d-d35e-4fb5-a5c3-7773c20a72d9" # User Access Administrator
$Scope = "/"
# Assign the role to the managed identity at the root scope
New-AzRoleAssignment -ObjectId $ManagedIdentityId -RoleDefinitionId $RoleID -Scope $Scope

💡 Tip: You can execute this using Azure Cloud Shell.
Creating the Runbook
In the Automation Account, go to Runbooks → Create a New Runbook

Choose a Name, Runtime Environment, and select Browse from Gallery

In the Gallery, set Source to PowerShell Gallery.
Search for Remove-ElevatedAccess-Automation and select it.
Review + Create the Runbook.
Once created, Publish the Runbook—otherwise, jobs won’t execute.
Configuring Entra Roles for the Managed Identity
Since the Automation Account needs to manage user access, it requires Directory Reader permissions.
Open the Microsoft Entra Admin Center
Expand the menus and select Roles & Administrators → Directory Reader.
Click Add assignment.
Search for the Managed Identity using:
Object ID (copied earlier), OR
Automation Account Name.
Assign the role as Active (can be permanent or time-restricted).
Provide a meaningful justification and confirm the assignment.
Step 3: Creating the Logic App
Now that the Automation Account and Runbook are ready, we’ll create the Logic App to query logs and trigger access removal.
Steps
Search for and access Logic apps in the Azure portal
Click Add to create a new logic app, and choose the Hosting Plan. Since this app runs every 2 hours (up to 372 times/month), the Consumption Plan is recommended to keep costs low.
Fill out the Basic Information and enable Log Analytics (if needed).
Review + create the logic app.
Step 4: Configuring Logic App Permissions
Before setting up the Logic App workflow, we need to assign permissions to the logic apps managed identity.
Resource Group Access
The Logic App requires Reader access to the Resource Group containing the Log Analytics Workspace
Steps
In the Logic App, go to Identity → Azure Role Assignments
Click Add Role Assignment (Preview). Select Resource Group (where Log Analytics is located). Assign Reader (RBAC Role).
Log Analytics Workspace Access
To query log data, the Logic App also needs Log Analytics Reader permissions.
Steps
Open the Log Analytics Workspace that collects Entra Audit Logs, which we configured in the last post on monitoring the elevated access events.
Navigate to Access Control (IAM) → Add Role Assignment
Select Log Analytics Reader (RBAC Role).
Under Managed Identity, search for and select the Logic App.
Review + assign the role.
Automation Account Access
Since the Logic App will create a job in the Runbook, it needs direct permissions on the Automation Account.
Steps
Navigate to the Automation account.
Go to Access Control (IAM) → Add Role Assignment.
Assign the following roles to the Logic App’s Managed Identity:
Reader
Automation Job Operator
Now that the infrastructure is ready, we can move on to configuring the Logic App workflow to automate access removal.
Restricting Elevated Access in Entra - Logic App Workflow
Now that we have all the moving pieces in place, it’s time to put them together into a fully functional Logic App.
Here’s the complete Logic App logic:

Step-By-Step Configuration Guide
Set the trigger to use Recurrence
Set the Interval to 2 and Frequency to Hour.
Configure the Time Zone and optionally set a Start Time for better time management.
Add the Run query and list results V2 action from the Azure Monitor Logs connector
Create the API connection
Provide a Connection Name
Select Managed Identity as the Authentication Type
Choose your Log Analytics Workspace and configure the query using this KQL:
AuditLogs
| where TimeGenerated >= ago(2h)
| where Category =~ "AzureRBACRoleManagementElevateAccess"
| where ActivityDisplayName =~ "User has elevated their access to User Access Administrator for their Azure Resources"
| extend Actor = tostring(InitiatedBy.user.userPrincipalName)
| extend UserId = tostring(InitiatedBy.user.id)
| extend IPAddress = tostring(InitiatedBy.user.ipAddress)
| project
TimeGenerated,
Actor,
UserId,
OperationName,
IPAddress,
Result,
LoggedByService
Set Time Range Type to Set in query.
Add an Initialize variable action to store the output from the Automation Account runbook.
Add the Create job action from the Azure Automation connector
Create the API connection
Provide a Connection Name
Select Managed Identity as the Authentication Type
Choose the Automation Account created earlier Set Wait For Job to Yes. Set the Runbook Parameter “UserId” to the Actor value from the query.
Note: This automatically creates a For Each loop, running the action for every user who has elevated their access.
Add the Get job output action from the Azure Automation connector
Select the same Automation Account
Set Job ID to the Job ID value from the created job.
The Logic app logic to handle the time restriction on the elevated access is complete at this point.
Now we'll add logic to handle the output and ready the data for further handling.
Handle the Output
Add a Condition action from the Control in-app Connector
Compare Get Job Output Content to see if it contains:
“Successfully removed Elevated Access for user”
If True, we'll append a string to the variable.
For this, add the Append to string variable action to the True fork of the Condition
If True, append the following string to the variable: "Successfully removed Elevated Access for User: @{items('For_each')?['Actor']}"
Check if the Variable is Empty
Add another Condition outside the For Each loop.
Use this function to check the length of the variable:
length(variables('var_Output'))
Compare the length with 0 using this function:
int(0)
If True → Terminate with Status Succeeded
For this, add a Terminate action from the Control in-app connector, in the True fork.
If False → Add a Compose action (ready for further handling, like sending an email with successful access removal)
And that’s it!
With this Logic App active, it will:
Collect activation logs.
Remove elevated access.
Log the removal for tracking.
Runbook Output: Human-Readable Logs
The Runbook is designed to generate clear, readable output.

Audit Log Events Captured:
User Elevated Access
User Access Removed

Known Issues & Considerations
UI Inconsistencies
Currently, there’s a UI issue where the “Active Elevated Access” count does not always update correctly when access is removed programmatically.
Example:
My tenant has a single Global Admin but the warning shows 3 users under Elevated Access.

Opening the management fly-out menu does show the correct amount though.

Timing Considerations
The 2-hour schedule means that access could be removed soon after it’s granted.
Ways to improve this:
Set a specific Start Time – This will allow all admins to know when the Logic App runs.
Use an Event Hub – Stream logs in real-time and trigger the Logic App only when the Elevated Access assignment event is recorded, using a Delay action.
TL;DR - ARM Template deployment
Don’t want to configure everything manually?
I’ve created an ARM template that deploys:
Logic App
Automation Account
Runbook
API Connections
Note: The Log Analytics Workspace is NOT included.
You can get the ARM template from my GitHub.
How to Deploy the Template
Search for and access Deploy a custom template in the Azure portal
Select Build your own template in the editor
Upload the JSON template
Modify parameters as needed - Review + create to deploy the template!
Final Thoughts
With this setup, we’ve effectively put a timer on God Mode, transforming permanent elevated access into a time-restricted, automated process. By leveraging Azure Logic Apps, Automation Accounts, and Microsoft Entra logs, we’ve built a solution that:
Monitors elevated access activations
Automatically removes access after a set period
Logs and tracks changes for auditing
This approach not only reduces security risks but also ensures compliance with the Zero Trust principals by limiting unnecessary administrative privileges. Plus, it’s fully customizable, so you can integrate notifications, approval workflows, or event-based triggers as needed.
So, next time an admin enables God Mode, they can rest assured—it won’t last forever.
And now, the mandatory bad joke!
Why was the computer cold?
It left its Windows open! 😎
What’s Next?
Try it yourself. Deploy the setup using the ARM template from my GitHub.
Got ideas or improvements? Drop a comment or open a pull request.
Want more automation tricks? Subscribe to the blog for upcoming deep dives.
Let’s keep making security smarter, not harder.