Testing SSL URLs when using SSL Termination

Here’s the situation, SSL is setup to terminate at the load balancer.  Sticky sessions are setup as well, so once you hit a particular WFE, your future requests are routed to the same box.  The problem is that there is not an easy way to validate that the sites are responding from a client machine, or an automation tool.  In this scenario, sticky sessions are handled using cookies, and if you clear your cookies in the browser, you cannot predict which web front end you’ll hit with your next request.  With SharePoint, you could extend the web application with an HTTP URL, and then use host files to hit the HTTP URL, but the downside of that approach is that you’re not confirming the SSL components are working.  Also, if you extend to a new IIS web site, your HTTP URL will be in a separate app domain which could result in your test request to HTTP working, but the SSL site not working.

In order to tackle this scenario, we created a PowerShell script that will send an web request with the appropriate cookie to allow for validating multiple SSL terminated URLs against all the machines in a farm.  In order to do the test, you need a few pieces of information:

  • The URLs to test.
  • The name of the cookie used for sticky sessions.  You’ll typically have one cookie name per unique URL
  • The value of the cookie.  You’ll typically have one cookie value per server handling requests

The key to being able to pull this off via script is to us an HttpWebRequest object.  This object allows you to add cookies to a request, as well as get the response status code and the data contained in the response.  There is a sample PowerShell script attached to the post that will perform the test.  In general, the script loops through the URL’s, then loops through each server and validates the response from each server.  If the URL is considered a failure, the request is retried up to a total of 5 times.  If all the retries fail, the URL-server combo is added to a collection of bad servers.  The bad servers can then be sent via email, or you could do some remediation, like recycle an application pool. 

Here’s a rundown of the major parts of the script:

  • Storage for the required data is done with hashtables.  This will need to be updated to match your environment.  The script can currently handle testing two environments.  In my example, I have a set of values for a production environment, and a set of values for a test environment.
    • $prodServers  -  Associate a server name with a cookie value.
    • $prodCookieNames  -  Associates the URL to a cookie name.
    • $testServers and $testCookieNames  -  the same as above, but for a test environment.
    1: #Associate a servername to a cookie value
    2: $prodServers = @{"ServerName01" = "0000000001.20480.0000";
    3:                     "ServerName02" = "0000000002.20480.0000";
    4:                     "ServerName03" = "0000000003.20480.0000";
    5:                     "ServerName04" = "0000000004.20480.0000";}
    8: #Associate a URL to a cookie name
    9: $prodCookieNames = @{    "https://teams.contoso.com" = "BIGipServerpl_teams_80"; 
   10:                         "https://mysite.contoso.com" = "BIGipServerpl_sp_mysite.contoso.com_80"; 
   11:                         "http://apps.contoso.com" = "BIGipServerpl_sp_apps.contoso.com_80"}


  • TestUrl function.  This function makes the web request, then does an initial test of the status code and content length.  The content length check was to rule out requests that don’t fit our failure content.  We were testing for the error response described here, as any status code 400 or higher.

  • TestResponse function.  This function runs validation on the response from TestUrl.  In order to test for the HTML for the “An unexpected error has occurred.”, I replace the carriage return/line feeds, tabs and spaces, then do a match against the response for the text “<body>anunexpectederrorhasoccurred.</body>”.  I also check if the response is empty which should only occur when a response status code is 400 or larger.

  • SendEmail function.  This function sends email with the server-URL combinations that failed.