This blog is authored and technically implemented by @Hesham Saad with hearty thanks to our collaborator and use-cases executive mind brain @yazanouf
Before we dig deep on monitoring TEAMS CallRecords Activity Logs, please have a look at "Protecting your Teams with Azure Sentinel" blog post by @Pete Bryan on how to ingest TEAMS management logs into Azure Sentinel via the O365 Management Activity API
This section we will go into details on how to ingest TEAMS CallRecords activity logs into Azure Sentinel via the Microsoft Graph API and mainly leveraging CallRecords API which is a Graph webhook API that will give access to the Calls activity logs. SOC team can subscribe to changes to CallRecords via Azure Sentinel and using the Microsoft Graph webhook subscriptions capability, allowing them to build near-real-time reports from the data or to alert on specific scenarios , use cases which mentioned above.
Technically you can use the call records APIs to subscribe to call records and look up call records by IDs, the call records API is defined in the OData sub-namespace, microsoft.graph.callRecords
.
So, what are the key resources types returned by the API ?
Resource | Methods | Description |
CallRecord | Get callRecord | Represents a single peer-to-peer call or a group call between multiple participants |
session | Get callRecord List sessions |
A peer-to-peer call contains a single session between the two participants in the call. Group calls contain one or more session entities. In a group call, each session is between the participant and a service endpoint. |
segment | Get callRecord List sessions |
A segment represents a media link between two endpoints. |
The callRecord entity represents a single peer-to-peer call or a group call between multiple participants, sometimes referred to as an online meeting. A peer-to-peer call contains a single session between the two participants in the call. Group calls contain one or more session entities. In a group call, each session is between the participant and a service endpoint. Each session contains one or more segment entities. A segment represents a media link between two endpoints. For most calls, only one segment will be present for each session, however sometimes there may be one or more intermediate endpoints. For more details click here
Below is the main architecture diagram including the components to deploy Teams CallRecords Activity Logs Connector:
Create and register Azure AD APP to handle the authentication and authorization to collect data from the Graph API. Here are the steps - navigate to the Azure Active Directory blade of your Azure portal and follow the steps below:
Last step is to collect the CallRecords activity data and ingest it into Azure Sentinel via a Logic App.
Navigate to Azure Sentinel workspace, click at Playbooks blade and follow the steps below:
{
"changeType": "created",
"clientState": "secretClientValue",
"expirationDateTime": "2022-11-20T18:23:45.9356913Z",
"latestSupportedTlsVersion": "v1_2",
"notificationUrl": "https://outlook.office.com/webhook/3ec886e9-86ef-4c86-bfff-2d0321f3313e@2006d214-5f91-4166-8d92-95f5e3ad9ec6/IncomingWebhook/9c6e121ed--x-x-x-x99939f71721fcbcc7/03c99422-50b0-x-x-x-ea-a00e-2b0b-x-x-x-12d5",
"resource": "/communications/callRecords"
}
The complete Playbook code view have been uploaded to github repo as well, please click here for more details and check out the readme section.
NotificationURL code (Hosted in Azure Function) sample:
using System.Net;
using System.IO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using System;
public static async Task<IActionResult> Run(HttpRequest req, ILogger log, TextWriter outputBlob)
{
log.LogInformation($"Webhook was triggered!");
// Grab the validationToken URL parameter
If(reg.QueryString.HasValue)
{
string Token = req.Query["validationtoken"];
if(!string.isNullorEmpty(Token))
{
log.LogInformation($"Validation token: {Token}");
return (ActionResult)new OkObjectResult(validaTokentionToken);
}
}
JObject jsonContent;
string notifContent;
using (var reader = new StreamReader(reg.Body))
{
notifContent = reader.ReadToEnd();
Log.LogInformation(notifContent);
jsonContent =JObject.Parse(notifContent);
}
}
To get a list of call records without the need to hard-code / set CallRecord ID you need to do the following:
When the Playbook run successfully, it will create a new custom log table 'TEAMSGraphCallRecords_CL' that will have the CallRecords activity logs, you might wait for a few minutes till the new CL table been created and the CallRecords activity logs been ingested.
Navigate to Azure Sentinel workspace, click at Logs blade and follow the steps below:
Before building any detections or hunting queries on the ingested TEAMS CallRecords Activity data we can parse and normalize the data via a KQL Function to make it easier to use:
The parsing function have been uploaded as well to the github repo.
Part (2): we will share a couple of hunting queries and upload them to github, it's worth to explore Microsoft Graph API as there are other TEAMS related APIs logs that can be ingested based on the requirements and use cases:
...etc
We will be continuing to develop detections and hunting queries for Microsoft 365 solutions data over time so make sure you keep an eye on GitHub. As always if you have your own ideas for queries or detections please feel free to contribute to the Azure Sentinel community.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.