Guide 04
Scenario YAML
Users, groups, ACLs, tokens, and lab policy are declared in a labldap.dev/v1alpha1 LabScenario file. Bootstrap compiles that file and writes real 389 DS entries. The YAML is the lab definition — not an in-memory directory.
Users and groups
apiVersion: labldap.dev/v1alpha1
kind: LabScenario
metadata:
name: compose-lab
spec:
directory:
suffix: "dc=example,dc=test"
peopleRDN: "ou=people"
groupsRDN: "ou=groups"
users:
- id: alice
uid: alice
passwordFile: /run/secrets/user-alice
enabled: true
attributes:
givenName: Alice
sn: Anderson
mail: alice@example.test
groups:
- id: staff
members:
- user: alice
What it becomes
| YAML | Directory |
|---|---|
users[].id / uid | uid= |
passwordFile | userPassword (hashed by 389 DS) |
enabled: false | nsAccountLock |
attributes | extra string attrs (givenName, sn, mail) |
groups[].id | cn= (groupOfNames) |
members.user | member: uid=… |
The shipped Compose lab is deploy/compose/scenario.yaml. Schema: config/schema/v1alpha1.json.
Rules
- No inline passwords. Point at a
passwordFile.make compose-upwrites those files undersecrets/. - Groups cannot be empty. 389
groupOfNamesneeds a member. Nested groups stay off unlessnestedGroups: true. - YAML is the compiled baseline, not a live sync loop. UI / REST / MCP can add users later. Soft reset restores this file.
- Changing the file means re-bootstrap. The running control plane does not remount a new scenario on the fly.
allowRawACI: false. Declareacls:in YAML. Do not paste 389 ACI text.
ACLs
acls:
- id: staff-read
principal: { kind: group, ref: staff }
target: { kind: suffix }
permissions: [read, search, compare]
attributes:
allow: ["*"]
deny: [userPassword]
That compiles to 389 ACIs. Seed user alice can search the suffix, bind as herself, and cannot read userPassword.
Apply
Edit deploy/compose/scenario.yaml (or set LABLDAP_SCENARIO_FILE), then make compose-up. Bind as a seeded user, not Directory Manager:
ldapsearch -H ldap://127.0.0.1:3389 -ZZ \
-x -D 'uid=alice,ou=people,dc=example,dc=test' \
-y secrets/user-alice \
-b 'dc=example,dc=test' '(uid=alice)'
The shipped suffix is dc=example,dc=test.
Baseline vs runtime
| Path | What happens |
|---|---|
| Scenario YAML | Compiled at bootstrap. Soft reset target. |
| UI / REST / MCP | Live mutations on 389 DS until reset or volume wipe. |
make compose-reset | Destroy the volume, apply the YAML again. |
Full version: docs/guides/scenario.md.