Jump to content
Welcome to our new Citrix community!
  • 0

Enable SSL to VDA failed - CNG cert


Casey Hautala

Question

Finally getting around to enabling TLS on my VDAs to get the internal HTML5 receiver working. I'm using the following guides:

http://www.carlstalhood.com/virtual-delivery-agent-vda-7-12/#sslvda

 

https://www.citrix.com/blogs/2014/12/11/how-to-secure-ica-connections-in-xenapp-and-xendesktop-7-6-using-ssl/

 

https://docs.citrix.com/en-us/xenapp-and-xendesktop/7-12/secure/tls.html

 

I have the cert from my Internal CA, installed it but when running the Enable-VdaSSL.ps1 get the following error:

"Verification of the certificate failed. Please install a valid certificate and try again."

The cert was generated with a CNG template CSR, it has a private key that corresponds to the cert, but the key is not easily accessible from powershell. Do I need to generate a new CSR/Cert with a Legacy template?

 

Any Ideas? 

  • Like 1
Link to comment

1 answer to this question

Recommended Posts

  • 0

Hello

 

I have fix the enable vda script to support CNG private key 

 

<#
.SYNOPSIS
    Enable/Disable SSL listener on the VDA

.DESCRIPTION
    Enable or disable SSL listener on the VDA. To enable SSL listener, the computer certificate to use should be
    specified, otherwise the first available certificate will be used. Optionally, the SSL port, version and cipher
    suite to use can be specified.

.PARAMETER Disable
    Disables the VDA SSL listener.
.PARAMETER Enable
    Enables the VDA SSL listener.
.PARAMETER SSLPort
    Specifies the SSLPort to use. Default is port 443.
.PARAMETER SSLMinVersion
    Specifies the minimum SSL version (allowed values are SSL_3.0, TLS_1.0, TLS_1.1 and TLS_1.2). Default is TLS_1.0. 
.PARAMETER SSLCipherSuite
    Specifies the SSLCipherSuite to use (allowed values are GOV, COM and ALL). Default is ALL.
.PARAMETER CertificateThumbPrint
    Specifies the certificate thumbprint to identify the certificate to use.

.EXAMPLE
    To install the VDA SSL listener using the single computer certificate that is present
    Enable-VdaSSL -Enable
.EXAMPLE
    To disable the VDA SSL listener 
    Enable-VdaSSL -Disable
.EXAMPLE
    To install the VDA SSL listener using the specified computer certificate
    Enable-VdaSSL -Enable -CertificateThumbprint "373641446CCA0343D1D5C77EB263492180B3E0FD"
.EXAMPLE
    To install the VDA SSL listener on a port other than 443
    Enable-VdaSSL -Enable -SSLPort 4000
.EXAMPLE
    To install the VDA SSL listener using non-default SSLMinVersion and SSLCipherSuite
    Enable-VdaSSL -Enable -SSLMinVersion "TLS_1.2" -SSLCipherSuite "GOV"
#>
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')]
Param(
    [Parameter(Mandatory=$True, Position=1, ValueFromPipeline=$False, ParameterSetName = "DisableMode")]
    [switch] $Disable,

    [Parameter(Mandatory=$True, Position=1, ValueFromPipeline=$False, ParameterSetName = "EnableMode")]
    [switch] $Enable,
    
    [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName = "EnableMode")]
    [int] $SSLPort = 443,

    [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName = "EnableMode")]
    [ValidateSet("SSL_3.0", "TLS_1.0", "TLS_1.1", "TLS_1.2")]
    [String] $SSLMinVersion = "TLS_1.0",

    [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName = "EnableMode")]
    [ValidateSet("GOV", "COM", "ALL")]
    [String] $SSLCipherSuite = "ALL",

    [Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName = "EnableMode")]
    [string]$CertificateThumbPrint 
    )

    Set-StrictMode -Version 2.0
    $erroractionpreference = "Stop"

    #Check if the user is an administrator
    if(!([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
    {
        Write-Host "You do not have Administrator rights to run this script.`nPlease re-run this script as an Administrator."
        break
    }

    #Write Header
    Write-Host "Enable SSL to VDA for CNG Crypto API Certificate"
    Write-Host "Running command Enable-VdaSSL to enable or disable SSL to VDA."
    Write-Host "This includes:"
    Write-Host "`ta.Disable SSL to VDA or"
    Write-Host "`tb.Enable SSL to VDA"
    Write-Host "`t`t1.Setting ACLs"
    Write-Host "`t`t2.Configuring Firewall"
    Write-Host "`t`t3.Setting registry keys"
    Write-Host ""
    Write-Host ""

    # Registry path constants 
    $ICA_LISTENER_PATH = 'HKLM:\system\CurrentControlSet\Control\Terminal Server\Wds\icawd'
    $ENABLE_SSL_KEY = 'SSLEnabled'
    $SSL_CERT_HASH_KEY = 'SSLThumbprint'
    $SSL_PORT_KEY = 'SSLPort'
    $SSL_MINVERSION_KEY = 'SSLMinVersion'
    $SSL_CIPHERSUITE_KEY = 'SSLCipherSuite'

    $POLICIES_PATH = 'HKLM:\SOFTWARE\Policies\Citrix\ICAPolicies'
    $ICA_LISTENER_PORT_KEY = 'IcaListenerPortNumber'
    $SESSION_RELIABILITY_PORT_KEY = 'SessionReliabilityPort'
    $WEBSOCKET_PORT_KEY = 'WebSocketPort'

    #Read ICAListener, SessionReliability and WebSocket ports from the registry
    try
    {
        $IcaPort = (Get-ItemProperty -Path $POLICIES_PATH -Name $ICA_LISTENER_PORT_KEY).IcaListenerPortNumber
    }
    catch
    {
        $IcaPort = 1494
    }

    try
    {
        $SessionReliabilityPort = (Get-ItemProperty -Path $POLICIES_PATH -Name $SESSION_RELIABILITY_PORT_KEY).SessionReliabilityPort
    }
    catch
    {
        $SessionReliabilityPort = 2598
    }

    try
    {
        $WebSocketPort = (Get-ItemProperty -Path $POLICIES_PATH -Name $WEBSOCKET_PORT_KEY).WebSocketPort
    }
    catch
    {
        $WebSocketPort = 8008
    }

    if(!$IcaPort)
    {
        $IcaPort = 1494
    }
    if(!$SessionReliabilityPort)
    {
        $SessionReliabilityPort = 2598
    }
    if(!$WebSocketPort)
    {
        $WebSocketPort = 8008
    }

    switch($PSCmdlet.ParameterSetName)
    {
        "DisableMode"
        {
            #Turning off SSL by setting SSLEnabled key to 0
            Set-ItemProperty -Path $ICA_LISTENER_PATH -name $ENABLE_SSL_KEY -Value 0 -Type DWord -Confirm:$false

            if($PSCmdlet.ShouldProcess("This will delete any existing firewall rules for Citrix SSL Service and enable rules for ICA, CGP and Websocket services if present.", "Are you sure you want to perform this action?`nThis will delete any existing firewall rules for Citrix SSL Service and enable rules for ICA, CGP and Websocket services if present.", "Configure Firewall"))
            {
                #Delete any existing rules for Citrix SSL Service
                netsh advfirewall firewall delete rule name="Citrix SSL Service" | Out-Null

                #Enable any existing rules for ICA, CGP and HTML5 ports
                netsh advfirewall firewall set rule name="Citrix CGP Server Service" protocol=tcp localport=$SessionReliabilityPort new enable=yes | Out-Null
                netsh advfirewall firewall set rule name="Citrix ICA Service" protocol=tcp localport=$IcaPort new enable=yes | Out-Null
                netsh advfirewall firewall set rule name="Citrix Websocket Service" protocol=tcp localport=$WebSocketPort new enable=yes | Out-Null
            }

            else
            {
                Write-Host "Firewall configuration skipped."
            }

            Write-Host "SSL to VDA has been disabled."
        }

        "EnableMode"
        {
            $RegistryKeysSet = $ACLsSet = $FirewallConfigured = $False

            $Store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My", "LocalMachine")
            $Store.Open("ReadOnly")
        
            if($Store.Certificates.Count -eq 0)
            {
                Write-Host "No certificates found in the Personal Local Machine Certificate Store. Please install certificates and try again."
                Write-Host "`nEnabling SSL to VDA failed."
                $Store.Close()
                break
            }

            elseif($Store.Certificates.Count -eq 1)
            {
                if($CertificateThumbPrint)
                {
                    $Certificate = $Store.Certificates[0]
                    $Thumbprint = $Certificate.GetCertHashString()
                    if($Thumbprint -ne $CertificateThumbPrint)
                    {
                        Write-Host "No certificate found in the certificate store with thumbprint $CertificateThumbPrint"
                        Write-Host "`nEnabling SSL to VDA failed."
                        $Store.Close()
                        break
                    }
                }

                else
                {
                    $Certificate = $Store.Certificates[0]
                }
            }

            else
            {
                if(!$CertificateThumbPrint)
                {
                    Write-Host "More than one certificates found in the certificate store, please specify the thumbprint using -CertificateThumbPrint option."
                    Write-Host "`nEnabling SSL to VDA failed."
                    $Store.Close()
                    break
                }

                else
                {
                    $Certificate = $Store.Certificates | where {$_.GetCertHashString() -eq $CertificateThumbPrint}

                    if(!$Certificate)
                    {
                        Write-Host "No certificate found in the certificate store with thumbprint $CertificateThumbPrint"
                        Write-Host "`nEnabling SSL to VDA failed."
                        $Store.Close()
                        break
                    }
                }                
            }
            
                
            #Validate the certificate
                
            #Validate expiration date
            $ValidTo = [DateTime]::Parse($Certificate.GetExpirationDateString())
            if($ValidTo -lt [DateTime]::UtcNow)
            {
                Write-Host "The certificate is expired. Please install a valid certificate and try again."
                Write-Host "`nEnabling SSL to VDA failed."
                $Store.Close()
                break
            }
            Write-Host "Certificate Expiration Date OK"
            #Check certificate trust
            if(!$Certificate.Verify())
            {
                Write-Host "Verification of the certificate failed. Please install a valid certificate and try again."
                Write-Host "`nEnabling SSL to VDA failed."
                $Store.Close()
                break
            }
            Write-Host "CA Trust Verfication OK"
            #Check private key availability
            try
            {
            
               
                $key = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($Certificate)
                $fileName = $key.key.UniqueName
                $path = "$env:ALLUSERSPROFILE\Microsoft\Crypto\Keys\$fileName"
                Write-Host "CNG Private key: " $path.
               
                
            }
            catch
            {
                
                Write-Host "Unable to access the Private Key of the Certificate or one of its fields."
                Write-Host "`nEnabling SSL to VDA failed."
                $ErrorMessage = $_.Exception.Message
        
                Write-Host $ErrorMessage
               
               
                $Store.Close()
                break
            }

         

            #Determine the name of the service
            if (Get-Service | Where-Object {$_.Name -eq 'porticaservice'}) 
            {
                $username = 'NT SERVICE\PorticaService'
                $serviceName = 'PortIcaService'
            } 
            else 
            {
                $username = 'NT SERVICE\TermService'
                $serviceName = 'TermService'
            }

            if($PSCmdlet.ShouldProcess("This will grant $serviceName read access to the certificate.", "Are you sure you want to perform this action?`nThis will grant $serviceName read access to the certificate.", "Configure ACLs"))
            {
                $key = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($Certificate)
                $fileName = $key.key.UniqueName
                $path = "$env:ALLUSERSPROFILE\Microsoft\Crypto\Keys\$fileName"
                icacls $path /grant `"$username`"`:RX | Out-Null
                Write-Host "ACLs set."
                Write-Host ""
                $ACLsSet = $True
            }

            else
            {
                Write-Host "ACL configuration skipped."
            }

            if($PSCmdlet.ShouldProcess("This will delete any existing firewall rules for port $SSLPort and disable rules for CGP, ICA and Websocket services, if present.", "Are you sure you want to perform this action?`nThis will delete any existing firewall rules for port $SSLPort and disable rules for CGP, ICA and Websocket services, if present.", "Configure Firewall"))
            {
                #Delete any existing rules for the SSLPort
                netsh advfirewall firewall delete rule name=all protocol=tcp localport=$SSLPort | Out-Null
                        
                #Delete any existing rules for Citrix SSL Service
                netsh advfirewall firewall delete rule name="Citrix SSL Service" | Out-Null
                        
                #Creating firewall rule for Citrix SSL Service
                netsh advfirewall firewall add rule name=”Citrix SSL Service” dir=in action=allow service=$serviceName profile=any protocol=tcp localport=$SSLPort | Out-Null

                #Disable any existing rules for ICA, CGP and HTML5 ports
                netsh advfirewall firewall set rule name="Citrix CGP Server Service" protocol=tcp localport=$SessionReliabilityPort new enable=no | Out-Null
                netsh advfirewall firewall set rule name="Citrix ICA Service" protocol=tcp localport=$IcaPort new enable=no | Out-Null
                netsh advfirewall firewall set rule name="Citrix Websocket Service" protocol=tcp localport=$WebSocketPort new enable=no | Out-Null

                Write-Host "Firewall configured."
                $FirewallConfigured = $True
            }

            else
            {
                Write-Host "Firewall configuration skipped."
            }

            # Create registry keys to enable SSL to the VDA
            Write-Host "Setting registry keys..."
            Set-ItemProperty -Path $ICA_LISTENER_PATH -name $SSL_CERT_HASH_KEY -Value $Certificate.GetCertHash() -Type Binary -Confirm:$False 
            switch($SSLMinVersion)
            {
                "SSL_3.0"
                {
                    Set-ItemProperty -Path $ICA_LISTENER_PATH -name $SSL_MINVERSION_KEY -Value 1 -Type DWord -Confirm:$False
                }
                "TLS_1.0"
                {
                    Set-ItemProperty -Path $ICA_LISTENER_PATH -name $SSL_MINVERSION_KEY -Value 2 -Type DWord -Confirm:$False
                }
                "TLS_1.1"
                {
                    Set-ItemProperty -Path $ICA_LISTENER_PATH -name $SSL_MINVERSION_KEY -Value 3 -Type DWord -Confirm:$False
                }
                "TLS_1.2"
                {
                    Set-ItemProperty -Path $ICA_LISTENER_PATH -name $SSL_MINVERSION_KEY -Value 4 -Type DWord -Confirm:$False
                }
            }

            switch($SSLCipherSuite)
            {
                "GOV"
                {
                    Set-ItemProperty -Path $ICA_LISTENER_PATH -name $SSL_CIPHERSUITE_KEY -Value 1 -Type DWord -Confirm:$False
                }    
                "COM"
                {
                    Set-ItemProperty -Path $ICA_LISTENER_PATH -name $SSL_CIPHERSUITE_KEY -Value 2 -Type DWord -Confirm:$False
                }
                "ALL"
                { 
                    Set-ItemProperty -Path $ICA_LISTENER_PATH -name $SSL_CIPHERSUITE_KEY -Value 3 -Type DWord -Confirm:$False
                }
            }

            Set-ItemProperty -Path $ICA_LISTENER_PATH -name $SSL_PORT_KEY -Value $SSLPort -Type DWord -Confirm:$False

            # NOTE: This must be the last thing done when enabling SSL as the Citrix Service
            #       will use this as a signal to try and start the Citrix SSL Listener!!!!
            Set-ItemProperty -Path $ICA_LISTENER_PATH -name $ENABLE_SSL_KEY -Value 1 -Type DWord -Confirm:$False
        
            Write-Host "Registry keys set."
            Write-Host ""
            $RegistryKeysSet = $True

            $Store.Close()

            if($RegistryKeysSet -and $ACLsSet -and $FirewallConfigured)
            {
                Write-Host "`nSSL to VDA enabled.`n"
            }
            else
            {
                Write-Host "`n"

                if(!$RegistryKeysSet)
                {
                    Write-Host "Configure registry manually or re-run the script to complete enabling SSL to VDA."
                }

                if(!$ACLsSet)
                {
                    Write-Host "Configure ACLs manually or re-run the script to complete enabling SSL to VDA."
                }
                    
                if(!$FirewallConfigured)
                {
                    Write-Host "Configure firewall manually or re-run the script to complete enabling SSL to VDA."
                }
            }
        }
    }


 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...