Mapping LDAP Groups to Portal Roles

Most enterprises already encode who-belongs-to-what in LDAP or Active Directory, so the cleanest way to drive portal permissions is to reuse those groups rather than maintain a second membership list. This how-to ingests LDAP groups into the catalog and maps them onto portal roles, so a change in the directory flows through to portal access automatically. It extends Role-Based Access Control Setup within Authentication, RBAC & Security Governance.

Prerequisites

  • Backstage 1.20+ with RBAC already enforcing permissions on identity.
  • Read access to your LDAP/AD directory: a bind account, base DN, and the group and user object filters.
  • The @backstage/plugin-catalog-backend-module-ldap installed in the backend.
  • A clear mapping from directory groups to portal roles agreed with whoever owns access policy.
Prerequisites for LDAP group mapping RBAC enforcement, LDAP read access, the LDAP module, and an agreed group-to-role map enable directory-driven access. RBAC enforcing LDAP read access LDAP module group→role map Directory-driven access
The directory stays the single source of membership — the portal reads it rather than maintaining a parallel list that drifts.

Exact Configuration

  1. Configure the LDAP ingestion so users and groups become catalog entities.

    # app-config.yaml
    # Requires @backstage/plugin-catalog-backend-module-ldap >= 0.9.0
    catalog:
      providers:
        ldap:
          default:
            target: ldaps://ldap.example.com
            bind:
              dn: ${LDAP_BIND_DN}
              secret: ${LDAP_BIND_SECRET}
            users:
              dn: ou=people,dc=example,dc=com
              map: { rdn: uid, name: uid, displayName: cn, email: mail }
            groups:
              dn: ou=groups,dc=example,dc=com
              map: { rdn: cn, name: cn, members: member }
    
  2. Map directory groups to portal roles in the RBAC policy so membership grants a role.

    # rbac-policy.csv
    # role assignments derive from ingested Group entities
    g, group:default/platform-admins, role:default/admin
    g, group:default/service-owners, role:default/owner
    p, role:default/admin, catalog-entity, update, allow
    p, role:default/owner, catalog-entity, read, allow
    
  3. Schedule re-ingestion so directory changes propagate on a cadence.

    # app-config.yaml
    catalog:
      providers:
        ldap:
          default:
            schedule:
              frequency: { minutes: 30 }
              timeout: { minutes: 5 }
    
LDAP groups become portal roles LDAP groups ingest as Group entities, the RBAC policy maps groups to roles, and roles grant permissions. LDAP group platform-admins Group entity in catalog RBAC mapping group → role permissions granted
Because the role is bound to the group rather than to individuals, adding a person to the LDAP group is all it takes to grant access.

Validation

# Requires curl, jq
# 1. LDAP groups ingested as Group entities
curl -s "${PORTAL_URL}/api/catalog/entities?filter=kind=group" | jq '[.[].metadata.name] | length'
# Expected: matches the directory group count

# 2. A user carries the expected group membership
curl -s "${PORTAL_URL}/api/catalog/entities/by-name/user/default/asmith" \
  | jq '.relations[] | select(.type=="memberOf") | .targetRef'
# Expected: group:default/platform-admins (or the user's real groups)

# 3. The role grants the expected permission (check an authorized action)
curl -s -o /dev/null -w "%{http_code}\n" -X PUT "${PORTAL_URL}/api/catalog/..." \
  -H "Authorization: Bearer ${ADMIN_USER_TOKEN}"
# Expected: 200 for a user in an admin-mapped group
LDAP mapping validation checks Groups ingest, users carry membership, and mapped roles grant the expected permissions. Groups ingested count matches Membership set memberOf relations Role grants expected access
Verify membership relations before permissions — a role that fails to grant usually traces back to a user missing the memberOf edge.

Edge Cases & Troubleshooting

Symptom Root Cause Resolution
No groups ingested Wrong base DN or group filter Verify the group DN and object class against the directory
Users have no membership members attribute mapped wrong Map the correct attribute (member vs memberUid)
Nested groups missing LDAP does not expand nesting Flatten nested groups during ingestion or in the directory
Access lags a directory change Re-ingestion interval too long Shorten the schedule, or trigger on directory events
Stale members retain access Removed users not pruned Ensure ingestion removes members no longer in the group
LDAP mapping pitfalls by class Wrong DNs and attribute maps are ingestion issues; lagging changes and stale members are freshness issues. Ingestion no groups no membership → fix DN + attribute Freshness access lags stale members → shorten + prune
Stale membership is a security bug, not a cosmetic one — ensure re-ingestion removes people, not just adds them.

Frequently Asked Questions

Map groups to roles, or assign roles to individuals?

Map groups. Individual assignments drift the moment someone changes teams and become an audit nightmare at scale. Binding roles to directory groups means access follows the directory automatically — a leaver removed from the group loses portal access without anyone touching the portal.

What about nested LDAP groups?

Backstage does not expand LDAP nesting on its own, so a role bound to a parent group will not pick up members of child groups unless you flatten the hierarchy. Either resolve nesting in the directory before ingestion or post-process ingested groups to expand membership; decide which and document it, because silent non-expansion is a common source of “why can’t they access it” tickets.