IDM Deployment Patterns: Centralized Repo- Based vs. Immutable File-Based

Introduction

I recently blogged about how customers can architect ForgeRock Access Management to support an immutable, DevOps style deployment pattern — see link. In this post, we’ll take a look at how to do this for ForgeRock Identity Management (IDM).

IDM is a modern OSGi-based application, with its configuration stored as a set of JSON files. This lends itself well to either a centralized repository- (repo) based deployment pattern, or a file-based immutable pattern. This article explores both options, and summarizes the advantages and disadvantages of each.

IDM Architecture

Before delving into the deployment patterns, it is useful to summarize the IDM architecture. IDM provides centralized, simple management, and synchronization of users, devices, and things. It is a highly flexible product, and caters to a multitude of different identity management use cases, from provisioning, self-service, password management, synchronization, and reconciliation, to workflow, relationships, and task execution. For more on IDM’s architecture, check out the following link.

IDM’s core deployment architecture is split between a web application running in an OSGi framework within a Jetty Web Server, and a supported repo. See this link for a list of supported repos.

Within the IDM web application, the following components are stored:

  • Apache Felix and Jetty Web Server hosting the IDM binaries
  • Secrets
  • Configuration and scripts — this is the topic of this blog.
  • Policy scripts
  • Audit logs (optional)
  • Workflow BAR files
  • Bundles and application JAR files (connectors, dependencies, repo drivers, etc)
  • UI files

Within the IDM repo the following components are stored:

  • Centralized copies of configuration and policies — again, the topic of this blog
  • Cluster configuration
  • Managed and system objects
  • Audit logs (optional)
  • Scheduled tasks and jobs
  • Workflow
  • Relationships and link data

Notice that configuration is listed twice, both on the IDM node’s filesystem, and within the IDM repo. This is the focus of this blog, and how manipulation of this can either support a centralized repository deployment pattern, or a file-based immutable configuration deployment pattern.

Centralized, Repo-Based Deployment Pattern

This is the out-of-the-box (OOTB) deployment pattern for IDM. In this model, all IDM nodes share the same repository to pull down their configuration on startup, and if necessary, overwrite their local files. Any configuration changes made through the UI or over REST (REST ensures consistency) are pushed to the repo and then down to each IDM node via the cluster service. The JSON configuration files within the …/conf directory on the IDM web application are present, but should not be manipulated directly, as this can lead to inconsistencies in the configuration between the local file system and the authoritative repo configuration.

The following component-level diagram illustrates this deployment pattern:

Configuration Settings

The main configuration items for a multi-instance, immutable, file-based deployment pattern are:

  • The …/resolver/boot.properties file: This file stores IDM boot specifics like the IDM host, ports, SSL settings, and more. The key configuration item in this file for this blog post is openidm.node.id, which needs to be a string that is unique to each IDM node to allow the cluster service to identify each host.
  • The …/conf folder: This contains all JSON configuration files. On startup, these files will be pushed to the IDM repo. As a best practice (see link), the OOTB …/conf directory should not be used. Instead, a project folder containing the contents of the …/conf and …/script directory should be created, and IDM started with the “-p </path/to/my/project/location>” flag. This ensures OOTB and custom configurations are kept separately to ease version control, upgrades, backouts, and others.
  • The …/<my_project>/conf/system.properties file: This file contains 2 key settings:
openidm.fileinstall.enabled=false

This option is commented out OOTB; meaning, IDM will monitor the IDM filesystem for configuration changes, and push any changes to the repo. For production, running this setting should be left at default on the first boot of IDM node 1 to load all configurations into the repo, and then set to false (uncommented) on all IDM nodes, to prevent configuration changes made on disk from polluting the repo.

openidm.config.repo.enabled=false 

This option is also commented out OOTB; meaning, IDM will read and load its configuration from the repo.

  • The …/<my_project>/conf/config.properties file. The key setting in this file is:
felix.fileinstall.enableConfigSave=false 

This option is again commented by default; meaning, any changes made to the repository via REST or the UI are pushed down to the local IDM configuration files.

Following are key advantages and disadvantages of this deployment pattern:

Advantages

  • This is the OOTB configuration; so, other than specifying unique node names, no additional configuration changes are required.
  • Customers can use the IDM Admin UI to make configuration changes. Those changes will propagate to other nodes in the cluster automatically, which is easier for those new to IDM.
  • This approach does not rely on mature DevOps processes to ensure configuration consistency. All config is in the repo, and this manages configuration data consistency between IDM nodes.
  • There is little benefit from choosing the immutable pattern if the IDM configuration remains static for extended periods of time. For example, if IDM is used to synchronise between two external datastores, then this configuration will most likely remain static for long periods of time.

Disadvantages

  • Will not support customers who follow immutable DevOps patterns where a complete application is treated as code, with all configuration pushed to a repository like GIT, and pushed to each environment up to production.
  • There is no easy way to support “stack by stack” deployments, whereby a server is taken out of service, and its configuration is updated and tested in isolation before it is promoted to the rest of the IDM pool. All configuration is persisted in the repo, so any configuration changes made are propagated to all IDM nodes in the cluster. This also complicates backout procedures.
  • Any manipulation of the configuration files on the IDM filesystem can lead to configuration inconsistencies between IDM nodes.
  • This approach will allow manipulation of configuration through the UI, as there is no real audit tracking or verification of a user’s actions.

Immutable, File-Based Deployment Pattern

The key difference in this model is IDM’s configuration is not stored in the repository. Instead, IDM pulls the configuration from the local filesystem and stores it in memory. The repo is still the authoritative source for all other IDM components (cluster configuration, schedules, and optionally, audit logs, system and managed objects, links, relationships, and others).

The following component level diagram illustrates this deployment pattern:

Configuration Settings

The main configuration items for a multi-instance, immutable, file-based deployment pattern are:

  • The …/resolver/boot.properties file: This file stores IDM boot specifics like the IDM host, ports, SSL settings, and more. The key configuration item in this file for this blog post is openidm.node.id, which needs to be a string unique to each IDM node to let the cluster service identify each host.
  • The …/conf folder: This contains all JSON configuration files. On startup, these files will be pushed to the IDM repo. As a best practice, (see link), the OOTB …/conf directory should not be used. Instead, a project folder containing the contents of the …/conf and …/script directory should be created, and IDM started with the “-p </path/to/my/project/location>” flag. This ensures OOTB and custom configurations are kept separately, to ease version control, upgrades, backouts, and others.
  • The …/<my_project>/conf/system.properties file: This file contains two key settings:
openidm.fileinstall.enabled=false

This setting can either be left commented (for example, true by default) or uncommented, and explicitly set to true. This, combined with the setting below, pushes all configurations except those from your project’s directory (such as …/conf and …/script) to the repo.

openidm.config.repo.enabled=false 

This setting needs to be uncommented to ensure IDM does not read the configuration from the repo, or push the configuration to the repo:

  • The …/<my_project>/conf/config.properties file. The key setting in this file is:
felix.fileinstall.enableConfigSave=false 

This setting needs to be uncommented. This means any changes made via REST or the UI are not pushed down to the local IDM filesystem. This effectively makes the IDM configuration read-only, which is key to immutability.

Note: Direct manipulation of configuration files and promotion to other IDM environments can fail if the JSON files contain crypto material. See the following KB article for information on how to handle this. You can also use the IDM configexport tool (IDM version 6.5 and above).

The following presents key advantages and disadvantages of this deployment pattern:

Advantages

  • Follows core DevOps patterns for immutable configuration. Push configuration into a repo like GIT, parameterize, and promote up to production. A customer knows without doubt which configuration is running in production.
  • This pattern offers the ability to pre-bake the configuration into an image (such as, a Docker image, an Amazon Machine Image, and others) for auto-deployment of IDM configuration using orchestration tools.
  • Supports “stack by stack” deployments, as configuration changes can be made to a single node without impacting the others. Rollback is also far simpler—just restore the previous configuration.
  • The IDM configuration is set to read-only; meaning, accidental UI- or REST-based configuration changes cannot alter the configuration, and potentially go on to impact functionality.

Disadvantages

  • As each IDM node holds its own configuration, the UI cannot be used to make configuration changes. This could present a challenge to customers new to IDM.
  • The customer is left to ensure processes are put in place so all IDM nodes run from exactly the same configuration. This requires strong DevOps methodologies and experience.
  • There is a limited benefit for customers who do not modify their IDM configuration often.

Summary of Configuration Parameters

The following table summarizes the key configuration parameters used in the centralized repo, and in file-based, immutable deployment patterns:

Conclusion

There you have it, two different deployment patterns—the centralized, repo-based pattern for customers who wish to go with the OOTB configuration, and/or do not update the IDM configuration often, and the immutable, file- based deployment pattern for those customers who demand it and/or are well-versed in DevOps methodologies and wish to treat IDM like code.