This is for someone who already has bin/idm. It gets a client directory,
a vault target, and a first import onto disk. Building from source, the
engine jars, the macOS Keychain, and TLS are in install.md.
You run commands from the client directory. The DirXMLDev checkout is only
where bin/idm lives. Call it by path (~/IdeaProjects/DirXMLDev/bin/idm) or
put it on PATH. Client content never goes in the DirXMLDev repository.
bin/idm with no arguments lists every command. bin/apps --help lists the
Identity Applications helper.
client-acme/
environments.properties vault targets — gitignored, mode 600
secrets-stg.properties driver secrets — gitignored, mode 600
secrets-prd.properties
tree/ the driver set as code — committed
cases/ regression corpus for simulate — committed
deploy-log/<env>.jsonl one line per deploy or operation — committed
deploy-snapshots/<env>/ LDIF taken before every write — gitignored
catalog/ package jars (optional) — committed
Ignore environments.properties, secrets*.properties, deploy-snapshots/,
and *.ldif before the first commit. A redacted copy of the two property
files is in examples/.
bin/idm looks for environments.properties in $IDM_ENVIRONMENTS, then the
working directory, then ~/.idm/environments.properties.
tree/ is the source of truth: one file per policy, filter, form, and so on,
plus three manifests (driverset.xml, library/library.xml,
drivers/<driver>/driver.xml). You commit it. You do not hand-edit the
manifests; operations update them.
A plain-language map is tree-layout.md. The short version:
tree/
driverset.xml which drivers exist
config-values.xml driver-set GCVs
library/ shared policies, ECMAScript, mapping tables
drivers/<driver>/ that driver's policies, filter, channels
drivers/<driver>/provisioning/ JSON forms and PRDs (User Application driver)
.package-baseline/ pre-edit copy of a customized packaged object
.gitattributes written by import: * -text, so line endings stay exact
cases/, environments.properties, and secrets-*.properties sit beside
tree/, not inside it.
One block per environment. The prefix is the name you pass to --env and, on
production, to --confirm. The hosts below are fictional.
# --- staging ---
stg.url=ldaps://idm-stg.example.com:636
stg.bindDn=cn=idm-deploy,ou=sa,o=system
stg.passwordEnv=IDM_STG_PASSWORD
stg.driverSet=cn=driverset1,o=system
stg.tier=stg
stg.secrets=secrets-stg.properties
stg.sshHost=idm-stg.example.com
stg.sshUser=idm
# --- production ---
prd.url=ldaps://idm.example.com:636
prd.bindDn=cn=idm-deploy,ou=sa,o=system
prd.passwordEnv=IDM_PRD_PASSWORD
prd.driverSet=cn=driverset1,o=system
prd.tier=prd
prd.secrets=secrets-prd.properties
prd.requires=stg
# --- a lab with a private CA, or reached through an SSH tunnel ---
lab.url=ldaps://127.0.0.1:6636
lab.bindDn=cn=admin,ou=sa,o=system
lab.passwordKeychain=lab/cn=admin
lab.driverSet=cn=driverset1,o=system
lab.tier=dev
lab.trustAll=true # opt in: accept any certificate (and skip the host-name check a tunnel breaks)Required for every environment: url, bindDn, a password, driverSet.
tier is dev, stg, or prd (default dev when omitted).
The password is one of four keys, for password and for every other secret
(appsPassword, appsSecret, and each key in the secrets file):
| Key | Value |
|---|---|
<k>= |
A literal. Throwaway labs only |
<k>Env=VAR |
An environment variable |
<k>Command=… |
A command whose stdout is the secret (op read …, pass show …) |
<k>Keychain=service[/account] |
macOS Keychain. install.md has the security commands |
chmod 600 environments.properties secrets-*.propertiesThe tool warns when either file is readable by other users. It never prints a secret.
What the other keys do
secrets— file of shim passwords, Remote Loader passwords, and named passwords. A new driver's deploy refuses until each required secret is present (MISSING SECRET: <driver>.<key>in the plan). Existing drivers are left alone unless you pass--secrets missingor--secrets all.requires— on a production deploy, a green deploy of the same tree commit to that other environment must already be indeploy-log/.- (optional) the DirXML Trace Viewer:
bin/idm viewer.installonce, thendriver.trace view --env stg --driver Dopens it connected, or--fileon a trace file, for reading trace on the desktop. sshHost/sshUser— key-based SSH to the engine host, for reading a driver's trace file. Without themdriver.trace tailstreams the trace over LDAP instead (the engine's debug events;--followor--seconds N), so they are optional.servers—<serverDn>=<url>;…: the other servers of a multi-server driver set, when their URLs cannot be derived from the tree; import, deploy and the clone reach each server's own driver settings through them.trustAll— LDAPS verifies the server certificate against the JDK truststore (install.md §4.3).trustAll=trueopts in to accepting any certificate and skips the host-name check, for a lab with a private CA or an SSH tunnel; never on production.formsUrl,appsUser,appsPassword(any of the four forms), optionalappsClient(defaultrbpmrest) andappsSecret— only forbin/appsand forform.edit --env.
Give each environment its own eDirectory user with rights on its driver set
(and on the User Application driver's AppConfig when you deploy forms or
PRDs). admin is fine on a lab.
The tree holds one value per GCV and shim parameter: the base, what a fresh vault or a lab gets. A value that must differ per stage — the AD driver's domain name, a URL, a container DN — goes in one file per environment, beside the tree and committed with it:
# overrides/prd.properties
drivers/AD Driver.gcv.drv.domain.dns.name = corp.example.com
drivers/AD Driver.shim.pub-heartbeat-interval = 5
driverset.gcv.company.name = ACME CorpKeys are drivers/<driver>.gcv.<name> (a GCV the driver's scope defines,
its own or a linked GCV resource or the driver set's), drivers/<driver>.shim.<name>
(a shim parameter), drivers/<driver>.ecv.<name> (an engine control value),
drivers/<driver>.shim-auth-server and drivers/<driver>.shim-auth-id (the
driver object's own connection settings: a Remote Loader host, an AD account,
a REST base URL) and driverset.gcv.<name>. vault.diff and
vault.deploy --env prd use the base with prd's file applied, so the plan
shows prd's values and a stg deploy never sees them. import-live --env prd
folds the other way: a value prd's file covers refreshes that file when the
vault differs and leaves the base alone. validate reports a key that names
nothing (override-unknown) and a key set for one environment but not
another (override-missing-env). simulate tree/ --cases cases/ --env prd
runs the corpus with prd's values applied. The files are plain text, and
idm override.set tree/ --env prd --key "drivers/AD Driver.gcv.drv.domain.dns.name" --value corp.example.com
(with override.remove) edits them as an operation: the key is checked against
the tree before anything is written. Secrets are not overrides; they stay in the
environment's secrets file. That includes a shim auth id that is a credential
rather than a user name (an OAuth client id, an API key): put
<driver>.shim-auth-id=… in the secrets file, leave it out of the tree, and
the deploy applies it, the diff and the plan never show it, and an import never
writes it into the tree.
The live vault is the ground truth when you can reach it.
bin/idm import-live tree/ --env stg
bin/idm validate tree/
bin/idm vault.diff tree/ --env stgimport-live reads url, bindDn, the password, and driverSet from the
environment. A driver-set DN before the output directory overrides driverSet:
bin/idm import-live "cn=driverset1,o=system" tree/ --env stgThe older form, with credentials in IDM_JAVA_OPTS, still works when you have
no environments file yet:
IDM_JAVA_OPTS="-Dldap.url=ldaps://idm-stg.example.com:636 -Dldap.bindDn=cn=idm-deploy,ou=sa,o=system -Dldap.password=…" \
bin/idm import-live "cn=driverset1,o=system" tree/Do not put a real password in shell history. Prefer --env.
Other sources, when the vault is not the one you trust yet:
bin/idm import-project ~/designer_workspace/Client tree/
bin/idm import DriverSet-export.xml tree/
bin/idm import-ldif driverset.ldif tree/An LDIF the reader accepts is a subtree export from the driver set's DN
downwards, every entry with its objectClass values and the DirXML data
attributes (XmlData, DirXML-Data, DirXML-ShimConfigInfo,
DirXML-ConfigValues, DirXML-DriverFilter, DirXML-EngineControlValues,
DirXML-Policies, the entitlement and AppConfig objects). A plain
ldapsearch -b <driver set DN> -s sub '(objectClass=*)' gives exactly that;
an export that names attributes must include objectClass, and one whose
base is a driver rather than the driver set still works but yields only that
driver. When the reader finds no driver set it now says what the file held.
What to expect the first time:
validateon a tree imported from a running vault reports 0 errors. Warnings and infos (template placeholders, missing localisations) are normal. An error on a production tree is a finding: report it, and do not edit the tree to silence it.vault.diffright afterimport-livereports no differences. Exit status 1 means the tree and the vault differ.- Import writes
tree/.gitattributes(* -text) so git does not rewrite line endings. Keep that file. A CRLF inside an ECMAScript resource must survive checkout or the next diff will show it.
git add tree/ && git commit -m "Import stg driver set"These commands only read the tree.
bin/idm query tree/ drivers
bin/idm query tree/ artifacts "AD Driver"
bin/idm query tree/ chain "AD Driver" sub
bin/idm query tree/ gcvs "AD Driver"
bin/idm query tree/ tables "AD Driver"
bin/idm query tree/ fishbone "AD Driver"
bin/idm show tree/ "drivers/AD Driver/subscriber/sub-ctp-Transform"
bin/idm refs tree/ "library/lib-Shared"show, refs, and package.diff take an artifact path: the object's
name, with no filename extension (drivers/AD Driver/subscriber/sub-ctp-Transform,
not ….policy.xml). chain takes sub or pub.
bin/idm check tree/ loads the tree and exits 1 when a link points at nothing.
Before the first deploy, bin/idm doctor checks JDK 21, the simulator jar, and
lib/*.jar. --json is the same report. --env <name> also lists environments
(name, tier, and whether a URL, bind DN, password, and driver set are set) and
probes that environment's LDAPS. Passwords and bind DNs are not printed.
A command that changes the vault refuses unless IDM_AGENT_ALLOW_WRITE=1 or
--confirm <env> for that environment: vault.deploy --yes or --step,
vault.rollback --yes, vault.import-clone --yes, and the operate commands
that change a driver (driver.start|stop|restart|migrate|resync|submit,
driver.cache clear, driver.secrets set|remove, driver.trace set|reset).
--dry-run and read-only commands are not writes. The check runs before a
secret is resolved and before LDAP opens. --confirm prd satisfies both this
gate and the production tier.
GitHub Actions runs those doctor and write-gate tests without the proprietary
jars (mvn -B -Pidm.portable test). The full suite is mvn test where the
jars and the simulator are installed. Workstation setup and the CI variables
are install.md §2.4.
- Hand the same directory to an agent: agents.md.
- Change, prove, and deploy: day-to-day.md.
- The same loop as one narrative: walkthrough.md.
- File-by-file layout: tree-layout.md.
- Fictional samples: examples/.