Blog Post

Microsoft Sentinel Blog
6 MIN READ

O365 & AAD Multi-Tenant Custom Connector - Azure Sentinel

Hesham_Saad's avatar
Hesham_Saad
Icon for Microsoft rankMicrosoft
Nov 09, 2020

 

Overview & Use Case

 

Thanks to Ofer_Shezaf  and @Yaniv Shasha for the brainstorming, contributing and proof reading! 

 

A multi-national organization having multiple branches with different identities across the globe, each branch have it's own separate tenant (AAD & O365) logs and the global SOC team are looking for a way on how to ingest these logs coming from all branches to their main parent tenant via Azure Sentinel.

 

While Azure Sentinel can’t natively do that using the out-of-the box data connectors (Office 365 / Azure AD), we cover your back with O365 & AAD Multi-Tenancy custom connector via an Azure Sentinel Playbook (Logic App) that invoke the Office 365 Management API & Graph API to read from multiple tenants and writes to a custom table in Sentinel, same can be done using Azure Function.

 

Implementation

 

With the help of Office 365 Management API & Microsoft Graph API we can invoke specific content types cross-tenants:

 

API Content-Type / Activity Log
Office 365 Management API Audit.AzureActiveDirectory
Office 365 Management API Audit.Exchange
Office 365 Management API Audit.SharePoint
Office 365 Management API Audit.General (includes all other workloads not included in the previous content types)
Office 365 Management API DLP.All (DLP events only for all workloads)
Graph API audit-Logs
Graph API Sign-in Logs

 

So, tell us more about the steps?

 

Assuming, we have a parent tenant (Pt) & a child tenant (Ct) and the requirements is to invoke the "Ct" tenant O365 Management API & Graph APIs to pull Office 365 & AAD logs and ingest at "Pt" ones.

 

Step(1): Prep & App Registration

  • Ensure that "Ct" Office 365 Security & Compliance audit logs is enabled 
  • Log in to "Ct" Azure tenant, http://portal.azure.com
  • Search for App Registration > New Registration
  • Type Name, ensure of selecting the right "supported account type": Accounts in any organizational directory (Any Azure AD directory - Multitenant), then click Register button
  • Follow the below gif / step-by step guide on how to define and configure the API permissions & create the secret:

  • Click at “API permissions”
    • Add a permission > Office 365 Management API > Application permissions
    • Select and check “ActivityFeed.Read” , “ActivityFeed.ReadDlp” & “ServiceHealth.Read”
    • Add a permission > Microsoft Graph
    • Select and check “Directory.Read.All”, “AuditLog.Read.All”
    • Click at “grant admin consent” link
  • Click at “Certificates & secrets”
    • Under Client secrets > Add client secret
  • Get the following values:
    • Application / Client ID
    • Tenant ID
    • Secret
    • Azure Active Directory Domain
  • Register the API subscription via PowerShell, run the below PowerShell as administrator and connect to the "Ct" tenant directory, ensure of replacing $ClientID, $ClientSecret, $tenantdomain and $TenantGUID with the above copied values:

 

 

Connect-AzAccount # connect via child "Pt" admin account

# Populate with App ID and Secret from your Azure AD app registration 
$ClientID = "<Client_ID>"  
$ClientSecret = "<Secret>"  
$loginURL = "https://login.microsoftonline.com/"  
$tenantdomain = "<tenant-domain>.onmicrosoft.com"  
# Get the tenant GUID from Properties | Directory ID under the Azure Active Directory section 
$TenantGUID = "<tenant_ID>"  
$resource = "https://manage.office.com"  
$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 "https://manage.office.com/api/v1.0/$tenantGuid/activity/feed/subscriptions/start?contentType=Audit.AzureActiveDirectory&PublisherIdentifier=$Publisher" 
Invoke-WebRequest -Method Post -Headers $headerParams -Uri "https://manage.office.com/api/v1.0/$tenantGuid/activity/feed/subscriptions/start?contentType=DLP.ALL&PublisherIdentifier=$Publisher" 
Invoke-WebRequest -Method Post -Headers $headerParams -Uri "https://manage.office.com/api/v1.0/$tenantGuid/activity/feed/subscriptions/start?contentType=Audit.General&PublisherIdentifier=$Publisher" 
Invoke-WebRequest -Method Post -Headers $headerParams -Uri "https://manage.office.com/api/v1.0/$tenantGuid/activity/feed/subscriptions/start?contentType=Audit.Exchange&PublisherIdentifier=$Publisher" 
Invoke-WebRequest -Method Post -Headers $headerParams -Uri "https://manage.office.com/api/v1.0/$tenantGuid/activity/feed/subscriptions/start?contentType=Audit.SharePoint&PublisherIdentifier=$Publisher" 

 

 

 

Step(2): Cross-Tenants Custom Connector

 

 

 

Notes & Consideration

 

  • You can customize the parsers at the connector's flow with the required and needed attributed / fields based on your schema / payload before the ingestion process, also you can create custom Azure Functions once the data being ingested to Azure Sentinel
  • Azure Function can be used to create custom connector for multi-tenant access, here’s a great example created by Jon Nord invoking Office 365 Management API which you can extend and add Graph API as well.
  • Couple of points to be considered while using Logic Apps:

 

Get started today!

 

We encourage you to try it now!

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.

 

Updated Nov 03, 2021
Version 2.0

18 Comments

  • Yann_CARTE's avatar
    Yann_CARTE
    Copper Contributor

    Hi Folks,

    Great article it helps a lot when starting with logic apps 😉

     

    One comment : Microsoft provides workbooks, queries, ... based on Microsoft log analytics table "OfficeActivity" . How can we translate from our custom log parsing to Microsoft standard attributes names and values ?

  • sferina's avatar
    sferina
    Copper Contributor

    Thank you for sharing. This is a wonderful workaround. But I have some questions about the afterward. When we send this kind of logs to PT, the logs will be kept on custom tables so I guess the built-in analytics rules for O365 can not work because built-in rule queries work with the default tables not for the custom tables am I right? 

  • No problem TH-Zenon75  -  please refer to the post top section "Assuming, we have a parent tenant (Pt) & a child tenant (Ct) and the requirements is to invoke the "Ct" tenant O365 Management API & Graph APIs to pull Office 365 & AAD logs and ingest at "Pt" ones."

     

    The use case here is to invoke and pull logs from specific tenant (called child Ct tenant) to ingest at the parent (Pt) tenant.

  • TH-Zenon75's avatar
    TH-Zenon75
    Copper Contributor

    Many thanks for the post. Can you please be more specific about the concepts Parent Tenant (Pt) and Child Tenant (Ct)? I do not understand the difference between them.

  • Hesham_Saad Thanks for the post. I was actually checking on this a couple of days back. 

    Since this feature was available in the Office 365 connector and was then depreciated due to some security concerns, do you know what concerns were there exactly. 

    Also isn't it more appropriate to allow the customer to accept the risk and allow the same functionality.

    Because it was really easy and straightforward to use the the OOTB connector to connect external O365 tenants and we would get the logs under OfficeActivity table and not as Custom logs. Also the burden of cost per run of log ingestion would have been avoided.

    I really think we should make Logic Apps free, since most workarounds and custom features end up with Logic Apps.

  • GaryBushey's avatar
    GaryBushey
    Bronze Contributor

    I'm guessing this ingestion would not be free anymore since it is not using the OOTB connector?