Provisioner

The Provisioner connects Wren:IDM to external systems through connector plugins and exposes them as CREST resources under the /system endpoint. Wren:IDM ships with one provisioner implementation: the Wren:ICF (OpenICF) provisioner, which integrates with Identity Connector Framework connectors.

Architecture

The provisioner layer consists of three cooperating services.

System Object Set Service

OSGi service class

org.forgerock.openidm.provisioner.impl.SystemObjectSetService

OSGi persistent identifier

org.forgerock.openidm.provisioner

Router mapping

/system

The System Object Set Service is a singleton that owns the /system route and acts as a hub across all active provisioner instances. It aggregates any number of running ProvisionerService implementations. It dispatches system-level actions to the appropriate instance, such as testing connections, triggering live sync, and generating connector configurations. It also implements the ScheduledService interface, so the Wren:IDM Scheduler can trigger live sync through it. No configuration file is required. The service starts unconditionally.

OpenICF Provisioner Service

OSGi service class

org.forgerock.openidm.provisioner.openicf.impl.OpenICFProvisionerService

OSGi persistent identifier

org.forgerock.openidm.provisioner.openicf

Configuration file

provisioner.openicf-[name].json

One OpenICF Provisioner Service instance is created per connector configuration file. Each instance registers its own routes under /system/<name> and /system/<name>/{objectClass}, where <name> is read from the name field of the configuration file. The service resolves the connector bundle asynchronously via ConnectorInfoProviderService and builds a ConnectorFacade when the connector info becomes available. Setting enabled to false in the configuration prevents connector initialisation and route registration while keeping the OSGi service active.

Connector Info Provider Service

OSGi service class

org.forgerock.openidm.provisioner.openicf.impl.ConnectorInfoProviderService

OSGi persistent identifier

org.forgerock.openidm.provisioner.openicf.connectorinfoprovider

Configuration file

provisioner.openicf.connectorinfoprovider.json (optional)

The Connector Info Provider Service loads connector bundles from the local file system and from remote Wren:ICF connector servers. It makes these bundles available to all provisioner instances. Because its OSGi configuration policy is OPTIONAL, the service starts without a configuration file using built-in defaults.

Connector Info Provider configuration

The optional provisioner.openicf.connectorinfoprovider.json file controls where connectors are loaded from and how remote connector servers are reached.

provisioner.openicf.connectorinfoprovider.json structure
{
  "connectorsLocation": "connectors",
  "remoteConnectorServers": [
    {
      "name": "myServer",
      "host": "connector-host.example.com",
      "port": 8759,
      "key": { "$crypto": { "type": "x-simple-encryption", "value": { "cipher": "AES/CBC/PKCS5Padding", "data": "..." } } },
      "useSSL": false,
      "timeout": 0,
      "protocol": "websocket"
    }
  ],
  "remoteConnectorServersGroups": [
    {
      "name": "myGroup",
      "algorithm": "failover",
      "serversList": [ "myServer" ]
    }
  ]
}
connectorsLocation

Path to the directory containing local connector JAR files. Relative paths resolve against the Wren:IDM installation directory (the --install-location / -i startup parameter), or the process working directory when that parameter is not set. Default: connectors.

remoteConnectorServers

List of remote Wren:ICF connector servers to connect to.

name

Unique name for this server. Referenced as connectorHostRef in provisioner configuration files. Required.

host

Hostname or IP address of the remote connector server. Required.

port

TCP port. Default: 8759.

key

Shared secret used to authenticate with the remote server. Store as an encrypted value using the $crypto wrapper. To produce the encrypted value, use the Crypto service encrypt action, the Wren:IDM admin UI, or the CLI local:encrypt command. See Crypto service. Required.

useSSL

Whether to use SSL/TLS. Default: false.

timeout

Connection timeout in milliseconds, passed as the timeout parameter to the ICF RemoteFrameworkConnectionInfo constructor. The ICF framework defines the exact scope (TCP establishment vs. socket read). 0 means no timeout. Default: 0.

protocol

Set to "websocket" to use the WebSocket-based ICF 1.5 protocol. Default: absent (ICF 1.4 Java serialisation protocol is used).

remoteConnectorServersGroups

Load-balancing groups over named remote servers. A group name can be used as a connectorHostRef value just like a single server name.

name

Group identifier, referenced as connectorHostRef in provisioner configs.

algorithm

Load-balancing strategy: "failover" always sends to the first available server in order. "roundrobin" distributes requests across all servers in the list.

serversList

Ordered list of server names from remoteConnectorServers to include in this group. For the failover algorithm, the first reachable server in this list is used. Order therefore determines failover priority.

Connector configuration

One configuration file per connector is required.

The [name] portion after the dash is only a Configuration Admin alias. The name field inside the JSON body always determines the actual system name used in resource paths, regardless of this alias.

The value must be alphanumeric. A name that fails this check causes a configuration activation error (JsonValueException).

Example provisioner.openicf-ldap.json (illustrative, abbreviated)
{
  "name": "ldap",
  "enabled": true,
  "connectorRef": {
    "bundleName": "org.forgerock.openicf.connectors.ldap-connector",
    "bundleVersion": "[1.4.0.0,1.5.0.0)",
    "connectorName": "org.identityconnectors.ldap.LdapConnector",
    "connectorHostRef": "myServer"
  },
  "poolConfigOption": {
    "maxObjects": 10,
    "maxIdle": 10,
    "maxWait": 150000,
    "minEvictableIdleTimeMillis": 120000,
    "minIdle": 1
  },
  "operationTimeout": {
    "CREATE": -1,
    "UPDATE": -1,
    "DELETE": -1,
    "SEARCH": -1,
    "SYNC": -1,
    "TEST": -1,
    "AUTHENTICATE": -1,
    "SCHEMA": -1,
    "VALIDATE": -1,
    "SCRIPT_ON_CONNECTOR": -1,
    "SCRIPT_ON_RESOURCE": -1
  },
  "configurationProperties": {},
  "resultsHandlerConfig": {
    "enableNormalizingResultsHandler": true,
    "enableFilteredResultsHandler": true,
    "enableCaseInsensitiveFilter": false,
    "enableAttributesToGetSearchResultsHandler": true
  },
  "syncFailureHandler": {
    "maxRetries": 5,
    "postRetryAction": "logged-ignore"
  }
}
name

The system identifier. It becomes the route segment at /system/<name>. Required.

enabled

Set to false to disable this connector without removing the configuration file. Default: true.

connectorRef

Identifies the connector bundle to load.

bundleName

OSGi bundle symbolic name of the connector. Required.

bundleVersion

Version or version range of the connector bundle. Uses OSGi range syntax, where [ is inclusive and ) is exclusive (e.g. [1.4.0.0,1.5.0.0)). Required.

connectorName

Fully-qualified Java class name of the connector implementation. Required.

connectorHostRef

Name of the remote server or group that hosts this connector. The value may be a server name or a group name defined in remoteConnectorServersGroups. See Connector Info Provider configuration. Omit for locally-deployed connector JARs. When absent, the connector bundle is resolved from the local connectorsLocation directory instead. When set to a name that does not match any entry in remoteConnectorServers or remoteConnectorServersGroups, the connector facade cannot be initialised. All operations on this connector then return ServiceUnavailableException at runtime.

configurationProperties

Connector-specific key/value properties passed directly to the connector. The available keys are connector-dependent. To discover them, call createCoreConfig (see System-level actions) with a request body containing a connectorRef object. The response includes a configurationProperties map with key names and type metadata. Copy this map into the configuration file. For the full annotated schema including per-operation option names, call createFullConfig with a body containing both connectorRef and an (initially empty) configurationProperties object.

poolConfigOption

Connection pool settings for the connector instance. When this block is omitted, the ICF framework’s own defaults apply unchanged. The example values shown in the configuration skeleton (10 / 10 / 150000 / 120000 / 1) are illustrative. The actual ICF framework defaults may differ. To get the true defaults for a specific connector, call createCoreConfig (see System-level actions). The returned skeleton includes a poolConfigOption block populated with the ICF framework defaults for that connector.

  • maxObjects – Maximum total number of objects (idle + active) in the pool.

  • maxIdle – Maximum number of idle objects to keep in the pool.

  • maxWait – Maximum wait time in milliseconds for a pooled connection before an error is thrown.

  • minEvictableIdleTimeMillis – Minimum time in milliseconds an idle connection must remain in the pool before becoming eligible for eviction.

  • minIdle – Minimum number of idle connections to maintain.

operationTimeout

Per-operation timeouts in milliseconds. -1 means no timeout. Recognised keys: CREATE, UPDATE, DELETE, SEARCH, SYNC, TEST, AUTHENTICATE, SCHEMA, VALIDATE, SCRIPT_ON_CONNECTOR, SCRIPT_ON_RESOURCE, GET, RESOLVEUSERNAME. Keys not in this set are never read and have no effect.

resultsHandlerConfig

Controls the ICF results handler chain applied to search results returned by the connector. When this block is omitted, the ICF framework’s own defaults for each field apply. To discover the effective defaults for a specific connector, call createCoreConfig (see System-level actions). The returned skeleton includes a resultsHandlerConfig block populated with the ICF framework defaults.

enableNormalizingResultsHandler

When true, attribute names in search results are normalised to the IDM-side names defined in objectTypes before being returned.

enableFilteredResultsHandler

When true, Wren:IDM applies the requested filter expression in-memory after receiving all results from the connector. Disable this only when the connector natively supports the filter expression, to avoid fetching the full result set from the remote system.

enableCaseInsensitiveFilter

When true, the IDM-side filtered results handler compares attributes case-insensitively. Has no effect when enableFilteredResultsHandler is false.

enableAttributesToGetSearchResultsHandler

When true, the results handler trims search results to include only the attributes the query explicitly requests. It removes unrequested attributes after the connector returns them.

syncFailureHandler

Retry and error strategy for live sync delta processing. See Live sync.

objectTypes

Schema for each connector object type. See Object types.

operationOptions

Per-operation access control and option definitions. See Operation options.

systemActions

Named script actions that can be invoked on the connector or target resource. See Script system actions.

Object types

The objectTypes map defines the schema for each object class exposed by the connector. This field is optional. When absent, the map defaults to empty. Only the automatically-added ICF ALL handler is available, and no /system/<name>/<objectType> resource routes are registered until at least one entry is defined. Keys are IDM-side names chosen by the operator (e.g. account, group). These names have no special meaning in the provisioner code. The ICF ObjectClass identity depends entirely on nativeType.

Example objectTypes entry
{
  "objectTypes": {
    "account": {
      "$schema": "http://json-schema.org/draft-03/schema",
      "id": "__ACCOUNT__",
      "type": "object",
      "nativeType": "__ACCOUNT__",
      "properties": {
        "uid": {
          "type": "string",
          "nativeName": "__NAME__",
          "nativeType": "string"
        },
        "password": {
          "type": "string",
          "nativeName": "__PASSWORD__",
          "nativeType": "JAVA_TYPE_GUARDEDSTRING",
          "flags": [ "NOT_READABLE", "NOT_RETURNED_BY_DEFAULT" ]
        }
      }
    }
  }
}

Each object type entry:

$schema

Not read by the ICF provisioner.

type

Not read by the ICF provisioner.

id

Not read by the ICF provisioner. Set it to the same value as nativeType (e.g. ACCOUNT).

nativeType

ICF ObjectClass name at the connector level. This is the field actually read by the ICF provisioner code to identify the connector object class. By convention, id should carry the same value.

properties

Map of IDM-side attribute names to attribute schema definitions.

Each attribute entry:

type

JSON schema type or Java type constant. Common values: string, boolean, integer, JAVA_TYPE_GUARDEDSTRING, JAVA_TYPE_GUARDEDBYTEARRAY.

nativeName

The ICF attribute name on the target system (e.g. NAME, PASSWORD, cn, sAMAccountName).

nativeType

Java type used for ICF serialisation.

flags

Optional array of modifier flags. When the flags array is absent or empty, the attribute is updateable, creatable, readable, returned by default, single-valued, and optional. Available flag values:

  • NOT_CREATABLE – Cannot be set during object creation.

  • NOT_UPDATEABLE – Cannot be modified after creation.

  • NOT_READABLE – Cannot be read from the target system.

  • NOT_RETURNED_BY_DEFAULT – Not included in results unless explicitly requested.

  • MULTIVALUED – Holds a list of values rather than a single value.

  • PASSWORD – Marks the attribute as a credential value.

  • NOT_QUERYABLE – Cannot be used in query filter expressions.

  • AUDITED – Value is included in audit log entries.

  • STORE_IN_REPOSITORY – Value is persisted in the Wren:IDM repository.

  • IGNORE – Defined in the schema but not passed to the connector.

  • REMOTE – Value is generated externally and must be read back before being sent to the resource.

Operation options

The operationOptions map controls whether specific ICF operations are permitted and what additional options are passed to the connector. Keys are ICF operation names. The valid key set is the same as for operationTimeout. Recognised keys: CREATE, UPDATE, DELETE, SEARCH, SYNC, TEST, AUTHENTICATE, SCHEMA, VALIDATE, SCRIPT_ON_CONNECTOR, SCRIPT_ON_RESOURCE, GET, RESOLVEUSERNAME.

Example (illustrative, denies DELETE on accounts and scopes a SEARCH restriction to account)
{
  "operationOptions": {
    "DELETE": {
      "denied": true,
      "supportedObjectTypes": [ "account" ]
    },
    "SEARCH": {
      "denied": false,
      "supportedObjectTypes": [ "account" ]
    }
  }
}

Each entry accepts:

denied

When true, the operation is blocked and returns an error to the caller. Default: false.

denied: true has no effect unless supportedObjectTypes is also present on the same entry. When supportedObjectTypes is absent, the denied check is not evaluated. The operation proceeds as if no operationOptions entry existed for that key, and no restriction applies. This check runs before any other per-operation logic on the connector. When it blocks, getConnectorFacade0() throws ForbiddenException immediately, and no further processing occurs.
supportedObjectTypes

List of IDM-side object type names (keys from objectTypes) to which this entry applies. When present, the denied check and operationOptionInfo options are scoped to the listed types. When absent, the denied check is never evaluated (regardless of the denied value), and operationOptionInfo options apply to all object types.

operationOptionInfo

JSON schema (draft-03) describing additional ICF OperationOptions properties to include when this operation is invoked. Valid option names are connector-specific. To discover them, call the createFullConfig action (see System-level actions), which returns an annotated configuration skeleton that includes the operationOptions schema for the connector. The provisioner applies the defined options automatically from the connector configuration on each invocation. Callers do not pass them explicitly in the HTTP request.

Resource paths and operations

System objects are addressed at:

/system/<name>/<objectType>/<id>

where:

  • <name> is the value of the provisioner’s name field.

  • <objectType> is a key from objectTypes.

  • <id> is the object identifier. URL-encode it when it contains special characters such as / or +.

The system/ prefix is optional. Both system/ldap/account/jdoe and ldap/account/jdoe are accepted as identifiers.

The ObjectClassResourceProvider handles CREST requests for a given object type and delegates each operation to the corresponding ICF API operation:

  • Create → CreateApiOp

  • Read → GetApiOp

  • Update → UpdateApiOp

  • Delete → DeleteApiOp

  • Patch → UpdateApiOp

  • Query → SearchApiOp

Operations not supported by the connector return NotSupportedException. An operation blocked by denied: true in operationOptions also returns an error.

The authenticate action on an object instance verifies a credential against the connector via AuthenticationApiOp. The action requires username and password as request additional parameters (HTTP query parameters). For example: POST /openidm/system/ldap/account?_action=authenticate&username=jdoe&password=secret On success it returns the connector Uid of the authenticated object.

Update and patch operations support a separate re-authentication mechanism. If the request includes an X-OpenIDM-Reauth-Password HTTP header, the provisioner reads the username from the request body. It uses the attribute named by the first entry of configurationProperties.accountUserNameAttributes. It then verifies the credential via AuthenticationApiOp before applying the change.

The denied/supportedObjectTypes coupling also governs re-authentication ordering. When it blocks the operation, the X-OpenIDM-Reauth-Password header above is never evaluated.

System-level actions

Actions are invoked on the /system singleton (SystemObjectSetService) via a CREST action request.

test

Returns connection status for all active provisioner instances as a JSON array. To test a single named system, include id as a field in the request body (e.g. { "id": "ldap" }). The response is then a single status object rather than an array. Each status object contains the following fields:

  • name: system name.

  • enabled: boolean.

  • config: config path.

  • connectorRef.

  • objectTypes: list of configured type names.

  • ok: boolean connection success.

  • error: present when the connection fails.

    The per-connector test action (see Per-connector actions) returns this same object for a single connector instance.

testConfig

Tests a connector configuration payload without persisting it. The request body must be a full connector configuration including a name field.

liveSync / activeSync

Triggers live sync for a specific object type. Requires a source query parameter in the form system/<name>/<objectType> (e.g. ?source=system/ldap/account). The system/ prefix is optional here too, per Resource paths and operations. For example, source=ldap/account is equally valid. The optional boolean query parameter detailedFailure controls whether the syncDelta field is included inside the lastException object of the action response body. When false (the default), the syncDelta field is removed from lastException before the response is returned. When true, the full syncDelta object is retained in lastException.

availableConnectors

Lists all connector types available through the active Connector Info Provider.

createConfiguration

Multi-phase configuration wizard invoked as POST /system?_action=createConfiguration.

Phase 1 (empty request body)

Returns a list of available connectors.

Phase 2 (body contains connectorRef but no configurationProperties)

Generates the core configuration skeleton for the selected connector.

Phase 3 (body contains both connectorRef and configurationProperties)

Validates and returns the full configuration.

When the connector type is already known, createCoreConfig and createFullConfig complete phases 2 and 3 directly, without the phase-1 connector listing step.

createCoreConfig

Single-call equivalent of phase 2 of createConfiguration (generates the core configuration skeleton). Endpoint: POST /system?_action=createCoreConfig. The request body must be a JSON object containing a connectorRef object (with bundleName, bundleVersion, and connectorName). The configurationProperties field must be absent or null.

Example request body
{
  "connectorRef": {
    "bundleName": "org.forgerock.openicf.connectors.ldap-connector",
    "bundleVersion": "[1.4.0.0,1.5.0.0)",
    "connectorName": "org.identityconnectors.ldap.LdapConnector"
  }
}
createFullConfig

Single-call equivalent of phase 3 of createConfiguration (validates and returns the full annotated configuration). Endpoint: POST /system?_action=createFullConfig. The request body must contain both connectorRef and a configurationProperties object (may be the map returned by createCoreConfig, populated with actual values).

Per-connector actions

Actions can be invoked directly on a connector instance at /system/<name>.

test

Tests the connection for this specific connector and returns its status object.

livesync

Triggers live sync for this connector instance, equivalent to calling the liveSync system action with this connector as the source. The action name at the per-connector endpoint is livesync (all lowercase). At the system-level endpoint the equivalent action is liveSync (camelCase). Internally, getActionAsEnum() resolves both names case-insensitively. Either endpoint accepts any casing variant (e.g. LIVESYNC, LiveSync).

script

Executes a named system action defined in systemActions. See Script system actions.

Live sync

Live sync captures changes that occurred on the external system since the last invocation and delivers them to Wren:IDM. Not all connectors support live sync. Support depends on the connector implementing SyncApiOp.

On each invocation, the provisioner reads a sync stage object from repo/synchronisation/pooledSyncStage. The stage ID is derived from the source path by removing all / characters and uppercasing the result (for example, system/ldap/account becomes SYSTEMLDAPACCOUNT). The previous stage is passed to ProvisionerService.liveSynchronize(), and the returned updated stage is written back to the repository. On the first invocation for a given source, no stage record exists in the repository. The provisioner passes null as the stage to the connector’s sync API. When the connector receives a null sync token, it determines its own starting point. This behavior is connector-specific, and Wren:IDM does not control it.

The Scheduler can trigger live sync automatically. Set the scheduler job’s invokeService to "provisioner" and place action and source in the invokeContext block.

Example live sync scheduler job (schedule-liveSync-ldap.json)
{
  "enabled": true,
  "type": "cron",
  "schedule": "0/15 * * * * ?",
  "persisted": true,
  "invokeService": "provisioner",
  "invokeContext": {
    "action": "liveSync",
    "source": "system/ldap/account"
  }
}

The invokeContext fields are:

action

Must be "liveSync" (or "activeSync", which is a recognised alias at the system-level endpoint). The value is resolved case-insensitively via Utils.asEnum. "livesync", "LIVESYNC", and "liveSync" are all accepted. Use "liveSync" (camelCase) as the canonical form to match the system-level action name.

source

Resource path in the form system/<name>/<objectType> identifying the object type to sync. The system/ prefix is optional here too, per Resource paths and operations.

Sync failure handling

The syncFailureHandler object in the connector configuration controls what happens when processing a sync delta fails.

syncFailureHandler configuration
{
  "syncFailureHandler": {
    "maxRetries": 5,
    "postRetryAction": "dead-letter-queue"
  }
}
maxRetries

Number of retry attempts before invoking postRetryAction. -1 or absent means retry indefinitely, and postRetryAction is never called. 0 means call postRetryAction immediately on first failure without retrying.

postRetryAction

Action taken when retries are exhausted. Accepts a string shorthand or a script object:

"dead-letter-queue"

Persists the failed sync delta to repo/synchronisation/deadLetterQueue/<systemIdentifier>/<token>. The stored document contains the following top-level fields:

  • token: the sync token value, also used as the resource ID.

  • systemIdentifier: the connector name, also used as the sub-path.

  • objectType: the object type being synced.

  • uid: the ICF UID of the affected object.

  • failedRecord: the connector object payload at the time of failure, if available.

  • failureCause: the exception message string.

    Query or drain the queue via the standard repository API at that path.

"logged-ignore"

Logs the failure and discards the delta.

{ "script": { …​ } }

Calls a custom script. The inner script object uses the standard Wren:IDM script registry format. Set "type" to the language identifier (e.g. "groovy", "javascript"). Supply the script body via "source" (inline text) or "file" (path to a script file). See Scripts for the full field reference and supported engines. The script receives the following bindings:

  • context: request context.

  • syncFailure: map with keys token, systemIdentifier, objectType, uid, and failedRecord.

  • failureCause: the exception that caused the failure.

  • failureHandlers: a map with pre-built "loggedIgnore" and "deadLetterQueue" handler instances the script can delegate to.

Omitting syncFailureHandler entirely has the same effect as an absent maxRetries: sync deltas are retried indefinitely.

Script system actions

The systemActions list defines named scripts that execute on the connector or the target resource via the script action at /system/<name>.

Example systemActions entry
{
  "systemActions": [
    {
      "scriptId": "resetPassword",
      "actions": [
        {
          "systemType": "provisioner.openicf.*",
          "actionType": "Groovy",
          "actionSource": "// Groovy script body"
        }
      ]
    }
  ]
}
scriptId

The action name, passed as the scriptId query parameter when invoking the script action at /system/<name>. For example: POST /system/ldap?_action=script&scriptId=resetPassword. Required.

actions

List of system type-specific script entries. The systemType value is matched as a regular expression against the provisioner type string (e.g. provisioner.openicf). Required.

systemType

Regular expression matched against the provisioner type. Required.

actionType

Script language identifier (e.g. Groovy, JavaScript). Required.

actionSource

Inline script text. Mutually exclusive with actionFile.

actionFile

Path to a script file, resolved against the Wren:IDM project root. Mutually exclusive with actionSource. When both are present, actionFile takes precedence and actionSource is ignored.