2011-09-29 9 views
6

Próbuję uzyskać dostęp do mojego serwera TFS programowo spoza domeny, w której jest zainstalowany serwer. Podstawowy program testowy będzie wyglądać następująco:Programowy dostęp do TFS 2010 spoza domeny

class Program 
    { 
     static void Main(string[] args) 
     { 
      Uri tfsUri = new Uri("<serverUri>"); 
      TfsConfigurationServer _ConfigurationServer = TfsConfigurationServerFactory.GetConfigurationServer(tfsUri); 
      CatalogNode projectCollectionCatalog = _ConfigurationServer.CatalogNode.QueryChildren(new[] { CatalogResourceTypes.ProjectCollection }, false, CatalogQueryOptions.None)[0]; // actual connection tries to happen here 
     } 
    } 

innej wersji z poświadczeniami przymusowej:

class Program 
    { 
     static void Main(string[] args) 
     { 
      Uri tfsUri = new Uri("<serverURI>"); 
      TfsConfigurationServer _ConfigurationServer = new TfsConfigurationServer(tfsUri, new NetworkCredential("<DifferentKindOfUsernames>", "<Password>")); 
      CatalogNode projectCollectionCatalog = _ConfigurationServer.CatalogNode.QueryChildren(new[] { CatalogResourceTypes.ProjectCollection }, false, CatalogQueryOptions.None)[0]; 
     } 
    } 

Inna wersja z mieszanką zarówno poprzedniej wersji:

public class ConnectByImplementingCredentialsProvider : ICredentialsProvider 
    { 
     public ICredentials GetCredentials(Uri uri, ICredentials iCredentials) 
     { 
      return new NetworkCredential("<DifferentKindOfUsernames>", "<Password>", "<DomainOrNot>"); 
     } 

     public void NotifyCredentialsAuthenticated(Uri uri) 
     { 
      throw new ApplicationException("Unable to authenticate"); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      string _myUri = @"<serverUri>"; 

      ConnectByImplementingCredentialsProvider connect = new ConnectByImplementingCredentialsProvider(); 
      ICredentials iCred = new NetworkCredential("<DifferentKindOfUsernames>", "<Password>", "<DomainOrNot>"); 
      connect.GetCredentials(new Uri(_myUri), iCred); 

      TfsConfigurationServer configurationServer = 
           TfsConfigurationServerFactory.GetConfigurationServer(new Uri(_myUri), connect); 
      configurationServer.EnsureAuthenticated(); 


     } 
    } 

oraz wersja z aktywnym katalogiem Impersonator:

class Program 
    { 
     static void Main(string[] args) 
     { 
      using (new Impersonator("<DifferentKindOfUsernames>", "<DomainOrNot>", "<Password>")) 
      { 
       Uri tfsUri = new Uri("<serverUri>"); 
       TfsConfigurationServer _ConfigurationServer = TfsConfigurationServerFactory.GetConfigurationServer(tfsUri); 
       CatalogNode projectCollectionCatalog = _ConfigurationServer.CatalogNode.QueryChildren(new[] { CatalogResourceTypes.ProjectCollection }, false, CatalogQueryOptions.None)[0]; // actual connection tries to happen here 
      } 
     } 
    } 

serverURI jest w postaci http://<servername>:8080/tfs lub http://<serverip>:8080/tfs (oba testowane, z plikiem hostów zaktualizowanym), który jest ustawiony jako adres URL powiadomień na serwerze TFS. Ten program działa w domenie.

DifferentKindOfUsernames jest to wszystko z "DOMENA \ nazwa_użytkownika", "lokalnie usunięta nazwa_użytkownika", "LOCALMACHINE \ nazwa_użytkownika" z odpowiednim hasłem, hasło jest takie samo w domenie i na komputerze.

Ten prosty dostęp nie będzie działać spoza domeny, a ja mam ten błąd:

TF30063: You are not authorized to access <serverUri> 

tłumaczone w kontekście internetowej (stosując ten sam proces w internetowej ASP.NET), to jest 401 błąd:

The remote server returned an error: (401) Unauthorized. 

nawet jeśli (testowane rzeczy do tej pory):

  • mam mapowanie pomiędzy lokalnym użytkownika/hasło, którzy prowadzą s program na maszynie outsider domeny i aktywne konto katalogowe, które ma dostęp administracyjny do TFS (nawet z włączonymi uprawnieniami personifikacji na TFS).
  • Dodaję klucz rejestru BackConnectionNames z nazwą maszyny zewnętrznej outsider i ip, jak opisano here.
  • I wyłącza sprawdzanie sprzężenia zwrotnego, jak opisano here.
  • Używam odmiany Personelu usługi Active Directory z inną kombinacją nazwy użytkownika/domeny lub komputera. Osoba zarządzająca usługą Active Directory została opisana jako here.
  • Dodałem adres IP serwera TFS do lokalnej strefy internetowej (również wypróbowałem zaufaną stronę) w domenie zewnętrznej opcje zabezpieczeń serwera IE, takie jak opisane here.

Testowałem dostęp do serweraURI z przeglądarki. Uri działa i mam dostęp do kolekcji TFS, jeśli podaję referencje z DomainName \ User + Password. Testowałem to przed każdą z modyfikacji, które opisałem wcześniej. Zastanawiam się, jaka może być różnica między programowym dostępem i dostępem do przeglądarki, oprócz wszystkich rzeczy, które przetestowałem do tej pory.

+0

Nadal nie masz dostępu do serwera TFS z komputera, na którym obecnie używasz tego kodu. Musisz sprawdzić wszelkie dodatkowe ustawienia zabezpieczeń/uprawnień w TFS. Nie wierzę, że to jest problem programowania. – qJake

+0

@SpikeX: Mam dostęp do serwera TFS z urządzenia. Otworzyłem wymagane porty i mam dostęp do identyfikatora URI za pośrednictwem przeglądarki internetowej z tymi samymi danymi uwierzytelniającymi, których użyłem w przypadku osoby podszywającej się. Jeśli klient sieci działa, oczekuję, że mój program zrobi to samo, ale tak się nie stanie. Widzę informacje, które powinny być pobrane przez mój program, jeśli udało mu się połączyć (Kolekcja i Lista projektów). Widzę, dlaczego jest rozmazany między błędem programisty (brakujące lub błędne inicjowanie poświadczeń) a błędem sieci/serwera (problem z konfiguracją). – Matthieu

+0

Następnie moje następne głupie pytanie brzmi: twój URI zawiera 'http: //' i numer portu, prawda? – qJake

Odpowiedz

4

Nie przekazujesz referencji, aby zbudować połączenie. Oznacza to, że używasz aktualnie zalogowanych poświadczeń z hosta spoza domeny.Nie jestem ekspertem od uwierzytelniania systemu Windows, ale myślę, że może to w pewnych okolicznościach działać w sposób przejrzysty (jeśli nazwa użytkownika i hasło są identyczne), ale wydaje się, że zależy to od używanej wersji NTLM, systemów operacyjnych klienta i serwera , relacje zaufania i strefy bezpieczeństwa, konfiguracja IIS i być może faza księżyca.

Innymi słowy, prawdopodobnie chcesz przekazać poświadczenia do połączenia:

TfsConfigurationServer _ConfigurationServer = new TfsConfigurationServer(uri, new NetworkCredential("username", "password", "DOMAIN")); 

Należy pamiętać, że jest to zalecane, aby włączyć SSL/TLS, jeśli łączysz się z serwerem nad niezaufane (publiczne) sieć.

(poprawiłem tego użyć trzy-Arg konstruktor NetworkCredential. - mój błąd Jak można zauważyć, jeśli umieścić DOMAIN\username w argumencie nazwę użytkownika NetworkCredential będzie traktować go jako \DOMAIN\username zamiast DOMAIN\username to, ja. Przypuśćmy, że nikt nie pozwala mi pisać kodu C#.)

+0

Jeszcze nie działa. Istnieje wiele sposobów na podszywanie się pod użytkownika dla TFS, a ja przetestowałem kilka z nich bez powodzenia. Ten daje ten sam błąd TF30063. Zaktualizuję moje pytanie, aby przedstawić inną wersję kodu, którą przetestowałem do tej pory. – Matthieu

+0

Dzięki za edycję, jest to o wiele bardziej przejrzyste. Z ciekawości, co się stanie, jeśli wywołasz tfs.ensureAuthenticated() zamiast próbować zapytać o dane katalogu? Zakładam, że nadal masz błąd? –

+0

Tak To ten sam błąd. Przeprowadzałem analizę sieci. Odpowiem na twój komentarz z wynikiem. – Matthieu