This article is contributed. See the original author and article here.



Thanks to @Enrique Saggese  and @Yaniv Shasha for the brainstorming and proof reading!


Managing and minimizing risk in your organization starts with understanding the types of risks found in the modern workplace. Some risks are driven by external events and factors that are outside of direct control. Other risks are driven by internal events and user activities that can be minimized and avoided. Some examples are risks from illegal, inappropriate, unauthorized, or unethical behavior and actions by users in your organization. These behaviors include a broad range of internal risks from users:

  • Leaks of sensitive data and data spillage

  • Confidentiality violations

  • Intellectual property (IP) theft

  • Fraud

  • Insider trading

  • Regulatory compliance violations

Insider risk management uses the full breadth of service and 3rd-party indicators to help you quickly identify, triage, and act on risk activity. By using logs from Microsoft 365 and Microsoft Graph, insider risk management allows you to define specific policies to identify risk indicators. These policies allow you to identify risky activities and to act to mitigate these risks, for more details Insider Risk Management in Microsoft 365


Alerts in M365 Compliance Insider Risk Management dashboard are automatically generated by risk indicators that match policy conditions . This dashboard enables a quick view of all alerts needing review, open alerts over time, and alert statistics for your organization. All policy alerts are displayed with the following information to help you quickly identify the status of existing alerts and new alerts that need action:

  • Status

  • Severity

  • Time detected

  • Case

  • Case status


Case & Architecture


SOC team asked how to export Insider Risk Management alerts to Azure Sentinel for enrichment and aggregate these insider risk information with other data sources for monitoring, detection & hunting ?


Our use case for today is a corporate policy – standard communications to detect, alert and report on “Offensive language in email”, a built-in classifiers in Microsoft 365 scan sent email messages from Exchange Online mailboxes in your organization for different types of compliance issues. These classifiers use a combination of artificial intelligence and keywords to identify language in email likely to violate anti-harassment policies.




Starting October 16, 2020, you will no longer be able to create policies using "Offensive Language in email" template. Any active policies that use this template will work until they're permanently removed in January 2021. We are deprecating the Offensive Language built-in classifier that supports this template to optimize and fine tune false positives. To address risk issues for offensive language, we recommend using Microsoft 365 communication compliance policies.






Here’s the high-level architecture design / flow:



Insider risk management alert information is exportable to Azure Sentinel via the Office 365 Management Activity API schema. You can use the Office 365 Management Activity APIs to export alert information to other applications your organization may use to manage, enrich or aggregate insider risk information.







  • Sign in to Microsoft 365 Compliance Portal

  • Under Solutions > … Show All > Insider risk management

  • Click at Insider risk settings

    • Define and check “Policy indicators”, “Policy timeframes”

    • Exports Alerts  > Office 365 Management Activity API (On)

  • Click at Policies

    • Create Policy > type a Name and choose a policy template, our use case today to detect and alert on an “offensive language in email” > Next

    • Define target users & groups

    • Specify what content to prioritize 

    • Select policy indicators 

    • Set policy timeframes

    • Review and Submit




  • Open Outlook and send a test message with an offensive language keywords to trigger the alert, usually it might take up to 24 hrs to start capturing communications and generate the alert based on the classifiers detection




  • Go to Insider Risk Management blade, and check the alerts:




  • Sign in to Azure Portal and create a new App-registration:

    • API permissions: Office 365 Management APIs  > Application Permissions (ActivityFeed.Read)

    • Grant admin consent

    • Certificates & secrets: add new client secret

    • Keep a note for client secret, application-client ID, tenant ID and domain name to register the API subscription

    • Register the API subscription via PowerShell, open PowerShell as admin, connect to your tenant with a privileged account to register the API subscription ensure that you add the proper client secret, application-ID, tenant ID and domain name & ensure that the content-type is Audit.General a direct link to download the raw script at github:



$ClientID = "<app_id>"  
$ClientSecret = "<client_secret>"  
$loginURL = ""  
$tenantdomain = "<domain>"  
$TenantGUID = "<Tenant GUID>"  
$resource = ""  
$body = @{grant_type="client_credentials";resource=$resource;client_id=$ClientID;client_secret=$ClientSecret} 
$oauth = Invoke-RestMethod -Method Post -Uri $loginURL/$tenantdomain/oauth2/token?api-version=1.0 -Body $body  
$headerParams = @{'Authorization'="$($oauth.token_type) $($oauth.access_token)"}   
$publisher = New-Guid
Invoke-WebRequest -Method Post -Headers $headerParams -Uri "$tenantGuid/activity/feed/subscriptions/start?contentType=Audit.General&PublisherIdentifier=$Publisher" 



  • Deploy IRM-Alerts Connector:

    • Sign in to Azure Sentinel

      • Playbooks > Add Playbook

      • Logic app designer:

        • Recurrence (step):

          • Interval: 1

          • Frequency: Day

        • Variable (step):

          • Name: AuditGeneral

          • Type: String

          • Value:


        • HTTP (step):

          • Method: GET

          • URI: Dynamic Content > AuditGeneral

          • Headers:

          • (Accept) – (application/json)

          • (Content-Type ) – (application/json)

          • Authentication: Active Directory OAuth

        • Parse JSON (step):

          • Content: Dynamic Content > Body

          • Use sample payload to generate schema:

            • {
                  "items": {
                      "properties": {
                          "contentCreated": {
                              "type": "string"
                          "contentExpiration": {
                              "type": "string"
                          "contentId": {
                              "type": "string"
                          "contentType": {
                              "type": "string"
                          "contentUri": {
                              "type": "string"
                      "required": [
                      "type": "object"
                  "type": "array"

        • For each (step):

          • Select an output from previous steps: Dynamic Content > Body

          • HTTP (step):

            • Method: GET

            • URI: Dynamic Content > contentUri

            • Headers:

              • (Accept) – (application/json)

              • (Content-Type) – (application/json)

            • Authentication: Active Directory OAuth

          • Send data (step):

            • JSON Request body: Dynamic Content > Body

            • Custom Log Name: Compliance_IRM_AuditGeneral

    • Save the playbook steps and hit run for triggering




The logic app code view have been uploaded as well to github, please ensure to change the subscription ID and resource group values.


Monitoring, Aggregating, Parsing and Enriching


  • Under Azure Sentinel general section > Logs

    • A new custom log table been generated “Compliance_IRM_AuditGeneral_CL”

    • Here’s the Insider Risk Management alert(s) schema structure pulled from Office 365 Management API to Azure Sentinel Log Analytics workspace:

      • Alert Type: Custom

      • Category: InsiderRiskManagement

      • Name: alert title

      • Source: Office 365 Security & Compliance

      • Status: Investigating

      • Creation time

      • Operation: Alert Triggered, Alert Updated

      • Record Type: 40

      • Workload: Security Compliance Center

      • Data:

        • UPN

        • Risky User ID

        • Activation DateTime

      • Severity




Parsing the data can be done easily via a function, the function query have been uploaded to github as well:




A couple of enriching queries (for example):


Monitoring operations activities and result status of the alerted IRM UPN user



let IRMAlertsLog = Compliance_IRM_AuditGeneral_CL | where Category == "InsiderRiskManagement" | where RecordType_d == "40" | extend IRM_UPN = tostring(parse_json(Data_s).userPrincipalName);
| project AlertType_s, Category, Comments_s, IRM_UPN, Name_s, Severity_s, Source_s, Status_s
| join (AuditLogs
        | extend AuditLogs_UPN = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
        | project TimeGenerated, AuditLogs_UPN, OperationName, Result)
        on $left.IRM_UPN == $right.AuditLogs_UPN
| project TimeGenerated, AlertType_s, Category, Comments_s, IRM_UPN, Name_s, Severity_s, Source_s, Status_s, OperationName, Result



Monitoring signin logs locations and status of the alerted IRM UPN user



| where Category == "InsiderRiskManagement"
| where RecordType_d == "40"
| extend IRM_UPN = tostring(parse_json(Data_s).userPrincipalName)
| join (SigninLogs
        | project UserPrincipalName, IPAddress, Location) 
on $left.IRM_UPN == $right.UserPrincipalName
| project TimeGenerated, AlertType_s, Category, Comments_s, IRM_UPN, Name_s, Severity_s, Source_s, Status_s, IPAddress, Location, CreationTime_t, Operation_s, RecordType_d, ResultStatus_s




Get started today!


We encourage you to try it now and start hunting in your environment. 

You can also contribute new connectors, workbooks, analytics and more in Azure Sentinel. Get started now by joining the Azure Sentinel Threat Hunters GitHub community.



Brought to you by Dr. Ware, Microsoft Office 365 Silver Partner, Charleston SC.