Automatic user synchronization using command-line interface
CXO user synchronization is a mechanism using which users can be automatically updated to match an external user-management services (like Active Directory Federation Services). CXO does not provide a direct connector to such external services, but rather an API which CXO clients can use to automate their processes. To facilitate easier service integration, CXO provides a command-line interface to interacting with the API.
This guide explains how to set up the synchronization of CXO users using the CXO User synchronization command-line interface.
Deployment
CXO User synchronization allows automated adding / removing of users to user groups within CXO. For that purpose, CXO (left) offers a User Sync API that is secured by CXO Identity provider (IDP). In order to call the API, the caller needs to attach token to the user sync request. This token needs to be verified by the IDP in order to accept the request.
The command-line interface is a automation-friendly executable that orchestrates obtaining access tokens. Furthermore, it provides a number of execution options to improve the locality of change, and reduce efforts to call CXO user sync API.
To see the OpenAPI specification of the User Sync API, open <cxo-url>/public/swagger (example from CXO training environment) and search for users/synchronize
.
Command-line interface
The command-line interface (or CLI) provides the functionality of synchronizing the users of one or many CXO Applications with an external repository.
Prerequisite
The tool requires the .Net 6.0 runtime to be installed on the machine
Or soon .Net 8.0 runtime
Installation
The tool is distributed as a zip archive, simply unzip it in the desired location and it is ready to use.
Usage
You may run it from the installation folder by opening the command line and calling the executable: CXO.User.Synchronization.Client.CLI.exe
Running it in the following way will list all the options / parameters available../CXO.User.Synchronization.Client.CLI.exe
Parameters
Parameter | Short | Description |
---|---|---|
--cxoUrl | N/A | URL of CXO |
--idpUrl | N/A | URL of the CXO identity provider. |
--clientId | -c | Identity provider - client Id. See the Security section on how to obtain this value. |
--privateKey | -p | Identity provider - client private key. See the Security section on how to obtain this value. |
--input | -i | Path of the input file. See the Inputs section. |
--applicationsFile | -a | The file path to a list of applications to synchronize. |
--masterDatabaseConnectionString | -m | Connection string of the master database. Using this option all applications (from given master database) will be synchronized. If this option is set, (-a --applicationsFile) option should not be set. |
--filterApplications | -f | A comma-separated list of application |
--maxParallelism | -P | Default(1) . Represents the max number of applications to synchronize in parallel. This value should be at most equal to the amount of CXO instances available. |
--init | N/A | Initializes the input file and applicationsFile with an example text at the path specified to each parameter. |
Endpoints
As described in the Deployment section, the CLI interacts with CXO. For that reason, you need to provide CXO and IDP URLs using --cxoUrl and --idpUrl options, respectivelly.
These URLs can be easily found in the CXO Configurator → Settings tab (see example below)
If you call the following from the command line./CXO.User.Synchronization.Client.CLI.exe --cxoUrl "<your-cxo-url>" --idpUrl "<your-idp-url>"
you would see that cxoUrl and idpUrl are no longer listed as missing required parameters
Security
In order for CXO to process the User synchronization request, the CLI to be authenticated by the CXO Identity Provider (IDP). This is done by associating the CLI with a certain type of IDP client.
You need to register a User synchronization client in CXO IDP. This is done by opening the Identity Provider configuration > New Client, and then creating a client with User synchronization client type
The value of the Client Id should be passed to the CLI with (--clientId, -c) option.
When saving you will obtain a private key that the CLI uses to sign messages it sends to the identity provider.
This key is what needs to be passed to the CLI with (--privateKey, -p) option.
If you call the following from the command line./CXO.User.Synchronization.Client.CLI.exe --cxoUrl "<your-cxo-url>" --idpUrl "<your-idp-url>" -p "<your-private-key>" -c "<your-client-id>"
you would see that privateKey and clientId are no longer listed as missing required parameters
Inputs
CLI requires the list of users with their corresponding CXO user groups to be supplied as a json file. This input is mandatory, so no passing this file will result in an error. As for the file content, for each user, the following can be specified:
Field | Optional/Mandatory | Limitations |
---|---|---|
User name | Mandatory | unique, not null, at most 300 characters |
Full name | Optional | at most 2000 characters |
Optional | value email address format, at most 2000 characters | |
User groups | Mandatory | For each group: unique, not null, at most 300 characters |
Additionally, if supplied with (--applicationsFile, -a), another json file will specify which applications to synchronize. As for the file content, for each application, the following can be specified:
(mandatory) ID of the CXO application, which can be found in the configurator
(optional) Name of the CXO application, primarily for logging purposes
To see the structure of these json files, run the CLI in the init mode using --init option
./CXO.User.Synchronization.Client.CLI.exe -p "<your-private-key>" -c "<your-client-id>" --init -a "./applications.json" -i "./input.json"
Running this code snippet will result in two files applications.json and input.json created and initialized with examples.
Putting it all together (example: Powershell)
If you are calling the CLI from a Powershell script, The end result is that you will be calling the CLI something like this (example in Powershell):
$clientId = 'TestUserSynchronization'
$clientSecret = 'MIIEp....<the rest of the private key>'
$cxoUrl = 'https://cxo-dev-t03.cxo-dev.local'
$idpUrl = 'https://cxo-dev-t03.cxo-dev.local/idp'
$appsFile = '.\applications.json'
$inputFile = '.\users.json'
$exe = './CXO.User.Synchronization.Client.CLI.exe'
& $exe "--cxoUrl" $cxoUrl "--idpUrl" $idpUrl "-c" $clientId "-p" $clientSecret "-i" $inputFile "-a" $appsFile | Write-Host
This code-snippet would will automatically synchronize the applications and users from the two input json files.
Troubleshooting
Synchronizing users takes too much time
The time it takes to synchronize the users (i.e. run the command line) is proportional to the number of users in your CXO applications.
In CXO, each action related to the user (adding/updating/removing) can cause a side effect in the system. Examples are updating the storyboard assignments and logging changes in the audit trail. The most time consuming operation is removing a user, then adding a user, and the fastest of all operations is updating a user.
If you experience slow performance, try the following:
Run the command line interface more often to make sure not too many users are added / removed.
In the web application configuration (web.config file), in httpRuntime, the executionTimeout value can be increased
Synchronization fails due to DbUpdateConcurrencyException
The synchronization of CXO application users occurs within a single transaction. When a user is updated or deleted many other resources (conversations, storyboards, reports, etc..) also need to be modified. For performance reasons, CXO doesn’t lock these resources. If they are modified while the synchronization is in progress an error will occur and the transaction will be rolled back.
If this error occurs, try the following:
Retry
Make sure the user synchronization runs at a time where CXO is not in use.
Pause the CXO services before running the synchronization.
To pause the CXO services there are two options:
1. Stop programmatically while the user synchronization is ongoing (refer to the code snippet below).
Stop-Service -Name "CXO-Cockpit Agent"
Stop-Service -Name "CXO-Cockpit Export Service"
<run synchronizatiob>
Stop-Service -Name "CXO-Cockpit Agent"
Stop-Service -Name "CXO-Cockpit Export Service"
2. Adjust active periods using Configurator
Open the Configurator > Configuration > Schedule.xml
Edit the cron-expression of the following jobs so that they are not run while the user synchronization is ongoing: ScreenshotsOnDemandJob, CleanUpJob
You can use a CRON expression editor to define a period when the services will not be running.
See examples below on how to pause it between 2 AM and 4 AMLeave time for export jobs to complete before the user synchronization begins