Cisco Voice Portal
CVP FTP
Allow Anonymous Read & Write Access
Configure FTP to only allow login from VXML Servers
Configure the Upload Folder Security to have Full access for the User “IUSR”
- Open IIS
- Select Server Home (root level)
- Select FTP IP Address and Domain Restrictions
- Edit Feature - Deny for unspecificed users
- Add the following:
- 127.0.0.1
- A side VXML Server IP
- B side VXML Server IP
CVP FTP Firewall Config
netsh advfirewall firewall add rule name="FTP (non-SSL)" action=allow protocol=TCP dir=in localport=21 netsh advfirewall set global StatefulFtp enable
Sip Normalization Rules
http://www.cisco.com/c/en/us/td/docs/voice_ip_comm/cucm/sip_tn/9_1_1/sip_t_n/preface.html
M = {}
function M.inbound_ANY(msg)
-- Remove the display name from the Remote Party ID Header Inbound
local rpid = msg:getHeader("Remote-Party-ID")
local uri = string.match(rpid, "(<.+>.+)")
msg:modifyHeader("Remote-Party-ID",uri)
end
function M.inbound_ANY_ANY(msg)
-- Remove the display name from the Remote Party ID Header Outbound
local rpid = msg:getHeader("Remote-Party-ID")
local uri = string.match(rpid, "(<.+>.+)")
msg:modifyHeader("Remote-Party-ID",uri)
end
return M
CVP TLS 1.2
You need to add the following to the VXML Server Tomcat Parameters via the registry and restart:
-Dhttps.client.protocol=TLSv1.2
Registry Options Location:
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Apache Software Foundation\Procrun 2.0\VXMLServer\Parameters\Java\Options]
Set Value - Local Variables
Create Local variables (similar to session variables) by using the JavaScript node “Set value”
SHA 256 Example
// CVP Rhino: SHA-256 via Java MessageDigest
function sha256_sql(accountNum) {
if (!accountNum) return null;
// Convert JS string to UTF-8 bytes
var javaStr = new java.lang.String(accountNum);
var bytes = javaStr.getBytes("UTF-8");
// Create SHA-256 digest
var md = java.security.MessageDigest.getInstance("SHA-256");
md.update(bytes);
var digest = md.digest();
// Convert byte array to hex string
var hex = '';
for (var i = 0; i < digest.length; i++) {
var h = (digest[i] & 0xFF).toString(16);
if (h.length === 1) h = '0' + h;
hex += h;
}
return hex.toUpperCase();
}
// Example usage
var accountNum = "4111111111111111";
var hash = sha256_sql(accountNum);
// Expected output: 9BBEF19476623CA56C17DA75FD57734DBF82530686043A6E491C6D71BEFE8F6E
- Uses Java’s MessageDigest, which handles byte arrays directly.
- Converts the string to UTF-8 bytes, matching SQL Server’s NVARCHAR behavior in HASHBYTES('SHA2_256', NVARCHAR).
- Outputs a hex string in uppercase, exactly like SQL Server’s CONVERT(VARCHAR(64), HASHBYTES(…), 2).
CVP’s JavaScript engine (Rhino) runs on the JVM. That means every Java class is accessible from your JS code using the Packages namespace. Example: java.security.MessageDigest becomes Packages.java.security.MessageDigest in JS. So in the above code, it is calling the Java MessageDigest.getInstance method to get a SHA-256 digest object.
You can instantiate objects, call methods, and access constants just like in Java.
Retrieving the Length of a Session Variable in Call Studio
var str = {Data.Session.pin};
eval(str.length);
Converting a double to a Integer
var str = {Data.Session.MyDoubleValue} eval(parseInt(str, 10));
var str = {Data.Session.MyDoubleValue} eval(str | 0);
var str = {Data.Session.MyDoubleValue}; myint = ~~str; eval (myint);
var a = 5; var b = 3; var c = a+b; eval (c);
removing first character from a string
var str = {Data.Session.var1}; eval(str.substring(1));
Removing leading digit of phone number and adding +353
var enteredNum = {Data.Element.Digits_EnterPhoneNum.value}; var e164Num = '+353' + enteredNum.slice(1); eval(e164Num);
Be careful how strings are returns - I found you had to quote as follows - but not sure why above works - which is also a string i.e. using eval(mybanana); doesn't work.
var mybanana = 'banana'; eval("mybanana");
So do no use eval if you want to return an integer. Convert to a string and just have the string as the last line as in the below example.
var pollDurationInt;
pollDurationInt = {Data.Session.pollDuration};
pollDurationInt = parseInt(pollDurationInt,10);
pollDurationInt = pollDurationInt .toString();
pollDurationInt;
user.microapp.error_code
WSM
WSM URL
Updating CVP Routes Manually
If you don't have access to CVP Ops console or CCE12 PCCE Admin Inventory does not have B side and you need to update CVP B side routing. This should not be used in Production. After making a change the srv.xml and sip.properties file - you will need to restart CVP Call Server
SRV Records
File: C:\Cisco\CVP\conf\srv.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <locater> <host name="cucmlabcluster.mydomain.com"> <record destination="10.0.0.101" port="5060" securePort=" " priority="10" weight="10"/> </host> <host name="voicebrowser.mydomain.com"> <record destination="CUCMA.mydomain.com" port="5060" securePort=" " priority="10" weight="10"/> <record destination="CUCMB.mydomain.com" port="5060" securePort=" " priority="10" weight="10"/> </host> </locater> </xml>
Route Setting
File: C:\Cisco\CVP\conf\sip.properties This includes the number to SIP SRV Group mapping and a RONA settings - see below for an example
# System configuration static routes for local routing without an outbound proxy. SIP.System.Proxy.Route = 777!,voicebrowser.mydomain.com;91!,voicebrowser.mydomain.com;92!,voicebrowser.mydomain.com;XXXXX,cucmlabcluster.mydomain.com;0!,cucmlabcluster.mydomain.com; # System configuration DN patterns to match for setting call specific Expires header (RONA) on outbound invites from sip b2bua. SIP.System.OutboundInviteTimeout = XXXXX,15;0!,60;
CVP Shadow Queue & Agent Gadget for Specific Customer
- Use above approach to log the call, including policy / account number and router call keys.
The above approach captures if a call is in queue or not, it does not capture if the call was answered or not. So to get this info:
- Use a Finesse Workflow on the Agent PC which updates the record as Call answered which updates the Database (very simple to do) - just need a Simple Webservice to front the Database.
- A update once an hour / day can also update the database using the TCD records which can correct / records if necessary.
CVP Certs
VAV - Virtual Agent/Assistant Voice
Smart Licensing 401 Error
Error Occurred Internal Server Error. Try again later or contact your system administrator.
The Browser Developer tools Network tab show a RC (Response Code) of 401 in the JSON response from the Call Server as per below (the second line)
ucce-lab-cvp-ops.example.com - - [16/Jun/2022:12:40:14 +0100] "GET /cvp-orm/rest/i18n/bundle?time=1655379615935 HTTP/1.1" 200 11318 ucce-lab-cvp-ops.example.com - - [16/Jun/2022:12:40:15 +0100] "GET /cvp-orm/rest/smartlicense/licensetype?time=1655379616150 HTTP/1.1" 401
- When trying to select the license type, we get error “Internal Server Error. Try again later or contact your system administrator”.
- Checked the browser console logs and see if we get 401 error and also from the Tomcat logs
- Checked the Password mentioned in the webservicescredentials.xml are same on OAMP and CVP box for which you are getting the above error
- Role specified in webservicescredentials.xml is WSM.USER_ROLE_Serviceability_Administrationny - Both are the identical
- NOAMP will check the webservicescredentials.xml file when orm.oamp.id is updated correctly in “orm.properties” file.
FIX
- open orm.properties file on the OAMP and copy the orm.oamp.id line and replace the same line in the callserver orm.properties files.
- Restart WSM on the Call Servers
CVP Certificates
CVP Call Servers
command to delete the self-signed certificates:
%CVP_HOME%\jre\bin\keytool.exe -storetype JCEKS -keystore %CVP_HOME%\conf\security\.keystore -delete -alias wsm_certificate %CVP_HOME%\jre\bin\keytool.exe -storetype JCEKS -keystore %CVP_HOME%\conf\security\.keystore -delete -alias vxml_certificate %CVP_HOME%\jre\bin\keytool.exe -storetype JCEKS -keystore %CVP_HOME%\conf\security\.keystore -delete -alias callserver_certificate
command to create the self-signed certificates (for 10 years):
%CVP_HOME%\jre\bin\keytool.exe -storetype JCEKS -keystore %CVP_HOME%\conf\security\.keystore -genkeypair -alias wsm_certificate -keysize 2048 -keyalg RSA -validity 3650 %CVP_HOME%\jre\bin\keytool.exe -storetype JCEKS -keystore %CVP_HOME%\conf\security\.keystore -genkeypair -alias vxml_certificate -keysize 2048 -keyalg RSA -validity 3650 %CVP_HOME%\jre\bin\keytool.exe -storetype JCEKS -keystore %CVP_HOME%\conf\security\.keystore -genkeypair -alias callserver_certificate -keysize 2048 -keyalg RSA -validity 3650
Reporting Server
command to delete the self-signed certificates:
%CVP_HOME%\jre\bin\keytool.exe -storetype JCEKS -keystore %CVP_HOME%\conf\security\.keystore -delete -alias wsm_certificate %CVP_HOME%\jre\bin\keytool.exe -storetype JCEKS -keystore %CVP_HOME%\conf\security\.keystore -delete -alias callserver_certificate
command to create the self-signed certificates (for 10 years)
%CVP_HOME%\jre\bin\keytool.exe -storetype JCEKS -keystore %CVP_HOME%\conf\security\.keystore -genkeypair -alias wsm_certificate -keysize 2048 -keyalg RSA -validity 3650 %CVP_HOME%\jre\bin\keytool.exe -storetype JCEKS -keystore %CVP_HOME%\conf\security\.keystore -genkeypair -alias callserver_certificate -keysize 2048 -keyalg RSA -validity 3650
Example on how to Export New Certs
%CVP_HOME%\jre\bin\keytool.exe -storetype JCEKS -keystore %CVP_HOME%\conf\security\.keystore -export -alias wsm_certificate -file %CVP_HOME%\conf\security\wsm.crt %CVP_HOME%\jre\bin\keytool.exe -storetype JCEKS -keystore %CVP_HOME%\conf\security\.keystore -export -alias callserver_certificate -file %CVP_HOME%\conf\security\callserver.crt
Securing CVP
Quays - QID 38863 - Weak SSL/TLS Key Exchange
Add to the Java Options key located at: Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Apache Software Foundation\Procrun 2.0\OPSConsoleServer\Parameters\Java\
Note above is for CVP Ops console tomcat - but you can also set it for wsm, callserver, vxmlserver tomcat installs etc.
-Djdk.security.defaultKeySize=DiffieHellman:2048 -Djdk.tls.ephemeralDHKeySize=2048