2011-09-29 6 views
6

Sto tentando di accedere al mio server TFS al livello programmatico dall'esterno del dominio in cui è installato il server. Un programma di test di base sarebbe simile a questa:Accesso a livello di programmazione a TFS 2010 dall'esterno del dominio

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

Un'altra versione, con le credenziali forzata:

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]; 
     } 
    } 

Un'altra versione con un mix di entrambi versione precedente:

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(); 


     } 
    } 

e una versione con una directory attiva 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 sotto forma di http://<servername>:8080/tfs o http://<serverip>:8080/tfs (entrambi testati, con file host aggiornato) che è ciò che viene impostato come URL di notifica sul server TFS. Questo programma funziona all'interno del dominio.

DifferentKindOfUsernames essere qualsiasi cosa da 'DOMINIO \ Nome utente', 'NomeDuplicato Locally', 'NomeUtente LOCALMACHINE' con la password appropriata, la password è la stessa nel dominio e sulla macchina.

Questo semplice l'accesso non funziona al di fuori del dominio, e non ho questo errore:

TF30063: You are not authorized to access <serverUri> 

tradotto in un contesto web (utilizzando lo stesso processo in un sito asp.net), si tratta di un 401 errore:

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

anche se (cose testato finora):

  • ho un mapping tra l'utente/password locale che gestiscono s il programma sulla macchina outsider di dominio e un account di directory attivo che ha accesso di amministratore a TFS (anche con i diritti di rappresentazione su TFS attivato).
  • Aggiungo una chiave di registro BackConnectionNames con il nome del computer esterno del dominio e l'ip come descritto here.
  • Disabilito il controllo di loopback come descritto in here.
  • Uso un identificatore di Active Directory con diverse combinazioni di utente/dominio o nome computer. Impersonator di Active Directory descritto here.
  • Ho aggiunto l'IP del server TFS all'area Internet locale (provato anche come sito attendibile) nelle opzioni di sicurezza IE del server esterno del dominio come descritto in here.

Ho verificato l'accesso al serverURI da un browser. L'uri funziona e ho accesso alla collezione TFS se fornisco le credenziali con DomainName \ User + Password. Ho provato questo prima di qualsiasi delle modifiche che ho descritto prima. Mi chiedo quale potrebbe essere la differenza tra l'accesso programmatico e l'accesso al browser oltre a tutte le cose che ho testato finora.

+0

Non si ha ancora accesso al server TFS dalla macchina su cui si sta eseguendo questo codice. È necessario verificare eventuali ulteriori impostazioni di sicurezza/autorizzazione all'interno di TFS. Non credo che questo sia un problema di programmazione. – qJake

+0

@SpikeX: ho accesso al server TFS dalla macchina. Ho aperto le porte richieste e ho avuto accesso all'URI tramite un browser Web con le stesse credenziali che ho usato con un imitatore. Se il client web funziona, mi aspetto che il mio programma faccia lo stesso, ma non lo fa. Riesco a vedere le informazioni che dovrebbero essere recuperate dal mio programma se fosse in grado di connettersi (raccolta e elenco dei progetti). Posso capire perché è sfocato tra un errore di programmazione (inizializzazione di credenziali mancanti o errate) e un errore di rete/server (problema di configurazione). – Matthieu

+0

Quindi la mia prossima domanda stupida è, il tuo URI contiene 'http: //' e un numero di porta, corretto? – qJake

risposta

4

Non stai passando le credenziali per costruire la connessione. Ciò significa che stai utilizzando le credenziali di accesso correntemente dall'host al di fuori del dominio.Non sono un esperto di autenticazione di Windows, ma penso che questo, in determinate circostanze, funzioni in modo trasparente (se il nome utente e la password sono identici) ma sembra dipendere dalla versione NTLM utilizzata, dai sistemi operativi client e server , relazioni di fiducia e zone di sicurezza, la configurazione di IIS e forse la fase lunare.

In altre parole, probabilmente si desidera passare le credenziali per la connessione:

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

Si noti che è fortemente raccomandato per abilitare SSL/TLS, se ci si connette al server tramite una attendibile (pubblico) Rete.

(ho corretto questa opzione per utilizzare il costruttore di tre arg per NetworkCredential -. Il mio errore Come si nota, se si mette DOMAIN\username nell'argomento nome utente per NetworkCredential, verrà trattato come \DOMAIN\username invece di DOMAIN\username questo, io. supponiamo, perché nessuno mi consente di scrivere il codice C#)

+0

Non ancora funzionante. Esistono molti modi per impersonare un utente per TFS e ne ho provato alcuni senza successo. Questo dà lo stesso errore TF30063. Aggiornerò la mia domanda per presentare la versione diversa del codice che ho provato finora. – Matthieu

+0

Grazie per la modifica, questo è molto più chiaro. Per curiosità, cosa succede se chiami tfs.ensureAuthenticated() invece di provare a interrogare i dati del catalogo? Suppongo tu abbia ancora un errore? –

+0

Sì È lo stesso errore. Ho fatto qualche analisi della rete. Risponderò al tuo commento con il risultato. – Matthieu

Problemi correlati