Ingesting Office 365 Alerts with Graph Security API
Published Nov 05 2019 11:25 AM 19.4K Views
Microsoft

Ingesting Office 365 Alerts with Graph Security API

During recent Azure Sentinel workshops some customers have asked for the possibility to ingest Office 365 alerts into Azure Sentinel. While Azure Sentinel has Office 365 Connector, this connector  ingests Exchange mailbox audit logs and SharePoint audit logs and as such it doesn’t include Office 365 alerts.

 

With Office 365 alerts administrators can be alerted about anomalous or malicious activity in their Office 365 environment, for example malware campaign detection or suspicious email forwarding. To learn more about Office 365 alerts you can refer to Alerts in the Office 365 Security & Compliance Center. Administrators can also define their custom alerts in Office 365 Security & Compliance Center.

 

While Office 365 alerts connector may be be released in future, in the meantime we can leverage Graph Security API to ingest Office 365 alerts into Azure Sentinel. Also, as this approach is based on Graph Security API, you can use it to get alerts from other Microsoft Security Products that support Graph Security API and don't have Azure Sentinel alerts connectors released yet.

 

 

1.   Using Microsoft Graph Security API to read Office 365 Alerts

As with most Microsoft security products, you can access Office 365 alerts through Microsoft Graph Security API. This API provides restful access to Microsoft security alerts. To further understand possible queries via Graph Security API you can review sample queries in github repository.

To test out Graph queries we will use Microsoft Graph API Explorer. Before running security alerts queries, please ensure you have at least minimum permission in the API Explorer to read security alerts. You should have SecurityEvents.ReadAll as minimum. To check/add your permissions click on modify permissions link on left side of Graph Explorer.

clipboard_image_1.png

Once we have the right permission, we need to form a query to retrieve Office 365 alerts. Let’s start with initial query for all alerts:

/security/alerts

As we are interested to retrieve only Office 365 alert, we will apply following filter that we put into Graph Explorer:

/security/alerts?$filter=vendorInformation/provider eq 'Office 365 Security and Compliance' and category eq 'ThreatManagement'

clipboard_image_2.png

 

In the Response section please note lastModifiedDateTime field, this is the datetime of when alert was created/modified in Office 365. We will use this field later to retrieve only alerts since this datetime.

 

2.      Ingesting alerts

Once we retrieve the list of Office 365 alerts through Graph Security API, we will ingest them into Azure Sentinel. We will be using Azure Sentinel Playbook. As we can’t ingest directly into SecurityAlerts table, we will be ingesting into custom logs Office365Alerts_CL table. Our playbook will be running at scheduled interval (e.g. every 5 mins). 

 

In the playbook logic we will first check for the most recent lastModifiedDateTime in the Office365Alerts_CL table and then retrieve only new alerts since that datetime. If the table is empty or doesn't exist, we will retrieve all alerts from Office 365 (this is the initialization phase).

 

Now, let’s have a look at each step in more details.

 

3.      Creating Azure Sentinel Playbook

You can create new playbook in your Azure Sentinel environment, in the Playbooks section.

clipboard_image_3.png

Once the playbook is created, add Recurrence function from the list of available functions and set recurrence to your defined time, e.g. every 5 mins:

clipboard_image_4.png

 

4.      Retrieving the most recent lastModifiedDateTime.

Now, we will be looking for the latest alert in Office365Alerts_CL table and the datetime of when it was modified/created. As mentioned earlier, this information is populated by Office 365 and is stored in lastModifiedDateTime field. If there are no alerts in Office365Alerts_CL table or table doesn’t exist, we will retrieve all Office365 alerts and initialize the table.

 

Let's put together corresponding KQL Query. First, we need to check, if Office365Alerts_CL already exists. As there’s no built-in function in KQL to check for table existence, we will use union and isfuzzy=true operator. If isfuzzy is set to true, the set of union sources is reduced to the set of table references that exist and are accessible at the time. If at least one such table is found, it will produce warning, but query will still execute. The default value is false, meaning that any query against non-existing table will yield an error.

 

1. We will be doing union with new oldDateTime variable that will contain only one record, which is historical date (set to 1st of January 1900). We don’t expect to have any alerts generated before this date.

 

This is how we define the oldDateTime variable:

 

 

 let oldDateTime = view () { print lastModifiedDateTime_t=datetime("1900-01-01 00:00:00") };

 

 

 

2. After we define the variable, we can execute the union function. We will be joining oldDateTime with Office365Alerts_CL table. We will use arg_max function to get the most recent lastModifiedDateTime_t value.

 

 

 

Office365Alerts_CL |  summarize arg_max(lastModifiedDateTime_t, lastModifiedDateTime_t)  | project lastModifiedDateTime_t

 

 

 

And this is how the final query looks like – note we added one more arg_max function that compares oldDateTime we defined earlier (Step 1) and the latest lastModifiedDateTime in Office 365Alerts_CL table. If there are no alerts in Office365Alerts_CL table, the query will just return oldDateTime value.

 

 

 

let oldDateTime = view () { print lastModifiedDateTime_t=datetime("1900-01-01 00:00:00") };
union isfuzzy=true
(oldDateTime),
(Office365Alerts_CL |  summarize arg_max(lastModifiedDateTime_t , lastModifiedDateTime_t )  | project lastModifiedDateTime_t )
| summarize arg_max(lastModifiedDateTime_t , lastModifiedDateTime_t )
| project lastModifiedDateTime_t   

 

 

 

5.      Execute Query in the Playbook

To execute previous query in Playbook against Sentinel Log Analytics workspace, we will add Azure Log Analytics Action into the playbook:

clipboard_image_5.png

 

Now, we can add our query into Azure Log Analytics action:

 

snip3.jpg

 

6.      Using Get alerts Action

Once we have the filter expression, we can run Graph API query to get the list of Office 365 Alerts. Azure Sentinel Playbook comes with Microsoft Graph Security action (currently in preview) that allows to easily run Graph Security API queries.

 

First, let’s add Microsoft Graph Security API action into our Playbook:

clipboard_image_7.png

 

And now we will look for GetAlerts function:

clipboard_image_8.png

 

Next, enable filtering on Get alerts action:

clipboard_image_9.png

Now, add the Graph Security API query to retrieve the list of Office 365 Alerts that we have created in Step 1 and include datetime filter as below. Please, don’t forget to add space into “Filter alerts” box after adding lastModifiedDateTime_t variable from the list of dynamic variables.

 

This is the final Graph Security API query:

snip2.jpg

 
 

And now added into Playbook action:

Snip1.png

 
 

7.      Ingest Office 365 alerts into Azure Sentinel

As a final step, we will ingest Office 365 alerts that we retrieved in previous step into Office365Alerts_CL table. We will do so by adding Azure Log Analytics Send Data action into our playbook.

Before doing so, we first add For each action that will iterate through all Office 365 Alerts received through Graph Security API in the previous step

clipboard_image_12.png

 

Now we add Send Data action from Azure Log Analytics Data Collector

clipboard_image_13.png

 

And now we can ingest alerts into source log table which is Office365Alerts – note that you will have two CurrentItem items – please ensure you select the one that is associated to the Alerts iteration.

clipboard_image_14.png

8.      Summary

To test the playbook, we can execute it by clicking on Run Trigger and selecting Recurrence in Playbook page

clipboard_image_15.png

Once the playbook execution is completed, we can check for alerts by running query in Azure Sentinel Logs:

clipboard_image_0.png

 

And we are done. In this article we have demonstrated how to use Graph Security API to ingest Office 365 Alerts into custom table in Azure Sentinel. We have built Azure Sentinel playbook and leveraged new Graph Security API action to retrieve Office 365 alerts and ingest them into Azure Sentinel Custom Logs table. As a next step we can for example translate these alerts into Sentinel incidents through custom alert rules. 

 

For your reference, this is the final playbook:

snip4.jpg

 
22 Comments
Bronze Contributor

The link Microsoft Security Products that support Graph Security API  appears to only take you to the Bing homepage.

Microsoft

Thanks @Gary Bushey , the link has been fixed

Copper Contributor

Thanks for taking the time to put this together.

 

As per "Step 5", it seems there have been some changes to the "Run Query and List Results" step.

 

There is now a "Time Range" box.

 

My setup appears to be ingesting duplicate alerts from 365 Sec and Compliance Centre

 

Any chance you're able to test on your side and confirm if any changes need to be made to the logic app please?

Microsoft

Hi @security_maverick , yes, I've noticed these changes, I'm looking into it now. Thanks for flagging. 

Copper Contributor

"Run Query and List Results" for Azure Log Analytics connector is depreciated now. I was trying to create this playbook but could not find this. After some researching, I found about it.  Looks like time management of alerts will need a new way now.

Microsoft

Hi @ihsmktier_00 where did you find the run query has been deprecated please? I'm not aware of it. There's just been released new version of run query than now includes also time range for the query.

Brass Contributor

Hi @Stefan Simon ,

 

Brilliant article! Very detailed and the easiest example I have seen to pull events from the ISG.

 

Regards

 

Pieter 

Copper Contributor
Microsoft

Hi @security_maverick , yes, I've noticed these changes, I'm looking into it now. Thanks for flagging.

 

I'm having duplicate data, did you find how to avoid it?

Thank you

Copper Contributor

@Ozzzz 

I am still waiting on feedback from Stefan.

Copper Contributor

@Stefan Simon 

Here, Azure Log Analytics connector does not list any actions.

ihsmktier_00_0-1586809463232.png

 

 

 

Copper Contributor

@ihsmktier_00  - check for Azure Monitor instead of Azure Log Analytics - you'll find it there

Copper Contributor

Best practice on the this in production is to monitor the successful running of your LogicApp / Playbook as well - if the app fails for example you really need to know about it!

 

One issue with this is around the Graph version of the alert not always having all the data in it  - malicious links alerting for example - doesn't actually have the user in it - we need to go looking in the portal for this. There is a lot of different alerts that need to be catered for / parsed individually in the "create an alert in sentinel" to have something that can entity link with other alerts and incidents.

 

Is there any sign of an official connector being ready?

Brass Contributor

@Stefan Simon 

 

What permissions do i need to use Microsoft Graph Api through Playbook - Logic APP as fas as i understand there is a user connection so i must delegate that user the permissions to Microsoft Graph Api ?

 

Any example article is welcome

Copper Contributor

Hello,

@Stefan Simon 

Thank you for this info. Is there any update on the Time Range to be specified in the run query and list results action?

Copper Contributor

@Stefan Simon , 

I`m not able to find the categories Office 365 ... and ThreatManagement.

When I run the query to display all alerts I see alerts from ASC and Sentinel but nothing related to Office365.  I see the malware in Quarantine in the O365 portal I can`t grab this via API Calls. 

 

brunhuber_0-1593777028506.png

 

Copper Contributor

@Stefan Simon 
There is possibility to use logic app for patch alerts for : provider  Office 365 Security and Compliance ?

Copper Contributor

@Stefan Simon 
There is possibility to use logic app for get Air investigation evidence/status and pool into Sentinel ?

Copper Contributor

@Stefan Simon 
Hi Stefan, I was able to recreate this playbook, thanks to your detailed steps . However, every time the playbook runs, it fetches all the data again on my Office365 security and alerts account, and thus flooding my sentinel logs with duplicates. Anything should I change on the current playbook? 

Copper Contributor

Hi @Stefan Simon ,
Thank you for this post.
Can you please upload the JSON template of this playbook?

Brass Contributor

Are there still no connectors to ingest regular o365 alerts?

Copper Contributor

@julotc I found this article - Connect Microsoft Defender for Office 365 (formerly Office 365 ATP) data to Azure Sentinel | Microso... and was wondering if this does exactly what this article is trying to achieve with graph api and logic app! Please correct me if I am wrong.

Copper Contributor

Hi! Any news about that? We are a lot of customers with the same problem. 

Version history
Last update:
‎Nov 02 2021 05:43 PM
Updated by: