IDM 7.2.2

Workflow

Guide to enabling and using ForgeRock® Identity Management workflows.

IDM provides an embedded workflow and business process engine based on Flowable and the Business Process Model and Notation (BPMN) 2.0 standard. This guide describes how to configure the workflow engine, and how to manage workflow tasks and processes using the REST interface and the admin UI.

Workflows are not supported with a DS repository. If you are using a DS repository for IDM data, you must configure a separate JDBC repository as the workflow datasource.

ForgeRock Identity Platform™ serves as the basis for our simple and comprehensive Identity and Access Management solution. We help our customers deepen their relationships with their customers, and improve the productivity and connectivity of their employees and partners. For more information about ForgeRock and about the platform, see https://www.forgerock.com.

The ForgeRock Common REST API works across the platform to provide common ways to access web resources and collections of resources.

BPMN 2.0 and workflow tools

Business Process Model and Notation 2.0 is the result of consensus among Business Process Management (BPM) system vendors. The Object Management Group (OMG) has developed and maintained the BPMN standard since 2004.

BPMN 2.0 lets you add artifacts that describe your workflows and business processes to IDM, for provisioning and other purposes. You can create workflow definitions using a text editor or the ForgeRock Workflow Editor UI. The ForgeRock Workflow Editor UI is an open-source project that is not supported or included in IDM. This visual workflow editor can be set up as a standalone node server or integrated directly with IDM.

Scripts inside BPMN 2.0 XML files have access to the following scripting variables:

  • openidm

  • identityServer

  • console

For example, to log a message with Groovy:

console.log('my message')

For more information about the graphical notations and XML representations for events, flows, gateways, tasks, process constructs, and more, see BPMN 2.0 Constructs.

IDM does not support the following constructs:

The following terms are reserved and cannot be used as variable names: out, out:print, lang:import, context, and elcontext.

Enable workflows

IDM embeds a Flowable Process Engine that starts in the OSGi container. Workflows are not active by default. IDM needs two configuration files to activate the workflow bundle:

workflow.json

The Flowable engine configuration, including the data source.

datasource.jdbc-default.json

The default data source for Flowable.

When you enable workflows in the admin UI, IDM creates workflow.json in your project’s conf/ directory.

  1. Log in to the admin UI.

  2. From the navigation bar, select Configure > System Preferences.

  3. On the System Preferences page, click the Workflow tab.

  4. Enable the display of workflows, and click Save.

  5. Optionally, configure the workflow engine.

  6. Configure the workflow data source.

Configure the workflow engine

IDM creates the default workflow.json file with the following structure:

{
    "useDataSource" : "default",
    "workflowDirectory" : "&{idm.instance.dir}/workflow",
    "userResource": {
        "path": "managed/user",
        "queryFilter": "/userName eq \"${username}\""
    },
    "groupResource": {
        "path": "managed/group",
        "queryFilter": "/id eq \"${gid}\""
    }
}
useDataSource

The datasource configuration file that points to the repository where Flowable should store data.

By default, this is the datasource.jdbc-default.json file. For information about changing the data store that Flowable uses, see Configure the Workflow Data Source.

workflowDirectory

Specifies the location where IDM expects to find workflow processes. By default, IDM looks for workflow processes in the project-dir/workflow directory.

In addition to these default properties, you can configure the Flowable engine history level:

{
    "history" : "audit"
}

When a workflow is executed, information can be logged as determined by the history level. The history level can be one of the following:

  • none This level results in the best performance for workflow execution, but no historical information is retained.

  • activity Logs all process instances and activity instances, without details.

  • audit This is the default level. All process instances, activity instances, and submitted form properties are logged so that all user interaction through forms is traceable and can be audited.

  • full This is the highest level of history logging and has the greatest performance impact. This history level stores all the information that is stored for the audit level, as well as any process variable updates.

Configure workflow email

Workflows can send an email using the following methods:

Flowable email tasks

To use workflow email tasks, add the email configuration to workflow.json.

Example email configuration:

"mail" : {
    "host" : "mail.example.com",
    "port" : 1025,
    "username" : "username",
    "password" : "password",
    "useSSL" : false,
    "starttls" : true,
    "defaultFrom" : "workflow@example.com",
    "forceTo" : "overrideSendToEmail@example.com"
}
scriptTask

Example script:

openidm.action("external/email", "send", { "to": "bob@example.com" }, { waitForCompletion: true });

Configure the workflow data source

The Flowable engine requires a JDBC database. The connection details to the database are specified in the datasource.jdbc-default.json file. If you are using a JDBC repository for IDM data, you will already have a datasource.jdbc-default.json file in your project’s conf/ directory. In this case, when you enable workflows, IDM uses the existing JDBC repository and creates the required Flowable tables in that JDBC repository.

If you are using a DS repository for IDM data, you must configure a separate JDBC repository as the workflow datasource. For more information, see Select a repository.

To specify a Flowable data source separate from your existing IDM repository, create a new datasource configuration file in your project’s conf/ directory (for example, datasource.jdbc-flowable.json) with the connection details to the separate data source. Then, reference that file in the useDataSource property of the workflow.json file (for example, "useDataSource" : "flowable").

For more information about the fields in this file, see JDBC Connection Configuration.

Custom workflow object mapping

For custom object mapping, edit the default workflow.json configuration:

"userResource": {
    "path": "managed/user",
    "queryFilter": "/userName eq \"${username}\""
},
"groupResource": {
    "path": "managed/group",
    "queryFilter": "/id eq \"${gid}\""
}

Do not replace ${username} or ${gid} in the queryFilter; for example:

  • OK: "queryFilter": "/callSign eq \"${username}\""

  • NOT OK: "queryFilter": "/callSign eq \"${callsign}\""

Test workflow integration

IDM reads workflow definitions from the /path/to/openidm/workflow directory.

The /path/to/openidm/samples/provisioning-with-workflow/ sample provides a workflow definition (contractorOnboarding.bar) that you can use to test the workflow integration.

  1. Create a workflow directory in your project directory and copy the sample workflow to that directory:

    cd project-dir
    mkdir workflow
    cp samples/provisioning-with-workflow/workflow/contractorOnboarding.bar workflow/
  2. Verify the workflow integration by using the REST API. The following REST call lists the defined workflows:

    curl \
    --header "X-OpenIDM-Username: openidm-admin" \
    --header "X-OpenIDM-Password: openidm-admin" \
    --header "Accept-API-Version: resource=1.0" \
    --request GET \
    "http://localhost:8080/openidm/workflow/processdefinition?_queryFilter=true"

    The result is similar to:

    {
      "result": [
        {
          "_id": "contractorOnboarding:1:5",
          "_rev": "1",
          "candidateStarterGroupIdExpressions": [],
          "candidateStarterUserIdExpressions": [],
          "category": "Examples",
          "deploymentId": "1",
          "description": null,
          "eventSupport": {},
          "executionListeners": {},
          "graphicalNotationDefined": false,
          "hasStartFormKey": true,
          "historyLevel": null,
          "ioSpecification": null,
          "key": "contractorOnboarding",
          "laneSets": [],
          "name": "Contractor onboarding process",
          "participantProcess": null,
          "processDiagramResourceName": "contractorOnboarding.contractorOnboarding.png",
          "properties": {},
          "resourceName": "contractorOnboarding.bpmn20.xml",
          "revisionNext": 2,
          "startFormHandler": null,
          "suspended": false,
          "suspensionState": 1,
          "taskDefinitions": null,
          "tenantId": "",
          "variables": null,
          "version": 1
        }
      ],
      "resultCount": 1,
      "pagedResultsCookie": null,
      "totalPagedResultsPolicy": "NONE",
      "totalPagedResults": -1,
      "remainingPagedResults": -1
    }

For more information about the above workflow, see Provision users with workflow.

For more information about managing workflows over REST, see Workflows.

Create workflows

For more information about the graphical notations and XML representations for events, flows, gateways, tasks, process constructs, and more, see BPMN 2.0 Constructs.

IDM does not support the following constructs:

  1. Create a workflow definition, and save it with a bpmn20.xml extension.

  2. Package the workflow definition file in a Business Archive File (.bar). A .bar file is similar to a .zip file, but with a different extension.

  3. Copy the .bar file to the openidm/workflow directory.

  4. Invoke the workflow using a script (openidm/script/), or directly, using the REST interface. For more information, see Invoke workflows.

    You can also schedule the workflow to be invoked repeatedly, or at a future time.

Workflow definition comparison

Versions of IDM prior to 7.0 used the Activiti workflow engine. If you are upgrading from one of these versions, your current workflow definitions will continue to work in compatibility mode, but new definitions must be written for the new engine, Flowable. The following overview shows the main differences between the old and new workflow definitions:

You can view additional upgrade information in the Flowable Migration Guide.

  1. Change all occurrences of activiti to flowable. Update examples:

    • Namespace

      xmlns:flowable="http://flowable.org/bpmn"
    • Elements

      <flowable:formProperty id="givenName" name="First Name" type="string" required="true"></flowable:formProperty>
      <flowable:formProperty id="sn" name="Last Name" type="string" required="true"></flowable:formProperty>
      <flowable:formProperty id="department" name="Department" type="string"></flowable:formProperty>
  2. Change task.getExecution(), per the changes to the sample file contractorOnboarding.bpmn20.xml:

    getExecution-flow-upgrade

Query workflows

The workflow implementation supports filtered queries that let you query the running process instances and tasks, based on specific query parameters. To perform a filtered query, send a GET request to the workflow/processinstance context path, including the query in the URL.

For example, the following query returns all process instances with the business key "newOrder", as invoked in the previous example:

curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"http://localhost:8080/openidm/workflow/processinstance?_queryId=filtered-query&processInstanceBusinessKey=newOrder"

Any workflow properties can be queried using the same notation; for example, processDefinitionId=managedUserApproval:1:6405. The query syntax applies to all queries with _queryId=filtered-query. The following query returns all process instances that were started by the user openidm-admin:

curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--request GET \
"http://localhost:8080/openidm/workflow/processinstance?_queryId=filtered-query&startUserId=openidm-admin"

You can also query process instances based on the value of any process instance variable, by prefixing the variable name with var-. For example:

var-processvariablename=processvariablevalue

Invoke workflows

You can invoke workflows and business processes from any trigger point within IDM, including reacting to situations discovered during reconciliation. Workflows can be invoked from script files, using the openidm.create() function, or directly from the REST interface.

The following sample script extract shows how to invoke a workflow from a script file:

/*
 * Calling 'myWorkflow' workflow
 */

var params = {
  "_key": "myWorkflow"
};

openidm.create('workflow/processinstance', null, params);

The null in this example indicates that you do not want to specify an ID as part of the create call. For more information, see openidm.create().

You can invoke the same workflow from the REST interface with the following REST call:

curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--request POST \
--data '{"_key":"myWorkflow"}' \
"http://localhost:8080/openidm/workflow/processinstance?_action=create"

For more information, see Workflows.

There are two ways in which you can specify the workflow definition that is used when a new workflow instance is started.

  • _key specifies the id attribute of the workflow process definition, for example:

    <process id="sendNotificationProcess" name="Send Notification Process">

    If there is more than one workflow definition with the same _key parameter, the latest deployed version of the workflow definition is invoked.

  • _processDefinitionId specifies the ID that is generated by the Flowable Process Engine when a workflow definition is deployed; for example:

    "sendNotificationProcess:1:104";

    To obtain the processDefinitionId, query the available workflows, for example:

    {
      "result": [
        {
          "name": "Process Start Auto Generated Task Auto Generated",
          "_id": "ProcessSAGTAG:1:728"
        },
        {
          "name": "Process Start Auto Generated Task Empty",
          "_id": "ProcessSAGTE:1:725"
        },
        ...
      ]
    }

    If you specify a _key and a _processDefinitionId, the _processDefinitionId is used because it is more precise.

Use the optional _businessKey parameter to add specific business logic information to the workflow when it is invoked. For example, the following workflow invocation assigns the workflow a business key of "newOrder". This business key can later be used to query "newOrder" processes.

curl \
--header "X-OpenIDM-Username: openidm-admin" \
--header "X-OpenIDM-Password: openidm-admin" \
--header "Accept-API-Version: resource=1.0" \
--request POST \
--data '{"_key":"myWorkflow", "_businessKey":"newOrder"}' \
"http://localhost:8080/openidm/workflow/processinstance?_action=create"

Access to workflows is based on IDM roles, and is configured in your project’s conf/process-access.json file. For more information, see Secure Access to Workflows.

Workflow audit

The audit service logs workflow information in the activity event topic (default location: openidm/audit/activity.audit.json).

Example workflow audit events using the provisioning-with-workflow sample:

Each step shows the action performed along with the resulting audit data.

  1. user1 completes the Contractor Onboarding Form.

    {
      "_id": "f24ac83b-200c-449d-b017-d12b9c6c9091-3871",
      "timestamp": "2020-05-06T17:39:52.021Z",
      "eventName": "workflow-create_process",
      "transactionId": "f24ac83b-200c-449d-b017-d12b9c6c9091-3865",
      "userId": "user1",
      "runAs": "user1",
      "objectId": "workflow/processinstance/6",
      "operation": "CREATE",
      "changedFields": [],
      "revision": null,
      "status": "SUCCESS",
      "message": "Process created. processDefinitionId = contractorOnboarding:1:5, processDefinitionKey = null, businessKey = null",
      "passwordChanged": false
    }
  2. manager1 self-assigns the task.

    {
      "_id": "f24ac83b-200c-449d-b017-d12b9c6c9091-5748",
      "timestamp": "2020-05-06T17:43:18.058Z",
      "eventName": "workflow-update_task",
      "transactionId": "f24ac83b-200c-449d-b017-d12b9c6c9091-5744",
      "userId": "manager1",
      "runAs": "manager1",
      "objectId": "workflow/taskinstance/36",
      "operation": "UPDATE",
      "changedFields": [
        "/assignee"
      ],
      "revision": null,
      "status": "SUCCESS",
      "message": "Task updated",
      "passwordChanged": false
    }

    "changedFields":["/assignee"] only displays when conf/audit.json contains the property "watchedFields" : [ "assignee" ]. For a complete list of fields that can be watched in this situation, see the API Descriptor for UPDATE workflow/taskinstance/.

  3. manager1 completes the task. Notice that transactionId is correlated to all managed/user, and other, operations.

    {
      "_id": "f24ac83b-200c-449d-b017-d12b9c6c9091-5868",
      "timestamp": "2020-05-06T17:43:22.138Z",
      "eventName": "activity",
      "transactionId": "f24ac83b-200c-449d-b017-d12b9c6c9091-5838",
      "userId": "user1",
      "runAs": "user1",
      "objectId": "managed/user/d736487d-c146-4a0e-b677-ebfd6805b1d2",
      "operation": "CREATE",
      "changedFields": [],
      "revision": "000000001edd9dc2",
      "status": "SUCCESS",
      "message": "create",
      "passwordChanged": false
    }
    {
      "_id": "f24ac83b-200c-449d-b017-d12b9c6c9091-5871",
      "timestamp": "2020-05-06T17:43:22.141Z",
      "eventName": "activity",
      "transactionId": "f24ac83b-200c-449d-b017-d12b9c6c9091-5838",
      "userId": "user1",
      "runAs": "user1",
      "objectId": "internal/usermeta/cd237cca-913e-481e-9282-ba16c84b5131",
      "operation": "CREATE",
      "changedFields": [],
      "revision": "0000000030b45c3e",
      "status": "SUCCESS",
      "message": "create",
      "passwordChanged": false
    }
    {
      "_id": "f24ac83b-200c-449d-b017-d12b9c6c9091-5876",
      "timestamp": "2020-05-06T17:43:22.145Z",
      "eventName": "relationship_created",
      "transactionId": "f24ac83b-200c-449d-b017-d12b9c6c9091-5838",
      "userId": "user1",
      "runAs": "user1",
      "objectId": "managed/user/d736487d-c146-4a0e-b677-ebfd6805b1d2/authzRoles/ee5bbbce-a020-45db-ab41-66c80d84d8be",
      "operation": "CREATE",
      "changedFields": [],
      "revision": "00000000fe6da3a7",
      "status": "SUCCESS",
      "message": "Relationship originating from managed/user/d736487d-c146-4a0e-b677-ebfd6805b1d2 via the relationship field authzRoles and referencing internal/role/openidm-authorized was created.",
      "passwordChanged": false
    }
    {
      "_id": "f24ac83b-200c-449d-b017-d12b9c6c9091-5879",
      "timestamp": "2020-05-06T17:43:22.147Z",
      "eventName": "relationship_created",
      "transactionId": "f24ac83b-200c-449d-b017-d12b9c6c9091-5838",
      "userId": "user1",
      "runAs": "user1",
      "objectId": "managed/user/d736487d-c146-4a0e-b677-ebfd6805b1d2/manager/b58e5695-9e43-4e76-b89c-e5d69d3bf52d",
      "operation": "CREATE",
      "changedFields": [],
      "revision": "000000008dcca1b6",
      "status": "SUCCESS",
      "message": "Relationship originating from managed/user/d736487d-c146-4a0e-b677-ebfd6805b1d2 via the relationship field manager and referencing managed/user/038e65de-95ce-4180-94d3-4ea64bf25c6b was created.",
      "passwordChanged": false
    }
    {
      "_id": "f24ac83b-200c-449d-b017-d12b9c6c9091-5882",
      "timestamp": "2020-05-06T17:43:22.149Z",
      "eventName": "relationship_created",
      "transactionId": "f24ac83b-200c-449d-b017-d12b9c6c9091-5838",
      "userId": "user1",
      "runAs": "user1",
      "objectId": "managed/user/d736487d-c146-4a0e-b677-ebfd6805b1d2/_meta/d9299603-b768-44b6-a4c9-9b6441ca212e",
      "operation": "CREATE",
      "changedFields": [],
      "revision": "0000000027b29fb4",
      "status": "SUCCESS",
      "message": "Relationship originating from managed/user/d736487d-c146-4a0e-b677-ebfd6805b1d2 via the relationship field _meta and referencing internal/usermeta/cd237cca-913e-481e-9282-ba16c84b5131 was created.",
      "passwordChanged": false
    }
    {
      "_id": "f24ac83b-200c-449d-b017-d12b9c6c9091-5908",
      "timestamp": "2020-05-06T17:43:22.778Z",
      "eventName": "activity",
      "transactionId": "f24ac83b-200c-449d-b017-d12b9c6c9091-5838",
      "userId": "user1",
      "runAs": "user1",
      "objectId": "internal/notification/12aa1698-bb1e-42c6-a92d-2e959c217ad0",
      "operation": "CREATE",
      "changedFields": [],
      "revision": "000000004d025d75",
      "status": "SUCCESS",
      "message": "create",
      "passwordChanged": false
    }
    {
      "_id": "f24ac83b-200c-449d-b017-d12b9c6c9091-5911",
      "timestamp": "2020-05-06T17:43:22.781Z",
      "eventName": "relationship_created",
      "transactionId": "f24ac83b-200c-449d-b017-d12b9c6c9091-5838",
      "userId": "user1",
      "runAs": "user1",
      "objectId": "internal/notification/12aa1698-bb1e-42c6-a92d-2e959c217ad0/target/eec80d30-be1e-4c5d-9873-b4395373c833",
      "operation": "CREATE",
      "changedFields": [],
      "revision": "00000000b4c7a701",
      "status": "SUCCESS",
      "message": "Relationship originating from internal/notification/12aa1698-bb1e-42c6-a92d-2e959c217ad0 via the relationship field target and referencing managed/user/038e65de-95ce-4180-94d3-4ea64bf25c6b was created.",
      "passwordChanged": false
    }
    {
      "_id": "f24ac83b-200c-449d-b017-d12b9c6c9091-5920",
      "timestamp": "2020-05-06T17:43:22.791Z",
      "eventName": "activity",
      "transactionId": "f24ac83b-200c-449d-b017-d12b9c6c9091-5838",
      "userId": "user1",
      "runAs": "user1",
      "objectId": "internal/notification/eec030e5-e520-4cf1-99c2-a9bbecb0627b",
      "operation": "CREATE",
      "changedFields": [],
      "revision": "0000000033465ada",
      "status": "SUCCESS",
      "message": "create",
      "passwordChanged": false
    }
    {
      "_id": "f24ac83b-200c-449d-b017-d12b9c6c9091-5923",
      "timestamp": "2020-05-06T17:43:22.794Z",
      "eventName": "relationship_created",
      "transactionId": "f24ac83b-200c-449d-b017-d12b9c6c9091-5838",
      "userId": "user1",
      "runAs": "user1",
      "objectId": "internal/notification/eec030e5-e520-4cf1-99c2-a9bbecb0627b/target/11eb13f8-991f-45ea-95dc-e8f0fd0b95c3",
      "operation": "CREATE",
      "changedFields": [],
      "revision": "000000005134a80d",
      "status": "SUCCESS",
      "message": "Relationship originating from internal/notification/eec030e5-e520-4cf1-99c2-a9bbecb0627b via the relationship field target and referencing managed/user/d736487d-c146-4a0e-b677-ebfd6805b1d2 was created.",
      "passwordChanged": false
    }
  4. The audit service logs the workflow-complete_task event.

    {
      "_id": "f24ac83b-200c-449d-b017-d12b9c6c9091-5926",
      "timestamp": "2020-05-06T17:43:22.827Z",
      "eventName": "workflow-complete_task",
      "transactionId": "f24ac83b-200c-449d-b017-d12b9c6c9091-5838",
      "userId": "manager1",
      "runAs": "manager1",
      "objectId": "workflow/taskinstance/36",
      "operation": "complete",
      "changedFields": [],
      "revision": null,
      "status": "SUCCESS",
      "message": "Task completed",
      "passwordChanged": false
    }

Custom workflow templates

The embedded workflow engine integrates with the default End User UI. For simple custom workflows, you can use the standard Flowable form properties, and have the UI render the corresponding generic forms automatically. For more complex functionality, including input validation, rich input field types, complex CSS, and more, you must define a custom form template.

The default workflows provided with IDM use the Vue JS framework for display in the End User UI. To write a custom form template, you must have a basic understanding of the Vue JS framework and how to create components. A sample workflow template is provided at /path/to/samples/provisioning-with-workflow/workflow/contractorOnboarding.bar. To extract the archive, run the following command:

jar -xvf contractorOnboarding.bar
inflated: contractorForm.js
inflated: contractorOnboarding.bpmn20.xml

The archive includes the workflow definition contactorOnboarding.bpmn20.xml and the corresponding JavaScript template contractorForm.js to render the workflow in the UI.