How to Enable SSL on Cloud Connectors to Secure XML Traffic v0.3

Updated verion of my set-CTXCloudConnectorToSecureXMLTraffic.ps1 script due to name and location changes of the Citrix Cloud Connector installation.

<#
    set-CTXCloudConnectorToSecureXMLTraffic_v03.ps1

    v0.3 - New Broker Service Name and Path -> Citrix Remote Broker Provider - x64 - Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
    v0.2 - Check for Certificates
    v0.1 - Initial Version

    https://support.citrix.com/article/CTX221671
    
    netsh http add sslcert ipport=0.0.0.0:443
    certhash=PASTE_CERT_HASH_HERE_FROM_NOTEPAD
    appid={PASTE_XD_GUID_HERE_BETWEEN{}_FROM_NOTEPAD

    Browse to HKEY_LOCAL_MACHINE\Software\Citrix\DesktopServer\
    Right-click DesktopServer, select New > DWORD (32-bit) Value
    Name: XmlServicesEnableNonSsl
    Value Data: 0

#>


# To obtain the Citrix Broker Service GUID on the Cloud Connector, in the Registry Editor, select Find, and search for Citrix Remote Broker Provider - x64. 
# The search should return an entry in the following registry location Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
$keys = Get-Item -Path Registry::"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"

foreach($key in $keys){
    if((get-itemproperty $key[0].PsPath).DisplayName -eq 'Citrix Remote Broker Provider - x64'){
        $CtxBrokerServiceValues = ($key.Name).Substring(71,38)        
    }
}


# Check for Certificates
$certs = (Get-ChildItem Cert:\LocalMachine\My\)
$selectedCert = $null

$certNames = $certs | ForEach-Object { $_.Subject }
write-host "******* Installed Cert Subjects **********" -ForegroundColor Green
$i = 0
foreach($certname in $certnames){
    $i++
    write-host "$i - $certname"
}
#$certNames
write-host ""

[int]$selectedCertName = Read-Host "Enter the number of the certificate you want to select"

if ($selectedCertName -le $i -AND $selectedCertName -gt 0) {
    #$selectedCert = $certs | Where-Object { $_.Subject -eq $selectedCertName }
    $selectedCert = $certs[$selectedCertName-1]
    $selectedCert
}
else {
    Write-Host "Certificate not found." -ForegroundColor Yellow
    $selectedCert = $null
    break # exit if no certificate is selected
}


# Get CC Computer Certificate Thumbprint
#$certhash = (Get-ChildItem Cert:\LocalMachine\My\).Thumbprint
$certhash = $selectedCert.Thumbprint


# Note: The “Citrix Broker Service GUID” being used to create the SSL binding may change with the Connector upgrades, however, no change is required to the SSL binding. 
# The binding would persist through these changes and SSL would continue to be enabled for the XML traffic.
#netsh http add sslcert ipport=0.0.0.0:443 certhash=$certhash appid=$appID
netsh http add sslcert ipport=0.0.0.0:443 certhash=$certhash appid=$CtxBrokerServiceValues

# Allow only secure traffic
$registryPath = "HKLM:\Software\Citrix\DesktopServer"
$Name = "XmlServicesEnableNonSsl"
$value = "0"
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null

Tastatur funktioniert nach sperren des Rechners in der Sitzung nicht mehr

Wenn man eine Desktop Session im Vollbildmodus offen hat und den Rechner mit „STRG+ALT+ENT“ sperrt, funktioniert danach die Tastatur innerhalb der Sitzung nicht mehr.

Je nach Anwendung innerhalb der Sitzung sieht so aus, als ob die „ALT-Taste“ gedrückt sei nach der Entsperrung.

Lösung:
Durch einmaliges drücken der „Alt“ Taste kann man einfach weiterschreiben.

Problem ist nachstellbar mit der Citrix WorksapceApp (CWA) 2203CU5 für Windows.
Mit CWA 2203CU4 tritt das Problem nicht auf.

How to use Citrix DaaS REST APIs

Ich nutzte sehr viel das Citrix PowerShell SDK um meine Citrix Umgebungen zu automatisieren und Informationen auszulesen.

Was mich dabei immer störte was, dass ich die PowerShell SDK immer auf dem neusten Stand halten musste und ich die Skripte nicht überall nutzen konnte.

Da ich habe ich angefangen mich mit den Citrix DaaS REST APIs auseinanderzusetzen.
About Citrix DaaS REST APIs | Citrix DaaS REST APIs

Die Dokumentation ist sehr gut und es gibt inzwischen auch PowerShell Beispiele. Get started with Citrix Cloud APIs | Citrix Cloud API overview

Die Voraussetzung um die REST APIs zu nutzen ist ein Citrix Cloud Account und ein „API Access Client“.
Wie man diesen generiert ist in der „Citrix Developer Documentation“ beschrieben:
https://developer-docs.citrix.com/en-us/citrix-cloud/citrix-cloud-api-overview/get-started-with-citrix-cloud-apis.html#create-an-api-client

Weiterhin benötigt man die Customer ID aus dem Citrix Cloud Portal.
Einfach anmelden an https://citrix.cloud.com und rechts oben findet man die „CCID“.

Bzw. unter den „Account Settings“.

Ich habe eine PowerShell Funktion, geschrieben mit der man sich einen „BearerToken“ holen kann.

function getBearerToken {
    param (
        [Parameter(Mandatory=$true)]
        [string] $baseURL,
        [Parameter(Mandatory=$true)]
        [string] $clientID,
        [Parameter(Mandatory=$true)]
        [string] $clientSecret
    )

    $tokenUrl = "https://$baseURL/cctrustoauth2/root/tokens/clients"

    $response = Invoke-WebRequest $tokenUrl -Method POST -Body @{
        grant_type = "client_credentials"
        client_id = $clientID
        client_secret = $clientSecret
    }

    # $tokenResponse = Invoke-RestMethod -Uri $tokenUrl -Method Post -Body $tokenBody
    # $accessToken = $tokenResponse.access_token

    $bearerToken = (ConvertFrom-Json $response.Content).access_token
    return $bearerToken
}

Für die weiteren Schritte benötigt man auch seine SiteID. Diese kann man über die folgende Funktion ermitteln.

function GetMe {
    param (
        [Parameter(Mandatory=$true)]
        [string] $baseURL,
        [Parameter(Mandatory=$true)]
        [string] $bearerToken,
        [Parameter(Mandatory=$true)]
        [string] $customerId
    )

    $requestUri = "https://$baseURL/cvad/manage/me"

    $headers = @{
        "Accept" = "application/json";
        "Authorization" = "CWSAuth Bearer=$bearerToken";
        "Citrix-CustomerId" = $customerid;
    }

    $response = Invoke-RestMethod -Uri $requestUri -Method GET -Headers $headers 

    return $response
}

Hier ein Beispiel wir man diese Funktionen nutzt und welche Informationen man noch angeben muss.

# Select your Citrix Cloud Region.
# In this excample EU region is assigned to the variable $baseURL

$baseAPACS = 'api-ap-s.cloud.com' # If your Citrix Cloud account is set to the Asia Pacific South region.
$baseEU = 'api-eu.cloud.com' # If your Citrix Cloud account is set to the European Union region.
$baseUS = 'api-us.cloud.com' # If your Citrix Cloud account is set to the United States region.
$baseJP = 'api.citrixcloud.jp' # If your Citrix Cloud account is set to the Japan region.

$baseURL = $baseEU

$customerId = "XXXXXXXXX"

$secureClientCSV = "PATH TO THE CSV"

$secureClient = Import-Csv $secureClientCSV 
$secretID = $secureClient.ID
$secret = $null

# Check if secureClient file contains german or english headers
if(($secureClient.PSObject.Properties.Name).contains('Secret')){
    $secret = $secureClient.Secret
}elseif(($secureClient.PSObject.Properties.Name).contains('Geheimnis')){
    $secret = $secureclient.Geheimnis
}else{
    Write-Error "Check your 'secureclient.csv file!"

}

$bearerToken = getBearerToken -baseURL $baseURL -clientID $secretID -clientSecret $secret
#$bearerToken

$response = GetMe $baseEU $bearerToken $customerId
$mysiteID = $response.Customers.Sites.Id

Mit dem BearerToken und der SiteID kann man z.B. sich dann z.B. alle Admins in der Citrix Cloud Umgebung, oder die DeliveryGroups ausgeben lassen bzw. auch MaschineCatalogs oder Applications anlegen.

Als Beispiel die Funktion, mit der man sich alle Citrix Cloud Admin Accounts abrufen kann:

function GetAdminAccounts {
    param (
        [Parameter(Mandatory=$true)]
        [string] $baseURL,
        [Parameter(Mandatory=$true)]
        [string] $bearerToken,
        [Parameter(Mandatory=$true)]
        [string] $customerid,
        [Parameter(Mandatory=$true)]
        [string] $siteId
    )

    $requestUri = "https://$baseURL/cvad/manage/Admin/Administrators"

    $headers = @{
        "Accept" = "application/json";
        "Content-Type" = "application/json; charset=utf-8";
        "Authorization" = "CWSAuth Bearer=$bearerToken";
        "Citrix-CustomerId" = $customerid;
        "Citrix-InstanceId" = $siteId;
    }

    $response = Invoke-RestMethod -Uri $requestUri -Method GET -Headers $headers 

    return $response
}

Mehr kommt in der nächsten Zeit.

Stay tuned 🙂

How to Enable SSL on Cloud Connectors to Secure XML Traffic v0.2

A little update to my set-CTXCloudConnectorToSecureXMLTraffic.ps1 script.

Now it lists all available certificates on the machine and you have to select the one you want to use.

<#
    set-CTXCloudConnectorToSecureXMLTraffic.ps1

    v0.2 - Check for Certificates
    v0.1 - Initial Version

    https://support.citrix.com/article/CTX221671
    
    netsh http add sslcert ipport=0.0.0.0:443
    certhash=PASTE_CERT_HASH_HERE_FROM_NOTEPAD
    appid={PASTE_XD_GUID_HERE_BETWEEN{}_FROM_NOTEPAD

    Browse to HKEY_LOCAL_MACHINE\Software\Citrix\DesktopServer\
    Right-click DesktopServer, select New > DWORD (32-bit) Value
    Name: XmlServicesEnableNonSsl
    Value Data: 0

#>

# Find Citrix Broker Service GUID on the Cloud Connector
New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT | Out-Null
$keys = Get-Item "HKCR:\Installer\Products\*"
Remove-PSDrive -Name "HKCR"

foreach($key in $keys){
    if((get-itemproperty $key[0].PsPath).Productname -eq 'Citrix Broker Service'){
        $CtxBrokerServiceValues = Get-ItemProperty $key.PSPath
    }
}

# Format the String of the Service GUID
# It is important to mention that the entry in the registry is presented without the dashes for the GUID. 
# Please make that the dashes are added in the following format: 8-4-4-4-12
$appID = '{' + ($CtxBrokerServiceValues.PSChildName) + '}'
$appID = $appID.Insert(9,'-')
$appID = $appID.Insert(14,'-')
$appID = $appID.Insert(19,'-')
$appID = $appID.Insert(24,'-')


# Check for Certificates
$certs = (Get-ChildItem Cert:\LocalMachine\My\)
$selectedCert = $null

$certNames = $certs | ForEach-Object { $_.Subject }
write-host "******* Installed Cert Subjects **********" -ForegroundColor Green
$i = 0
foreach($certname in $certnames){
    $i++
    write-host "$i - $certname"
}
#$certNames
write-host ""

[int]$selectedCertName = Read-Host "Enter the number of the certificate you want to select"

if ($selectedCertName -le $i -AND $selectedCertName -gt 0) {
    #$selectedCert = $certs | Where-Object { $_.Subject -eq $selectedCertName }
    $selectedCert = $certs[$selectedCertName-1]
    $selectedCert
}
else {
    Write-Host "Certificate not found." -ForegroundColor Yellow
    $selectedCert = $null
    break # exit if no certificate is selected
}


# Get CC Computer Certificate Thumbprint
#$certhash = (Get-ChildItem Cert:\LocalMachine\My\).Thumbprint
$certhash = $selectedCert.Thumbprint


# Note: The “Citrix Broker Service GUID” being used to create the SSL binding may change with the Connector upgrades, however, no change is required to the SSL binding. 
# The binding would persist through these changes and SSL would continue to be enabled for the XML traffic.
netsh http add sslcert ipport=0.0.0.0:443 certhash=$certhash appid=$appID


# Allow only secure traffic
$registryPath = "HKLM:\Software\Citrix\DesktopServer"
$Name = "XmlServicesEnableNonSsl"
$value = "0"
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null

How to Enable SSL on Cloud Connectors to Secure XML Traffic

I will not explain how to do it, this is explained in the CTX221671.

But because I’m a bit lazy, I wrote a quick and dirty script to get the AppID of the Service (Citrix Broker Service GUID) and the Cert-Hash of the computer certificate of the Citrix Cloud Connector and set it via netsh.

This is version 0.1!
No error handling etc.

<#
    set-CTXCloudConnectorToSecureXMLTraffic.ps1

    v0.1 - Initial Version

    https://support.citrix.com/article/CTX221671
    
    netsh http add sslcert ipport=0.0.0.0:443
    certhash=PASTE_CERT_HASH_HERE_FROM_NOTEPAD
    appid={PASTE_XD_GUID_HERE_BETWEEN{}_FROM_NOTEPAD

    Browse to HKEY_LOCAL_MACHINE\Software\Citrix\DesktopServer\
    Right-click DesktopServer, select New > DWORD (32-bit) Value
    Name: XmlServicesEnableNonSsl
    Value Data: 0

#>

# Find Citrix Broker Service GUID on the Cloud Connector
New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT | Out-Null
$keys = Get-Item "HKCR:\Installer\Products\*"

foreach($key in $keys){
    if((get-itemproperty $key[0].PsPath).Productname -eq 'Citrix Broker Service'){
        $CtxBrokerServiceValues = Get-ItemProperty $key.PSPath
    }
}

# Format the String of the Service GUID
# It is important to mention that the entry in the registry is presented without the dashes for the GUID. 
# Please make that the dashes are added in the following format: 8-4-4-4-12
$appID = '{' + ($CtxBrokerServiceValues.PSChildName) + '}'
$appID = $appID.Insert(9,'-')
$appID = $appID.Insert(14,'-')
$appID = $appID.Insert(19,'-')
$appID = $appID.Insert(24,'-')


# Get CC Computer Certificate Thumbprint
$certhash = (Get-ChildItem Cert:\LocalMachine\My\).Thumbprint

# Note: The “Citrix Broker Service GUID” being used to create the SSL binding may change with the Connector upgrades, however, no change is required to the SSL binding. 
# The binding would persist through these changes and SSL would continue to be enabled for the XML traffic.
netsh http add sslcert ipport=0.0.0.0:443 certhash=$certhash appid=$appID


# Allow only secure traffic
$registryPath = "HKLM:\Software\Citrix\DesktopServer"
$Name = "XmlServicesEnableNonSsl"
$value = "0"
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null