Upgrade Guide

This guide provides instructions for upgrading Wren:IDM to the new version.

Wren:IDM 7.3.0

If you are upgrading to the Wren:IDM 7.3.0, please follow the steps below.

Migrate Felix web console configuration

The Felix web console is now disabled by default and the built-in Felix fallback credentials are no longer accepted. The web console is available only when it is explicitly enabled in the conf/felix.webconsole.json file.

Add the following property to the conf/config.properties file, so that the Felix web console accepts only the Wren:IDM security provider:

+ # Require the Wren:IDM security provider for the Felix web console. This disables the built-in Felix
+ # fallback credentials; the console is available only when enabled in conf/felix.webconsole.json.
+ felix.webconsole.security.providers=wrenidm

If you use the Felix web console, enable it in the conf/felix.webconsole.json file and set a strong password:

Example 1. Felix web console configuration
{
+ "enabled" : true,
  "username" : "admin",
- "password" : "admin"
+ "password" : "<strong-password>"
}

When the enabled property is missing, the web console is disabled and all requests to it are rejected with 404 Not Found.

Review configuration save setting

The felix.fileinstall.enableConfigSave property in the conf/config.properties file is now respected. In previous versions, this property was ignored and configuration changes (for example changes made through the REST API or the Admin UI) were always written back to the configuration files in the conf/ directory.

The default config.properties file in Wren:IDM 7.2.0 and earlier contains felix.fileinstall.enableConfigSave=false. If you keep this line, configuration changes will no longer be written back to the configuration files after the upgrade. To keep the previous behavior, remove or comment out the property:

- # Disable file configuration update
- felix.fileinstall.enableConfigSave=false
+ # Configuration changes are written back to the configuration files by default,
+ # uncomment the following line to disable it.
+ #felix.fileinstall.enableConfigSave=false

The deprecated felix.fileinstall.disableConfigSave property is no longer supported. If you use it, replace it with felix.fileinstall.enableConfigSave.

Update connector bundle versions

The bundled Wren:ICF connectors have been upgraded:

  • Groovy connector to version 1.5.4.0

  • LDAP connector to version 1.5.3.3

If your provisioner configuration files (conf/provisioner.openicf-*.json) reference an exact connector version, or a version range that does not include the new version, update the bundleVersion field:

Example 2. Provisioner bundle version migration
{
  "connectorRef" : {
    "bundleName" : "org.wrensecurity.wrenicf.connectors.groovy-connector",
-   "bundleVersion" : "1.5.3.1",
+   "bundleVersion" : "1.5.4.0",
    "connectorName" : "org.forgerock.openicf.connectors.scriptedrest.ScriptedRESTConnector"
  },
  ...
}

If you build custom scripted connectors with the custom scripted connector bundler, rebuild them against the Groovy connector 1.5.4.0.

Migrate Scripted REST connector scripts

The http-builder library (groovyx.net.http) is no longer shipped with the Groovy connector and Wren:IDM. Scripted REST connector scripts that use RESTClient or other groovyx.net.http classes must be migrated to the Apache HttpClient API.

Follow these steps to migrate your scripts:

  1. Migrate customizer script

    Remove the decorate closure that creates the RESTClient instance and configure the HTTP client in the init closure instead (for example default headers, cookie store or preemptive authentication). The reference CustomizerScript.groovy is available in the GitHub repository.

  2. Migrate operation scripts

    Remove all @Grab annotations and groovyx.net.http imports. Use the connection binding variable (an org.apache.http.client.HttpClient instance) instead of the customizedConnection variable to execute HTTP requests.

    Example 3. Delete script migration
    // Before
    @Grab(group = 'org.codehaus.groovy.modules.http-builder', module = 'http-builder', version = '0.7.1')
    import groovyx.net.http.RESTClient
    
    def connection = customizedConnection as RESTClient
    
    connection.delete(path: '/users/' + uid.uidValue)
    ...
    // After
    import org.apache.http.HttpResponse
    import org.apache.http.client.HttpClient
    import org.apache.http.client.ResponseHandler
    import org.apache.http.client.methods.HttpDelete
    import org.identityconnectors.framework.common.exceptions.ConnectorException
    import org.identityconnectors.framework.common.exceptions.UnknownUidException
    
    def connection = connection as HttpClient
    
    def path = 'users/' + URLEncoder.encode(uid.uidValue, 'UTF-8')
    connection.execute(new HttpDelete(configuration.serviceAddress.resolve(path)), { HttpResponse response ->
        def status = response.statusLine.statusCode
        if (status == 404) {
            throw new UnknownUidException(uid, objectClass)
        }
        if (status >= 300) {
            throw new ConnectorException(response.statusLine.toString())
        }
    } as ResponseHandler)
    ...

    Unlike RESTClient, Apache HttpClient does not throw an exception for error HTTP status codes and does not parse the response body. Check the response status code and parse the response body (for example with groovy.json.JsonSlurper) in your scripts.

Review customized authorization scripts

The default authorization scripts have been hardened and some requests that were previously allowed are now rejected:

  • End users can only read workflow process definitions (workflow/processdefinition/*).

  • End users can only claim a task (set themselves as the assignee) or return it to the queue (set the assignee to null) when updating a workflow task instance. Only users with the openidm-admin or openidm-tasks-manager role can assign a task to other users.

  • When a request to start a workflow process contains the _processDefinitionId field, the authorization is evaluated against this process definition only and the _key field is ignored.

  • The source (from) field of patch copy and move operations is now also checked against the editable managed object properties. Patch operations that copy or move a value from a private property are rejected.

If your project contains customized copies of the script/access.js or script/router-authz.js files, review the reference access.js and router-authz.js files from the GitHub repository and apply the changes to your scripts.

Example 4. Workflow process definition access rule
{
    "pattern"   : "workflow/processdefinition/*",
    "roles"     : "openidm-authorized",
-   "methods"   : "*",
-   "actions"   : "read",
+   "methods"   : "read",
+   "actions"   : "",
    "customAuthz": "isOneOfMyWorkflows()"
},

Wren:IDM 7.2.0

If you are upgrading to the Wren:IDM 7.2.0, please follow the steps below.

Migrate custom scripts to lodash 4

The lodash library available to server-side JavaScript scripts (bin/defaults/script/lib/lodash.js) has been upgraded from version 2.4.1 to version 4.18.1. Several functions were removed or renamed in lodash 4, so you must update all custom scripts that use them, including customized copies of the default scripts (such as policy.js or router-authz.js) in your project.

The following table lists the most commonly used functions that must be replaced:

lodash 2 lodash 4

_.contains

_.includes

_.pluck

_.map

_.findWhere

_.find

_.where

_.filter

_.any

_.some

_.all

_.every

_.pairs

_.toPairs

_.indexBy

_.keyBy

Example 5. Policy script migration
- if (value !== undefined && !_.contains(params.types, type)) {
+ if (value !== undefined && !_.includes(params.types, type)) {
...
- managedObjectConfig = _.findWhere(managedConfig.objects, {"name": objectName});
+ managedObjectConfig = _.find(managedConfig.objects, {"name": objectName});

See the lodash changelog for the complete list of changes.

Wren:IDM 7.1.0

No manual migration is needed when upgrading to the Wren:IDM 7.1.0.

Wren:IDM 7.0.0

If you are upgrading to the Wren:IDM 7.0.0, please follow the steps below.

Migrate Wren:ICF connector bundle names

The connector bundle naming has changed from the OpenICF namespace to the Wren:ICF namespace. Update the bundleName field in all provisioner configuration files (conf/provisioner.openicf-*.json).

Example 6. Provisioner bundle name migration
{
  "connectorRef" : {
-   "bundleName" : "org.forgerock.openicf.connectors.ldap-connector",
+   "bundleName" : "org.wrensecurity.wrenicf.connectors.ldap-connector",
    "bundleVersion" : "...",
    "connectorName" : "org.identityconnectors.ldap.LdapConnector"
  },
  ...
}

Migrate launcher configuration

Some changes were introduced to the conf/launcher.json file, so you must update your existing launcher configuration before starting the new version. Review the reference launcher.json from the GitHub repository and apply the following changes to your configuration:

  • Update the OSGi bundle list to reflect renamed or newly required bundles.

The easiest approach is to start from the reference launcher.json and re-apply any project-specific customizations on top of it.

Migrate to Felix HTTP Jetty service

PAX Web has been removed in favor of standard OSGi Http Whiteboard. The following changes to the config.properties` file are required for migration to the Felix HTTP Jetty service:

Example 7. Felix HTTP Jetty service migration
- # Configures the web embedded Web server via the following file
- org.ops4j.pax.web.config.file=&{launcher.project.location}/conf/jetty.xml
-
- # Enable pax web http/https services to enable jetty
- org.osgi.service.http.enabled=true
- org.osgi.service.http.secure.enabled=true
+ # Enable Felix HTTP Jetty service
+ org.apache.felix.http.enable=true

Migrate to HikariCP JDBC connection pool

Support for the deprecated BoneCP JDBC connection pool has been completely removed. If your project is still using BoneCP, please migrate to HikariCP.

Example 8. HikariCP JDBC connection pool configuration
{
  "driverClass" : "org.postgresql.Driver",
  "jdbcUrl" : "jdbc:postgresql://&{openidm.repo.host}:&{openidm.repo.port}/idmdb",
  "username" : "wrenidm",
  "password" : "wrenidm",
  "connectionTimeout" : 30000,
  "connectionPool" : {
    "type" : "hikari",
    "minimumIdle" : 20,
    "maximumPoolSize" : 50
  }
}

Migrate configuration property (conf/config.properties) to enable JDBC health monitoring:

- # enables the statistics MBean for BoneCP. Enabling this will have a performance impact on BoneCP.
- openidm.bonecp.statistics.enabled=false

+ # Enables HikariCP MBean (JMX) monitoring
+ wrenidm.hikaricp.statistics.enabled=false

Migrate Workflows

The workflow engine was migrated from Activiti to Flowable, so the process definitions also needed to be migrated. Follow these steps to migrate your workflows:

  1. Perform database backup

    Dump all tables with the prefix act_ from the Wren:IDM database. Refer to your database documentation for information on dumping database data.

  2. Migrate process definitions

    Update your BPMN process definitions and all associated files (such as HTML forms) to use Flowable annotations. See Flowable documentation for more information.

    Example 9. Process execution listener migration
    <!-- Before -->
    <definitions xmlns:activiti="http://activiti.org/bpmn" targetNamespace="http://www.activiti.org/test">
      <process id="userRole" name="User Role Assignment" isExecutable="true">
        <extensionElements>
          <activiti:executionListener event="start" class="org.activiti.engine.impl.bpmn.listener.ScriptExecutionListener">
            <activiti:field name="script">
              <activiti:string>
                execution.setVariable('status', 'RUNNING')
              </activiti:string>
            </activiti:field>
            <activiti:field name="language" stringValue="groovy" />
          </activiti:executionListener>
    ...
    <!-- After -->
    <definitions xmlns:flowable="http://flowable.org/bpmn" targetNamespace="http://www.flowable.org/processdef">
      <process id="userRole" name="User Role Assignment" isExecutable="true">
        <extensionElements>
          <flowable:executionListener event="start" class="org.flowable.engine.impl.bpmn.listener.ScriptExecutionListener">
            <flowable:field name="script">
              <flowable:string>
                execution.setVariable('status', 'RUNNING')
              </flowable:string>
            </flowable:field>
            <flowable:field name="language" stringValue="groovy" />
          </flowable:executionListener>
    ...
  3. Migrate running process instances

    Get identifiers of all running process instances:

    curl \
    --header "X-OpenIDM-Username: openidm-admin" \
    --header "X-OpenIDM-Password: openidm-admin" \
    --request GET \
    "http://localhost:8080/openidm/workflow/processinstance?_queryId=query-all-ids&_fields=id,processDefinitionId&_prettyPrint=true"
    {
      "result" : [{
        "_id" : "1",
        "processDefinitionId" : "userRole:1:50"
      }, {
        "_id" : "2",
        "processDefinitionId" : "userRole:2:100"
      } ],
      ...
    }

    Migrate all process instances to the latest process definitions:

    curl \
      --header "X-OpenIDM-Username: openidm-admin" \
      --header "X-OpenIDM-Password: openidm-admin" \
      --request POST \
      "http://localhost:8080/openidm/workflow/processinstance/1?_action=migrate"
    {"Successfully migrated process instance":"1"}
    
    curl \
      --header "X-OpenIDM-Username: openidm-admin" \
      --header "X-OpenIDM-Password: openidm-admin" \
      --request POST \
      "http://localhost:8080/openidm/workflow/processinstance/2?_action=migrate"
    {"Successfully migrated process instance":"2"}
    ...