Production-grade make-ldif templates and shell scripts for generating realistic LDAP test data in ForgeRock Directory Services (DS).
Stop writing LDAP test data by hand. This repo gives you runnable templates that generate thousands of realistic users, nested groups, service accounts, and org hierarchies β ready to import into ForgeRock DS.
β‘ Advanced Techniques for Generating Test Data Using make-ldif in ForgeRock DS
Related articles:
- Initializing ForgeRock DS from LDIF Files: A Step-by-Step Guide
- Extracting and Mapping Attributes from LDIF for ForgeRock IDM
- Validating IDM Mappings with Simulated LDIF Data
- IAMDevBox.com β Identity & Access Management Blog
- Production-grade make-ldif templates β users, groups, service accounts, org hierarchy
- Nested group generation β multi-level group trees with configurable depth
- Realistic fake data β names, emails, departments, phone numbers
- Shell scripts β generate + import in one command
- Docker Compose β spin up ForgeRock DS with test data pre-loaded
- Scalable β tested with 10K, 100K, and 1M entries
git clone https://github.com/IAMDevBox/forgerock-ds-test-data.git
cd forgerock-ds-test-data
# Option 1: Generate LDIF only
./scripts/generate.sh --count 1000 --output output/test-data.ldif
# Option 2: Generate + import into running DS instance
./scripts/generate-and-import.sh \
--count 5000 \
--host localhost \
--port 1636 \
--bind-dn "cn=Directory Manager" \
--bind-password "password"
# Option 3: Docker Compose (DS + pre-loaded test data)
docker compose up -dforgerock-ds-test-data/
βββ templates/
β βββ users-basic.template # Simple user entries (100-10K scale)
β βββ users-realistic.template # Users with full attributes + departments
β βββ groups-nested.template # Multi-level nested group hierarchy
β βββ service-accounts.template # Service accounts with restricted attributes
β βββ org-hierarchy.template # Organization units + users + groups
β βββ combined.template # Full enterprise directory scenario
βββ scripts/
β βββ generate.sh # Run make-ldif with a template
β βββ generate-and-import.sh # Generate + ldapmodify in one step
β βββ validate-ldif.sh # Validate generated LDIF before import
β βββ cleanup.sh # Remove test data by base DN
βββ docker/
β βββ docker-compose.yml # ForgeRock DS 7.x with test data
β βββ Dockerfile # DS image with make-ldif pre-configured
β βββ setup.sh # Bootstraps DS + imports test data
βββ examples/
β βββ 1000-users.ldif # Pre-generated sample (1K users)
β βββ enterprise-scenario.ldif # Pre-generated enterprise scenario
βββ tests/
β βββ validate_ldif.py # Python script to validate LDIF structure
βββ README.md
Generates minimal inetOrgPerson entries. Fastest for bulk testing.
./scripts/generate.sh --template templates/users-basic.template --count 10000Generated entry example:
dn: uid=user-0001,ou=people,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
uid: user-0001
cn: User 0001
sn: Last0001
givenName: User
mail: user-0001@example.com
userPassword: {SSHA}changeit
Generates users with departments, job titles, managers, phone numbers, and employee IDs. Best for IDM mapping tests.
./scripts/generate.sh --template templates/users-realistic.template --count 5000Generated entry example:
dn: uid=jsmith-0042,ou=people,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: extensibleObject
uid: jsmith-0042
cn: Jane Smith
sn: Smith
givenName: Jane
mail: jsmith-0042@corp.example.com
telephoneNumber: +1-555-0042
departmentNumber: ENG-200
employeeNumber: EMP-0042
title: Senior Engineer
manager: uid=mgr-0008,ou=people,dc=example,dc=com
userPassword: {SSHA}changeit
Generates a 3-level group tree: Division β Department β Team. Each team contains 5-15 users.
./scripts/generate.sh --template templates/groups-nested.template --count 500Structure:
cn=Engineering,ou=groups,dc=example,dc=com
βββ cn=Platform-Team,ou=groups,dc=example,dc=com
βββ cn=Backend-Squad,ou=groups,dc=example,dc=com
βββ uid=dev-001,ou=people,dc=example,dc=com
βββ uid=dev-002,ou=people,dc=example,dc=com
Generates service accounts with constrained attributes (no personal info, explicit purpose tags).
./scripts/generate.sh --template templates/service-accounts.template --count 50Generates a complete enterprise directory: 5K users, 200 groups (nested 3 levels), 50 service accounts, 10 OUs.
./scripts/generate.sh --template templates/combined.template./scripts/generate.sh [OPTIONS]
Options:
--template FILE Template file (default: templates/users-basic.template)
--count N Number of primary records (default: 1000)
--suffix DN Base DN suffix (default: dc=example,dc=com)
--output FILE Output LDIF file (default: output/generated.ldif)
--ds-home PATH ForgeRock DS home dir (default: /opt/opendj)
--help Show this help./scripts/generate-and-import.sh [OPTIONS]
Options:
--count N Number of entries (default: 1000)
--host HOST DS hostname (default: localhost)
--port PORT DS LDAPS port (default: 1636)
--bind-dn DN Bind DN (default: cn=Directory Manager)
--bind-password PW Bind password (default: password)
--suffix DN Base DN (default: dc=example,dc=com)
--no-ssl Use plain LDAP instead of LDAPSSpin up a ForgeRock DS 7.x instance with 1000 test users pre-loaded:
docker compose up -d
# Wait for DS to be ready
docker compose logs -f ds | grep "The server has started"
# Verify test data
ldapsearch -H ldap://localhost:1389 \
-D "cn=Directory Manager" -w password \
-b "dc=example,dc=com" "(objectClass=inetOrgPerson)" uid cn mail | head -30The Docker setup:
- Starts ForgeRock DS 7.x
- Creates the
dc=example,dc=comsuffix - Generates 1000 users via
make-ldif - Imports the LDIF on first boot
| Entry Count | Template | Generation Time | Import Time |
|---|---|---|---|
| 1,000 | users-basic | ~1s | ~5s |
| 10,000 | users-realistic | ~8s | ~45s |
| 100,000 | users-realistic | ~75s | ~8min |
| 1,000,000 | users-basic | ~12min | ~90min |
For 100K+ entries, use offline import via import-ldif instead of ldapmodify:
# Offline bulk import (much faster for large datasets)
/opt/opendj/bin/import-ldif \
--backendID userRoot \
--ldifFile output/generated.ldif \
--isCompressed falseBefore using in staging/prod pipelines:
- Verify no real employee data in templates
- All passwords are
{SSHA}changeitor test-only hashes - Domain is
example.com, not a real company domain - No real certificate data embedded
- Email addresses use
@example.comor@corp.example.com
- ForgeRock DS 6.5+ / OpenDJ 3.5+ (for
make-ldifbinary) - Bash 4.x+
- For Docker: Docker 20.10+, Docker Compose 2.x
- For Python validator: Python 3.8+
MIT β free to use, fork, and adapt for your own IAM projects.
- π IAMDevBox.com β IAM engineering blog
- π make-ldif Tutorial
- π§ ForgeRock DS LDIF Import Guide
- πΊ IAM Tools Comparison