Problems accessing TFS through ASP.NET using Kerberos delegation

Problem: Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer not using correct identity when being referenced from remote server using Keberos delegation

Servers in play:
srv-tfs01 - Team Foundation Server
deb-web05 - Web application server

Server setup for srv-tfs01:
Enabled Kerberos authentication in IIS
cscript adsutil.vbs set w3svc/3/root/NTAuthenticationProviders "Negotiate, NTLM"

Setup service principle names for TFS service account:
setspn -a http/srv-tfs01.<fully qualified domain> <domain>\<service account> -- for TCP/IP
setspn -a http/srv-tfs01 <domain>\<service account> -- for NETBIOS

Server setup for dev-web05:
Enabled Kerberos delegation (for any service) through Active Directory Users and Computers (ADUC)

IIS settings for web application
Turned off Enable anonymous access in Directory Security
Turned on Integrated Windows authentication in Directory Security

web.config
<identity impersonate="true"/>

Registry changes
Gave Domain Users group read athority to
HKEY_USERS\.Default\Software\Microsoft\VisualStudio\8.0\TeamFoundation\Servers -- necessary so users can resolve TFS servers

Domain:
Windows 2003 domain functional level


Scenario:
When a user attempts to use my web application to browse Team Foundation server, their Kerberos credentials are not being picked up by the VersionControlServer object in the Team Foundation Server API. Authorized
TFS users receive TF14002: <domain>\dev-web05$ is not a member of Team Foundation Valid Users group when attempting to browse a project using my web application. Examining the Security event log the srv-tfs01 server shows two seperate Kerberos logins; one for the user using the web site, the second is the DEV-WEB05$ machine account. Unauthorized users receive the message TF50309: You do not have sufficient permissions to perform this operation. When looking at the Security event log on srv-tfs01, I find only one Kerberos
login, the user who is attempting to browse.
There is an overload for the constructor of
Microsoft.TeamFoundation.Client.TeamFoundationServer that takes in a NetworkCredential object. I've tried passing in System.Net.CredentialCache.DefaultNetworkCredential with the same result. However, if I create a new NetworkCredential object providing username, password, and domain, the user is able to browse but under whatever identity was provided by the NetworkCredential object I created, not their own. Also, when attempting to download a file from TFS while using the NetworkCredential object I created, I get the same TF14002: <domain>\dev-web05$ is not a member of Team Foundation Valid Users group
To run some tests, I created a domain group and put the dev-web05 machine account in it. Then I added it to Team Foundation by right clicking on the server in Visual Studio 2005 > Team Foundation Server Settings > Security. I gave the account the View Server-Level Information permission so it would show up in the Team Foundation Valid Users group. I attempted to browse again and nothing showed up.


I added the same group to a Readers group of a project in Visual Studio by right clicking the server > Team Foundater Server Settings > Group Membership. I specifically added it to the Reader group of a projcect my
test account did not have access to. When I logged on again to browse, the entry in which the account did not have access to appeared in the list.


Relavent code:

public override System.Collections.Generic.Dictionary<string,
string> listItemsInProject()
{
//declare local varaibles
string servername = "
http://srv-tfs01:8080";
Microsoft.TeamFoundation.Client.TeamFoundationServer server =
new Microsoft.TeamFoundation.Client.TeamFoundationServer(servername);

Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer
versionControl = null;
System.Collections.Generic.Dictionary<string, string> collection
= new Dictionary<string, string>();
Microsoft.TeamFoundation.VersionControl.Client.ItemSet items =
null;

try
{
//authenticate user
server.EnsureAuthenticated();
//afer this statement, property server.AuthenticatedUserName returns
correct username

//create version control object
versionControl =
(Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer)server.GetService(typeof(Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer));
// versionControl object is created successfully

//retrieve all items for current project path
items = versionControl.GetItems(this.Project,
Microsoft.TeamFoundation.VersionControl.Client.RecursionType.OneLevel);
//this statement throws the error TF14002: <domain>\dev-web05$ is not a
member of Team Foundation Valid Users group.


//loop through items
foreach (Microsoft.TeamFoundation.VersionControl.Client.Item
item in items.Items)
{
//declare variables
System.Text.StringBuilder key = new StringBuilder();
System.Text.StringBuilder value = new StringBuilder();

//check to make sure it's not the folder it's in
if (item.ItemType ==
Microsoft.TeamFoundation.VersionControl.Client.ItemType.Folder &&
item.ServerItem.ToUpper() == this.Project.ToUpper())
{
//continue
continue;
}

//populate list item object

value.Append(item.ServerItem.Substring(item.ServerItem.LastIndexOf("/") + 1));

//check to see if it's a folder
if (item.ItemType ==
Microsoft.TeamFoundation.VersionControl.Client.ItemType.Folder)
{
//append folder
value.Append(" [Folder]");
}

//add value
key.Append(item.ServerItem);

//add to collection
collection.Add(key.ToString(), value.ToString());
}

//return the list
return collection;
}
catch (Exception ex)
{
//bubble error
throw ex;
}
finally
{
//cleanup
server.Dispose();
server = null;
versionControl = null;
collection = null;
}
}



[7642 byte] By [ShawnSesna] at [2008-1-7]
# 1

It was my understanding that TFS only supports NTLMv2 authentication.

CRathjen-MSFT at 2007-10-2 > top of Msdn Tech,Visual Studio Team System,Team Foundation Server - General...
# 2
Where is that documented at? I read through

Team Foundation Server Security Concepts

Team Foundation Server Security Architecture

Team Foundation Server Security for Users and Groups

(All found on http://msdn2.microsoft.com/en-us/library/ms253147(VS.80).aspx)

I found nothing regarding support for specific authentication protocols, nor any mention of supported protocols.

Exerpt from Team Foundation Server Security Concepts under Authentication topic:

"Team Foundation Server security is integrated with Windows integrated authentication and the security features of Windows Server 2003"

The above statement leads me to believe thet Kerberos is supported. Access to our TFS through Visual Studio 2005 is working fine with Kerberos enabled. I've taken a look at the Security logs and found that all clients accessing TFS through Visual Studio 2005 are logging on to the server via Kerberos.

ShawnSesna at 2007-10-2 > top of Msdn Tech,Visual Studio Team System,Team Foundation Server - General...
# 3

I'm sorry, I thought you were indicating you couldn't access TFS at all via Kerberos; if you have VS clients able to do so then there must be something more subtle going on.

I'll forward this thread to a couple other people (a little more familiar with our auth story than I am!) and see if they have suggestions.

CRathjen-MSFT at 2007-10-2 > top of Msdn Tech,Visual Studio Team System,Team Foundation Server - General...
# 4

Ah! I sometimes don't quite word things correctly, apologies for giving you the wrong impression Smile

Thank you for fowarding, any help is much appreciated.

ShawnSesna at 2007-10-2 > top of Msdn Tech,Visual Studio Team System,Team Foundation Server - General...
# 5

As far as I'm aware, Kerberos is not supported with TFS 2005. The default credentials object will work with NTLM. So unless you've changed something on the server to force Kerberos auth, you are actually using NTLM.

Also, the account that's indicated as not having access is a machine account (somedomain\machine$). The only way to add that account to the appropriate group in TFS 2005 would be to use tfssecurity.exe, as the GUI doesn't support it (that's fixed in TFS 2008 for RTM).

Buck

BuckHodges at 2007-10-2 > top of Msdn Tech,Visual Studio Team System,Team Foundation Server - General...
# 6

Server setup for srv-tfs01:
Enabled Kerberos authentication in IIS
cscript adsutil.vbs set w3svc/3/root/NTAuthenticationProviders "Negotiate, NTLM"

The above statement sets IIS to try Kerberos first, if it doesn't work, fall back to NTLM. I can tell by the Security Log that clients are logging in via Kerberos.

Correct, the GUI doesn't allow the ability to assign machine accounts to TFS. However, I cheated, I added the machine account to an NT group and added that.

Where did you find that Kerberos wasn't supported in TFS 2005?

ShawnSesna at 2007-10-2 > top of Msdn Tech,Visual Studio Team System,Team Foundation Server - General...
# 7

Having looked into the TFS API code, it appears that Microsoft.TeamFoundation.VersionControl.Client.Repository.QueryItems uses a new HttpWebRequest to poll the TFS server for requested items but does not set the credentials property of the web request. I'm not 100% sure of this, but I believe that this has to be set for the web request to use non-default credentials, which would be the web server itself. My guess is that the API needs to pass throught the credentials from the VersionControlServer so that the QueryItems method can use them.

Additionally, Microsoft.TeamFoundation.VersionControl.Client.FileDownloader.DownloadFile is not passing through the current impersonated user into the spawned thread, which also uses a HttpWebRequest, which results in the exact same conditions described above.

I'm just guessing, but does this sound accurate?

ShawnSesna at 2007-10-2 > top of Msdn Tech,Visual Studio Team System,Team Foundation Server - General...
# 8

The application tier code in TFS 2005 doesn't support Kerberos (only NTLM).

Buck

BuckHodges at 2007-10-2 > top of Msdn Tech,Visual Studio Team System,Team Foundation Server - General...
# 9

I promise you that the call to QueryItems sets the credentials. Otherwise, a lot of stuff would be broken.

File downloads and uploads occur on a background thread from the thread pool. In TFS 2005, impersonated identities do not flow through to those threads. That's been fixed in TFS 2008.

Buck

BuckHodges at 2007-10-2 > top of Msdn Tech,Visual Studio Team System,Team Foundation Server - General...
# 10

Thank you for your responses Smile I guess I'll have to wait until TFS 2008 then.

ShawnSesna at 2007-10-2 > top of Msdn Tech,Visual Studio Team System,Team Foundation Server - General...

Visual Studio Team System

Site Classified