top of page

God Mode with a Timer: Using Logic Apps to Restrict Elevated Access in Entra

Writer's picture: Sebastian F. MarkdannerSebastian F. Markdanner

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!

Superhero with lightning emblem stands proudly against bright, colorful backdrop. Text reads "God Mode With a Timer." Energetic, vibrant mood.

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

Flowchart showing Microsoft Entra process: Admin enables access, logs event, Sentinel monitors, Logic App queries and collects data, automation executes removal.

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

  1. Access the Azure portal, search for and access Virtual Network

    Microsoft Azure portal showing a search for "virtual net" with results. Lists services, resources, and recent activity on the left.

  1. Choose Create and fill out the basic information

    Azure setup screen titled "Create virtual network" with fields for subscription, resource group, VNet name, and region. Text explains VNet benefits.

  2. Skip Security Settings—these aren’t needed for this setup.


  3. On the IP addresses page, remove the default subnet, and choose to Add a subnet. Fill the basic information of the subnet.

    Azure setup screen for creating a virtual network and adding a subnet. Includes IPv4 details, security settings, and navigation buttons.

  4. Enable Private Endpoint Network Policy for Network Security Groups. This is required for the Private Link setup later.

    Network policy settings for private endpoints. Dropdown shows "Network security groups." Buttons for Add and Cancel. Clean design.

  5. Review + Create the Virtual Network

    Azure interface for creating a virtual network, showing basics, security, IP addresses, and tags. "Create" button is highlighted.

 

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

  1. Search for and access Automation Accounts in the Azure portal

    Microsoft Azure dashboard showing a search for "automation a." Services and documentation appear in a panel. Blue and white interface.

  2. Choose Create and fill out the basic info for the Automation Account

    Azure interface showing "Create an Automation Account." Fields for subscription, resource group, account name, and region are filled.

  3. Under Managed Identity, choose:

    • System Assigned (single service), OR

    • User Assigned (multi-service)

    • This guide uses System Assigned.

    "Webpage titled 'Create an Automation Account' with options for 'Managed Identities'. 'System assigned' is checked, 'User assigned' is unchecked."

  4. 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.

    Azure interface showing steps to create an automation account with private endpoint. Options and fields are highlighted in red.

  1. Review + Create the Automation account

    Azure interface showing "Create an Automation Account" setup with details like name, subscription, and region. Status reads "Validation passed".

 

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

  1. 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
Azure portal showing a managed identity page. Text and a PowerShell script with command lines below. Highlighted Object ID in red.

💡 Tip: You can execute this using Azure Cloud Shell.


Creating the Runbook

  1. In the Automation Account, go to Runbooks → Create a New Runbook

Azure portal interface showing "Runbooks" tab. Two published runbooks listed with PowerShell types. "Create" button highlighted in red.

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

Azure portal screenshot showing "Create a Runbook" page. "Remove-ElevatedAccess" is entered. Options for PowerShell 7.2 are selected.

  1. In the Gallery, set Source to PowerShell Gallery.

    Search for Remove-ElevatedAccess-Automation and select it.

    Azure portal screen displaying "Browse Gallery". PowerShell script "Remove-ElevatedAccess-Automation" is highlighted. Blue and white theme.

  1. Review + Create the Runbook.

    Once created, Publish the Runbook—otherwise, jobs won’t execute.

    Azure PowerShell Runbook editor displaying a script for removing Microsoft Entra Elevated Access. Visible sidebar and menu options like Save, Publish.

Configuring Entra Roles for the Managed Identity

Since the Automation Account needs to manage user access, it requires Directory Reader permissions.


  1. Open the Microsoft Entra Admin Center

  2. Expand the menus and select Roles & Administrators → Directory Reader.

    Administrative roles screen in Microsoft Entra, showcasing various roles like Directory Readers. Sidebar highlights "Roles & admins" section.

  3. Click Add assignment.

  4. Search for the Managed Identity using:

    • Object ID (copied earlier), OR

    • Automation Account Name.

      Admin dashboard at Microsoft Entra, showing "Add assignments" for roles. A member is selected with details. Clean, technical interface.

  1. Assign the role as Active (can be permanent or time-restricted).

    Provide a meaningful justification and confirm the assignment.

    Admin center screen for adding assignments. Settings tab open, fields for assignment dates, and a justification text box visible.

 

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

  1. Search for and access Logic apps in the Azure portal

    Search bar in Azure portal shows results for "logic app"; options include Logic Apps Custom Connector and App Services. Azure services menu visible.

  1. 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.

    Azure Logic App interface showing hosting plans: Consumption, Standard, Hybrid. Options listed are Multi-tenant, Workflow, and App Service.

  1. Fill out the Basic Information and enable Log Analytics (if needed).

    Review + create the logic app.

    Azure Logic App creation screen showing project and instance details. Fields include subscription, resource group, and more, with blue and white UI.

 

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

  1. In the Logic App, go to Identity → Azure Role Assignments

    Microsoft Azure interface showing "LA-ElevatedAccess-we" Identity details. "Azure role assignments" highlighted. Blue and white theme.

  1. Click Add Role Assignment (Preview). Select Resource Group (where Log Analytics is located). Assign Reader (RBAC Role).

    Azure interface showing role assignments. Left: roles listed under a subscription. Right: Add role assignment section with fields for scope, role, etc.

 

Log Analytics Workspace Access

To query log data, the Logic App also needs Log Analytics Reader permissions.

Steps

  1. Open the Log Analytics Workspace that collects Entra Audit Logs, which we configured in the last post on monitoring the elevated access events.

    Microsoft Azure interface showing Log Analytics workspace named "log-EntraAuditLogs-we". Includes menu options, essential details, and setup steps.

  1. Navigate to Access Control (IAM) → Add Role Assignment

    Azure interface showing "Access control (IAM)" section. Options include "Add role assignment" and buttons for checking access and permissions.

  1. Select Log Analytics Reader (RBAC Role).

    Azure interface showing "Add role assignment." Role: Log Analytics Reader with description and details in a table. Blue and white theme.

  1. Under Managed Identity, search for and select the Logic App.

    Azure interface for role assignment, showing "Log Analytics Reader" role. No members selected, managed identity option checked.

  1. Review + assign the role.

    Azure portal screen for adding a role assignment. Shows "Log Analytics Reader" role, member details, and navigation options.

 

Automation Account Access

Since the Logic App will create a job in the Runbook, it needs direct permissions on the Automation Account.


Steps

  1. Navigate to the Automation account.

    Go to Access Control (IAM) → Add Role Assignment.

    Azure Access Control IAM screen showing role assignment options. Buttons for adding roles, checking access, and managing permissions. Blue and white interface.

  1. Assign the following roles to the Logic App’s Managed Identity:

    • Reader

    • Automation Job Operator

    Azure role assignment page showing job functions like Automation Contributor. Lists roles, descriptions, and details in a table format.
    Azure portal screenshot shows "Add role assignment" for Automation Job Operator. Includes member details and managed identities selection.
    Azure portal screen shows "Add role assignment" with details like Role, Scope, Members, and Description. The highlighted role is "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:

Flowchart depicting an automated process to manage elevated access, including query, job creation, and conditions for success or termination.

Step-By-Step Configuration Guide

  1. Set the trigger to use Recurrence

    Azure Logic App Designer interface, "Add a trigger" panel open with "Recurrence" and "Sliding Window" options. Blue and white theme.

  • Set the Interval to 2 and Frequency to Hour.

  • Configure the Time Zone and optionally set a Start Time for better time management.

    Scheduler screen showing recurrence settings. Interval set to 2 hours, time zone is Brussels, Copenhagen, Madrid, Paris.

  1. Add the Run query and list results V2 action from the Azure Monitor Logs connector

    Interface showing "Add an action" with "monitor" searched. "Azure Monitor Logs" selected. Option "Run query and list results V2 (Preview)" highlighted.

  1. Create the API connection

    Provide a Connection Name

    Select Managed Identity as the Authentication Type

    Azure Monitor interface for connection setup. Fields labeled "Connection Name" with "Elevated Access Logic app" and "Authentication Type" with dropdown.

  1. 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.

    Flowchart with "Recurrence" and "Query for Elevated Access Event" nodes. Right panel shows audit log query details, including parameters.

  1. Add an Initialize variable action to store the output from the Automation Account runbook.

    Interface with "Add an action" panel, search bar with "initial", and "Initialize variable" option. Blue and purple accents.

  1. Add the Create job action from the Azure Automation connector

    UI showing "Add an action" with "Azure Automation" options: Create job, Get job output, Get status of job. Search bar typed "automation".

  1. Create the API connection

    Provide a Connection Name

    Select Managed Identity as the Authentication Type

    Create connection screen for Azure Automation. Fields: "Connection Name" with "Elevated Access Logic" and "Authentication Type." Button: "Create new."

  1. 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.

    Job creation interface for removing elevated access with fields: Subscription, Resource Group, Runbook Name, and dynamic content options.


  1. Add the Get job output action from the Azure Automation connector

    Search bar with "automation" typed in, options for Azure Automation including "Get job output" highlighted. Blue and white interface.

  1. Select the same Automation Account

    Set Job ID to the Job ID value from the created job.

    Flowchart interface in a software application. It shows steps for removing elevated access. Text boxes and dropdowns detail job settings.

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

  1. Add a Condition action from the Control in-app Connector

    Software interface showing "Add an action" with search for "condition." Options include Control and Condition in a dropdown menu.

  1. Compare Get Job Output Content to see if it contains:

    “Successfully removed Elevated Access for user”

    Flowchart interface showing process steps like "Create job for removing Elevated Access" and "Get job output" with variables. Search bar and options visible.
    Interface screenshot showing a condition expression setup. "Successfully removed Elevated Access for user" message is highlighted in blue.

  1. 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

    Menu titled "Add an action" with options for variable operations. "Append to string variable" is highlighted. Simple UI design.

  1. If True, append the following string to the variable: "Successfully removed Elevated Access for User: @{items('For_each')?['Actor']}"

    Flow chart for removing elevated access. Includes actions like "For each" loop, job creation, string functions, and condition checks.

Check if the Variable is Empty

  1. Add another Condition outside the For Each loop.

    Use this function to check the length of the variable:

    length(variables('var_Output'))

    Flowchart editor showing decision paths and conditions. Text includes "If no successful removal - terminate" and various string functions.

  • Compare the length with 0 using this function:

    int(0)

    Workflow interface showing a condition expression box with "int(0)". Below, a dropdown lists string functions.

  1. If True → Terminate with Status Succeeded

    For this, add a Terminate action from the Control in-app connector, in the True fork.

    Add an action menu with "terminate" typed in the search bar. Options include "Terminate" under Control. White and blue UI elements.
    Flowchart with decision branches for "If no successful removal - terminate." Arrows show "True" leading to "Terminate" box. Simple interface.

  1. If False → Add a Compose action (ready for further handling, like sending an email with successful access removal)

    Flowchart with a decision box: "If no successful removal - terminate," leading to "Terminate" and "Compose Variable for further use." White background.

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.

Azure interface displaying a job log for removing elevated access. Black text window shows user ID and role removal details, status: completed.

Audit Log Events Captured:

  • User Elevated Access

  • User Access Removed

Azure activity log showing two entries: User role removed and elevated for Access Admin. Both actions are marked as successful.

 

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.

Notification bar with text, "You have 3 users with elevated access." Suggests deleting unnecessary access. Background is white, with blue link.

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

Text showing "Users with elevated access." Includes guidance on access elevation and a note: "1 user has elevated access in this tenant."

Timing Considerations

The 2-hour schedule means that access could be removed soon after it’s granted.


Ways to improve this:


  1. Set a specific Start Time – This will allow all admins to know when the Logic App runs.

  2. 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

  1. Search for and access Deploy a custom template in the Azure portal

    Search bar with query "deploy a custom." Results show services like "Deploy a custom template," marketplace items, and documentation links.

  2. Select Build your own template in the editor

    Azure deployment interface showing options to select a custom template, build in editor, or use common templates like VMs and web apps.

  3. Upload the JSON template

    Azure template editor showing JSON code. Options to add resources and load files are visible. Text includes schema, contentVersion, parameters, and resources.

  4. Modify parameters as needed - Review + create to deploy the template!

    Azure management interface for custom deployment setup. Includes options like template edit, subscription selection, and instance details.

 

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.

bottom of page