Auditing Conditional Access events and changes is crucial regarding your hygiene in Azure AD for your modern workplace. With the goal that we receive appropriate notifications and alerts if special events occur. Thanks to Azure Log Analytics (also referred to as Azure Monitor) we can easily filter and create alerts based on events. This post starts where most of the others end - giving you practical examples of KUSTO queries to search your Azure AD Audit logs with Log Analytics.
Default log retention in AAD
A point which get's raised often is the default log retention in Azure Active Directory (AAD). Azure Active Directory stores all activity reports depending on your license for 7 or 30 days:
- Azure AD Free and Basic: 7 days
- Azure AD Premium P1 and P2: 30 days
To retain and further process Azure Active Directory Audit Logs for a longer time period (because a 30 day audit trail is likely too short for most organizations) we can:
- Stream to an Azure Event Hub
- Archive to Blob Storage
- Forward them to Azure Log Analytics
With Log Analytics the KUSTO query language can be used to query the forwarded log entries and we can create alert rules based on custom queries.
Forward AAD logs to Log Analytics
To forward the logs to Azure Log Analytics you first need to create a new Log Analytics Workspace. Afterwards navigate to your Azure Active Directory, select Monitoring, Audit logs and then Export Data Settings.
As I want to show you some cool queries with Log Analytics afterwards we only choose Log Analytics. But you could also choose (additionally to) stream to an event hub. Or archive them directly on a storage account.
Forward Intune Logs to Log Analytics
Connect your Log Analytics Workspace in the Intune dashboard under "Monitoring/Diagnostics settings" like you did for the Azure AD part. As displayed in the diagnostics settings the following types of entries will be forwarded:
- IntuneDeviceComplianceOrg (device compliance data entries for all devices)
Below you will find some queries I have used a couple of times for reports, alerts and investigation purpose. Please note that for most of the queries you will need to work with the Azure AD object ID e.g. of a group or user. You can easily gather the ID by visiting your Azure Active Directory users and groups in the Azure portal. Another benefit is that the object ID does not change and cannot be modified like the userPrincipalName attribute.
- Make sure that you update the object IDs and user principal names according to your Azure AD tenant
- Note that the output of the queries below is mostly truncated by the "project" statement if you need more output remove the project statement or add the properties you actually need
- Note that it takes a few minutes (observations from my side show usually a delay of 5 to 10 minutes) until your log and audit data is available in log analytics
Monitor CA excluded group changes
If you have gathered your accounts excluded from all conditional access policies (usually fallback admins and AAD-Connect accounts) in an AAD group, we can run a query to evaluate if someone got added to that group:
The following Azure AD Group was in my case excluded from Conditional Access policies:
- Group Name: GS-AccountsExcludedFromConditionalAccess
- AAD-Object ID: 657085c0-0608-4b31-95e9-9925f83caa54 (we will need this one for the query below)
AuditLogs | where TargetResources.id in ('657085c0-0608-4b31-95e9-9925f83caa54') and ActivityDisplayName == "Add member to group" | project ActivityDateTime, ActivityDisplayName , TargetResources.userPrincipalName, InitiatedBy.user.userPrincipalName
Monitor emergency access administrator sign-ins
Querying all sign-ins for an account within the last 7 days like a fallback account where usually no sign-ins should occur (multiple accounts can be addedd to the array):
SigninLogs | where UserPrincipalName in ('[email protected]', '[email protected]') and TimeGenerated <= now(-7d)
CA policy modifications
Modifications to Conditional Access policies and the actor can be investigated with:
AuditLogs | where Category == "Policy" | project ActivityDateTime, ActivityDisplayName , TargetResources.displayName, InitiatedBy.user.userPrincipalName
Changes on accounts
Find modifications on sensitive accounts like a password reset or security info reset:
AuditLogs | where OperationName == "Update user" and TargetResources.userPrincipalName in ("[email protected]") | project TimeGenerated, InitiatedBy.user.userPrincipalName, TargetResources.userPrincipalName, TargetResources.modifiedProperties
Intune app protection policy modifications (MAM)
Although Intune app protection policies do not directly belong to Conditional Access you might enforce an app protection policy in Conditional Access and want to track those changes:
IntuneAuditLogs | where OperationName contains "ManagedAppPolicy" | extend d=parse_json(Properties) | project Identity, OperationName, tostring(d.TargetDisplayNames)
Based on the queries mentioned before Azure Monitor allows us to trigger alerts. We can take actions based on alerts with action groups like:
- Phone calls
- Azure Automation runbooks
Please note that the action group will be saved in an Azure resource group and you need to create an action group by using the Azure portal.
As an example here's an alert rule which wil be triggered when a new user gets addedd to the group of conditional access excluded accounts. As condition specifiy custom log search and then configure the tresholds and evaluation scheduled as needed.
When triggering the alert we receive an email:
As soon as the sign-in log receives entries for a fallback admin we trigger a new alert with the following alert rule:
With the implementation of Azure Log Analytics and Azure Monitor we have powerful possibilities to take the most out of audit and sign-in events from Azure Active Directory, Conditional Access and Microsoft Intune. The alerting in Azure Monitor can be further extended by passing the data to Microsoft Flow or Azure Functions with web-hooks allowing powerful automation without scripting.