Hands-Free TFS Install - Part 4 - Script for Configuring TFS for HTTPS and SSL Only

July 17, 2007 at 11:55 am | In Team Foundation Server |

This blog post is part of a 4-part series. The other parts are:

Introduction

Nothing in this blog post is new or revolutionary. All the tools and techniques I’m about to show you have been around for quite some time.

Why would you want to configure TFS for HTTPS only?

There are three different scenarios for configuring TFS access:

  1. Out-of-the-box configuration. TFS web services listen on HTTP port 8080 with no SSL
  2. HTTP + HTTPS. TFS web services listen on HTTP 8080 and an additional port with SSL. (See MSDN Walkthrough: Setting up Team Foundation Server with Secure Sockets Layer (SSL))
  3. HTTPS only. TFS web services listen on HTTPS port 8080, or any other port. No HTTP access. (See MSDN How to: Configure Team Foundation Server for HTTPS and SSL Only)

The main reason you would want to configure SSL for TFS is so that you can expose your TFS server to the Internet and allow people to access from remote locations using an encrypted connection.

The scripts that form the rest of this post are the command-line equivalents of the guidance given in the above MSDN articles.

Can’t I already do this another way?

There’s nothing stopping you achieving this in other ways. You could use Microsoft ISA server to publish an internal TFS server securely. You could allow remote users access via a VPN.

All client-server and server-server communication for TFS is standard HTTP traffic. (Except the build server - it uses .NET Remoting on port 9191, until TFS 2008 when it will be WCF) .

Danger! Heed the warnings!

From How to: Configure Team Foundation Server for HTTPS and SSL Only:

If you configure Team Foundation Server to use any customized ports, such as HTTPS and SSL, you will not be able to install any service packs for Team Foundation Server after making those changes. Installation of service packs will fail. You must reconfigure Team Foundation Server to its default settings before you can apply service packs for Team Foundation Server.

Before we get started, you’ll need the following:

  • Obtain a valid SSL certificate from your corporate root CA, or third-party root CA
  • Make sure adsutil.vbs is available (Usually found in C:\Inetpub\AdminScripts\adsutil.vbs)
  • Install the IIS 6.0 Resource Kit (docco)
  • Install PowerShell
  • Install SQL management tools (osql.exe)

Preparing your certificate for import

I’m not going to cover how to obtain a trusted SSL certificate, there’s plenty of other resources out there for that. Before you can use IISCertDeploy.vbs to deploy the certificate, you need to export the certificate as a *.PFX file.

Follow the instructions on TechNet Export a Server Certificate (IIS 6.0). At the end of it you should have a single *.PFX file and a password for the file.

IIS Web Site Identifiers

Each web site in IIS has a unique identifier. The Default Web Site is always ‘1′. We can find out the identifiers of the other web sites by issuing the following command:

set ADSUTIL=C:\Inetpub\AdminScripts\adsutil.vbs

cscript %ADSUTIL% GET W3SVC/1/ServerComment

cscript %ADSUTIL% GET W3SVC/2/ServerComment

cscript %ADSUTIL% GET W3SVC/3/ServerComment

cscript %ADSUTIL% GET W3SVC/4/ServerComment

Your results should be similar to the following. These are the identifiers used throughout the rest of these scripts.

  • /W3SVC/1 Default Web Site : 80
  • /W3SVC/2 SharePoint Central Administration : 17012
  • /W3SVC/3 Team Foundation Server : 8080
  • /W3SVC/4 TeamPlain Web Access : 81

Configure TFS Webservices for SSL

Before we can configure TFS web services to listen on port 8080 with HTTPS, we need to move the non-SSL ones out of the way to port 8081. We can do that by manipulating the “ServerBindings” key using the Adsutil.vbs SET command.

set ADSUTIL=C:\Inetpub\AdminScripts\adsutil.vbs

cscript %ADSUTIL% SET W3SVC/3/ServerBindings “:8081:”

Now we are ready to install the certificate and attach it to the Team Foundation Server web site. To do this, we use the IISCertDeploy.vbs script from the IIS 6.0 Resource Kit Tools. We’re going to configure SSL on the standard TFS port 8080.

set PFXFILE=your_certificate_private.pfx

set PFXPASS=yourCertificatepassword

cscript IISCertDeploy.vbs -q ON -c %PFXFILE% -p %PFXPASS% -i w3svc/3 -port “:8080:”

Configuring Digest + Integrated authentication

The next step in the MSDN guidance is to configure Integrated AND Digest authentication. This is done using the adsutil.vbs script again. We’re going to update the AuthFlags node in the IIS metabase.

  • Digest Authentication = AuthMD5 = Bitmask 16
  • Integrated Authentication = AuthNTLM = Bitmask 4

So adding the bitmasks, we end up with Bitmask 20.

cscript %ADSUTIL% SET W3SVC/3/AuthFlags 20

Now, if you had performed this operation through the IIS manager GUI, it would prompt you “do you wish to apply this setting to all children?” … Or something to that effect. That means that we have to apply the same setting to each folder like this:

cscript %ADSUTIL% SET W3SVC/3/Root/aspnet_client/AuthFlags 20

cscript %ADSUTIL% SET W3SVC/3/Root/Build/AuthFlags 20

cscript %ADSUTIL% SET W3SVC/3/Root/services/AuthFlags 20

cscript %ADSUTIL% SET W3SVC/3/Root/VersionControl/AuthFlags 20

cscript %ADSUTIL% SET W3SVC/3/Root/Warehouse/AuthFlags 20

cscript %ADSUTIL% SET W3SVC/3/Root/WorkItemTracking/AuthFlags 20

Require Secure Channel (SSL)

The next step in the MSDN guidance is to configure the website to ‘Require Secure Channel’. This is done by modifying the AccessSSL node in the IIS metabase. Once again, we have to apply it to each subfolder as well.

cscript %ADSUTIL% SET /W3SVC/3/AccessSSL TRUE

cscript %ADSUTIL% SET /W3SVC/3/Root/aspnet_client/AccessSSL TRUE

cscript %ADSUTIL% SET /W3SVC/3/Root/Build/AccessSSL TRUE

cscript %ADSUTIL% SET /W3SVC/3/Root/services/AccessSSL TRUE

cscript %ADSUTIL% SET /W3SVC/3/Root/VersionControl/AccessSSL TRUE

cscript %ADSUTIL% SET /W3SVC/3/Root/Warehouse/AccessSSL TRUE

cscript %ADSUTIL% SET /W3SVC/3/Root/WorkItemTracking/AccessSSL TRUE

Configure SSL on the Default Web Site (SharePoint team sites)

We’re going to configure the Default Web Site to listen with HTTPS on port 443. This means that your users will be able to access their Windows SharePoint Services (WSS) team sites using https://server/sites/TeamProject.

We still need to perform the same steps as above, but on the Default Web Site with ID ‘1′.

:: Configure SSL on Default Website (Sharepoint team sites) on port 443

cscript IISCertDeploy.vbs -q ON -c %PFXFILE% -p %PFXPASS% -i w3svc/1 -port “:443:”

:: Require secure channel (SSL) on the Default website

cscript %ADSUTIL% SET /W3SVC/1/AccessSSL TRUE

:: Enable Digest + Integrated auth on Default Website

cscript %ADSUTIL% SET W3SVC/1/AuthFlags 20

cscript %ADSUTIL% SET W3SVC/1/Root/Reports/AuthFlags 20

cscript %ADSUTIL% SET W3SVC/1/Root/ReportServer/AuthFlags 20

Configure SSL on the SharePoint Central Administration on port 17013

We’re going to configure SharePoint Central Administration on port 17013. The normal HTTP port is 17012, so we can’t use that port without moving it. The steps are the same again

:: Configure SSL on SharePoint Central Administration on port 17013

cscript IISCertDeploy.vbs -q ON -c %PFXFILE% -p %PFXPASS% -i w3svc/2 -port “:17013:”

:: Require secure channel (SSL) on the SharePoint Central Admin site

cscript %ADSUTIL% SET /W3SVC/2/AccessSSL TRUE

Updating TFS with the new server settings

Proceed with caution. Even though I tell everybody “DON’T _EVER_ TOUCH THE TFS DATABASES”, this case is OK - because MSDN tells us so :). Be sure to take a backup though.

At this time, we can also specify a Fully Qualified Domain Name (FQDN) that we want TFS to use at all times. Why would you do this? Well, the default TFS install usually only uses just the computer name in any of it’s settings. That means if you’re not connected to the VPN, or ISA doesn’t perform link translation correctly, you will end up with http://servername/ URLs that nobody can access from external. In the following sections, we’re going to change all the URLs that TFS uses to their full internet names with the https:// prefix. e.g. https://servername.domain.com/

SET FQDN=servername.domain.com

Updating the Reporting Services Server location

The Reporting Services virtual directories /Reports and /ReportServer are located in the Default Web Site. If we want our users to be able to access reports over a secure connection, we need to tell TFS to use this new location.

This location is stored in the registry and we can update it using reg.exe from C:\Windows\System32

:: Update the Registry Key for SQL Report Server

::HKLM\Software\Microsoft\VisualStudio\8.0\TeamFoundation\ReportServer - Key

reg add “HKLM\Software\Microsoft\VisualStudio\8.0\TeamFoundation\ReportServer” /v Key /d “https://%FQDN%” /f

Notes:

  • The /v parameter specifies the “Value” under the selected key to update. It’s a little confusing in this case, because the value is called “Key”.
  • The /d parameter specifies the data for the new value.
  • The /f parameter specifies that we want to force the overwrite of existing values

Updating the TfsIntegration database with the new SSL URLs

Now we need to tell TFS the new URLs. This is done by updating the tbl_service_interface table in the TfsIntegration database. We can do this from the command-line by using osql.exe which is included with the SQL Server Tools. If you have enabled SSL on different ports, don’t forget to update these URLs appropriately.

:: Update the integration table with the FQDN and SSL urls

osql -E -d TfsIntegration -Q “UPDATE dbo.tbl_service_interface SET url=’https://%FQDN%/ReportServer/ReportService.asmx‘ WHERE name=’ReportsService’”

osql -E -d TfsIntegration -Q “UPDATE dbo.tbl_service_interface SET url=’https://%FQDN%/Reports‘ WHERE name=’BaseReportsUrl’”

osql -E -d TfsIntegration -Q “UPDATE dbo.tbl_service_interface SET url=’https://%FQDN%:17013/_vti_adm/admin.asmx‘ WHERE name=’WSSAdminService’”

osql -E -d TfsIntegration -Q “UPDATE dbo.tbl_service_interface SET url=’https://%FQDN%‘ WHERE name=’BaseServerUrl’”

osql -E -d TfsIntegration -Q “UPDATE dbo.tbl_service_interface SET url=’https://%FQDN%/sites‘ WHERE name=’BaseSiteUrl’”

osql -E -d TfsIntegration -Q “UPDATE dbo.tbl_service_interface SET url=’https://%FQDN%/ReportServer‘ WHERE name=’DataSourceServer’”

osql -E -d TfsIntegration -Q “UPDATE dbo.tbl_service_interface SET url=’\\%FQDN%\sites‘ WHERE name=’BaseSiteUnc’”

:: Update the subscriptions table with the FQDN and SSL urls

:: BuildCompletionEvent

osql -E -d TfsIntegration -Q “UPDATE tbl_subscription SET address=’https://%FQDN%:8080/WorkItemTracking/v1.0/Integration.asmx‘ WHERE id=’1′”

:: DataChangedEvent

osql -E -d TfsIntegration -Q “UPDATE tbl_subscription SET address=’https://%FQDN%:8080/WorkItemTracking/v1.0/SyncEventsListener.asmx‘ WHERE id=’2′”

:: ProjectCreatedEvent

osql -E -d TfsIntegration -Q “UPDATE tbl_subscription SET address=’https://%FQDN%:8080/WorkItemTracking/v1.0/warehousecontroller.asmx‘ WHERE id=’3′”

:: DataChangedEvent

osql -E -d TfsIntegration -Q “UPDATE tbl_subscription SET address=’https://%FQDN%:8080/WorkItemTracking/v1.0/Integration.asmx‘ WHERE id=’4′”

Notes:

  • The command line parameters are case sensitive.
  • The “-E” parameter specifies that we should connect to SQL using Integrated authentication / Trusted connection.
  • The “-d” parameter specifies the database that we want to connect to
  • The “-Q” parameter specifies that we want to execute the following command and then exit.

Update Reporting Services Server to Require SSL

This is where things get interesting. We have to update an XML app.config file with a new value. To do this, I have created a simple powershell script to update the value which we then call from our batch script.

UpdateRSConfiguration.ps1

$file = “c:\Program Files\Microsoft SQL Server\MSSQL.3\Reporting Services\ReportServer\rsreportserver.config”

$config = [xml] (get-content $file)

$node = $config.Configuration.SelectSingleNode(”Add[@Key='SecureConnectionLevel']“)

$node.Value = “3″

$config.Save($file)

I really love how simple this is. Can you imagine doing something like this in a normal batch file?

I’ll explain what this script is doing line-by-line.

  • Line 1: Set a variable $file to the location of the Reporting Services app.config file
  • Line 2: Load the contents of $file as XML into the $config variable
  • Line 3: Select the <Add Key=”SecureConnectionLevel” Value=”X” /> XML node from the <Configuration> node of the config file stored in the $config variable.
  • Line 4: Update the Value of the node to our new value.
  • Line 5: Save the contents of the $config variable back out to the config file on disk.

Now we need to call this PowerShell script from our batch file. This is done by passing the script from the standard input.

:: Update RSReportServer.config to require ssl

powershell -command - < UpdateRSConfiguration.ps1

Update TFSServerUrl in the three other app.config files

There are three other app.config files that need updating, and we’ll do those in the same way as above. These scripts could easily be re-factored into one generic script, but I’ve kept them separate because they are each subtly different.

The config files that need to be updated are:

  • c:\Program Files\Microsoft Visual Studio 2005 Team Foundation Server\Web Services\Web.Config
  • c:\Program Files\Microsoft Visual Studio 2005 Team Foundation Server\CoverAn\CoverAn.exe.config
  • c:\Program Files\Microsoft Visual Studio 2005 Team Foundation Server\TFSServerScheduler\TFSServerScheduler.exe.config

Each of them needs to end up with a TfsNameUrl parameter. TFSServerScheduler.exe.config doesn’t have a TfsNameUrl parameter to start with, so we need to rename the BisDomainUrl key as well as set the value.

UpdateTFSWebConfig.ps1

$file = “c:\Program Files\Microsoft Visual Studio 2005 Team Foundation Server\Web Services\Web.Config”

$url = “https://servername.domain.com:8080

$config = [xml] (get-content $file)

$node = $config.configuration.appSettings.SelectSingleNode(”add[@key='TFSNameUrl']“)

$node.value = $url

$config.Save($file)

UpdateCoverAnConfig.ps1

$file = “c:\Program Files\Microsoft Visual Studio 2005 Team Foundation Server\CoverAn\CoverAn.exe.config”

$url = “https://servername.domain.com:8080

$config = [xml] (get-content $file)

$node = $config.configuration.appSettings.SelectSingleNode(”add[@key='TFSNameUrl']“)

$node.value = $url

$config.Save($file)

UpdateTFSSchedulerConfig.ps1

$file = “c:\Program Files\Microsoft Visual Studio 2005 Team Foundation Server\TFSServerScheduler\TFSServerScheduler.exe.config”

$url = “https://servername.domain.com:8080

$config = [xml] (get-content $file)

$node = $config.configuration.appSettings.SelectSingleNode(”add[@key='BisDomainUrl']“)

$node.key = “TFSNameUrl”

$node.value = $url

$config.Save($file)

Now we need to call these three update scripts, just like we did with the Reporting Services update script:

:: Update app.config files with HTTPS TFSServerUrl

powershell -command - < UpdateTFSWebConfig.ps1

powershell -command - < UpdateCoverAnConfig.ps1

powershell -command - < UpdateTFSSchedulerConfig.ps1

Configuring Team Plain Web Access for SSL

Just like all the other websites, we can configure Team Plain Web Access in exactly the same way. In this case, I’ve configured it with HTTPS on port 82. This is because port 443 is already taken by the Default Web Site / SharePoint.

:: Configure SSL on Team Plain Web Access SSL port 82

cscript IISCertDeploy.vbs -q ON -c %PFXFILE% -p %PFXPASS% -i w3svc/4 -port “:82:”

:: Require secure channel (SSL) on the Team Plain Web Access website

cscript %ADSUTIL% SET W3SVC/4/AccessSSL TRUE

Summary

So there you have it. In this final part, we have completed all the steps of the MSDN guidance How to: Configure Team Foundation Server for HTTPS and SSL Only using only the command-line. We’ve used batch, VBS, PowerShell and even SQL scripts, but in the end we got the result we were after.

Download the scripts

The latest version of all the scripts covered in this series can be download from this location:

Feedback

If you find these scripts useful please blog about them or leave a comment on the blog posts. If you want to provide some feedback please leave a comment here or send me an email via the contact form.

2 Comments »

RSS feed for comments on this post. TrackBack URI

  1. C’mon dude, I need this walkthrough right now :)

    Comment by Paul — July 17, 2007 #

  2. Very helpful. This type of command line configuration stuff is always very hard to find in the docs, and the examples are often lacking.

    Comment by mat roberts — December 15, 2007 #

Leave a comment

XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Blog at WordPress.com. | Theme: Pool by Borja Fernandez.
Entries and comments feeds.