Who changed that CME object?

The platform SDK makes it pretty easy for use to track changes to CME objects by means of a Conf Server Configuration instance, Protocol Management Service instance and an associated Event Broker instance to handle the following configuration server events:

  • EventObjectCreated
  • EventObjectUpdated
  • EventObjectDeleted

The only extra thing to do is to register for notifications as shown in the code snippet below:

Image

By setting the property “UseDeltaOptimization” to true in the Conf Server Configuration object this can be used as the basis for a Genesys Configuration audit and tracking tool. Life is a bit more complicated in reality since “EventObjectDeleted” only tells us the database ID (DBID) of what has been deleted so we need to keep an internal object cache to have full auditing – more of that in a later post.

Unfortunately although configuration server events tell us ‘What’ has changed, they do not tell us ‘Who’ made the change!

Registering for permissions events using a “RequestRegisterPermissionsNotification” does not help us either.

The required information is however contained on the Configuration Server log when the log level is set to trace. This information is also available in Solution Control Server logs and the log database when network logging is enabled. However trying to parse log files is a) resource intensive and b) not supported by Genesys!

There is a thread on the Genesys Discussion Forum about this (https://forums.genesyslab.com/showthread.php?t=894&highlight=username).

The answer to the problem is to configure alarm conditions in CME which match log events generated by Configuration Server. The relevant log events are 24200 (object created), 24201 (object changed) and 24202 (object deleted). These log events are defined in the ‘confserv.lms’ file in the configuration server installation folder:

Image

The good news is that these are standard level log events and we can prove that we get alarms by creating some alarm conditions in CME. The steps required are:

  • Ensure that standard level network logging is enabled on Config Server:

Image

  • Create alarm conditions for each of the log events (24200, 24201 and 24202):

Image

Putting the pieces together we need create a SCS Configuration instance, Protocol Management Service instance and an associated Event Broker instance to handle SCS “EventAlarmInfo” events. We also need to subscribe to Alarm Conditions:

Image

When the SCS “EventAlarmInfo” event fires we can then parse the log message text using regular expressions to extract the object Type, object DBID and username of the CME person who changed the object.

Here is an example of a log message and some C# code to parse out the data:

Description = “Object: [CfgPerson], name [readc06], DBID: [104] is changed by client, type [SCE], name: [ConfigManager], user: [readc06]”

// Regex out the data
string pattern = @”\[(.*?)\]”;
MatchCollection matches = Regex.Matches(eventAlarmInfo.AlarmDescription.LogMessageText,pattern);
string[] data = new string[matches.Count];
for (int i = 0; i < matches.Count; i++)
{
data[i] = “”;
Match match = matches[i];
data[i] = match.Groups[1].ToString();
}

if (data.Length >= 6)
{
objectType = data[0];
objectName = data[1];
DBID = Convert.ToInt32(data[2]);
clientType = data[3];
clientName = data[4];
username = data[5];
}

Image

So that is it – well nearly. Solution Control Server is a bit too clever and will not raise additional alarms when there is an existing alarm condition and therefore we could lose log events relating to other configuration changes.

The Framework 8 Management User Guide states: “Once configured, an alarm condition automatically triggers an alarm in response to an occurrence of the log event on which the alarm condition is based. If the same log event occurs subsequently while the alarm is active, the clearance timeout is reset.”

I raised a support ticket to double check on this functionality and Genesys confimed that to disable this behaviour we would need to raise a new Feature Request.

The challenge therefore is to ensure that the cancel timeout on each alarm condition is high enough to see the log event and low enough not to miss new log events. The minimum we can set the cancel timeout is 1 second but to make the alarms fire reliability the cancel timeout needs to be 2 seconds which means we run the risk of losing events during bulk configuration changes for example when using configuration wizards.

This is something we can probably live with for now.

Share

How to implement an ESP Server

ESP is a mechanism by which you can extend the functionality available in routing strategies. The Platform SDK provides the tools you need to write your own server component to listen for and respond to ESP requests. This is how.

The ESP server is developed in C# .NET using the Genesys Platform SDK.

  • An “ExternalServiceProtocolListener” instance is initialised and the service endpoint which specifies the port which the ESP server listens on is passed as a parameter. Note that this port number much match the port number configured on the CME application object (See below)
  • Create a new “RequestBrokerService” instance using the broker service factory
  • Register a request handler for ESP requests (Request3rdServer) with the request broker

Image

  • Create a request handler to process the ESP request. The standard key names passed are “Service“, “Method” and “Parameters“:

Image

  • Send back the response passing the results in a KeyValueCollection (responseParameters):

Image

Having developed the ESP server the steps to invoke it are as follows:

  1. In CME, create a new template of type “Third Party Server”
  2. Create an application object named using the template to represent the ESP Server component. It is important that the host and port be configured properly as Interaction Server will use these to establish a connection with the ESP server
  3. On the connections tab of each primary Interaction server, add a connection to the ESP server application
  4. On the connections tab of each primary URS server, add a connection to the primary Interaction Server
  5. Write a strategy to call the ESP service using an ESP block

My test strategy does the following:

  1. Initialises strategy variables
  2. Calls a service and associated service method via the ESP server.
  3. Assigns the result from the KVP returned to the relevant strategy variables
  4. Attaches the results to the call

Image

Image

Image

Image

Image

Image

Share

IVR and Routing Interfaces

What a busy month January was!

Following on from my previous post we now have GVP 8 running and configured to use Nuance ASR and TTS resources. We have started to prototype the speech recognition IVR applications for release 2 in Composer 8.0.2.

The release 2 IVR applications will need to interface to both SAP CRM and a third party payment service provider. Given the requirement to take payments the method of integration will obviously fall under PCI scrutiny.

To support the IVR integration work I have been developing a prototype which provides a generic interface between IVR applications and/or optionally Genesys Routing strategies and SAP CRM data services.

The prototype interface is implemented as a Window Communication Foundation (WCF) service host which can be deployed standalone as a Windows service or hosted under Microsoft Internet Information Services (IIS). The advantage of deploying the interface as a standalone Windows service is that we can create a Third Party Server application in CME and monitor the interface through SCI.

The primary function of the interface is to abstract the data services provided by SAP subsystems and to expose a simplified view of these services to the IVR applications and/or Genesys routing strategies. At the core of the interface is an object cache which manages the fetching and storage of SAP data entities in order to reduce any delays in providing responses back to the calling applications.

Security Considerations

The advantage of building the interface using WCF is that WCF implements many security standards and has a wide range of features available. One of the most important aspects of security is authentication. WCF can be configured to use many authentication methods:

  • Anonymous caller
  • User name and password
  • Certificate
  • Windows

The method of authentication is specified in Endpoint bindings. Therefore, the prototype interface can be configured to specify the required authentication method.

However, it is assumed that to meet PCI requirements the endpoints exposed by the interface will be configured in a message-based authentication mode with the use of mutual X.509 Digital Certificates.

Once certificates are setup and configured, the message exchange from the client to the interface service is digitally signed first by the client’s X.509 Digital Certificate (private-key) and then encrypted for the interface service with the service’s certificate (public-key). The interface is able to decrypt the message with its own private key and then validate that the message from the client is not tampered with via the client’s public key installed in its Trusted People certificate store. The message response from the interface to the client is then correspondingly signed first by the service and then encrypted for the client only by the public key found on the client’s X.509 Digital Certificate.

IVR Clients

For IVR applications developed in Genesys Composer the logical choice would be to expose the interface service by configuring a WCF endpoint using a standard Web HTTP Binding and to call it through either a Web Service Block or a Web Request Block.

The problem with this approach is that on the standard composer web blocks the Authentication Type property can only be set to anonymous or basic authentication (username and password). E.g. there is not support for certificate based authentication. In addition:

  • The Web Service block won’t work if the Web Service parameters are named double since URS considers it a reserved keyword
  • There are limitations on the WSDL definitions supported

Another big problem relates to being able to process Web Service results. When the “Map output values to variables” property is set to true, the Output Result property maps the Web Service response keys to AppState variables. If Map Output Values to Variables is set to false, the entire Web Service response will be assigned to a variable.

Therefore, it the web service result contains complex types we would end up with either lots of AppState variables to process or a variable containing the whole response to parse.

The alternative is the ECMAScript block which can be used to invoke JavaScript. This seems to be a better option. E.g. write a WCF client and instantiate it as a .NET object since we can then implement our choice of authentication and encryption.

Another advantage of this approach is that the WCF client if required can convert .NET objects in the response into a JavaScript Object Notation (JSON) string using standard .NET Framework 3.5 classes. JSON is the standard format used by Composer e.g. the data returned by the Web Service block is converted to JSON format.

Routing Clients

As I mentioned above the prototype interface provides services to both IVR applications and Genesys routing strategies.

We could use the same approach as above to access the interface from routing strategies (both for older strategies developed in IRD and for newer URS workflows developed in Composer).

However, Genesys provide an alterative approach using a custom server which implements the Genesys External Service Protocol (ESP). ESP is a mechanism by which you can extend the functionality available in routing strategies.

The Platform SDK provides the tools you need to write your own server component to listen for and respond to ESP requests. Therefore, in addition to supporting a routing interface via WCF e.g. HTTP bindings, my prototype interface also implements the functionality of an ESP server which allows the services exposed to be consumed via External Service blocks within a standard Genesys strategy.

I’ll cover off how this is done in a separate post.

Share