10.4 Entity Mapping and Alert Enrichment
Entity Mapping and Alert Enrichment
Introduction
Required role: Microsoft Sentinel Contributor for analytics rules. Sentinel Responder for incident management.
Entity mapping transforms raw KQL output columns into structured, typed entities that Sentinel uses for investigation. Without entity mapping, an alert is a block of text — the analyst must manually identify which field is the user, which is the IP, and which is the device. With entity mapping, the incident page displays clickable entities that link to investigation pages, entity timelines, and cross-incident correlation.
Entity mapping is the bridge between detection (the KQL query) and investigation (the incident page). Getting it right dramatically accelerates analyst triage speed.
Entity types and identifiers
Sentinel supports the following entity types, each with specific identifier fields.
Account entity. Represents a user or service account. Identifiers: FullName (domain\username), Name (username only), UPNSuffix (domain suffix), AadUserId (Entra Object ID), Sid (Windows SID). Map from: UserPrincipalName, Account, AccountName, AccountObjectId.
Host entity. Represents a computer or device. Identifiers: HostName, FullName (FQDN), DnsDomain, NetBiosDomain, AzureID, OMSAgentID. Map from: Computer, DeviceName, HostName.
IP entity. Represents a network address. Identifiers: Address. Map from: IPAddress, SourceIP, DestinationIP, RemoteIP, IpAddress.
URL entity. Represents a web address. Identifiers: Url. Map from: RequestURL, Url, RemoteUrl.
File entity. Represents a file. Identifiers: Name, Directory. Map from: FileName, FolderPath, InitiatingProcessFileName.
Process entity. Represents a running process. Identifiers: ProcessId, CommandLine. Map from: ProcessId, ProcessCommandLine.
FileHash entity. Represents a file hash. Identifiers: Algorithm (MD5, SHA1, SHA256), Value. Map from: SHA256, MD5, SHA1, FileHash.
Mailbox entity. Represents an email address. Identifiers: MailboxPrimaryAddress. Map from: RecipientEmailAddress, SenderMailFromAddress.
DNS entity. Represents a domain name. Identifiers: DomainName. Map from: Domain, DnsDomain, QueryName.
Configuring entity mapping in the rule wizard
In the analytics rule creation wizard (Tab 2: Set rule logic), the Entity mapping section allows you to add up to 5 entity mappings.
For each mapping: select the entity type (Account, Host, IP, etc.), select the identifier (FullName, Address, etc.), and map it to a column in your KQL query output.
Example mappings for the brute-force rule from subsection 10.2:
Entity 1: IP → Address → IPAddress
Entity 2: Account → FullName → CompromisedAccount
These mappings mean: when the rule fires, the incident shows the attacking IP as a clickable IP entity (with geolocation, reputation, and all other incidents involving this IP) and the compromised account as a clickable Account entity (with timeline, sign-in history, and all other incidents involving this user).
Example mappings for the inbox rule detection:
Entity 1: Account → FullName → UserPrincipalName
Entity 2: IP → Address → IPAddress
Entity 3: Mailbox → MailboxPrimaryAddress → ExternalAddress
Three entities mapped: the victim (Account), the attacker’s origin (IP), and the exfiltration destination (Mailbox).
Entity mapping by attack type
Different detection scenarios require different entity combinations. Use this reference when configuring entity mapping for new rules.
Identity attacks (brute-force, credential stuffing, password spray): Primary: IP → Address (attacking IP). Secondary: Account → FullName (targeted/compromised user). Optional: URL → Url (if phishing URL is known).
Email attacks (phishing, BEC, inbox rule creation): Primary: Account → FullName (compromised mailbox owner). Secondary: IP → Address (source of malicious action). Tertiary: Mailbox → MailboxPrimaryAddress (forwarding destination). Optional: URL → Url (phishing link).
Endpoint attacks (malware, suspicious process, lateral movement): Primary: Host → HostName (affected device). Secondary: Account → FullName (user who executed the process). Tertiary: Process → CommandLine (the suspicious process). Optional: FileHash → Value (malware hash). Optional: IP → Address (C2 IP).
Cloud infrastructure attacks (Azure resource modification, policy changes): Primary: Account → FullName (who made the change). Secondary: IP → Address (where the change came from). Custom detail: ResourceId (which Azure resource was affected).
Data exfiltration (mass download, USB copy, cloud sync): Primary: Account → FullName (the user exfiltrating). Secondary: Host → HostName (the device used). Secondary: IP → Address (destination if network-based). Custom details: FileCount, TotalSize, DestinationType.
Common entity mapping mistakes
Mistake 1: Mapping the wrong column. Your KQL outputs SourceIP but you map the entity identifier to IPAddress — the mapping fails silently (the entity appears as empty). Fix: the column name in the entity mapping must exactly match the column name in the KQL output. Run the query and check the output column names before configuring mapping.
Mistake 2: Mapping a concatenated field. Your KQL produces Account = strcat(Domain, "\\", Username) but you map Account → Name (which expects just the username, not domain\username). Fix: use Account → FullName for the concatenated value, or output Domain and Username as separate columns and map both identifiers.
Mistake 3: Mapping IP to a column with “N/A” values. Some data sources return “-” or “N/A” instead of empty for missing IP addresses. The entity mapping creates an IP entity with value “-” — which clutters the investigation graph. Fix: add | where IPAddress != "-" and IPAddress != "N/A" and isnotempty(IPAddress) in your KQL, or use | extend IPAddress = iff(IPAddress in ("-", "N/A", ""), "", IPAddress).
Mistake 4: Not mapping enough entities. A rule that only maps Account but not IP forces the analyst to manually look up the source IP — adding minutes to triage. Fix: map every entity the analyst needs for initial triage (typically Account + IP + Host for most detections).
Mistake 5: Mapping too many entities. A rule that maps 5 entities (Account, IP, Host, File, URL) when the investigation only needs Account and IP creates a cluttered incident page. Fix: map the primary investigation entities. Put secondary context in custom details.
Custom details: enriching alerts with context
Beyond entity mapping, custom details allow you to attach additional context fields from the KQL output to the alert. Custom details appear in the alert’s ExtendedProperties — visible to analysts in the incident detail pane and available to automation rules and playbooks.
Configuration: In the rule wizard (Tab 2), under Custom details, add key-value pairs: Key = the display name, Value = the KQL output column.
Example custom details for brute-force detection:
| Key | Value (column) | Purpose |
|---|---|---|
| FailureCount | FailureCount | How many failures before success |
| TargetAccounts | TargetAccounts | Which accounts were targeted |
| FailureReasons | FailureReasons | Why logons failed (wrong password, account locked) |
| SuccessTime | SuccessTime | When the compromise occurred |
| ApplicationUsed | AppDisplayName | Which application the attacker accessed |
Custom details give the analyst everything needed for initial triage without opening the investigation page or running additional queries. A well-enriched alert can be triaged in 30 seconds. A bare alert (no custom details) requires the analyst to run manual queries — adding 5-10 minutes per incident.
Alert detail overrides
Alert detail overrides let you dynamically set the alert title, description, severity, and tactics from KQL output columns. This is powerful for rules that detect multiple severity levels.
Example: dynamic severity based on failure count. A brute-force rule that detects 20 failures is Medium severity. The same rule detecting 100 failures is High severity.
In the KQL query, add a severity column:
| |
In the rule wizard, under Alert details, set Severity to use the AlertSeverity column. Each alert dynamically receives the appropriate severity based on the actual data.
Dynamic alert title: Make the alert title descriptive of the specific instance:
| |
Map AlertTitle as the alert name override. Instead of a generic “Brute force detected,” the analyst sees: “Brute force success: j.morrison@northgateeng.com from 203.0.113.47 (47 failures)” — immediately actionable without opening the incident.
Dynamic alert description
Beyond the title, override the alert description with investigation-ready context:
| |
The analyst opens the incident and reads a complete description with the attack summary and response steps — no need to run queries or consult a playbook document. This pattern transforms the alert from “something happened” to “here is exactly what happened and what to do about it.”
Entity correlation across incidents
Mapped entities enable Sentinel’s cross-incident correlation — one of its most powerful investigation capabilities.
When the same entity (same IP, same account, same device) appears in multiple incidents, Sentinel surfaces this in the incident details: “This entity appears in 3 other incidents.” This correlation happens automatically — but only if the entity is consistently mapped across all analytics rules.
Consistency requirement: If Rule A maps the attacking IP as IPAddress → IP entity, and Rule B maps the same concept as SourceIP → IP entity, both rules create IP entities — but only if both use the IP entity type and the Address identifier. If Rule B maps SourceIP to a custom detail instead of an entity, the IP from Rule B is invisible to entity correlation. Both rules must map the IP as an entity for correlation to work.
Cross-rule entity mapping standard: Define a standard for your rule library.
For user accounts: always project as UserPrincipalName and map to Account → FullName.
For IP addresses: always project as IPAddress and map to IP → Address.
For devices: always project as DeviceName and map to Host → HostName.
This standard ensures that any IP appearing in any rule’s output is correlated with all other IPs across all incidents. Document the standard in your detection engineering guidelines.
Enrichment queries: adding context at alert time
Beyond custom details (which are static values from the KQL output), you can enrich alerts by joining with additional data sources within the KQL query itself.
Pattern: Enrich with geolocation and risk score.
| |
The alert now contains: the user, IP, geographic location, risk level, risk reason, and whether the IP is a known VPN provider — all computed at alert time. The analyst does not need to run follow-up queries for this basic context.
Pattern: Enrich with historical context — is this IP new for this user?
| |
This enrichment adds “Is this IP new for this user?” — a critical context for triage. A risky sign-in from a user’s usual office IP is far less concerning than the same risk level from an IP the user has never used. The IsNewIP flag enables instant triage differentiation.
Pattern: Enrich with device compliance status.
| |
Suspicious process execution on a non-compliant device is higher risk than on a fully managed, compliant device. The IsCompliantDevice flag helps the analyst prioritise.
Entity mapping validation: automated testing
After deploying a new rule, validate that entity mapping works correctly — before relying on it for production investigation.
Manual validation: Create or wait for the rule to fire. Open the incident. Verify: each mapped entity appears as a clickable card in the incident details. Click each entity — does the entity page load with the correct data? Are the entity identifiers populated (not empty or “Unknown”)?
Automated validation query: After enabling a new rule, check its first alerts for entity mapping quality:
| |
If EmptyCount > 0 for any entity type, the mapping has an issue — the KQL output column is empty or in the wrong format for some alerts. Fix the KQL and redeploy.
Pattern: Enrich with user attributes from watchlist.
| |
This dynamically escalates severity for VIP users — combining entity mapping with alert enrichment in a single rule.
Entity mapping troubleshooting
Symptom: Entity appears as “Unknown” in the incident. Cause: the KQL output column contains a value that does not match the expected format for the entity identifier. For Account → FullName, the expected format is domain\username or username@domain.com. If the column contains just username without domain, use Account → Name instead of FullName.
Symptom: Entity is not clickable in the investigation graph. Cause: the entity type is mapped but the identifier is empty or null for that specific alert. Add a where isnotempty(IPAddress) filter in the KQL to ensure only alerts with populated entities are generated.
Symptom: No cross-incident correlation for an entity that appears in multiple rules. Cause: the entity is mapped using different entity types or different identifiers across rules. Standardise entity mapping across your rule library (see the cross-rule standard above).
Entity mapping best practices
Map every entity your investigation will need. If the analyst’s first action after opening the incident will be to look up the user’s sign-in history — map the Account entity. If they will check the IP’s reputation — map the IP entity. If they will check the device’s security posture — map the Host entity.
Use the most specific identifier. For Account: use FullName (domain\username) over Name when available — FullName uniquely identifies the account. For Host: use FQDN over NetBIOS name when available.
Do not map unnecessary entities. Mapping 5 entities when only 2 are investigation-relevant clutters the incident page. Map the entities the analyst needs for triage and initial investigation. Additional context goes in custom details.
Verify mapping after deployment. Create a test incident and open the investigation page. Are the entities displayed correctly? Can you click through to the entity timeline? If entities show as “Unknown” or are missing, the column mapping is incorrect — the KQL output column does not contain the expected format for the entity identifier.
Try it yourself
Open an existing analytics rule (or the one you created in subsection 10.2) and add entity mappings for Account and IP. Add custom details for at least 3 contextual fields. Enable alert detail overrides for the title (dynamic, based on KQL output). Wait for the rule to fire, then open the resulting incident. Verify: are the entities clickable? Do the custom details appear in the alert pane? Does the dynamic title display correctly?
What you should observe
The incident detail page shows the mapped entities as clickable cards. Clicking an Account entity opens the user's timeline with all recent activity. Clicking an IP entity shows geolocation and other incidents involving the same IP. Custom details appear in the Alert Details section. The dynamic title appears as the incident name in the queue — making it instantly recognisable without clicking in.
Knowledge check
NIST CSF: DE.AE-1 (Baseline of operations established), PR.DS-1 (Data-at-rest is protected). ISO 27001: A.8.15 (Logging), A.8.16 (Monitoring activities). SOC 2: CC7.2 (Monitor system components). Every configuration in this subsection contributes to the logging and monitoring controls that auditors verify.
Check your understanding
1. Your rule detects suspicious inbox rule creation. Which entity types should you map?