In this section

DE1.3 Entity Mapping and Alert Enrichment

6-8 hours · Module 1 · Free
What you already know

You understand the five-stage scheduled rule pipeline and have configured a test rule with a brute force detection query. This section teaches Stage 3 in depth — the enrichment stage where query results become investigable findings. You'll learn how entity mapping works architecturally, which entity types and identifiers exist, why the choice between strong and weak identifiers determines whether Sentinel can correlate your alerts across rules, and how custom details and dynamic alert content change the analyst's investigation experience.

Scenario

Your brute force rule fires. The SOC analyst opens the incident and sees: "Brute force detection — Medium severity." No account name. No IP address. No investigation graph. The analyst has to open the alert, find the raw query results, manually extract the username, search for it in SigninLogs, and piece together the investigation from scratch. A second analyst investigates a different incident from a different rule — also for s.chen@contoso.com — but doesn't know the first incident exists because Sentinel can't correlate them. No entity mapping means no entity merge. Two analysts, same user, same attack, no connection between their investigations. This is what entity mapping prevents.

Entity mapping is the mechanism that transforms a query result from a row of data into an investigable finding. When you map query result fields to Sentinel-recognized entity types, three things happen: the investigation graph populates with nodes the analyst can click and explore, Sentinel can correlate your alert with other alerts across rules that share the same entities, and Fusion can incorporate your custom rule's alerts into its multi-stage attack detection. Without entity mapping, none of these work. The alert exists, but it's operationally isolated — an island of data disconnected from the investigation infrastructure.

Estimated time: 45 minutes.

ENTITY MAPPING — FROM QUERY FIELD TO INVESTIGATION GRAPH QUERY RESULTS UserPrincipalName IPAddress DeviceName FailedCount Raw columns from KQL ENTITY MAPPING Account → FullName IP → Address Host → HostName Up to 10 mappings per rule Up to 3 identifiers per entity ENRICHED ALERT Entities field populated Investigation graph enabled Cross-alert correlation Fusion integration Up to 500 entities per alert INVESTIGATION Click entity → entity page Graph shows relationships Related alerts surfaced UEBA insights available Analyst investigates WITHOUT ENTITY MAPPING Empty investigation graph. No cross-alert correlation. No entity merge. No Fusion integration. Strong identifiers uniquely identify. Weak identifiers need combinations. Account: AadUserId (strong) vs Name alone (weak). IP: Address (strong for public, weak for private).

Figure DE1.3 — Entity mapping transforms raw query columns into recognized entity types that power the investigation graph, cross-alert correlation, and Fusion integration. Without mapping, the alert is data without investigation infrastructure.

Toggle each entity mapping component to see how it changes the analyst's investigation experience. Start with no mapping enabled — then add Account, IP, custom details, and dynamic content one at a time:

What entities are

Entities are Sentinel's classification system for the data elements in alerts. When Sentinel recognizes a data element as a specific entity type — an Account, an IP address, a Host — it knows what questions to ask about that element. For an Account entity, Sentinel can show the user's sign-in history, group memberships, recent activity, and UEBA anomaly score. For an IP entity, Sentinel can show geolocation, threat intelligence matches, and other alerts involving the same address. For a Host entity, Sentinel can show installed software, security posture, and other alerts involving the same device.

Without the entity classification, Sentinel sees s.chen@contoso.com as a string in a query result. With entity mapping, Sentinel sees it as an Account entity with a specific identity in Entra ID, a sign-in history, a risk profile, and relationships to other entities across every alert and incident in the workspace.

Sentinel supports over 20 entity types. The ones you use most frequently in detection rules are:

Account — user accounts, service accounts, managed identities. Identifiers include FullName, AadUserId (the Entra ID GUID), Name, UPNSuffix, NTDomain, Sid. This is the entity you map in nearly every detection rule because most security events involve a user or service identity.

Host — devices, servers, workstations. Identifiers include HostName, DnsDomain, NTDomain, NetBiosName, AzureID, OMSAgentID. Map this when your detection involves device-level activity — process execution, file system changes, registry modifications.

IP — network addresses. Identifiers include Address and AddressScope. Map both source and destination IPs when your query involves network connections — you can map multiple IP entities from the same rule, one for the source address and one for the destination.

URL — web addresses. The identifier is Url. Map this when your detection involves web requests, phishing links, or C2 communication.

File — files on disk. Identifiers include Name, Directory. Map this when your detection involves file creation, modification, or execution.

FileHash — hashes of files. Identifiers include Algorithm and Value. Map this when your detection involves known-bad file indicators.

Mailbox — email mailboxes. Identifiers include MailboxPrimaryAddress, DisplayName, UPN. Map this when your detection involves email-based attacks.

Strong and weak identifiers

Not all identifiers are equal. A strong identifier uniquely identifies an entity without ambiguity. A weak identifier can identify an entity under some circumstances but is not guaranteed to be unique.

This distinction matters because of entity merge behavior. When Sentinel encounters the same entity across multiple alerts — a sign-in anomaly alert and your brute force detection both involve s.chen@contoso.com — it merges the two entity instances into a single entity. The investigation graph shows one node for s.chen with both alerts connected to it. But this merge only works if the entity was identified with strong identifiers in both alerts. If one rule mapped only Name: "s.chen" (a weak identifier) and the other mapped FullName: "s.chen@contoso.com" (a strong identifier), Sentinel may not recognize them as the same entity. Two nodes. Two investigations. Same person.

Here are the strong identifier combinations for the three most common entity types:

Account entity — strong identifiers:

  • Name + UPNSuffix — maps to s.chen + contoso.com, reconstructing the full UPN
  • AadUserId — the Entra ID GUID, universally unique
  • Sid — the Windows Security Identifier (strong for non-built-in accounts)
  • Name + NTDomain — strong for domain accounts where NTDomain is not a built-in domain
  • FullName — the full UPN (s.chen@contoso.com)

Account entity — weak identifiers:

  • Name alone — s.chen without domain context is ambiguous. Multiple users across domains could share this name. Sentinel cannot reliably merge.

IP entity — strong identifiers:

  • Address — strong when the IP is a public/global address (e.g., 185.234.72.14)
  • Address + AddressScope — required for private/internal IPs (e.g., 10.0.1.50 in the Global or Local scope)

IP entity — weak identifiers:

  • Address for private IPs without AddressScope10.0.1.50 is ambiguous without knowing which network it belongs to

Host entity — strong identifiers:

  • HostName + NTDomain or HostName + DnsDomain — the hostname with domain context
  • AzureID — the Azure resource ID, universally unique
  • OMSAgentID — the Log Analytics agent identifier

The detection engineering rule: always use the strongest identifier available in your query results. If UserPrincipalName is available (which contains both name and domain), map it to FullName. If only AccountName is available, map it to Name and also map AccountDomain to UPNSuffix or NTDomain to create a strong combination. The extra 30 seconds of configuration saves hours of investigation fragmentation.

The July 2026 Account Name change

Starting July 2026, the Account entity's Name field will consistently hold only the UPN prefix for all accounts. Previously, Name could sometimes contain the full UPN (s.chen@contoso.com). After the change, Name will always contain only s.chen. If you have automation rules, playbooks, or hunting queries that compare Name against a full UPN value, they will break. Update them to reconstruct the full value from Name + UPNSuffix, or use AadUserId instead.

Entity mapping in practice

Your test rule from Section 1.2 currently has one entity mapping: Account → FullName → UserPrincipalName. That's a strong identifier — the full UPN uniquely identifies the user. But the rule is missing IP mapping, which means the source IP addresses from the brute force attempt don't appear in the investigation graph.

The brute force query produces FailedIPs as a make_set array. You can't directly map a set to an IP entity — entity mapping operates on individual column values, not arrays. To map IP entities, you need to restructure the query so that each result row includes an individual IP address. This is a design trade-off: the current query aggregates by user (one row per user with an array of IPs), which is clean for the analyst but prevents IP entity mapping. The alternative is to restructure for per-IP-per-user rows, which enables IP mapping but produces more result rows.

Here is the restructured version that supports both Account and IP entity mapping:

KQL
// Brute force detection — restructured for entity mapping
// Each row = one user + one source IP (enables both Account and IP mapping)
let threshold = 5;
SigninLogs
| where TimeGenerated > ago(20m)
| summarize FailedCount = count(iff(ResultType != 0, 1, int(null))),
    SuccessCount = count(iff(ResultType == 0, 1, int(null)))
    by UserPrincipalName, IPAddress
| where FailedCount >= threshold and SuccessCount > 0
| project UserPrincipalName, IPAddress, FailedCount, SuccessCount

The change is in the summarizeby UserPrincipalName, IPAddress instead of by UserPrincipalName alone. Each unique combination of user and IP address produces its own row. If s.chen was brute-forced from 3 different IPs, the query returns 3 rows instead of 1. More rows, but each row has a single IPAddress value that can be mapped to an IP entity.

The entity mapping configuration for this query:

Mapping 1 — Account:

  • Entity type: Account
  • Identifier: FullName → Column: UserPrincipalName

Mapping 2 — IP:

  • Entity type: IP
  • Identifier: Address → Column: IPAddress

Two mappings. Both use strong identifiers. The investigation graph now shows the user node connected to each source IP node. The analyst clicks the IP and sees geolocation, threat intelligence matches, and any other alerts involving that address — without running a query.

Here is the same entity mapping as a JSON configuration — the format used in ARM templates and detection-as-code deployments:

JSON
{
  "entityMappings": [
    {
      "entityType": "Account",
      "fieldMappings": [
        { "identifier": "FullName", "columnName": "UserPrincipalName" }
      ]
    },
    {
      "entityType": "IP",
      "fieldMappings": [
        { "identifier": "Address", "columnName": "IPAddress" }
      ]
    }
  ],
  "customDetails": {
    "FailedAttempts": "FailedCount",
    "SuccessfulLogins": "SuccessCount",
    "SourceIPs": "DistinctIPs"
  }
}

The entityMappings array defines which query columns map to which investigation graph entities. The customDetails object puts additional query fields directly on the alert card. Together they determine the analyst's triage experience — how quickly they can classify the alert without drilling into raw data.

What we see in template rules from the Content Hub

The template maps Account → Name → AccountName. No UPNSuffix. No NTDomain. The Name identifier alone is weak — "admin" could be any admin account on any domain. Sentinel can't merge this entity with the same user from other alerts that used FullName or AadUserId as their identifier. The template author used the lowest-common-denominator identifier because they couldn't know which fields your data source provides. You can — and you should upgrade every template rule's entity mapping to use the strongest identifiers your data source supports. It takes 2 minutes per rule and eliminates fragmented investigations.

Custom details and dynamic alert content

Entity mapping handles the structured entities — Account, IP, Host. But your query may produce additional fields that the analyst needs to see without drilling into the raw events. Custom details and dynamic alert content surface this information.

Custom details

Custom details map any query result field to a named key-value pair that appears directly on the alert and incident cards. You define the key name (what the analyst sees) and the column name (where the value comes from).

For the brute force rule, mapping FailedCount and SuccessCount as custom details means the analyst sees "FailedAttempts: 8" and "SuccessfulLogins: 1" on the incident card without opening the alert. These values go into the alert's ExtendedProperties field, which is indexed and queryable — meaning you can write hunting queries that filter alerts by custom detail values across your entire workspace.

Consider the difference in analyst experience. Without custom details, the incident card shows: "Brute force detection — Medium." The analyst opens the alert, clicks "View full details," navigates to the query results, and reads the columns to find how many failures occurred. With custom details, the incident card shows: "FailedAttempts: 8 | SuccessfulLogins: 1 | SourceIPs: [185.234.72.14, 91.215.85.xx]." The analyst triages without clicking. Ten incidents become triageable in the time it previously took to open one.

Dynamic alert content

Alert details override lets you template the alert name, description, severity, and tactics using values from the query results. Instead of a static alert name "Brute force detected," you define a template:

Brute force — {UserPrincipalName} from {IPAddress} ({FailedCount} failures)

When the rule fires, Sentinel renders the template with actual values: "Brute force — s.chen@contoso.com from 185.234.72.14 (8 failures)." The analyst reads the queue and immediately knows who was targeted, from where, and how aggressively — before opening the incident.

You can also template the severity dynamically. A brute force attempt with 5 failures might warrant Medium severity, while one with 50 failures from 10 different countries warrants High. To implement this, extend your query with a severity calculation column and map it to the alert severity override:

KQL
// Brute force with dynamic severity based on attack intensity
let threshold = 5;
SigninLogs
| where TimeGenerated > ago(20m)
| summarize FailedCount = count(iff(ResultType != 0, 1, int(null))),
    SuccessCount = count(iff(ResultType == 0, 1, int(null))),
    DistinctIPs = dcount(IPAddress)
    by UserPrincipalName, IPAddress
| where FailedCount >= threshold and SuccessCount > 0
| extend DynamicSeverity = case(
    FailedCount > 20 or DistinctIPs > 5, "High",
    FailedCount > 10, "Medium",
    "Low")
| project UserPrincipalName, IPAddress, FailedCount,
    SuccessCount, DistinctIPs, DynamicSeverity

The DynamicSeverity column outputs "High," "Medium," or "Low" based on the attack intensity. In the alert details override section of the wizard, you map this column to the severity field. Now a 6-failure brute force from a single IP creates a Low severity incident, while a 25-failure attack from 8 different countries creates a High severity incident — from the same rule, automatically calibrated by the query logic.

Operational constraints

Entity mapping has architectural limits you need to design around:

10 entity mappings per rule. Most rules need 2 to 4 (Account + IP + Host covers the majority of detections). If you need more than 10, your query is probably trying to do too much — consider splitting it into multiple rules.

3 identifiers per entity mapping. One required, two optional. Use all three when possible — more identifiers produce stronger entity identification and better cross-alert correlation.

500 entities per alert. This limit is divided equally across all entity mappings. Two mappings get 250 each. Five mappings get 100 each. For most detection rules, this is more than sufficient. For rules that summarize activity across hundreds of users, the limit matters — excess entities are silently dropped.

64 KB entity field size. The Entities field in the alert schema has a hard size limit. Alerts with too many entities or entities with large property bags get truncated. The project statement in your query controls this — project only the fields you need for entity mapping and custom details. Don't return the entire source table row.

Update your test rule

Open your test rule from Section 1.2. Edit it. On the Set rule logic tab:

  1. Update the query to the restructured version above (summarize by UserPrincipalName and IPAddress).
  2. Add the IP entity mapping: Entity type IP, Identifier Address, Column IPAddress.
  3. Add custom details: key "FailedAttempts", column FailedCount; key "SuccessfulLogins", column SuccessCount.
  4. Under Alert details, set the Alert Name Format to: Brute force — {{UserPrincipalName}} from {{IPAddress}}

Save the rule. The next time it fires, the alert will include both Account and IP entities, custom details visible on the incident card, and a dynamic name that tells the analyst what happened before they open it.

Detection Engineering Principle

Entity mapping is not optional enrichment — it is the mechanism that connects your detection to the investigation infrastructure. A rule without entity mapping produces alerts that exist in isolation: no investigation graph, no cross-alert correlation, no Fusion integration, no entity page insights. Every rule you build gets entity mapping with the strongest identifiers your data source provides. The 2 minutes of configuration eliminates hours of manual investigation work.

Next

Section 4 teaches severity classification and MITRE ATT&CK mapping — how to classify your rule's severity based on impact assessment rather than template defaults, and how ATT&CK technique mapping drives coverage measurement across your entire detection program.

Unlock the Full Course See Full Course Agenda