Twitter

Tuesday, September 9, 2014

Publishing Lync Topology Firewall Requirements (missing TCP Ports)

In a special scenario, where I faced certain issue publishing the Lync Topology, where the Lync Frontend Servers are located in Sub Domain, you need to open certain TCP Ports to at least one Root Domain Controller:

If you enabled the Lync Topology, you might face this issues:

Error: The given key was not present in dictionary.
Type: KeyNotFoundException

Error: An error occurred when attempting to add "computer" to "RTCGroupxxx"
Type: DeploymentException

CategoryInfo: InvalideOperation: ([0] Microsoft.R....Core.Service)
WebServer:pool.<fqdn> execution failed on an unrecoverable error.

Error: Cannot obtain the domain information for computer "Root DC fqdn". Please make sure the computer FQDN is correct.

Error: DsRoleGetPrimaryDomainInfromation failed with error "6BA".

Just missing are the requirements for Topology publishing.

If you are going to enable the Topology, you can use:
Enable-CsTopology [-Confirm [<SwitchParameter>]] [-Force <SwitchParameter>] [-GlobalCatalog <Fqdn>] [-GlobalSettingsDomainController <Fqdn>] [-Report <String>] [-SkipPrepareCheck <$true | $false>] [-WhatIf [<SwitchParameter>]]

Here you can specify the following parameter:

GlobalCatalog: Local Domain DC FQDN
GlobalSettingsDomainController: Root Domain DC FQDN
SkipPrepareCheck: can skip the Prepare Checks, e.g. Schema Prep or Forrest Prep

Overview of all required TCP Ports:

While you are publishing the Topology, a bunch of setting at the Root Level Domain must be done.
E.g. we assume, you also positioned all RTC and CS groups, the Lync relevant System Groups in the Root Domain.

 

During publishing the Topology changes are made here:


Root Domain:

- AD Configuration Partition: "CN=RTC Service,CN=Services,CN=Configuration,DC=<DOM>,DC=<DOM>"
Here the Topology writes all entries, e.g. POOLs, Conference Directories and more
This change require access via TCP PORT 88 and 389 only

- Lync System Groups (CS and RTC): "CN=USERS,DC=<DOM>,DC=<DOM>"
Here during publishing the Groups e.g.: RTCComponentUniversalServices, RTCHSUniversalService, RTCUniversalConfigReplicator and RTCUniversalServerAdmins are filled with the e.g. Frontend Server as group member.
This change require access via TCP PORT 139 and 445 only
(This Ports are also used during the PrepareCheck, also the Wizard AD Preparation Check)

- Other Changes are written to the Lync Share, the FileServer. This depends on where this server is located. You could also have placed it into the Root Domain.

Note:
After the Topology is published, you do not need this ports any further and could temporarily disable them.


Within the Lync Server AD Domain:

You find the Ports and protocols for internal servers in Lync Server 2013   here:http://technet.microsoft.com/en-us/library/gg398833.aspx 



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 ++++