On this page

After a compromised service principal incident, the first triage question is always the same: “What else can this identity reach?” The answer usually lives outside Sentinel, buried in entitlement exports, RBAC snapshots, or asset inventories that nobody wanted to pay analytics-tier ingestion costs to store.

On April 1, 2026, Microsoft shipped two Sentinel features into public preview that change how this works: data federation and custom graphs. Instead of copying every access table into the analytics tier, you federate external context in place and query across it.

The question I wanted to answer:

Can a low-profile service principal be traced to a crown-jewel resource without first copying all of that access context into native Sentinel tables?

Yes. Here’s how I did it, using:

  • An existing Sentinel workspace in the Defender portal
  • An Azure Data Lake Storage Gen2 federation connector
  • Two Delta-format context tables stored outside the analytics tier
  • KQL to correlate federated context with native telemetry
  • A custom graph to expose hidden privilege paths
  • A workbook report to keep the findings operational

What Shipped in April 2026

Data federation lets you keep investigative context in external stores like ADLS Gen2, Azure Databricks, or Microsoft Fabric and query it from Sentinel without promoting everything into the analytics tier. Powered by Fabric, federated tables appear alongside native Sentinel data in the data lake. Federation itself doesn’t generate ingestion or Sentinel storage fees. You’re billed through Sentinel’s existing data lake query and advanced insights meters when you actually run analytics on federated data. Custom graph operations are billed separately under the Sentinel graph meter. Your underlying ADLS, Databricks, or Fabric storage still has its own platform costs.

Custom graphs let you model relationships over that data and visualize them in the Defender portal using Graph Query Language (GQL). Think principal-to-resource paths, group memberships, and entitlement chains. You author graphs in Jupyter notebooks via the Sentinel VS Code extension, then schedule graph jobs to materialize them for team access in the Defender portal.

Both features are useful for context that changes slower than event telemetry. Asset inventories, entitlement snapshots, historical relationship data, and low-fidelity signals that still matter during triage all fit this pattern.


How The Workflow Fits Together

Architecture diagram showing ADLS Gen2 and Entra/Defender tables feeding into the Microsoft Sentinel Data Lake via federation and native ingestion, with KQL Hunting, Custom Graph, and Workbook outputs
Access context stays in ADLS Gen2. Sentinel federates it in place, then KQL and custom graphs surface hidden privilege paths.

The environment is intentionally small. One existing Sentinel workspace and just enough Azure infrastructure to answer the question:

ComponentPurpose
Existing Sentinel workspaceDefender-portal workspace and data lake target
ADLS Gen2Holds the Delta-format federation tables
Azure Key VaultStores the federation service principal secret
Service principalAuthenticates Sentinel to the ADLS source
Federated tablesResource criticality and principal-to-resource access context
Custom graph notebookBuilds a graph for privilege-path analysis
Workbook reportOperational view of privileged paths and resource criticality

The two federated tables are small and opinionated:

  • ResourceCriticality identifies which Azure resources matter most
  • PrincipalResourceAccess models who can reach those resources and how

The dataset includes a synthetic rogue identity so the investigation has an obvious attacker path:

  • shadow-sync-prod-sp
  • direct Storage Blob Data Owner on the storage account
  • direct Key Vault Secrets Officer on the crown-jewel vault

That’s enough to show the investigation pattern without inventing a giant fake dataset.


Configure the Federation Connector

From the Defender portal:

  1. Go to Microsoft Sentinel > Configuration > Data connectors
  2. Under Data federation, open Catalog
  3. Choose Azure Data Lake Storage
  4. Create a connector instance named federationlab
  5. Provide:
    • application (client) ID
    • Key Vault URI
    • secret name
    • ADLS URL
  6. Select the two demo tables from the ADLS source
Microsoft Defender portal showing the Data federation connectors page with the Azure Data Lake Storage Gen2 connector instance, status OK, and two federated tables attached
The ADLS Gen2 federation connector is healthy with both tables attached. Tap to expand.

Hunt with KQL First

First step. Confirm that Sentinel can join the federated context tables to answer the question that actually matters.

let ResourceCriticality = ResourceCriticality_federationlab;
let PrincipalResourceAccess = PrincipalResourceAccess_federationlab;
PrincipalResourceAccess
| where principalDisplayName == "shadow-sync-prod-sp"
| join kind=inner ResourceCriticality on resourceId
| project principalDisplayName, resourceName, criticality, accessRole, accessSource, detectionHint, riskLabel
Sentinel data lake KQL query joining federated ResourceCriticality and PrincipalResourceAccess tables, returning 4 rows showing rogue and legitimate service principal access paths
KQL join across two federated tables in the Sentinel data lake. 4 items in 1.87 seconds. Tap to expand.

The results tell the story in four rows:

  • shadow-sync-prod-sp has Key Vault Secrets Officer on the crown-jewel vault and Storage Blob Data Owner on the storage account, both via UnknownDirectGrant, flagged as simulated-bad-actor. That’s the rogue identity with direct, unexplained access to two high-value resources.
  • sentinel-data-federation-lab-sp has Key Vault Secrets User via InheritedPath and Storage Blob Data Reader via RoleAssignment, both labeled expected. That’s the legitimate lab workload identity with appropriate, traceable access.

The broader KQL pattern is just as useful. Remove the where filter and you get every principal with access to every critical resource. The full exposure map:

let ResourceCriticality = ResourceCriticality_federationlab;
let PrincipalResourceAccess = PrincipalResourceAccess_federationlab;
PrincipalResourceAccess
| join kind=inner ResourceCriticality on resourceId
| where criticality in ("crown-jewel", "high")
| summarize AccessRoles = make_set(accessRole), ResourceCount = dcount(resourceName) by principalDisplayName, riskLabel
| sort by ResourceCount desc

The graph is where this becomes easier to explain to another analyst or an incident owner.


Build the Custom Graph

I built the graph using the Microsoft Sentinel VS Code extension and its graph builder Python library. You can use AI-assisted authoring or write the graph model code directly.

Three node types:

  • EntraServicePrincipal
  • EntraUser
  • AzureResource

And one primary edge:

  • CAN_ACCESS
Privilege path analysis table showing rogue service principal with Key Vault Secrets Officer and Storage Blob Data Owner via UnknownDirectGrant, and legitimate service principal with Key Vault Secrets User via InheritedPath
The rogue SP has direct, unexplained access to both crown-jewel resources. The legitimate SP has scoped, traceable access. Tap to expand.
MATCH (sp:EntraServicePrincipal)-[rel_access:CAN_ACCESS]->(r:AzureResource)
WHERE sp.riskLabel = 'simulated-bad-actor'
RETURN sp, r, rel_access
LIMIT 50
Defender portal Graphs page showing the GQL query and graph visualization with shadow-sync-prod-sp connected to two Azure resources
Custom graph visualization in the Defender portal β€” 3 nodes, 2 edges. Tap to expand.
GQL query result in table view showing the rogue service principal's CAN_ACCESS edges to two Azure resources
GQL table view β€” the same graph data, queryable and repeatable. Tap to expand.

Add a Workbook Report

Creating workbook reports directly from data lake data entered public preview on April 1, 2026, the same release as federation and custom graphs. The workbook below isn’t a workaround. It’s a first-class capability that Microsoft is actively building into the data lake experience.

The workbook keeps the same findings usable after the initial investigation. Instead of rerunning the graph or the KQL join every time, the risky principal, sensitive resource, and access role stay visible in a format that fits day-to-day SOC operations.

The workbook KQL is the same federated join, shaped for an operational summary.

let ResourceCriticality = ResourceCriticality_federationlab;
let PrincipalResourceAccess = PrincipalResourceAccess_federationlab;
PrincipalResourceAccess
| join kind=inner ResourceCriticality on resourceId
| where criticality in ("crown-jewel", "high")
| project principalDisplayName, resourceName, criticality, accessRole, accessSource, riskLabel
| sort by riskLabel asc, criticality asc

The workbook includes:

  • Federated Identity Paths. Table of every principal-to-resource access path, with criticality and role columns, sourced from the federated join.
  • Why It Matters. Summary of key findings. Which rogue identities reached crown-jewel resources, how the path was validated, and what the SOC should watch.

This is a lightweight operational view, not a full dashboard. The goal is to keep the investigation findings visible without requiring an analyst to re-run queries every time the question comes up.

Defender portal workbook showing Federated Identity Paths table with principal, resource, criticality, and access columns
Workbook view: risky principals, resources, criticality, and access roles in one operational page. Tap to expand.

Limitations and Gotchas

  • The federated source must be publicly reachable. Private endpoints are not supported yet.
  • Key Vault networking must be set to allow public access from all networks during connector setup. You can restrict it after creation.
  • The connector authenticates via service principal + Key Vault. The Sentinel platform identity (msg-resources-*) needs Key Vault Secrets User on the vault. The ADLS service principal needs Storage Blob Data Reader.
  • Federation is read-only. You cannot write back to the federated source from Sentinel.
  • New federated data can take up to 15 minutes to appear in KQL queries and up to 24 hours to show in notebooks.
  • Table names include the connector instance name, for example ResourceCriticality_federationlab. Validate the final names in your environment.
  • Graphs created in interactive notebook sessions are ephemeral. Schedule a graph job to materialize the graph for team access in the Defender portal.
  • Graph API usage is billed via the Sentinel graph meter. Federated analytics are billed through the data lake query and advanced insights meters. Graph build and query workflows can also incur Advanced Data Insights and data lake storage charges for node/edge preparation. Your underlying ADLS/Databricks/Fabric platform costs are separate.
  • Graph authoring flows best through the Microsoft Sentinel VS Code extension.
  • Your workspace must be onboarded to the Sentinel data lake before federation will work.
  • Customer-Managed Keys (CMK) are not supported. Workspaces using CMK for encryption can’t access data lake experiences, including federation and graphs.
  • Maximum 100 federation connector instances per tenant.

Cleanup

If you reproduce this:

  • Delete the ADLS Gen2 storage account that held the federated context tables
  • Delete the Key Vault secret and the service principal
  • Remove the federation connector instance

Leave the Sentinel workspace alone unless you built a disposable one for testing.


Key Takeaways

  1. Federation answers the cost question. The biggest pushback on enriching Sentinel investigations is ingestion cost. Federation lets you query the context without paying to store it in the analytics tier.
  2. Small, opinionated context tables beat large data dumps. Two tables with the right columns answered a higher-value question than another pile of raw RBAC exports would have.
  3. Graphs make privilege paths explainable. A flat KQL result set tells you the answer. A graph tells the story. To another analyst, to an incident owner, to leadership.
  4. Materialize your graphs. Interactive notebook graphs are ephemeral. Schedule a graph job so the investigation is available to the team, not just to whoever ran the notebook.
  5. Start with the investigation question, not the feature. “Can this SP reach the vault?” is more useful than “let me try federation.” Work backwards from the triage question you actually need to answer.

Resources


Have you started using Sentinel data federation or custom graphs? I’d like to hear what investigation patterns you’re building with them β€” especially if you’re federating non-Microsoft context like CMDB or asset inventory data. Find me on LinkedIn or my other socials linked below.

Jerrad Dahlager

Jerrad Dahlager, CISSP, CCSP

Cloud Security Architect Β· Adjunct Instructor

Marine Corps veteran and firm believer that the best security survives contact with reality.

Have thoughts on this post? I'd love to hear from you.