LDAP / Active Directory feed for user identity normalization¶
Logs often carry display names, login names, or other string identities that do not match a single canonical user.id. An LDAP (Active Directory) feed can sync accounts into the lookup usernames2userid. Parsec then uses that lookup during asset identity normalization so user.name on events resolves to a stable user.id.
This is the same feed → lookup path as threat intelligence feeds, but the goal is identity consistency for Assets, Discover, and detections, not IOC watchlists.
What you need (LDAP input)¶
Before you write the feed, collect these values. They go into the feed’s input: section:
| Field | Required | Example | Meaning |
|---|---|---|---|
source |
yes | ldap://10.91.44.128 |
LDAP URL of the domain controller. Use ldap://host or ldap://host:389. For TLS use ldaps://host or ldaps://host:636. Feeds copies this URL into the LDAP connection uri. |
username |
yes | adldap@domain.int |
Bind account (UPN or DOMAIN\user). Needs read access to the users you search. |
password |
yes | (secret) | Password for that bind account. Do not commit real passwords into shared Library repos. |
base |
yes | dc=DOMAIN,dc=int |
LDAP base DN where the search starts (usually the domain root or a specific OU). |
filter |
yes | (&(objectClass=organizationalPerson)(objectCategory=person)) |
LDAP search filter that selects the user objects to sync. |
attributes |
yes | sAMAccountName displayName |
Space separated AD attributes to load. Every attribute used in schema / apply must appear here. |
period |
yes | 1h |
How often the feed re-runs the search (for example 1h, 1d). |
type |
yes | ldap |
Must be ldap so LogMan.io Feeds uses the LDAP source. |
Network requirement: the LogMan.io Feeds service must reach the host and port in source (firewall / DNS). Prefer a dedicated read only bind account limited to the OUs you need.
Also required on the LogMan.io side:
- Lookup
usernames2useridexists (common library,default: true, groupasset). - Parsers emit
user.name(or another field listed underusernames2useridin/Schemas/Mappings/Asset_<schema>.yaml).
For the SID based variant (sids2userid), see Threat intelligence feeds: Active Directory SID to user ID. For how Parsec applies asset lookups, see Asset management and activity stream.
What you get¶
| Piece | Role |
|---|---|
| LDAP / AD | Source of truth for account names (displayName, sAMAccountName, and similar) |
Feed (lmio/feed, type: ldap) |
Periodically reads AD and writes lookup rows |
Lookup usernames2userid |
Maps a username string (key) to user.id (attribute) |
| Parsec asset mapping | On each event, looks up user.name in usernames2userid and fills user.id when missing |
Active Directory → LDAP feed → usernames2userid → Parsec identity normalization → user.id on events / Assets
1. Lookup: usernames2userid¶
Common library declaration (/Lookups/usernames2userid.yaml):
---
define:
type: lookup/string
name: usernames2userid
label: User names to User ID
description_title: List of user names or other string values to user IDs
group: asset
default: true
keys:
- name: name
type: str
fields:
user.id:
type: str
- Key: the string as it appears in logs (for example
displayNameor another AD attribute you choose asapply.key). - Attribute
user.id: the canonical identity Parsec writes when normalization succeeds (oftensAMAccountName, orsAMAccountName@tenant).
ECS asset mapping wires this lookup to user.name:
identity:
usernames2userid:
- user.name
If user.id is already set on the event, Parsec does not overwrite it. The lookup still runs for asset context. When no lookup hits, optional fallback on user.name (for example lowercase_and_domain_removal) may still produce an id.
2. Create the LDAP feed¶
Add a feed declaration under /Feeds/ in the Library (or create it from the Lookups UI with a feed path). Fill every required input field from What you need.
---
define:
type: lmio/feed
name: LDAP User Name Extractor
schema:
sAMAccountName: str
displayName: str
input:
source: ldap://10.91.44.128
type: ldap
username: adldap@domain.int
password: XXX
base: dc=DOMAIN,dc=int
filter: (&(objectClass=organizationalPerson)(objectCategory=person))
attributes: sAMAccountName displayName
period: 1h
apply:
key: !ITEM EVENT displayName
user.id:
!JOIN
delimiter: "@"
items:
- !ITEM EVENT sAMAccountName
- !ARG TENANT
output:
lookup: usernames2userid
How this maps:
source/type: ldap: LogMan.io Feeds opens an LDAP connection (ldap://…orldaps://…) and searches on eachperiod.baseandfilter: limit the search to the OU / user objects you care about.attributes: only the AD attributes listed here are loaded into the feed schema.apply.key: becomes the lookup key. HeredisplayNamematches logs that carry the user’s display name inuser.name.apply.user.id: value stored on the lookup row. The example buildssAMAccountName@<tenant>with!JOINand!ARG TENANT. For a plain account name, use:
apply:
key: !ITEM EVENT displayName
user.id:
!CAST
what: !ITEM EVENT sAMAccountName
type: str
Choose the key attribute to match what your parsers put into user.name. If logs use sAMAccountName already, set both key and user.id from that attribute (or skip the feed for those sources).
Optional: emails → user.id¶
The same pattern fills useremails2userid from AD mail, which Parsec maps from user.email. See the Feeds test library feed LDAP User Email Extractor for the shape; output lookup must be useremails2userid.
3. Verify the lookup¶
- Wait for one feed
period(or trigger a feed run if your operations process allows it). - Open Lookups → usernames2userid and confirm keys (display names) and
user.idvalues. - Send or wait for an event where
user.nameequals a lookup key anduser.idis empty. - In Discover, confirm
user.idis filled. In Assets, the user principal should align with that id.
4. How automatic normalization uses the data¶
On the parse path, after enrichment, AssetIdentityProcessor (from /Schemas/Mappings/Asset_ECS.yaml):
- Reads
user.namefrom the event. - Looks up that string in
usernames2userid. - If the row has
user.id, writes it onto the event whenuser.idwas empty. - Continues with
useremails2userid/ fallbacks as configured.
That normalized user.id drives Assets inventory, activity stream principals, and consistent correlation on identity.
Related email lookup order: usernames first, then emails, then fallback. Details: Parsec asset management.
Practical tips¶
- Align case and format of feed keys with parsed
user.name(spaces, diacritics,DOMAIN\uservs display name). Mismatched keys silently miss. - Prefer a read only AD bind account limited to the needed OUs.
- Keep
periodshort enough for joiners and leavers (often1h); very large directories may need a longer period or a narrower filter. - One feed should own
usernames2useridcontent unless you have a clear merge strategy. - For Windows events that only carry SIDs, use a separate LDAP feed into
sids2userid(and Windows SID enrichers), not this lookup. - UI alternate names on an asset can complement lookups; the feed keeps directory scale mappings current automatically.
Related reading¶
- Threat intelligence feeds: feed declarations, including AD SID →
sids2userid - Asset management: Assets UI for analysts
- Parsec: identity normalization: how lookups fill
user.id - Lookups in detections: using lookups in correlation rules
- Lookups reference: lookup types and deployment