Twitter

Friday, August 29, 2014

Certificate requirements for internal servers

Lync is quiet strict in certificate validation. If you assign a non compatible certificate to Lync it will run into serious issues.
This is most likely happen if you are using dedicated certificate for each Lync service.
Especially the Lync WebServiceInternal certificate cannot be requested correctly, neither with Lync Wizard nor with the Request-CsCertificate command.

Here the problem is that both methods are requesting a certificate with a Subject Name of the Internal Web Services rather than the POOL FQDN.

Lync BUG:
The remote certificate is invalid according to the validation procedure. reason="The web ticket is invalid." ;faultcode="wsse:InvalidSecurityToken",Replace=false

In both, the TechNet and Help File the correct certificate is described. Therefore you need a valide process of requesting the correct certificate.

If you have a consolidated certificate for all services, this is issue is not present, because the Subject Name responds to the POOL FQDN.

Here I post a SNOOPER Tracing of what's happen with the wrong certificate:

You can simple test this by running the Test-CsAddressbookService command-let

Further Information:
Internal Certificate Deployment in Lync 2013 - How to and planning



SUPPORT TEST Result:

The test has successfully demonstrated the issue we expected:
The Test failed with 401 unauthorized error


The Snooper Analysis has shown the following errors:
TL_ERROR(TF_COMPONENT) [0]98CC.054C::08/26/2014-09:21:30.924.00352017 (WebInfrastructure,RemoteCertificateResolver.ResolveCertificate:remotecertficateresolver.cs(82))
(00000000030603DB)AuthenticationException. Remote certificate is not valid. <hostName, lyncfe01.customer.com> <port,443> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.


TL_INFO(TF_COMPONENT) [0]98CC.054C::08/26/2014-09:21:30.924.00352018 (WebInfrastructure,WebTicketRemoteSecurityTokenStore.EnsureIssuerSecurityToken:webticketremotesecuritytokenstore.cs(315))
(000000000289B908)Unable to ensure we have the SecurityToken from issuer lyncfe01.customer.com, port 443.

TL_VERBOSE(TF_COMPONENT) [0]98CC.054C::08/26/2014-09:21:30.925.0035201e (WebInfrastructure,WebTicketRemoteSecurityTokenStore.GetSigningTokenByThumbprint:webticketremotesecuritytokenstore.cs(84))
(000000000289B908)Did not find <thumbprint, 12DF9402A814C3C5F099D3E1974959F5037FA8B8> in dictionary.

TL_INFO(TF_COMPONENT) [0]98CC.054C::08/26/2014-09:21:30.925.0035201f (WebInfrastructure,WebTicketKeyStore.GetSigningTokenByThumbprint:webticketkeystore.cs(188))
Token not found in remote token store. <thumbprint, 12DF9402A814C3C5F099D3E1974959F5037FA8B8>

TL_ERROR(TF_COMPONENT) [0]98CC.054C::08/26/2014-09:21:30.925.00352020 (WebInfrastructure,OCSAuthModule.BeginAuthenticateUser:iismodule.cs(827))[2147532902]
Exception: System.IdentityModel.Tokens.SecurityTokenException: Unable to resolve SecurityKeyIdentifier found in the SamlAssertion signature. The SamlAssertion signature can not be validated for the Issuer https://lyncfe01.customer.com/367030ae-f2fb-5c02-be25-fe905fabf83c.
   at System.IdentityModel.Tokens.SamlAssertion.ReadSignature(XmlDictionaryReader reader, SecurityTokenSerializer keyInfoSerializer, SecurityTokenResolver outOfBandTokenResolver, SamlSerializer samlSerializer)   at System.IdentityModel.Tokens.SamlAssertion.ReadXml(XmlDictionaryReader reader, SamlSerializer samlSerializer, SecurityTokenSerializer keyInfoSerializer, SecurityTokenResolver outOfBandTokenResolver)   at System.IdentityModel.Tokens.SamlSerializer.LoadAssertion(XmlDictionaryReader reader, SecurityTokenSerializer keyInfoSerializer, SecurityTokenResolver outOfBandTokenResolver)   at System.IdentityModel.Tokens.SamlSerializer.ReadToken(XmlReader reader, SecurityTokenSerializer keyInfoSerializer, SecurityTokenResolver outOfBandTokenResolver)   at System.ServiceModel.Security.WSSecurityJan2004.SamlTokenEntry.ReadTokenCore(XmlDictionaryReader reader, SecurityTokenResolver tokenResolver)   at System.ServiceModel.Security.WSSecurityTokenSerializer.ReadTokenCore(XmlReader reader, SecurityTokenResolver tokenResolver)   at Microsoft.Rtc.Internal.WebServicesAuthFramework.OCSWebTicketCredentials.ExtractInstance(HttpRequest request)   at Microsoft.Rtc.Internal.WebServicesAuthFramework.OCSAuthModule.BeginAuthenticateUser(Object sender, EventArgs e, AsyncCallback cb, Object state)

 
TL_ERROR(TF_COMPONENT) [0]98CC.054C::08/26/2014-09:21:30.925.00352021 (WebInfrastructure,OCSAuthModule.BeginAuthenticateUser:iismodule.cs(940))[2147532902]
Exception: Microsoft.Rtc.Internal.WebServicesAuthFramework.WebTicketHttpHeaderException: Exception of type 'Microsoft.Rtc.Internal.WebServicesAuthFramework.WebTicketHttpHeaderException' was thrown.
   at Microsoft.Rtc.Internal.WebServicesAuthFramework.OCSAuthModule.BeginAuthenticateUser(Object sender, EventArgs e, AsyncCallback cb, Object state)
 

TL_INFO(TF_COMPONENT) [0]98CC.054C::08/26/2014-09:21:30.925.00352023 (WebInfrastructure,OCSAuthModule.SetHttpResponseOnException:iismodule.cs(1572))[2147532902]
Set response for exception: Microsoft.Rtc.Internal.WebServicesAuthFramework.WebTicketHttpHeaderException: Exception of type 'Microsoft.Rtc.Internal.WebServicesAuthFramework.WebTicketHttpHeaderException' was thrown.
   at Microsoft.Rtc.Internal.WebServicesAuthFramework.OCSAuthModule.BeginAuthenticateUser(Object sender, EventArgs e, AsyncCallback cb, Object state)
 

TL_ERROR(TF_COMPONENT) [0]98CC.054C::08/26/2014-09:21:30.925.00352024 (WebInfrastructure,OCSAuthModule.AddMsDiagnosticsHeader:iismodule.cs(1714))[2147532902]
Add Ms-diagnostics header <errorId,28032> <reason,The web ticket is invalid.>

TL_INFO(TF_IIS) [0]98CC.054C::08/26/2014-09:21:30.925.00352026 (WebInfrastructure,CAuthHelperGlobalModule::DumpEvent:SslNgMod.cpp(16))[2147532902]
Event: 3a2a4e84-4c21-4981-ae10-3fda0d9b0f83:0x0:56:GENERAL_SET_RESPONSE_HEADER, httpContext: 000000BFCEDFFE70, items: ContextId=null,HeaderName=X-Ms-diagnostics,HeaderValue=28032;source="lyncfe01.customer.com";reason="The web ticket is invalid.";faultcode="wsse:InvalidSecurityToken",Replace=false

TL_INFO(TF_IIS) [0]98CC.054C::08/26/2014-09:21:30.926.0035202a (WebInfrastructure,CAuthHelperGlobalModule::DumpEvent:SslNgMod.cpp(16))[2147532902]
Event: 3a2a4e84-4c21-4981-ae10-3fda0d9b0f83:0x0:56:GENERAL_SET_RESPONSE_HEADER, httpContext: 000000BFCEDFFE70, items: ContextId=null,HeaderName=X-MS-WebTicketURL,HeaderValue=https://lyncfe01.customer.com/WebTicket/WebTicketService.svc,Replace=false

TL_INFO(TF_IIS) [0]98CC.054C::08/26/2014-09:21:30.926.0035202d (WebInfrastructure,CAuthHelperGlobalModule::DumpEvent:SslNgMod.cpp(16))[2147532902]
Event: 3a2a4e84-4c21-4981-ae10-3fda0d9b0f83:0x0:56:GENERAL_SET_RESPONSE_HEADER, httpContext: 000000BFCEDFFE70, items: ContextId=null,HeaderName=X-MS-WebTicketSupported,HeaderValue=cwt,saml,Replace=false

If you wish requesting correct certificate, please copy and use my script:

Download Script

#****************************************************
#* (c) Thomas Poett, Microsoft MVP Lync *

#* contact: thomas.poett@live.de *

#* *

#* Frontend and Director Pool Certificate Request *

#* Version 1.0, 28.08.2014 *

#* *

#* Certificate Template must be WebServer *

#* You need to know your internal CA Name *

#* Run Script for each required Certificate *

#* *

#* BUG Warning: *

#* Lync Wizard and Request-Certificate for Internal *

#* Web Service request a certificate with a wrong *

#* Certificate Subject Name. *

#* This script addresses this issue correctly! *

#****************************************************
 
 




#Collect necessary user input
 
 
$CA = Read-Host 'Certificate Authority (Format FQDN\CA)'

$Organization = Read-Host 'ORGANIZATION'

$City = Read-Host 'CITY'

$State = Read-Host 'STATE'

$Country = Read-Host 'COUNTRY (2 characters, e.g. DE)'

$ComputerName = $env:ComputerName+"."+$env:userdnsdomain




#Lync PS command gaining topology information
 
 
$SIP_ALL = Get-CsSipDomain | Select-Object -ExpandProperty Identity

$SIPString = ""

foreach($tempUrl in $SIP_ALL)



{
 
$SIPString = $SIPString + $tempUrl+","





}
 
$SIPString = $SIPString.Substring(0,$SIPString.Length-1)

$DefaultSIPDomain = Get-CsSipDomain | where {$_.IsDefault -eq $true} | Select-Object -ExpandProperty Name




#Choose Certificate Type
 
 
$CertType = Read-Host 'Please provide the following number for the Certificate Service: 1= Default, 2= WebServicesInternal, 3= WebServiceExternal, 4= Consolidated, 5=WebServicesInternal+External'

if ($CertType -eq 1) {

Write-Host "Certificate is DEFAULT"

$AutoLogin = Read-Host 'Auto Login Server for SIP? Y/N'

if ($AutoLogin -eq "Y") {

#SIP.<SIPDomain> for AutoLogin

$SANString =""

foreach($tempUrl in $SIPString)



{
 
$SANString = $SANString + "SIP."+$tempUrl +","



}
 
$SANString = $SANString.Substring(0,$SANString.Length-1)

Write-Host "Your SAN:" + $SANString

$CERT = Request-CsCertificate -New -Type Default -ComputerFqdn $ComputerName -CA $CA -FriendlyName "Lync Default" -Template WebServer -AllSipDomain -DomainName $SANString -City $City -Country $Country -Organization $Organization -State $State

Set-CsCertificate -Type Default -Thumbprint $CERT.Thumbprint



}
 
else {

Write-Host "Your SAN:" + $SANString

$CERT = Request-CsCertificate -New -Type Default -ComputerFqdn $ComputerName -CA $CA -FriendlyName "Lync Default" -Template WebServer -AllSipDomain -City $City -Country $Country -Organization $Organization -State $State

Set-CsCertificate -Type Default -Thumbprint $CERT.Thumbprint



}

}


 
elseif ($CertType -eq 2) {

Write-Host "Certificate is WebServicesInternal"

#Lync PS command gaining topology information

$SURL_ALL = Get-CsSimpleUrlConfiguration | Select-Object -ExpandProperty SimpleUrl | Select-Object -ExpandProperty ActiveUrl

$SANString = ""

foreach($tempUrl in $SURL_ALL)



{
 
$SANString = $SANString + $tempUrl.replace("https://","") +","



}
 
# $surlString = $SANString.Substring(0,$SANString.Length-1)
 
 
$SANString = $SANString + "scheduler."+$DefaultSIPDomain +"," + ",ucupdates-r2."+$DefaultSIPDomain




 
#LYNCDISCOVERINTERNAL

foreach($tempUrl in $SIPString)



{
 
$SANString = $SANString + ",LyncDiscoverInternal."+$tempUrl



}
 
Write-Host "Your SAN:" + $SANString

$CERT = Request-CsCertificate -New -Type Default -ComputerFqdn $ComputerName -CA $CA -FriendlyName "Lync WebServices Internal" -Template WebServer -DomainName $SANString -City $City -Country $Country -Organization $Organization -State $State

Set-CsCertificate -Type WebServicesInternal -Thumbprint $CERT.Thumbprint



}


 
elseif ($CertType -eq 3) {

Write-Host "Certificate is WebServicesExternal"

#Lync PS command gaining topology information

$SURL_ALL = Get-CsSimpleUrlConfiguration | Select-Object -ExpandProperty SimpleUrl | where {$_.Component -ne "Cscp"} | Select-Object -ExpandProperty ActiveUrl

$SANString = ""

foreach($tempUrl in $SURL_ALL)



{
 
$SANString = $SANString + $tempUrl.replace("https://","") +","



}
 
#Get External Web Service FQDN

$Pool = Get-CsPool | where {$_.Computers -eq 'cie-lyncfe01.cie.int'}

$WebServer = "WebServer:"+$Pool.Identity

$ExtWebSrvURL = Get-CsService -Identity $WebServer | Select-Object -ExpandProperty ExternalFqdn

$SANString = $SANString + $ExtWebSrvURL




 
#LYNCDISCOVER

foreach($tempUrl in $SIPString)



{
 
$SANString = $SANString + ",LyncDiscover."+$tempUrl



}
 
Write-Host "Your SAN:" + $SANString

$CERT = Request-CsCertificate -New -Type WebServicesExternal -ComputerFqdn $ComputerName -CA $CA -FriendlyName "Lync WebServices External" -Template WebServer -DomainName $SANString -City $City -Country $Country -Organization $Organization -State $State

Set-CsCertificate -Type WebServicesExternal -Thumbprint $CERT.Thumbprint



}


 
elseif ($CertType -eq 4) {

Write-Host "Certificate is Consolidated"




 
#Lync PS command gaining topology information

$SURL_ALL = Get-CsSimpleUrlConfiguration | Select-Object -ExpandProperty SimpleUrl | Select-Object -ExpandProperty ActiveUrl

$SANString = ""

foreach($tempUrl in $SURL_ALL)



{
 
$SANString = $SANString + $tempUrl.replace("https://","") +","



}
 
# $surlString = $SANString.Substring(0,$SANString.Length-1)
 
 
$SANString = $SANString + "scheduler."+$DefaultSIPDomain + ",ucupdates-r2."+$DefaultSIPDomain




 
#LYNCDISCOVER and LYNCDISCOVERINTERNAL

foreach($tempUrl in $SIPString)



{
 
$SANString = $SANString + ",LyncDiscoverInternal."+$tempUrl + ",LyncDiscover."+$tempUrl



}


 
#Get External Web Service FQDN

$Pool = Get-CsPool | where {$_.Computers -eq 'cie-lyncfe01.cie.int'}

$WebServer = "WebServer:"+$Pool.Identity

$ExtWebSrvURL = Get-CsService -Identity $WebServer | Select-Object -ExpandProperty ExternalFqdn

$SANString = $SANString + "," + $ExtWebSrvURL




 
$AutoLogin = Read-Host 'Auto Login Server for SIP? Y/N'

if ($AutoLogin -eq "Y") {

#SIP.<SIPDomain> for AutoLogin

foreach($tempUrl in $SIPString)



{
 
$SANString = $SANString + ",SIP."+$tempUrl



}
 
Write-Host "Your SAN:" + $SANString

$CERT = Request-CsCertificate -New -Type Default,WebServicesInternal,WebServicesExternal -ComputerFqdn $ComputerName -CA $CA -FriendlyName "Lync Consolidated" -Template WebServer -DomainName $SANString -City $City -Country $Country -Organization $Organization -State $State

Set-CsCertificate -Type Default,WebServicesInternal,WebServicesExternal -Thumbprint $CERT.Thumbprint



}
 
else {

Write-Host "Your SAN:" + $SANString

$CERT = Request-CsCertificate -New -Type Default,WebServicesInternal,WebServicesExternal -ComputerFqdn $ComputerName -CA $CA -FriendlyName "Lync Consolidated" -Template WebServer -DomainName $SANString -City $City -Country $Country -Organization $Organization -State $State

Set-CsCertificate -Type Default,WebServicesInternal,WebServicesExternal -Thumbprint $CERT.Thumbprint



}

}


 
elseif ($CertType -eq 5) {

Write-Host "Certificate is WebServicesInternal+External"




 
#Lync PS command gaining topology information

$SURL_ALL = Get-CsSimpleUrlConfiguration | Select-Object -ExpandProperty SimpleUrl | Select-Object -ExpandProperty ActiveUrl

$SANString = ""

foreach($tempUrl in $SURL_ALL)



{
 
$SANString = $SANString + $tempUrl.replace("https://","") +","



}
 
# $surlString = $SANString.Substring(0,$SANString.Length-1)
 
 
$SANString = $SANString + "scheduler."+$DefaultSIPDomain + ",ucupdates-r2."+$DefaultSIPDomain




 
#LYNCDISCOVER and LYNCDISCOVERINTERNAL

foreach($tempUrl in $SIPString)



{
 
$SANString = $SANString + ",LyncDiscoverInternal."+$tempUrl + ",LyncDiscover."+$tempUrl



}


 
#Get External Web Service FQDN

$Pool = Get-CsPool | where {$_.Computers -eq 'cie-lyncfe01.cie.int'}

$WebServer = "WebServer:"+$Pool.Identity

$ExtWebSrvURL = Get-CsService -Identity $WebServer | Select-Object -ExpandProperty ExternalFqdn

$SANString = $SANString + "," + $ExtWebSrvURL




 
Write-Host "Your SAN:" + $SANString

$CERT = Request-CsCertificate -New -Type WebServicesInternal,WebServicesExternal -ComputerFqdn $ComputerName -CA $CA -FriendlyName "Lync Consolidated" -Template WebServer -DomainName $SANString -City $City -Country $Country -Organization $Organization -State $State

Set-CsCertificate -Type WebServicesInternal,WebServicesExternal -Thumbprint $CERT.Thumbprint



}


 
else {"Your input is not valid! - EXIT"}

Write-Host {"Your certificate as requested is assigned (as fare you didn't saw any related issues)."}

$RestartLyncService = Read-Host 'You need to restart your Lync Services? Y/N'

if ($RestartLyncService -eq "Y") {

Stop-CsWindowsService

Start-CsWindowsService



}
 
else {Write-Host {"Please RESTART your Lync Servises (Stop-CsWindowsService and Start-CsWindowsService."}}




# ++++ END of SCRIPT ++++