måndag 11 september 2017

Delegated Administration and ForgeRock Identity Management

What is Delegated Administration?
Through delegation of administration, a directory or application services infrastructure, such as ForgeRock Identity Management, can be designed to span multiple and / or non-structured organizations that have unique management requirements. In particular, the delegation of administration in resources can help organizations meet specific requirements for structural and operational independence.


Why do people need Delegated Administration?
People generally look to delegate administration (portions or full administration) for 3 reasons:
  1. Organizational Structure: Understanding and control over resources are bound to a structure defined by an organization. They need the ability to participate in shared resources, while still maintaining independence in the decision-making process.
  2. Legal Requirements: Configuring and maintaining the ability to operate in a manner consistent with regulatory (or other legal) requirements that may restrict access or activity (government, defense or financial institutions, for example).
  3. Operational Requirements: Today's applications and services leverage structured constraints based on metadata (attributes) for configuration, availability or security. This is not uncommon in hosting or outward facing scenarios


Foundational components providing Delegated Administration
  1. Organizational Units: Provides a way to scope and group objects
    1. Managed Objects (including. roles, users, orgs, devices)
    2. Policies (password policies)
    3. Connectors
    4. Workflows (associate workflows to organizations)
  2. Authorization Layer: Granular entitlement on what can be done thru the RESTful layer on what objects and organizations
  3. Ability to group entitlements into assignable Administrative Roles


What do people do in OpenIDM today?

Today, there is no formal model for delegated administration; however, users can define their own model and methods to accomplish basic delegation tasks. This is often unsupported (custom code) and not repeatable - making any “extended” or “custom endpoint” solution untenable in the long run.


Ref: Blog post from Simon Moffat


A better solution

With the addition of Hub City Media’s IDA module, delegated administration capabilities are provided by ForgeRock Identity Management and previous versions of OpenIDM (4.x) in a seamless and intuitive way. It allows administrators to deploy in such a way that administrative tasks can be fully delegated based upon a set of predefined conditions and attribute values.


Installation of Hub City Media’s IDA is simple and straightforward. The IDM administrator runs an installation script on a single or clustered IDM server and the installer handles deploying the required endpoints and user interface.


Once installed, the IDA administrative role can be assigned to a user responsible for configuring the system. Configuration involves creating Delegated Administration Policies that control who the delegated administrators are, who they can administer, and what specific operations are allowed.

Delegated Administration Policies

The power of IDA is in the policy framework. Clients can implement multiple Delegated Administration Policies to satisfy various requirements from the same system. Delegated Administration Policies contain:
  1. A Source Rule: a boolean expression based on user and relationship attributes. Any user that matches the Source Rule is an administrator in this policy.
  2. A Target Rule: any user that matches the Target Rule can be administered by any user who matches the Source Rule
  3. A Permissions Schema: defines what operations (create, delete, enable, disable) and identity data the administrator can perform on the target users. This permission schema defines very fine-grained control over each field.


These policies are configured from the user interface and there is no coding required.


User Interface and APIs

Once the policy is defined, authenticated users can access the IDA user interface and administer users based on those policies. The delegated administrator can only modify users they are allowed to, given the active policy, and they can only edit attributes defined in the policy.


Like other components of the Forgerock Platform, HCM has exposed the functionality of IDA as a set of REST endpoints. If customers want to use their own UI, they can do so while getting the benefit of IDA’s policy enforcement.


Conclusion


ForgeRock Identity Management is the ideal component to implement and solve complex identity management problems whether external-facing or internal-facing problems due to its flexibility. With the addition of Hub City Medias IDA component on top of ForgeRock Identity Management, organizations can easily structure and administer a large amount of identities and better adapt to internal organizational structures and legal requirements. Reach out to ForgeRock or Hub City Media to discuss how ForgeRock Identity Management and HCM IDA can be part of your Identity Management infrastructure or to request a demonstration.

måndag 28 augusti 2017

DevOps for ForgeRock Identity Management - The Configuration Management Story

Enterprise software packages quickly become a struggle to install, configure and maintain. Complex products often required multiple components in different tiers, and initial configurations to deployed on often several instances of the same server. For a production environment, you are looking at high availability and hardening the products during installation. A job that quickly becomes tedious if not impossible to do. Once an enterprise software product is deployed and installed it is common practice to keep it static for months or even years without changing its configuration because of the complex process of testing and putting a new release into production


Caring and feeding multiple servers requires an automated way of doing this. The term is Configuration management and is a common aspect of DevOps methodologies.

As of ForgeRock Identity Management 5.0, pre-made containerized images are available along with a DevOps guide (For those customers and partners with access to backstage) to aid in deploying using DevOps strategies. The samples and guide utilize components such as Kubernetes, Docker and Amazon EC2 Container Service. This article, however, offers some alternative thoughts and software suggestions that might complement or offer an alternate strategy.

CFengine was one of the first configuration management systems that were deployed in anything approaching widespread use and was followed later by Puppet and Chef. A bit over two years ago, Salt Stack‘s “Salt” entered the market, and took a radically different approach to the problem of “configure all of my servers to do X.”


Many of these Configuration management solutions sits on top of SSH to perform a remote execution. SSH being the de facto standard for secure and encrypted network traffic but with the drawback of being rather computation expensive - other solutions have proprietary protocols with agents deployed or leverage HTTPS.

The goal is to get ForgeRock Identity Management to install in an automated fashion with the required components configured and ready.


Some of the reasons why you would want to have an automated installation are because it is great for quickly setting up environments for development, testing and trying out different aspects and versions of a product. Troubleshooting configurations, collaborative build with support for cloud deployments. A consistent approach that is quick to setup and quick to tear down.


Efforts put into setting up the automated installation will provide a lot of leverage down the road, reaching the goal of a fully hands-off deployment and installation.


Tools and frameworks



Chef

Chef is a company & configuration management tool written in Ruby and Erlang. It uses a pure-Ruby, domain-specific language (DSL) for writing system configuration "recipes". Chef is used to streamline the task of configuring and maintaining a company's servers, and can integrate with cloud-based platforms such as Rackspace, Internap, Amazon EC2, Google Cloud Platform, OpenStack, SoftLayer, and Microsoft Azure to automatically provision and configure new machines. Chef contains solutions for both small and large scale systems, with features and pricing for the respective ranges.


Chef uses a master-agent setup, and in addition to a master server, a Chef installation also requires a workstation to control the master. The agents can be installed from the workstation using the ‘knife’ tool that uses SSH for deployment to ease installation. Chef configs are packaged into JSON files called ‘recipes’, and the software can run in client-server (called Chef-server) or standalone mode (called ‘Chef-solo’).




Puppet

Puppet is an open-source configuration management utility. It runs on many Unix-like systems as well as on Microsoft Windows, and includes its own declarative language to describe system configuration.



Ansible/Vagrant

Ansible is a free software platform for configuring and managing computers. It combines multi-node software deployment, ad hoc task execution, and configuration management. It manages nodes over SSH or PowerShell and requires Python (2.4 or later) to be installed on them. Modules work over JSON and standard output and can be written in any programming language. The system uses YAML to express reusable descriptions of systems.


Vagrant is computer software that creates and configures virtual development environments. It can be seen as a higher-level wrapper around virtualization software such as VirtualBox, VMware, KVM and Linux Containers (LXC), and around configuration management software such as Ansible, Chef, Salt and Puppet.




CFEngine

CFEngine is an open-source configuration management system, written by Mark Burgess. Its primary function is to provide automated configuration and maintenance of large-scale computer systems, including the unified management of servers, desktops, consumer and industrial devices, embedded networked devices, mobile smartphones, and tablet computers. CFEngine is written in C and claims to be the fastest and leanest solution on the market for Configuration Management.


Salt

Salt leverages the ZeroMQ message bus, a lightweight library that serves as a concurrency framework. It establishes persistent TCP connections between the Salt master and the various clients, over which communication takes place. Messages are serialized using msgpack, (a more lightweight serialization protocol than JSON or Protocol Buffers), resulting in severe speed and bandwidth gains over traditional transport layers, resulting in in the ability to fit far more data quickly through a given pipe. This translates into a non-technical statement of, “Salt establishes a persistent data pipe between servers in your environment that’s extremely fast and low-bandwidth.”


Salt also has a Vigrant add-on allowing you to spawn up virtual machines similar as to the Ansible/Vigrant combination discussed above.


Software Version Control and Management

ForgeRock Identity Management supports to be started pointing to a particular folder for its configuration files. This means for example that the software can be installed for instance under /opt/openidm and configuration files can be stored under /etc/openidm. ForgeRock Identity Management can then be started with the argument -p <directory of conf files>. This separates the default files from the customer specific ones, provides easier upgrades and a better overview.


To keep track of configuration files during development, test and QA as well as the finished production artifacts a software versioning control system is highly recommended. Software version control is the practice of deploying consistent software versions. This practice improves the chance for validation and testing and limits the amount of software defects and interoperability issues. The Software Version Control system should be integrated with the configuration management system to pull the appropriate branch. This pattern makes deployment easier, faster, less complex and easier to support.


Configuration Upgrade Procedures

The Upgrade procedure for ForgeRock Identity Management helps to ensure that the process of lifting ForgeRock Identity Management from one version to a newer one occurs smoothly and with minimal downtown. With the help of a configuration management system such as those listed and discussed above, assists in testing out the procedure. Since ForgeRock Identity Management acts as a hub component in the infrastructure, testing out integrations is also important during these upgrades and would, therefore, require in-depth planning.


Once the ForgeRock Identity Management upgrade procedure is defined and validated, the upgrade procedure should be referenced in all change documentation appropriate to the particular upgrade. The ForgeRock Identity Management Release Notes always contains valuable clues to important changes and information about a particular release.


Some discovered challenges



  • EULA Acceptance (You need to accept license during installation)
  • Download production binaries from Backstage requires login.
  • OpenIDM servers are unable to start if the OpenIDM JDBC repository is unavailable. Therefore, it is imperative that the JDBC repository is up and running before you attempt to start OpenIDM in a DevOps deployment.
  • Clustered OpenIDM servers are not removed from the cluster node list when they are brought down or when they fail. In elastic deployments, with servers frequently added to and removed from clusters, the cluster node list can grow to be quite large.


Conclusions



When you have the infrastructure to proactively manage change using a configuration management system, the fast pace of development no longer leaves you behind. Being able to quickly setup and deploy a new ForgeRock Identity Management system allows you to scale quickly in a known and repeatable manner as well as allows you to test out new features and capabilities and upgrades. Leveraging a DevOps philosophy and a configuration management system, although heavy initially in setting up, is an opportunity to get ahead.


Although there is an abundance of tools available to support your configuration management needs, there are available sample cookbooks or recipes to get ForgeRock Identity Management deployed and configured on the forgerock.org website. Picking one of these as a starting point will save time and effort.


References


måndag 21 augusti 2017

SCIM no longer a SCAM

Although the SCIM (System for Cross-domain Identity Management) standard has been around since 2011 it has seen little adoption among software vendors. Driving forces behind it can be considered Google, Salesforce.com, Sailpoint and Ping Identity and the idea behind the standard is to simplify exchange of user identity information between IT systems using identities - Identity Silos if you will.


The SCIM standard can be viewed as a successor to SPML (Service Provisioning Markup Language) developed by OASIS with the similar goal but based on an XML framework. With the emerging RESTful world to counter the heavy-weight and cumbersome XML based standards - SCIM was born. SCIM offers a light-weight schema that is JSON and REST-based with a concrete data model but as for any standard - it doesn't become a standard unless it is widely adopted, and here is where SCIM currently is struggling.


The current release of the SCIM standard is SCIM 2.0 and released as IETF RFC 7643 and IETF RFC 7644 with a complementing use-case document as IETF RFC 7642, but most implementations are still SCIM 1.1.


So what is it that SCIM typically can do? Mainly two things; CRUD operation on users and groups. For SCIM to work, the application needs to provide a SCIM compliant service and the integration needs to offer a SCIM compliant connector.


As of "ForgeRock Identity Management 5.5" (Referred to as IDM in this article), a SCIM 1.1 compliant connector will now be part of the product allowing IDM to interact with SCIM complaint services such as Google and WSO2 Identity Server to create, update, delete users and groups. However, since the connector is based on the OpenICF 1.4 framework the connector is backward compatible with previous versions of ForgeRock Identity Management implementing the OpenICF 1.4 framework.


This article will offer a step by step guide how to set up a SCIM compliant test environment based on WSO2 Identity Server, how to configure the SCIM connector in IDM making it ready to provision a set of users to WSO2 Identity Server.


Installation of WSO2 Identity Server is easy and the archive downloaded from WSO2s website with the binary bits is self-contained with everything required to install and run.


Make sure the $JAVA_HOME variable is set appropriately prior to invoking the wso2server.sh script. Possibly some manipulations are required in the startup script to reflect your particular environment.


The following steps are done to install WSO2 Identity Server:


1. Download and extract the wso2is-5.2.0.zip file
2. Run the wso2server.sh on *NIX or wso2server.bat file on Windows,  in the /bin directory
3. Once the server starts, point your Web browser to https://localhost:9443/carbon/
4. User dashboard is available at https://localhost:9443/dashboard


WSO2 Identity Server integrates WSO2s Charon, which is a fully Open Source implementation of the SCIM protocol and provides the necessary serverside components to facilitate a SCIM server exposing SCIM endpoints which expose Users and Groups resources in a RESTful way.


The next step once WSO2 Identity Server is up and running is to create a new service provider followed by configuring SCIM and OAuth.


Login to the admin dashboard (https://localhost:9443/carbon/) using the admin:admin credentials, the locate the Add New Service Provider.
For the inbound provisioning, define PRIMARY as the user/group store for SCIM and be ready to configure the OAuth part.
Configure OAuth and make sure to save the client secret and key  (SCIM connector uses client credential grant type).


Once the service provider is configured accordingly, the SCIM service is ready to be tested with IDM and the SCIM connector.


Unless running ForgeRock Identity Management 5.5 the actual connector needs to be deployed in the IDM install directory. Copy the connector jar file to $OPENIDM/connectors. The connector file is available via Backstage for customers with an active subscription and is not posted here for licensing purposes.

The connector also requires a configuration file that needs to be deployed made available to IDM. Copy the provisioner.openicf-scim.json to $OPENIDM/conf.


Provisioner.openicf-scim.json


{
   "name" : "scim"
   "enabled" : true,
   "connectorRef" : {
       "bundleName" : "org.forgerock.openicf.connectors.scim-connector",
       "connectorName" : "org.forgerock.openicf.connectors.scim.ScimConnector",
       "connectorHostRef" : "#LOCAL",
       "bundleVersion" : "1.4.0.0-SNAPSHOT"
   },
   "poolConfigOption" : {
       "maxObjects" : 10,
       "maxIdle" : 10,
       "maxWait" : 150000,
       "minEvictableIdleTimeMillis" : 120000,
       "minIdle" : 1
   },
   "resultsHandlerConfig" : {
       "enableNormalizingResultsHandler" : true,
       "enableFilteredResultsHandler" : false,
       "enableCaseInsensitiveFilter" : false,
       "enableAttributesToGetSearchResultsHandler" : false
   },
   "operationTimeout" : {
       "CREATE" : -1,
       "UPDATE" : -1,
       "DELETE" : -1,
       "TEST" : -1,
       "SCRIPT_ON_CONNECTOR" : -1,
       "SCRIPT_ON_RESOURCE" : -1,
       "GET" : -1,
       "RESOLVEUSERNAME" : -1,
       "AUTHENTICATE" : -1,
       "SEARCH" : -1,
       "VALIDATE" : -1,
       "SYNC" : -1,
       "SCHEMA" : -1
   },
   "configurationProperties" : {
       "SCIMEndpoint" : "https://localhost:9443/wso2/scim",
       "SCIMVersion" : 1,
       "authenticationMethod" : "BASIC",
       "user" : "admin",
       "password" : "admin",
       "tokenEndpoint" : "https://localhost:9443/oauth2/token"
       "clientId" : "FsvGkUww7vHYYgRh_Hd071iQQroa",
       "clientSecret" : null,
       "acceptSelfSignedCertificates" : true,
       "disableHostNameVerifier" : true,
       "maximumConnections" : 10,
       "httpProxyHost" : null,
       "httpProxyPort" : null
   },
   "objectTypes" : {
       "group" : {
           "$schema" : "http://json-schema.org/draft-03/schema",
           "id" : "__GROUP__",
           "type" : "object",
           "nativeType" : "__GROUP__",
           "properties" : {
               "displayName" : {
                   "type" : "string",
                   "required" : true,
                   "nativeName" : "displayName",
                   "nativeType" : "string"
               },
               "meta" : {
                   "type" : "object",
                   "nativeName" : "meta",
                   "nativeType" : "object",
                   "flags" : [
                       "NOT_CREATABLE",
                       "NOT_UPDATEABLE"
                   ]
               },
               "members" : {
                   "type" : "array",
                   "items" : {
                       "type" : "object",
                       "nativeType" : "object"
                   },
                   "nativeName" : "members",
                   "nativeType" : "object"
               },
               "__NAME__" : {
                   "type" : "string",
                   "required" : true,
                   "nativeName" : "__NAME__",
                   "nativeType" : "string"
               },
               "externalId" : {
                   "type" : "string",
                   "nativeName" : "externalId",
                   "nativeType" : "string"
               }
           }
       },
       "user" : {
           "$schema" : "http://json-schema.org/draft-03/schema",
           "id" : "__ACCOUNT__",
           "type" : "object",
           "nativeType" : "__ACCOUNT__",
           "properties" : {
               "phoneNumbers" : {
                   "type" : "array",
                   "items" : {
                       "type" : "object",
                       "nativeType" : "object"
                   },
                   "nativeName" : "phoneNumbers",
                   "nativeType" : "object"
               },
               "emails" : {
                   "type" : "array",
                   "items" : {
                       "type" : "object",
                       "nativeType" : "object"
                   },
                   "nativeName" : "emails",
                   "nativeType" : "object"
               },
               "__NAME__" : {
                   "type" : "string",
                   "required" : true,
                   "nativeName" : "__NAME__",
                   "nativeType" : "string"
               },
               "active" : {
                   "type" : "boolean",
                   "nativeName" : "active",
                   "nativeType" : "boolean"
               },
               "groups" : {
                   "type" : "array",
                   "items" : {
                       "type" : "object",
                       "nativeType" : "object"
                   },
                   "nativeName" : "groups",
                   "nativeType" : "object",
                   "flags" : [
                       "NOT_CREATABLE",
                       "NOT_UPDATEABLE"
                   ]
               },
               "costCenter" : {
                   "type" : "string",
                   "nativeName" : "costCenter",
                   "nativeType" : "string"
               },
               "division" : {
                   "type" : "string",
                   "nativeName" : "division",
                   "nativeType" : "string"
               },
               "employeeNumber" : {
                   "type" : "string",
                   "nativeName" : "employeeNumber",
                   "nativeType" : "string"
               },
               "organization" : {
                   "type" : "string",
                   "nativeName" : "organization",
                   "nativeType" : "string"
               },
               "profileUrl" : {
                   "type" : "string",
                   "nativeName" : "profileUrl",
                   "nativeType" : "string"
               },
               "userType" : {
                   "type" : "string",
                   "nativeName" : "userType",
                   "nativeType" : "string"
               },
               "x509Certificates" : {
                   "type" : "array",
                   "items" : {
                       "type" : "object",
                       "nativeType" : "object"
                   },
                   "nativeName" : "x509Certificates",
                   "nativeType" : "object"
               },
               "manager" : {
                   "type" : "object",
                   "nativeName" : "manager",
                   "nativeType" : "object"
               },
               "userName" : {
                   "type" : "string",
                   "required" : true,
                   "nativeName" : "userName",
                   "nativeType" : "string"
               },
               "timezone" : {
                   "type" : "string",
                   "nativeName" : "timezone",
                   "nativeType" : "string"
               },
               "photos" : {
                   "type" : "array",
                   "items" : {
                       "type" : "object",
                       "nativeType" : "object"
                   },
                   "nativeName" : "photos",
                   "nativeType" : "object"
               },
               "displayName" : {
                   "type" : "string",
                   "nativeName" : "displayName",
                   "nativeType" : "string"
               },
               "password" : {
                   "type" : "string",
                   "nativeName" : "__PASSWORD__",
                   "nativeType" : "JAVA_TYPE_GUARDEDSTRING",
                   "flags" : [
                       "NOT_READABLE",
                       "NOT_RETURNED_BY_DEFAULT"
                   ]
               },
               "meta" : {
                   "type" : "object",
                   "nativeName" : "meta",
                   "nativeType" : "object",
                   "flags" : [
                       "NOT_CREATABLE",
                       "NOT_UPDATEABLE"
                   ]
               },
               "entitlements" : {
                   "type" : "array",
                   "items" : {
                       "type" : "object",
                       "nativeType" : "object"
                   },
                   "nativeName" : "entitlements",
                   "nativeType" : "object"
               },
               "department" : {
                   "type" : "string",
                   "nativeName" : "department",
                   "nativeType" : "string"
               },
               "ims" : {
                   "type" : "array",
                   "items" : {
                       "type" : "object",
                       "nativeType" : "object"
                   },
                   "nativeName" : "ims",
                   "nativeType" : "object"
               },
               "name" : {
                   "type" : "object",
                   "nativeName" : "name",
                   "nativeType" : "object"
               },
               "nickName" : {
                   "type" : "string",
                   "nativeName" : "nickName",
                   "nativeType" : "string"
               },
               "locale" : {
                   "type" : "string",
                   "nativeName" : "locale",
                   "nativeType" : "string"
               },
               "roles" : {
                   "type" : "array",
                   "items" : {
                       "type" : "object",
                       "nativeType" : "object"
                   },
                   "nativeName" : "roles",
                   "nativeType" : "object"
               },
               "preferredLanguage" : {
                   "type" : "string",
                   "nativeName" : "preferredLanguage",
                   "nativeType" : "string"
               },
               "addresses" : {
                   "type" : "array",
                   "items" : {
                       "type" : "object",
                       "nativeType" : "object"
                   },
                   "nativeName" : "addresses",
                   "nativeType" : "object"
               },
               "title" : {
                   "type" : "string",
                   "nativeName" : "title",
                   "nativeType" : "string"
               },
               "externalId" : {
                   "type" : "string",
                   "nativeName" : "externalId",
                   "nativeType" : "string"
               }
           }
       }
   },
   "operationOptions" : {
       "CREATE" : {
           "objectFeatures" : {
               "__GROUP__" : {
                   "operationOptionInfo" : {
                       "$schema" : "http://json-schema.org/draft-03/schema",
                       "id" : "FIX_ME",
                       "type" : "object",
                       "properties" : { }
                   }
               },
               "__ACCOUNT__" : {
                   "operationOptionInfo" : {
                       "$schema" : "http://json-schema.org/draft-03/schema",
                       "id" : "FIX_ME",
                       "type" : "object",
                       "properties" : { }
                   }
               }
           }
       },
       "UPDATE" : {
           "objectFeatures" : {
               "__GROUP__" : {
                   "operationOptionInfo" : {
                       "$schema" : "http://json-schema.org/draft-03/schema",
                       "id" : "FIX_ME",
                       "type" : "object",
                       "properties" : { }
                   }
               },
               "__ACCOUNT__" : {
                   "operationOptionInfo" : {
                       "$schema" : "http://json-schema.org/draft-03/schema",
                       "id" : "FIX_ME",
                       "type" : "object",
                       "properties" : { }
                   }
               }
           }
       },
       "DELETE" : {
           "objectFeatures" : {
               "__GROUP__" : {
                   "operationOptionInfo" : {
                       "$schema" : "http://json-schema.org/draft-03/schema",
                       "id" : "FIX_ME",
                       "type" : "object",
                       "properties" : { }
                   }
               },
               "__ACCOUNT__" : {
                   "operationOptionInfo" : {
                       "$schema" : "http://json-schema.org/draft-03/schema",
                       "id" : "FIX_ME",
                       "type" : "object",
                       "properties" : { }
                   }
               }
           }
       },
       "TEST" : {
           "objectFeatures" : { }
       },
       "SCRIPT_ON_CONNECTOR" : {
           "objectFeatures" : { }
       },
       "SCRIPT_ON_RESOURCE" : {
           "objectFeatures" : { }
       },
       "GET" : {
           "objectFeatures" : {
               "__GROUP__" : {
                   "operationOptionInfo" : {
                       "$schema" : "http://json-schema.org/draft-03/schema",
                       "id" : "FIX_ME",
                       "type" : "object",
                       "properties" : {
                           "SORT_KEYS" : {
                               "type" : "string",
                               "nativeType" : null
                           },
                           "PAGED_RESULTS_OFFSET" : {
                               "type" : "integer",
                               "nativeType" : "integer"
                           },
                           "ATTRS_TO_GET" : {
                               "type" : "array",
                               "items" : {
                                   "type" : "string",
                                   "nativeType" : "string"
                               },
                               "nativeType" : "string"
                           },
                           "PAGE_SIZE" : {
                               "type" : "integer",
                               "nativeType" : "integer"
                           },
                           "PAGED_RESULTS_COOKIE" : {
                               "type" : "string",
                               "nativeType" : "string"
                           }
                       }
                   }
               },
               "__ACCOUNT__" : {
                   "operationOptionInfo" : {
                       "$schema" : "http://json-schema.org/draft-03/schema",
                       "id" : "FIX_ME",
                       "type" : "object",
                       "properties" : {
                           "SORT_KEYS" : {
                               "type" : "string",
                               "nativeType" : null
                           },
                           "PAGED_RESULTS_OFFSET" : {
                               "type" : "integer",
                               "nativeType" : "integer"
                           },
                           "ATTRS_TO_GET" : {
                               "type" : "array",
                               "items" : {
                                   "type" : "string",
                                   "nativeType" : "string"
                               },
                               "nativeType" : "string"
                           },
                           "PAGE_SIZE" : {
                               "type" : "integer",
                               "nativeType" : "integer"
                           },
                           "PAGED_RESULTS_COOKIE" : {
                               "type" : "string",
                               "nativeType" : "string"
                           }
                       }
                   }
               }
           }
       },
       "RESOLVEUSERNAME" : {
           "objectFeatures" : { }
       },
       "AUTHENTICATE" : {
           "objectFeatures" : { }
       },
       "SEARCH" : {
           "objectFeatures" : {
               "__GROUP__" : {
                   "operationOptionInfo" : {
                       "$schema" : "http://json-schema.org/draft-03/schema",
                       "id" : "FIX_ME",
                       "type" : "object",
                       "properties" : {
                           "SORT_KEYS" : {
                               "type" : "string",
                               "nativeType" : null
                           },
                           "PAGED_RESULTS_OFFSET" : {
                               "type" : "integer",
                               "nativeType" : "integer"
                           },
                           "ATTRS_TO_GET" : {
                               "type" : "array",
                               "items" : {
                                   "type" : "string",
                                   "nativeType" : "string"
                               },
                               "nativeType" : "string"
                           },
                           "PAGE_SIZE" : {
                               "type" : "integer",
                               "nativeType" : "integer"
                           },
                           "PAGED_RESULTS_COOKIE" : {
                               "type" : "string",
                               "nativeType" : "string"
                           }
                       }
                   }
               },
               "__ACCOUNT__" : {
                   "operationOptionInfo" : {
                       "$schema" : "http://json-schema.org/draft-03/schema",
                       "id" : "FIX_ME",
                       "type" : "object",
                       "properties" : {
                           "SORT_KEYS" : {
                               "type" : "string",
                               "nativeType" : null
                           },
                           "PAGED_RESULTS_OFFSET" : {
                               "type" : "integer",
                               "nativeType" : "integer"
                           },
                           "ATTRS_TO_GET" : {
                               "type" : "array",
                               "items" : {
                                   "type" : "string",
                                   "nativeType" : "string"
                               },
                               "nativeType" : "string"
                           },
                           "PAGE_SIZE" : {
                               "type" : "integer",
                               "nativeType" : "integer"
                           },
                           "PAGED_RESULTS_COOKIE" : {
                               "type" : "string",
                               "nativeType" : "string"
                           }
                       }
                   }
               }
           }
       },
       "VALIDATE" : {
           "objectFeatures" : { }
       },
       "SYNC" : {
           "objectFeatures" : { }
       },
       "SCHEMA" : {
           "objectFeatures" : { }
       }
   }
}


{
   "mappings" : [
       {
           "target" : "system/scim/user",
           "source" : "managed/user",
           "name" : "managedUser_systemScimUser",
           "onCreate" : {
               "type" : "text/javascript",
               "file" : "script/MU2SCIM-sync.js"
           },
           "onUpdate" : {
               "type" : "text/javascript",
               "file" : "script/MU2SCIM-sync.js"
           },
           "properties" : [
               {
                   "target" : "userName",
                   "source" : "userName"
               },
               {
                   "target" : "name/givenName",
                   "source" : "givenName"
               },
               {
                   "target" : "name/familyName",
                   "source" : "sn"
               },
               {
                   "target" : "displayName",
                   "source" : "description"
               },
               {
                   "target" : "active",
                   "default" : true
               },
               {
                   "target" : "password",
                   "source" : "password",
                   "transform" : {
                       "type" : "text/javascript",
                       "globals" : { },
                       "source" : "openidm.decrypt(source);"
                   },
                   "condition" : {
                       "type" : "text/javascript",
                       "globals" : { },
                       "source" : "object.password != null"
                   }
               }
           ],
           "policies" : [
               {
                   "situation" : "CONFIRMED",
                   "action" : "UPDATE"
               },
               {
                   "situation" : "FOUND",
                   "action" : "UPDATE"
               },
               {
                   "situation" : "ABSENT",
                   "action" : "CREATE"
               }
           ],
           "correlationQuery" : {
               "type" : "text/javascript",
               "source" : "var qry = { '_queryFilter': 'userName eq \"' + source.userName + '\"' }; qry;"
           }
       },
       {
           "source" : "system/scim/user",
           "target" : "managed/user",
           "name" : "systemScimUser_managedUser",
           "sourceQueryFullEntry" : false,
           "onCreate" : {
               "type" : "text/javascript",
               "file" : "script/SCIM2MU-sync.js"
           },
           "onUpdate" : {
               "type" : "text/javascript",
               "file" : "script/SCIM2MU-sync.js"
           },
           "properties" : [
               {
                   "target" : "userName",
                   "source" : "userName"
               },
               {
                   "target" : "givenName",
                   "source" : "name/givenName"
               },
               {
                   "target" : "sn",
                   "source" : "name/familyName"
               },
               {
                   "target" : "description",
                   "source" : "displayName"
               }
           ],
           "policies" : [
               {
                   "situation" : "CONFIRMED",
                   "action" : "UPDATE"
               },
               {
                   "situation" : "FOUND",
                   "action" : "UPDATE"
               },
               {
                   "situation" : "ABSENT",
                   "action" : "CREATE"
               }
           ],
           "correlationQuery" : {
               "type" : "text/javascript",
               "source" : "var qry = {'_queryId' : 'for-userName', 'uid' : source.userName}; qry;"
           }
       }
   ]
}


You also need the following onCreate/onUpdate scripts to deal with the complex SCIM objects:


SCIM2MU-sync.js


/*
* Copyright 2017-2017 ForgeRock AS. All Rights Reserved
*
* Use of this code requires a commercial software license with ForgeRock AS.
* or with one of its affiliates. All use shall be exclusively subject
* to such license between the licensee and ForgeRock AS.
*/


// Addresses
// a Managed user contains by default the following "Address" attributes:
// postalAddress
// address2
// city
// postalCode
// country
// stateProvince
if (source.addresses != null) {
print("Found addresses")
var address = source.addresses[0]
target.city = address.locality
target.country = address.country
target.stateProvince = address.region
target.postalCode = address.postalCode
target.postalAddress = address.streetAddress


}


// Email
if (source.emails != null) {
print("Found mail")
var email = source.emails[0]
target.mail = email.value
}


// Telephone
if (source.phoneNumbers != null) {
print("Found phones")
var phone = source.phoneNumbers[0]
target.telephoneNumber = phone.value
}


MU2SCIM-sync.js


/*
* Copyright 2017-2017 ForgeRock AS. All Rights Reserved
*
* Use of this code requires a commercial software license with ForgeRock AS.
* or with one of its affiliates. All use shall be exclusively subject
* to such license between the licensee and ForgeRock AS.
*/


target.__NAME__ = source.userName


// Addresses
// a Managed user contains by default the following "Address" attributes:
// postalAddress
// address2
// city
// postalCode
// country
// stateProvince


var address = {
locality: source.city,
country: source.country,
region: source.stateProvince,
postalCode: source.postalCode,
streetAddress: source.postalAddress,
type: "work"
}


target.addresses = [address]


// Email
if (source.mail != null) {
var email = {
value: source.mail,
type: "work"
}
target.emails = [email]
}


// Telephone
if (source.telephoneNumber != null) {
var phone = {
value: source.telephoneNumber,
type: "work"
}
target.phoneNumbers = [phone]
}


Conclusion


ForgeRock Identity Management is now ready to take advantage of the new SCIM connector and to provision users to a SCIM compliant service. In our case we are utilizing WSO2 Identity Server that has a SCIM compliant interface to accept inbound provisioning requests.


SCIM has long been the attempt to clean up the mess that was called SPML using a RESTful approach but has seen little adoption in the industry aside from a few advocate names. ForgeRock now recognizes the importance of this standard and provides an easy and efficient way to integrate with SCIM compliant services.