Access packages in Entra ID Governance are a great way to bundle resources together and then provide a user or multiple users access to these resources or access to resources via security groups. But what happens when a user gets removed from a security group that is part of an access package? The answer to that question is the user gets removed from the security group (obviously), and there by loses access to an application or similar. The user doesn’t automatically get reassigned the membership of the security group (or M365 group for that matter). You can of cause Reprocess the user’s assignment for that access package in by navigating to the assignments menu and select the user and press Reprocess and the user will then get added backup the resources that the user is missing. This is something I have been pondering for some time, especially how I can make sure that users with access packages keep their group membership even if a colleague removes them from the group, whether it be by accident or not.
The solution I came up with is to use Microsoft Sentinel to generate an alert when a user is removed from a security group using KQL. There is currently no way of knowing natively if a group is added to an access package or not using KQL, which is why the trigger for the alert is “Remove member from group.” I will go into further details later in this blog post about this, but when the alert is triggered, an incident is created, thereby triggering a PowerShell script that reprocesses all the users access package assignments in Entra ID Governance entitlement management. As mentioned, since there is no way of knowing if a group is added to an access package via KQL and therefore not possible to determine which assignment should be Reprocessed, all assignments for the user will get Reprocessed.
It’s important to note that when a user gets Reprocessed, the only thing that will happen is that the backend service will add the user’s missing resources that are defined in the access package. It will not run custom extension tasks related to the access package assignment policy.
In this blog post, I wanted to share with you a solution I developed to ensure users retain their group memberships in Entra ID, even if they are accidentally removed. By leveraging Microsoft Sentinel and PowerShell.
Pre-requisite resources:
- Azure Automation account
- Microsoft Sentinel setup with AuditLogs from Entra ID
- Service Principal with following permissions: EntitlementManagement.ReadWrite.All (Application)
The alert
The first thing needed for this to work is the KQL query that will find users who have been removed from groups:
This KQL query is designed to find users who have been removed from groups. When running the first two lines, you will also get devices that have been removed from groups. To overcome that, there is a filter on line 6.
In line 7, where isempty(Identity)
, this is added because when a user is removed from an access package, they, of course, get removed from the resources as well, and I don’t want to generate false alerts. There are other times when group owners remove users from a group, and they will show up in the output under Identity with “My Profile.” There is also Azure AD Identity Governance – User Management, Microsoft Approval Management, and Microsoft Substrate Management. These are system-generated events and should not be included in the results of the KQL query.
Azure AD Identity Governance – User Management is the service that removes users from groups when an access package assignment has been removed or has expired for a user. Looking at all the identities that were returned when I first designed the query, I found that when identity was empty, there was a UserPrincipal name in initiatedBy
.
The KQL query has been designed to only output the most important information, such as which users were removed (UPN and ObjectID) and which group they were removed from (Name and ObjectID), as well as when and who removed the user.
Now that the KQL query is designed and ready, we need to add it to Sentinel as a Scheduled Query Rule. Navigate to Microsoft Sentinel in your tenant, select Analytics, and then at the top of the window, select Create and then Scheduled Query Rule.
In the first window of the rule creation, you need to provide a name, description, and severity. MITRE ATT&CK is optional, but I’m using T1531 – Account Access Removal.
Name: User removed from group by another privileged user
Description: This rule detects when a user is removed from a security group by another privileged user.
Severity: Informational
I have chosen the severity as Informational because when the incident is triggered.
In the next window, you need to add an Entity mapping under Alert enhancement. You need to add account, then ObjectGuid, and map it to RemovedUserId.
Then, change the Query scheduling to run every 5 minutes and look 5 minutes back. The last thing you need to ensure is set is Trigger an alert for each event. This ensures that the PowerShell script will run for every user.
The remaining steps can be skipped because we will come back to Automated response later when the Azure Logic App has been configured. This is the part that will trigger the PowerShell script to run in the Automation Account.
Before we configure the automated response in Sentinel, we need to have the PowerShell script in place that will reprocess the users’ access package assignments. You need to add the following PowerShell script to your Azure Automation account as a Runbook.
The PowerShell script connects to the Microsoft Graph using a Service Principal, retrieves all the access package assignments for the user, and then reprocesses the assignment for each of them.
Once the PowerShell script has been added to the Automation Account, we can proceed to create the playbook in Microsoft Sentinel. Navigate to Automation in Microsoft Sentinel, select Create at the top, and in the drop-down menu, select Playbook with incident trigger.
This part is fairly straightforward. You need to select an Azure Subscription and a Resource Group where the playbook will be created (Azure Logic App).
The name for mine is Sentinel-ReprocessUsersAccessPackageAssignment.
When the information is provided, click Next and then Create playbook. Once the playbook is created, you will be taken to the Logic App Designer interface, where we will configure the steps to trigger the PowerShell script.
The first step we need to add is to get information about the user for whom the incident has been triggered. This is where the alert enhancement step comes into play. Add a new step, search for Sentinel, and then select Get accounts. After selecting Sentinel, add Entities in the Entities list.
Now save your changes, because you might need to add the Automation Operator permission to the Azure Logic App for the Automation Account. Navigate to the Identity menu of the Logic App, then select Azure role assignments and click Add role assignment at the top. In the fly-out menu to the right, select Resource group in the scope, then choose the Resource Group where the Automation Account is located. In the Role field, select Automation Operator, and then click Save.
Before we continue, you also need to assign Microsoft Sentinel Responder permissions to the Logic App. This can be done by navigating to the Log Analytics workspace where Microsoft Sentinel is set up, then selecting Access control and Add role assignments. Assign the Microsoft Sentinel Responder role to the Logic App’s managed identity.
After the permissions have been assigned, navigate back to the Logic App Designer. We can now add the next step to run the PowerShell script. Select New step, then search for Azure Automation and select the one called Azure Automation. In actions, select Create job.
(If you are asked to create a connection when selecting Azure Automation, then create one, provide it with a name, and select Logic Apps Managed Identity.)
Now you need to provide the information for the subscription and resource group where the Automation Account is created. Select No in Wait for job, then find the Runbook in the drop-down menu. You need to add a Runbook Parameter; here, you need to select Accounts ObjectGuid.
The next step you need to add (but you can skip it) is the step that will close the incident. There is no reason for it to stay open since the PowerShell script has done the job for us.
Click on New step, then search for Sentinel again, and select Update Incident. In Incident ARM ID, you need to add Incident ARM ID, then set Status to Closed. In Classification reason, you can select BenignPositive – SuspiciousButExpected. The last thing is the Close reason text; here, you can add “Closed automatically – EOM” or whatever you prefer.
Now that the Playbook has been configured, we need to link it as an Automated Response to the Scheduled Query Rule that was created in the beginning. Navigate back to Microsoft Sentinel, select Analytics, then select the rule in the list (named User removed from group by another privileged user) and click on Edit.
Click on Automated response at the top, and then click Add new. In the fly-out menu on the right, add a name for the automation rule and select Run playbook under Actions. When finished, select Apply, then Review and create.
Wrapping up
Now that everything has been put together, it’s time to test it out. I’m going to remove a user from a group that I know is added to an access package. By running this KQL query, I can see that the user I removed from the group has been added back to the group again.
The KQL query returns one result, and by looking at Identity, I can see that the Service Principal used in the PowerShell script to reprocess the user is the one initiating the reprocessing.
You can also run this KQL query to see which groups the user(s) have been added to (If any). However, be mindful that this KQL query will also return users added to groups if they were assigned to an access package.
Finale thoughts
Access packages in Entra ID Governance offers a streamlined way to manage resource access for users, but I do wish there was a setting in Entra ID Governance where group memberships were enforced if a security group was added to the Entra ID Governance catalog. This way, the only way to gain membership of a group would be through the access package, and similarly, if a user is removed, they would be automatically added back to the group. The latter part of this scenario is what I try to solve with this solution, though I still haven’t found a way to address the first part in a satisfactory manner.