Skip to content

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 usernames2userid exists (common library, default: true, group asset).
  • Parsers emit user.name (or another field listed under usernames2userid in /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 displayName or another AD attribute you choose as apply.key).
  • Attribute user.id: the canonical identity Parsec writes when normalization succeeds (often sAMAccountName, or sAMAccountName@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://… or ldaps://…) and searches on each period.
  • base and filter: 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. Here displayName matches logs that carry the user’s display name in user.name.
  • apply.user.id: value stored on the lookup row. The example builds sAMAccountName@<tenant> with !JOIN and !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

  1. Wait for one feed period (or trigger a feed run if your operations process allows it).
  2. Open Lookups → usernames2userid and confirm keys (display names) and user.id values.
  3. Send or wait for an event where user.name equals a lookup key and user.id is empty.
  4. In Discover, confirm user.id is 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):

  1. Reads user.name from the event.
  2. Looks up that string in usernames2userid.
  3. If the row has user.id, writes it onto the event when user.id was empty.
  4. 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\user vs display name). Mismatched keys silently miss.
  • Prefer a read only AD bind account limited to the needed OUs.
  • Keep period short enough for joiners and leavers (often 1h); very large directories may need a longer period or a narrower filter.
  • One feed should own usernames2userid content 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.