During my more than 20 years of consulting, automation has always been one of my priorities.
The key to automation is, for the most part, scripting. Luckily, these days, our products have public APIs and can be handled through a wealth of programming and script languages. This post provides a “quick-start” to XenMobile’s REST API. This will lead to my next article, which will be mostly examples of PowerShell scripts for interacting with the REST API. The documentation for XenMobile REST API can be found here: https://docs.citrix.com/en-us/xenmobile/server/rest-apis.html.
For XenMobile, this automation could be something like creating scheduled tasks to create certain reports, creating your own self-service portals, automating application updates to XenMobile, or similar.
John Pigeret, a former Citrix employee, wrote a three-part series of blog posts about using XenMobile’s SOAP API (which was the predecessor to today’s XenMobile REST API) to generate invitations and extract data from the XenMobile environment. With SOAP, programming proved somewhat cumbersome, and some tricks had to be employed in order to make authentication work, as authentication was time-based, and you had to convert between time zones to get it working. With the REST API of today, authentication is a breeze, and the rest can be handled through simple web requests. I will be providing examples in this article, written in PHP, and MS PowerShell, as I believe those are two very feasible platforms for people to use. The methodology, however, can be used in any scripting language. You could even use a simple Linux shell, with CURL, to perform the tasks.
Ward van Besien has also written a PowerShell module, which can be found here. The module is well-written, but I choose not to use it in this blog series, as I would rather show how to use the API directly.
So, first off, in order to “see” what you are doing, I truly recommend using Advanced REST Client, which is a plugin for Chrome. I have also used another Chrome plugin, Postman, for performing uploads of files like certificates and binary data (ipa, apk, mdx) to the XenMobile services. You will be seeing examples of how to use this software through this blog.
I have also had cases, especially with file uploads, where I was able to upload the file through Postman, but unable to do so through PowerShell. Since XenMobile REST API is encrypted, and only available on port 4443, it is hard to debug this traffic directly. In order to do so, I used my favorite Swiss Army Knife, NetScaler, to create an HTTP-based load-balanced vServer, pointing to XenMobile’s SSL/4443 port. This enabled me to send unencrypted traffic to NetScaler, so I could create Wireshark traces of the request going from Postman, and the subsequent request I try to send from my script. Comparing the POST requests in these traces, I could find the difference, and modify the script to have it working.
The first thing you need to do, is to authenticate to XenMobile. This is done by sending an HTTP POST request to https://<yourxenmobileserver>:4443/xenmobile/api/v1/authentication/login, with JSON payload in the form of ‘{“login:” “username”, “password”: “password”}’. What you receive in return, is an authentication token as seen below. This token needs to be added to the HTTP Headers for all subsequent requests. The token is valid until you have not been using it for the “idle period” set in XenMobile server configuration.
Now we have an authentication token to use, and can move on to actually talking to XenMobile. For our next request, we use this auth_token as a header value, as shown below:
In this picture, I also use a slightly different JSON body, saying I want to start with device number 0, and use an ascending sort order.
At the bottom of the picture, is the resultant JSON set. When I collapse the arrays, I can see that the JSON I get in my environment consists of the following nodes:
$json=Invoke-RestMethod -Uri https://xenmobileserver.lab.local:4443/xenmobile/api/v1/authentication/login -Body ‘{“login”:”username”,”password”:”password”}’ -ContentType application/json -Headers $headers -Method POST
$headers.add(“auth_token”,$json.auth_token)
$devices=Invoke-RestMethod -Uri https://xenmobileserver.lab.local:4443/xenmobile/api/v1/device/filter -Body ‘{}’ -ContentType application/json -Headers $headers -Method Post
foreach($device in $devices.filteredDevicesDataList)
{
$output=$device.platform + “: ” + $device.userName
Write-Output $output
}
$json='{“login”:”username”,”password”:”password”}’;
$ch = curl_init(‘https://xenmobileserver.lab.local:4443/xenmobile/api/v1/authentication/login’);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, “POST”);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
‘Content-Type: application/json’,
‘Content-Length: ‘ . strlen($json))
);
$result = curl_exec($ch);
$data=json_decode($result,true);foreach ($data as $name => $value)
{
if( “$name” == “auth_token”)
{
$token=$value;
}
else
{
die;
}
}$json=”{}”;
$ch = curl_init(‘https://xenmobileserver.lab.local:4443/xenmobile/api/v1/device/filter’);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, “POST”);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
‘Content-Type: application/json’,
‘Content-Length: ‘ . strlen($json),
‘Auth_token: ‘ . $token)
);
$result = curl_exec($ch);
$data=json_decode($result,true);foreach ($data[‘filteredDevicesDataList’] as $device)
{
echo $device[‘platform’] . “: ” . $device[‘userName’] . “\n”;
}
?>