Credential management via REST API

AVAILABLE IN 9.8.0 AND LATER

In a VFC system, numerous entities exist containing credential-type data. The endpoints covered in this article allow changing the credentials programmatically. With the following functionality, a custom integrator application can be implemented to rotate passwords of the different entities from a common password vault solution. With this approach, common technical accounts' password leakage or sharing can be prevented. This article introduces how these credentials can be managed via the v1 REST API in the following sections. To get generic information about REST API usage, please visit the Use the REST API article.

For the applications that manage credentials in the system, the following actions are required:

  • Listing entities: to identify the existing entities. The sensitive passwords are stored in an encrypted format in the database. With the API neither the plain nor the encrypted password cannot be retrieved.

  • Retrieve one entity by ID: to fetch the latest public values of an entity. Similar to the listing action the sensitive properties cannot be retrieved.

  • Modify properties of an entity: to actually change the credentials such as the password. Not every property of an entity can be updated. The allowed properties are listed in the REST API documentation site for every update endpoint. The modification action can be achieved with the PATCH HTTP method. This method allows the client to send only the changed properties to the server.

  • Verify the password change: send the known plain password to the system and retrieve a true or false value based on the sent plain password matching with the currently stored value. After a certain number of failed verification attempts the system blocks the API user from further requests to prevent password guessing.

The following sections cover descriptions and examples of how credential management can be achieved for different entities.

The following examples require a valid access token. To acquire an access token, use the Authentication endpoint. The different examples may require different permissions. Please, be aware to always use an access token that was acquired by a user with the right permissions.

User credentials

The non-AD synchronized user entities have an updateable password field that can be modified with the API. Note: the login name is not modifiable. The new password must match the configured password criteria i.e.: complexity or password history.

The following example shows how to change a user’s password with a PATCH method. The password has to be in plain format. The effect of the change takes place immediately after a successful PATCH update request.

PATCH https://VFC_MR_DOMAIN/verba/restapi/v1/users/16 Content-Type: application/json { "password": "new plain password" }

After the change, the modification can be verified with the following request. For the user password verification, only the plain password is needed to pass in the body of the POST request.

POST https://VFC_MR_DOMAIN/verba/restapi/v1/users/16/password/verify new plain password

Active Directory Synchronization Profile credentials

The Active Directory Synchronization Profile entities contain credential data to be able to connect to an LDAP server or a Microsoft Entra (formerly Azure AD) tenant. The updateable properties are various and depend on the type of the AD Synchronization Profile entity.

The following example shows how to change the login name and the password for an LDAP server in the same request. The password has to be in plain format. The effect of the change takes place immediately after a successful PATCH update request.

Request

PATCH https://VFC_MR_DOMAIN/verba/restapi/v1/adSyncProfiles/13F72189-2EEB-425F-885B-7D1BBA83DDEB Content-Type: application/json Accept: application/json { "userName": "john.doe", "ldapPassword": "new plain password" }

Response

{ "host": "ldap host", "port": 1234, "userName": "john.doe", "id": "13F72189-2EEB-425F-885B-7D1BBA83DDEB", "description": "LDAP AD Synchronization Profile description", "enabled": true, "type": "ldap" }

The non-sensitive data change can be validated with the previous response, which contains the whole entity object with the new modified values. The sensitive information can be verified with the following request. Due to an AD Synchronization Profile entities can have different types with different object properties, for password verification, the verified property name has to be passed with the checked plain password too.

POST https://VFC_MR_DOMAIN/verba/restapi/v1/adSyncProfiles/13F72189-2EEB-425F-885B-7D1BBA83DDEB/password/verify Content-Type: application/json Accept: application/json { "property": "ldapPassword", "value": "new plain password" }

Storage Target credentials

The VFC has numerous different Storage Target integrations which have different entity object schemas. These different schemas have different editable properties.

The following example shows how to change credentials for an Amazon S3 storage target in the same request. The password has to be in plain format. The effect of the change takes place immediately after a successful PATCH update request.

Request

PATCH https://VFC_MR_DOMAIN/verba/restapi/v1/storageTargets/11 Content-Type: application/json Accept: application/json { "accessKeyId": "amazons3_storage_keyid", "secretAccessKey": "new plain password" }

Response

{ "bucket": "bucket name", "region": "region", "objectLockEnabled": true, "objectLockMode": "compliance", "accessKeyId": "amazons3_storage_keyid", "id": 11, "name": "Amazon S3", "type": "amazon_s3" }

The non-sensitive data change can be validated with the previous response, which contains the whole entity object with the new modified values. The sensitive information can be verified with the following request. Due to a Storage Target entities can have different types with different object properties, for password verification, the verified property name has to be passed with the checked plain password too.

POST https://VFC_MR_DOMAIN/verba/restapi/v1/storageTargets/11/password/verify Content-Type: application/json Accept: application/json { "property": "secretAccessKey", "value": "new plain password" }

Import Source credentials

Similar to Storage Targets the different Import Source types have different object schema representations in the REST API. The modifiable properties depend on the specific type.

The following example shows how to change credentials for a Zoom Phones import source in one request. The password has to be in plain format. The effect of the change takes place immediately after a successful PATCH update request.

Request

PATCH https://VFC_MR_DOMAIN/verba/restapi/v1/importSources/1 Content-Type: application/json Accept: application/json { "apiKey": "zoom_api_key", "apiSecret": "new plain password" }

Response

{ "authType": "jwt", "apiKey": "zoom_api_key", "forwardProxyAddress": "proxy address", "forwardProxyPort": 1111, "forwardProxyUser": "zoom_proxyuser", "apiAddress": "https://api.zoom.us/v2/", "id": 1, "name": "Zoom Phone import", "type": "zoom_phones" }

The non-sensitive data change can be validated with the previous response, which contains the whole entity object with the new modified values. The sensitive information can be verified with the following request. Due to an Import Source entities can have different types with different object properties, for password verification, the verified property name has to be passed with the checked plain password too.

POST https://VFC_MR_DOMAIN/verba/restapi/v1/importSources/1/password/verify Content-Type: application/json Accept: application/json { "property": "apiSecret", "value": "new plain password" }

Server Configuration

A VFC deployment usually contains multiple servers with different server roles. There are two strategies to maintain the configurations of these servers.

Approach A: Change the configurations individually by every server. The solution is not recommended for deployments with multiple servers within.

Approach B: Organize the common server configurations to Configuration Profiles by server roles. This approach allows for maintaining the common configurations in one location. The solution is recommended for deployments with multiple servers within.

To read more about the topic, visit Server and service configuration.

The server configurations are stored in two locations in the system: in the central database that allows the management of the values via the user interface; and in every server’s registry that allows the local services to read them. The current configuration values can be retrieved from both locations. The system was designed like this to minimize the actions performed by the recorder services: when multiple configuration values and/or multiple extension configurations should be changed, then all changes can be configured without influencing the services, and when everything is configured in the central database, then all recorded changes can be pushed to the server at the same time.

Basically, the values stored in the central database and the registry should not be different, but after a server installation or a manual registry change, there can be differences. Before configuring the server, the differences must be eliminated by using the configurationDifferences endpoint. When the central database value is chosen as the proper value, then one or more configuration tasks will be generated that indicate the required changes in the registry and reread/restart actions for the affected services. When the server registry is chosen as the proper value, then the central database will be updated and no other action is required.

A server configuration change requires the following steps:

Step 1: Change the configurations in the central database. The changes don’t have a direct effect on the behavior of services after this change. Such changes are not considered as a difference between the registry and the central database, but a configuration task is generated instead, and the changes can be pushed to the servers' registry by executing this task.

Step 2: When the configuration tasks have been created for every server, these tasks must be applied to each server. After applying the tasks, the new configuration values will be pushed to the local registry, and the services will reread the new values and will start to work based on the new configuration.

The configuration passwords are stored in an encrypted format in the central database and the registry too. Contrary to the other entities the passwords are handled in a different way in the server configuration-related endpoints. Numerous integrations require a connection string in a complex format instead of dedicated configuration values. These connection strings contain the passwords in an encrypted format with unencrypted configuration values separated with separator characters in one configuration value. Based on that at the backend side, automatic password encryption is not possible. Due to that, the passwords have to be encrypted by the client with the usage of the dedicated password encryption endpoint.

Another difference between the server configuration-related endpoints and the other aforementioned introduced endpoints is password verification. As a result of the complex connection string format, there is no password verification action in these endpoints. The encrypted values can be retrieved by the client.

Server configuration examples

In the following sections, different use case examples demonstrate the usage of the server configuration-related endpoints.

Use case: There are differences between the central database and the local registry

When there are differences, then a few configuration API endpoints will respond with an HTTP 409 Conflict status and error code PREREQUISITE_NOT_MET.

Step 1: Retrieve the list of the differences for a specific server

Request:

GET https://VFC_MR_DOMAIN/verba/restapi/v1/servers/verbamr01/configurationDifferences

Response:

{ "differences": [ { "path": "\\Verba\\Email Settings\\TLSKeyPass", "valueRegistry": "old encrypted password", "valueDb": "NEW ENCRYPTED PASSWORD", "serverCustom": false }, { "path": "\\Verba\\Email Settings\\TLSCert", "valueRegistry": "foo", "valueDb": "", "serverCustom": false } ] }

Step 2: Resolve the differences

Based on the retrieved information, the differences must be resolved by specifying which data source contains the correct values. For the resolution, a list has to be sent with the correct data sources.

Request:

POST https://VFC_MR_DOMAIN/verba/restapi/v1/servers/verbamr01/configurationDifferences Content-Type: application/json { "resolutions": [ { "path": "\\Verba\\Email Settings\\TLSKeyPass", "correctSource": "DATABASE" }, { "path": "\\Verba\\Email Settings\\TLSCert", "correctSource": "REGISTRY" } ] }

Response:

"differences": []

If there are no more differences in the configuration, then an empty list will be retrieved. During this step, when the central database value is chosen, then configuration tasks will be created for the server.

 

Use case: Individual server configuration modification

Step 1: Change the configuration

Firstly, the current value can be retrieved by the server hostname (“verbamr01") and URL encoded registry path (“%5CVerba%5CEmail%20Settings%5CTLSKeyPass") with the next request:

GET https://VFC_MR_DOMAIN/verba/restapi/v1/servers/verbamr01/configuration?settingPath=%5CVerba%5CEmail%20Settings%5CTLSKeyPass&source=REGISTRY

If the value should be encrypted like in this case, the new value should be encrypted with the following request:

Request:

POST /verba/restapi/v1/encodePassword new plain password

Response:

NEW ENCRYPTED PASSWORD

This new value can be used to update the configuration in the local database.

PUT https://VFC_MR_DOMAIN/verba/restapi/v1/servers/verbamr01/configuration?settingPath=%5CVerba%5CEmail%20Settings%5CTLSKeyPass NEW ENCRYPTED PASSWORD

 

Step 2: Applying the configuration changes on the server

The following request can be used to list the created configuration tasks:

GET https://VFC_MR_DOMAIN/verba/restapi/v1/servers/verbamr01/configurationTasks

If the retrieved list is not empty, then the tasks must be applied to the server:

POST https://VFC_MR_DOMAIN/verba/restapi/v1/servers/verbamr01/configurationTasks

 

Use case: Multiple server configuration modifications with a configuration profile

The steps and the basic strategy are the same as the previous use case example. The only main difference is that while the last example on configuration was only associated with one server, then in this example multiple servers can be affected by the change.

The current configuration profile values can be retrieved similarly to the server configuration values by the registry path, but here the ID of the configuration profile is needed:

GET https://VFC_MR_DOMAIN/verba/restapi/v1/configurationProfiles/2/configuration?settingPath=%5CVerba%5CEmail%20Settings%5CTLSKeyPass

If the value should be encrypted then the encrypted value must be prepared. The configuration change can be done with the next request:

PUT https://VFC_MR_DOMAIN/verba/restapi/v1/configurationProfiles/1/configuration?settingPath=%5CVerba%5CEmail%20Settings%5CTLSKeyPass NEW ENCRYPTED PASSWORD

After one change, every server is affected that uses the changed configuration profile, so the necessary configuration tasks have been created by the system for every related server. The following request retrieves the list of the created configuration tasks for each server.

Request:

GET https://VFC_MR_DOMAIN/verba/restapi/v1/configurationTasks

Response:

{ "list": [ { "action": "send_config", "service": "", "server": "verbamr01", "configurationChanges": [ { "name": "\\Verba\\Email Settings\\TLSKeyPass", "value": "*********" } ] }, { "action": "restart", "service": "VerbaWebApp", "server": "verbamr01", "configurationChanges": null }, { "action": "send_config", "service": "", "server": "verbamr02", "configurationChanges": [ { "name": "\\Verba\\Email Settings\\TLSKeyPass", "value": "*********" } ] }, { "action": "restart", "service": "VerbaWebApp", "server": "verbamr02", "configurationChanges": null } ] }

From the retrieved list of tasks, a unique server hostname set should be collected (multiple tasks can exist for one server). Based on that unique set the configuration task application must be executed with the following requests on every affected server:

POST https://VFC_MR_DOMAIN/verba/restapi/v1/servers/verbamr01/configurationTasks
POST https://VFC_MR_DOMAIN/verba/restapi/v1/servers/verbamr02/configurationTasks

 

Use case: Configure a newly installed VFC server based on the configuration of another existing server

In cloud-based solutions, to decrease the load of a server, a possible solution is to start a new server with the same role to balance the load during peak times. This example shows a way how configuration management can be achieved for a similar use case.

In the example deployment, the verbamr01 server already exists and is configured. A new MR server has been started with a default configuration with the hostname verbamr02. With the recommended solution, the common configurations should be configured in the configuration profile. In this case, firstly, the used configuration profile should be determined with the following request:

Request:

GET https://VFC_MR_DOMAIN/verba/restapi/v1/servers/verbamr01

Response:

{ "hostname": "verbamr01", "role": "MR", "configurationProfileId": 2, "description": null, "tasks": null }

From this response, the configurationProfileId can be read out. That configuration profile can be set to the new server with the following requests. First, get the current server object from the new verbamr02.

Request:

GET https://VFC_MR_DOMAIN/verba/restapi/v1/servers/verbamr02

Response:

{ "hostname": "verbamr02", "role": "MR", "configurationProfileId": null, "description": "new server instance", "tasks": null }

Then change the configurationProfileId value in the object to the previously retrieved value and send it back for the update.

PUT https://VFC_MR_DOMAIN/verba/restapi/v1/servers Content-Type: application/json { "hostname": "verbamr02", "role": "MR", "configurationProfileId": 2, "description": "new server instance", "tasks": null }

For this scaling scenario, the custom server configuration values should be collected and saved as a template. To retrieve these configurations use the export endpoint.

Request:

GET https://VFC_MR_DOMAIN/verba/restapi/v1/servers/verbamr01/configuration/export?onlyServerCustomValues=true

That request only lists those configurations that overwrite the configuration profile values. The configurations are stored in an XML schema.

Response:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> <config> <category base="\Verba" displayname="Server Certificate" name="api_sec"> <item displayname="Verba Certificate Authority" isCustom="1" name="ApiCaCert" type="string">EF044E8HF74HF7HF894135B33E41FFC2W</item> <item displayname="Server Certificate" isCustom="1" name="ApiCert" type="string">FC3CEC46OI7744DHFIP917B92188C67C3RC</item> </category> <category base="\Verba" displayname="System" name="system"> <category base="\Verba" displayname="API Connection" name="apiconnection"> <item displayname="API URL" isCustom="1" name="ApiUrl" type="string">https://VFC_MR_DOMAIN/verba</item> </category> </category> </config>

That configuration list should be used as a template. After changing the values in the template, it can be sent for import to the new server with the following request:

PUT https://VFC_MR_DOMAIN/verba/restapi/v1/servers/verbamr02/configuration/import Content-Type: application/xml <?xml version="1.0" encoding="UTF-8" standalone="no"?> <config> <category base="\Verba" displayname="Server Certificate" name="api_sec"> <item displayname="Verba Certificate Authority" isCustom="1" name="ApiCaCert" type="string">G6782JGUFHI86894135B33E4RT10</item> <item displayname="Server Certificate" isCustom="1" name="ApiCert" type="string">ZU76P91RHOI7744DHFIP917BLKBL933J75JDG</item> </category> <category base="\Verba" displayname="System" name="system"> <category base="\Verba" displayname="API Connection" name="apiconnection"> <item displayname="API URL" isCustom="1" name="ApiUrl" type="string">https://VFC_MR_DOMAIN2/verba</item> </category> </category> </config>

After the configuration changes, the generated configuration tasks should be applied to the new server.

POST https://VFC_MR_DOMAIN/verba/restapi/v1/servers/localhost/configurationTasks