2011-09-29 11 views
6

Estoy intentando acceder a mi servidor TFS programáticamente desde fuera del dominio donde está instalado el servidor. Un programa de prueba básica se vería así:Acceso mediante programación a TFS 2010 desde fuera 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 
     } 
    } 

Otra versión, con credenciales forzada:

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

Otra versión con una mezcla de ambos versión anterior:

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


     } 
    } 

y una versión con un directorio activo 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 en forma de http://<servername>:8080/tfs o http://<serverip>:8080/tfs (ambos probados, con el archivo de hosts actualizado) que es lo que se establece como URL de notificación en el servidor TFS. Este programa funciona dentro del dominio.

DifferentKindOfUsernames siendo cualquier cosa desde 'DOMAIN \ Username', 'LocallyDuplicatedUsername', 'LOCALMACHINE \ Username' con la contraseña apropiada, siendo la misma la contraseña en el dominio y en la máquina.

Este sencillo el acceso no funcionará fuera del dominio, y tengo este error:

TF30063: You are not authorized to access <serverUri> 

traduce en un contexto web (utilizando el mismo proceso en un sitio web asp.net), se trata de una 401 de error:

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

incluso si (cosas probado hasta ahora):

  • tengo un mapeo entre el local de usuario/contraseña que corren s el programa en la máquina externa del dominio y una cuenta de directorio activo que tiene acceso de administrador a TFS (incluso con derechos de suplantación en TFS activado).
  • Agrego una clave de registro BackConnectionNames con el nombre de la máquina externa del dominio y la IP como se describe here.
  • Deshabilito la comprobación de bucle de retroceso como se describe here.
  • Utilizo un identificador de Active Directory con una combinación diferente de usuario/dominio o nombre de máquina. El identificador de Active Directory se describe here.
  • Agregué el IP del servidor TFS a la zona de internet local (también intenté en el sitio de confianza) en las opciones de seguridad de IE del servidor externo del dominio, como se describe en here.

He probado el acceso al serverURI desde un navegador. La uri funciona y tengo acceso a la Colección TFS si doy las credenciales con DomainName \ User + Password. Probé esto antes de cualquiera de las modificaciones que describí antes. Me pregunto cuál podría ser la diferencia entre el acceso programático y el acceso al navegador, además de todas las cosas que he probado hasta ahora.

+0

Aún no tiene acceso al servidor TFS desde la máquina en la que está actualmente ejecutando este código. Debe verificar la configuración adicional de seguridad/permisos dentro de TFS. No creo que esto sea un problema de programación. – qJake

+0

@SpikeX: Tengo acceso al servidor TFS desde la máquina. Abrí los puertos necesarios y tuve acceso al URI a través de un navegador web con las mismas credenciales que utilicé con un Impersonator. Si el cliente web funciona, espero que mi programa haga lo mismo, pero no es así. Puedo ver la información que mi programa debe recuperar si se pudo conectar (Colección y Lista de proyectos). Puedo ver por qué está borroso entre un error de programación (inicialización de credenciales faltantes o incorrectas) y un error de red/servidor (problema de configuración). – Matthieu

+0

Entonces mi siguiente pregunta estúpida es, su URI contiene 'http: //' y un número de puerto, ¿correcto? – qJake

Respuesta

4

No está aprobando credenciales para construir la conexión. Esto significa que está usando sus credenciales actualmente registradas desde el host fuera del dominio.No soy un experto en Autenticación de Windows, pero creo que esto, en ciertas circunstancias, puede funcionar de forma transparente (si el nombre de usuario y la contraseña son idénticos) pero parece depender de la versión NTLM que se utiliza, los sistemas operativos del cliente y del servidor , relaciones de confianza y zonas de seguridad, la configuración de IIS y quizás la fase de la luna.

En otras palabras, es probable que desee pasar las credenciales a la conexión:

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

Tenga en cuenta que es muy recomendable para habilitar SSL/TLS si se conecta a su servidor a través de una confianza (pública) red.

(I corregido esto para usar el constructor de tres arg para NetworkCredential -. Mi error Como nota, si se pone DOMAIN\username en el argumento de nombre de usuario para NetworkCredential, que lo tratará como \DOMAIN\username en lugar de DOMAIN\username Esto, me. supongamos que es por qué nadie me permite escribir el código C#.)

+0

No, todavía no funciona. Hay muchas maneras de suplantar a un usuario para TFS, y probé algunos de ellos sin éxito. Este da el mismo error TF30063. Actualizaré mi pregunta para presentar la versión diferente del código que probé hasta ahora. – Matthieu

+0

Gracias por la edición, esto es mucho más claro. Por curiosidad, ¿qué ocurre si llamas a tfs.ensureAuthenticated() en lugar de intentar consultar los datos del catálogo? Supongo que aún recibes un error. –

+0

Sí, es el mismo error. He estado haciendo un análisis de red. Responderé tu comentario con el resultado. – Matthieu

Cuestiones relacionadas