Just recently I came across an expired Server Certificate on my Citrix License Server v12.x. As everybody might know, the Citrix License Server is based on an Apache Tomcat webserver running on your Windows Server. During installation a self-signed server certificate is being issued and bound to the Apache's web server port 8083. So how are you supposed to renew the server certificate in case it has expired and you need secure access to the corresponding Citrix License Server features?
Usually you access the Citrix License Administration Console through the URL
- http://localhost:8082 or
- http://<FQDNofYourLicenseServer>:8082
As opposed to the unsecure connection you can access the Citrix Simple License Service through an secure connection via
- https://<FQDNofYourLicenseServer>:8083
thus requiring a corresponding server certificate reflecting the License Server's FQDN on the certificate.
As I use a PowerShell script for daily reports on my current license consumption and usage (which can be found here), I need secure access to the License Server's service. The script uses the Citrix.Licensing.Admin.V1 snapin and the included cmdlets Get-LicCertificate.ps1 as well as Get-LicInventory.ps1 to retrieve all information required for this purpose. The PowerShell script
Get-CitrixLicenses.ps1 can be found here, courtesy of Clint McGuire's efforts.
The snapin Citrix.Licensing.Admin.V1 has to be installed manually and can be found in LicensingAdmin_PowerShellSnapIn_x64.msi under the \x64\Licensing folder of your XenDesktop 7.x installation medium:
After the server certificate has expired the script stopped working. As soon as the script issued the cmdlet Get-LicInventory -AdminAddress https://<FQDNofYourLicenseServer>:8083/ I received an error stating:
Get-LicInventory : CertificateVerificationFailed
Keep in mind that the exact same error shows up in case you don't trust the server certifcate's issuer, which is usually the case in terms of a default installation.
Interlude
This error pointed me in another direction as well. In order to avoid any certificate related errors while running PowerShell cmdlets against the Citrix License Server's secure address, you have to read the CertHash property first, then provide it to the Get-LicInventory cmdlet, e.g.:
$ServerAddress = "https://<FQDNofYourLicenseServer:8083" $certhash = (Get-LicCertificate -AdminAddress $ServerAddress).certhash $LicAll = Get-LicInventory -AdminAddress $ServerAddress -CertHash $certhash
Then you should receive the corresponding License Server information, e.g.:
...
LicenseProductName : XDT
LocalizedLicenseProductName : Citrix XenDesktop Platinum
LicenseEdition : PLT
LicenseLocalizedEdition :
LicenseSubscriptionAdvantageDate : 2014:0826
LicenseType : Retail
LocalizedLicenseType : Retail
LicensesInUse : 44
LicensesAvailable : 44
LicenseOverdraft : 4
LicenseModel : UD
LocalizedLicenseModel : User/DeviceLicenseProductName : XDT
LocalizedLicenseProductName : Citrix XenDesktop Platinum
LicenseEdition : PLT
LicenseLocalizedEdition :
LicenseSubscriptionAdvantageDate : 2016:0806
LicenseType : Retail
LocalizedLicenseType : Retail
LicensesInUse : 16
LicensesAvailable : 55
LicenseOverdraft : 5
LicenseModel : UD
LocalizedLicenseModel : User/Device
...
Ok then, back to the actual renewal of the server certifcate….. My methodology looked as follows:
- create a new server certificate including a private key
- export the server certificate to pfx file format
- extract server certificate and private key from pfx to separate files
- exchange the Apache Tomcat's expired server certificate with newly created certificate
1. Request a new Server Authentication Certificate
As I sported a Microsoft PKI for internal use server certificates, I simply requested a new Server Authentication Certificate for my Citrix License Server on my Microsoft CA. You only have to ensure that you choose the correct certificate and mark the corresponding key as exportable. The Name should reflect the License Server's FQDN:
Issue the newly requested server certificate on your CA, then import/install it onto your Citrix License Server:
2. Export the Server Certificate inluding Private Key
After importing you need to export the server certificate including the private key, i.e. to the pfx file format. To achieve this simply open a MMC an add the Certificates Snap-in pointing to your Certificates - Current User store. There you should find the recently installed server certificate. Right-click the corresponding certificate and hit All Tasks | Export...:
Now rinse and repeat as we need to export the server certificate once more, this time around in cer file format, i.e. without your private key and Base-64 encoded X.509 (.CER):
3. Extract Private Key and Server Certificate from PFX
In order to achieve this I utilized GnuWin32's OpenSSL binaries for Windows. You can download them here. I downloaded and installed the Complete package, except sources. After installation you'll find the required openssl.exe executable file in C:\Program Files (x86)\GnuWin32\bin. In order to extract both the certificate as well as the certificate's key issue the following commands in an elevated command prompt:
openssl pkcs12 -in <ExportedCertificate>.pfx -nocerts -out key.pem -nodes openssl rsa -in key.pem -out server.key
After issueing these commands you should at least have two files available:
- key.pem
- server.key
4. Import newly created server certificate to Apache Tomcat
The previously exported server.key certificate file can now be used to replace the expired Apache server certificate located at C:\Program Files (x86)\Citrix\Licensing\LS\conf ... or ... C:\Program Files (x86)\Citrix\Licensing\WebServicesForLicensing\Apache\conf ...
Subsequently you have to verify or adjust the configuration file httpd-ssl.conf which can be found in C:\Program Files (x86)\Citrix\Licensing\WebServicesForLicensing\Apache\conf\extra
SSLCertificateFile "C:/program files (x86)/citrix/Licensing/WebServicesForLicensing/Apache/conf/server.crt" SSLCertificateKeyFile "C:/program files (x86)/citrix/Licensing/WebServicesForLicensing/Apache/conf/server.key"
As a final step restart the corresponding Citrix Licensing services.
Navigate to URL https:<FQDNofCitrixLicenseServer>:8083 and verify whether any certificate errors appear:
5. Script
The final script looks as follows:
<# .SYNOPSIS Reports on Citrix licenses in use for selected products. .DESCRIPTION This script will query your Citrix Licnese server and output the in use and total licenses for individual products. .NOTES Requires Citrix Licensing Snapin (Citrix.Licensing.Admin.V1) If your License server has a self-signed cert you may get license errors when running this. I've resolved this in my test environments by installing the cert as a Trusted Root CA Cert. Source: http://www.clintmcguire.com/scripts/get-citrixlicenses/ Author: Clint McGuire Version 1.0 Copyright 2013 Code edited by Alexander Ollischer Source: https://blog.ollischer.com Version 1.1 Copyright 2017 .EXAMPLES PS> .\Get-CitrixLicenses.ps1 Using 71 Citrix XenApp Enterprise of 132 available. #> ############################################################################################ #DEFINE THESE VARIABLES FOR YOUR ENVIRONMENT #Enter the URL for your License server, typically this uses HTTPS and port 8083 #E.G. "https://licensingservername:8083" $ServerAddress = "https://<LicenseServerName>.domain.local:8083" #Enter the license type you would like to output, this can be a comma separated list, include #each option in single quotes #E.G. 'Citrix XenApp Enterprise','Citrix XenDesktop Enterprise','Citrix EdgeSight for XenApp' $LicenseTypeOutput = 'Citrix XenApp Enterprise','Citrix XenDesktop Enterprise','Citrix EdgeSight for XenApp','Citrix XenApp Platinum','Citrix XenDesktop Platinum' ############################################################################################ #Path to HTMLReport File $FilePath = "C:\Scripts\LMC\LicAll.html" $smtpsettings = @{ To = "recipient@domain.local" From = "sender@domain.local" Subject = "Citrix License Usage" SmtpServer = "IPorFQDNofYourMailServer" } #Check for Licensing Snap-in, add if not currently added #PowerShell Snap-in is contained in: LicensingAdmin_PowerShellSnapIn_x64.msi if ( (Get-PSSnapin -Name Citrix.Licensing.Admin.V1 -ErrorAction SilentlyContinue) -eq $null ) { Add-PsSnapin Citrix.Licensing.Admin.V1 } #Create Hash tables $LicAll = @{} $LicInUse = @{} $LicAvailable = @{} #Build License Display hash table $certhash = (Get-LicCertificate -adminaddress $ServerAddress).certhash $LicAll = Get-LicInventory -AdminAddress $ServerAddress -CertHash $certhash Get-LicInventory -AdminAddress $ServerAddress -CertHash $certhash | ConvertTo-HTML | Out-File $FilePath ForEach ($LicInfo in $LicAll) { $Prod = $LicInfo.LocalizedLicenseProductName $InUse = $LicInfo.LicensesInUse $Avail = $LicInfo.LicensesAvailable if ($LicInUse.ContainsKey($Prod)) { if ($LicInUse.Get_Item($Prod) -le $InUse) { $LicInUse.Set_Item($Prod, $InUse) } } else { $LicInUse.add($Prod, $InUse) } if ($LicAvailable.ContainsKey($Prod)) { if ($LicAvailable.Get_Item($Prod) -le $Avail) { $LicAvailable.Set_Item($Prod, $Avail) } } else { $LicAvailable.add($Prod, $Avail) } } #Output license usage for each requested type. Foreach ($Type in $LicenseTypeOutput) { $OutPutLicInUse = $LicInUse.Get_Item($Type) $OutPutAvail = $LicAvailable.Get_Item($Type) Write-Host "Using" $OutPutLicInUse $Type "of" $OutPutAvail "available." } #Send Email Notification $Output = (Get-Content $FilePath | Out-String) Send-MailMessage @smtpsettings -Body $Output -BodyAsHtml -Encoding ([System.Text.Encoding]::UTF8)
Further reading: