4

My remote Git repository is hosted by the on premises TFS server. There are two ways to access its content:

To use the Restful API one can use the powershell Invoke-RestMethod command with the -UseDefaultCredentials and it works fine, no questions asked.

With git clone, however, I have no idea how to use the default credentials. The manager credential helper does not use them. When used for the first time it asks for the credentials.

So, the options I see are:

  • There an alternative git client, maybe with a limited functionality, but good enough to run clone that can use the default windows credentials.
  • There is a credential helper for windows that can use the default windows credentials.
  • There is an askpass implementation for windows that can use the default windows credentials.

The problem is that I could not find anything on the web that implements any of these options.

Edit 1

The approach suggested in https://github.com/git-for-windows/git/wiki/FAQ#how-do-i-access-a-repository-hosted-on-a-microsoft-team-foundation-server-inside-a-windows-domain does not seem to work. Please, observe:

C:\xyz\DevOps> $GitApiUrl
http://tfsserver:8080/tfs/DefaultCollection/code/_apis/git/repositories/MyConfigData
C:\xyz\DevOps> $ProjectName
dev_smoketest56oc
C:\xyz\DevOps> Test-Path .\params.json
False
C:\xyz\DevOps> Invoke-RestMethod -Uri "$GitApiUrl/items?path=$ProjectName.json&api-version=4.1" -UseDefaultCredentials -OutFile params.json
C:\xyz\DevOps> Test-Path .\params.json
True

As you can see the Restful API works without asking for credentials. Now let us try git clone:

C:\xyz\DevOps> $env:GIT_TRACE=1
C:\xyz\DevOps> git clone http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp a
09:13:21.405748 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/bin
09:13:21.406249 git.c:415               trace: built-in: git clone http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp a
Cloning into 'a'...
09:13:21.430369 run-command.c:637       trace: run_command: git remote-http origin http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp
09:13:21.459149 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
09:13:21.460654 git.c:654               trace: exec: git-remote-http origin http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp
09:13:21.460654 run-command.c:637       trace: run_command: git-remote-http origin http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp
09:13:21.481711 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
09:13:21.539575 run-command.c:637       trace: run_command: 'git credential-manager erase'
09:13:21.642660 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
09:13:21.644162 git.c:654               trace: exec: git-credential-manager erase
09:13:21.644162 run-command.c:637       trace: run_command: git-credential-manager erase
fatal: Authentication failed for 'http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp/'
C:\xyz\DevOps> $env:GIT_TRACE=0
C:\xyz\DevOps>

Authentication failed.

Edit 2

On the bash console:

$ GIT_CURL_VERBOSE=1

$ curl -v --ntlm -u : http://tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp -o 1.html 2> out.txt

$ curl -v --ntlm -u : http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp -o 2.html 2> out2.txt

The files 1.html and 2.html seem to represent the web page of the repository as in the browser, so both curl commands are successful.

The output files out.txt and out2.txt are very similar, the differences are in timestamps, guids and crypto strings. So, here is out.txt (I took the liberty to remove empty lines and scrub a few strings):

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 192.168.17.155...* TCP_NODELAY set* Connected to tfsserver (192.168.17.155) port 8080 (#0)* Server auth using NTLM with user ''> GET /tfs/DefaultCollection/code/_git/MyApp HTTP/1.1
> Host: tfsserver:8080
> Authorization: NTLM ***SCRUBBED***
> User-Agent: curl/7.60.0
> Accept: */*
> 
< HTTP/1.1 401 Unauthorized
< Content-Type: text/html; charset=us-ascii
< Server: Microsoft-HTTPAPI/2.0
< WWW-Authenticate: NTLM ***SCRUBBED***
< Date: Thu, 15 Nov 2018 23:07:58 GMT
< Content-Length: 341
< 
* Ignoring the response-body{ [341 bytes data]
100   341  100   341    0     0    642      0 --:--:-- --:--:-- --:--:--   642* Connection #0 to host tfsserver left intact* Issue another request to this URL: 'http://tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp'* Found bundle for host tfsserver: 0x4116f20 [can pipeline]* Re-using existing connection! (#0) with host tfsserver* Connected to tfsserver (192.168.17.155) port 8080 (#0)* Server auth using NTLM with user ''> GET /tfs/DefaultCollection/code/_git/MyApp HTTP/1.1
> Host: tfsserver:8080
> Authorization: NTLM ***SCRUBBED***
> User-Agent: curl/7.60.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Cache-Control: no-cache, no-store, must-revalidate
< Pragma: no-cache
< Content-Type: text/html; charset=utf-8
< Expires: -1
< Server: Microsoft-IIS/8.5
< X-TFS-ProcessId: e5b67424-832f-468b-8787-c7c05aef5396
< ActivityId: 50f62941-8163-4ee9-9c2b-81359ca72838
< X-TFS-Session: 50f62941-8163-4ee9-9c2b-81359ca72838
< X-VSS-E2EID: 50f62941-8163-4ee9-9c2b-81359ca72838
< X-FRAME-OPTIONS: SAMEORIGIN
< X-VSS-UserData: 34be4ed8-c4fd-4e9f-bdae-d1843df36b0f:mkharitonov
< X-AspNetMvc-Version: 4.0
< X-AspNet-Version: 4.0.30319
< Set-Cookie: __RequestVerificationToken_L3Rmcw2=***SCRUBBED***; path=/; HttpOnly
< Set-Cookie: __RequestVerificationToken27563503a-8c73-4ee0-8930-e1f466b255f5=***SCRUBBED***; path=/; HttpOnly
< Persistent-Auth: true
< X-Powered-By: ASP.NET
< P3P: CP="CAO DSP COR ADMa DEV CONo TELo CUR PSA PSD TAI IVDo OUR SAMi BUS DEM NAV STA UNI COM INT PHY ONL FIN PUR LOC CNT"
< Lfs-Authenticate: NTLM
< X-Content-Type-Options: nosniff
< Date: Thu, 15 Nov 2018 23:07:58 GMT
< Content-Length: 120608
< 
{ [183 bytes data]
100  117k  100  117k    0     0   167k      0 --:--:-- --:--:-- --:--:--  167k* Connection #0 to host tfsserver left intact
halfer
  • 19,824
  • 17
  • 99
  • 186
mark
  • 59,016
  • 79
  • 296
  • 580
  • _"The manager credential helper"_ - do you mean the [Git Credential Manager for Windows](https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases)? – CodeCaster Nov 14 '18 at 16:01
  • @CodeCaster - yes. Updated the question. – mark Nov 14 '18 at 16:31
  • By default credentials you mean the domain account used for windows? – max630 Nov 14 '18 at 22:11
  • https://github.com/git-for-windows/git/wiki/FAQ#how-do-i-access-a-repository-hosted-on-a-microsoft-team-foundation-server-inside-a-windows-domain probably you mean this – max630 Nov 14 '18 at 22:14
  • In `git clone` each time it asks for the credentials or only in the first time? – Shayki Abramczyk Nov 15 '18 at 09:32
  • Only the first time, which is the scope of this question. – mark Nov 15 '18 at 12:48
  • @max630 - for some reason it does not work. See **EDIT 1** – mark Nov 15 '18 at 14:17
  • As far as I understand, this is functionality of curl from msys2. What if you try to run `curl -v --ntlm -u : URL` from "Git bash"? It should print the authentication progress, and as far as I understand should authenticate succesfully. I don't know however how it should look like, and have no server to try wth. I have succeeded once with it, setting up local IIS server. – max630 Nov 15 '18 at 18:29
  • You should set up GIT_CURL_VERBOSE=1 to debug it – max630 Nov 15 '18 at 18:38
  • I can see in the curl there is the "Authorization: NTLM...." header but not in git. Maybe you should file a bug for them to https://github.com/git-for-windows/git/issues – max630 Nov 15 '18 at 19:24
  • Added **EDIT 2** – mark Nov 16 '18 at 00:51
  • curl alone seems to be working, you should run the "git clone" with GIT_CURL_VERBOSE=1 – max630 Nov 16 '18 at 04:26
  • another link to read: https://www.edwardthomson.com/blog/authenticating_git_clients_to_tfs_using_kerberos.html – max630 Nov 16 '18 at 04:43

1 Answers1

4

I cannot verify it to the end, but probably you should set http.emptyAuth to true in config (command git config --global http.emptyAuth true). At least after setting it my git 2.19.1.windows.1 has sent a Authorization: Negotiate ... header to a server which advertises this protocol.

Bottom line:

git config --global http.emptyAuth true

Does it if LFS is not in the picture. If LFS is involved, then prepend the host name with :@, e.g.

http://:@tfsserver:8080/tfs/DefaultCollection/code/_git/MyApp
mark
  • 59,016
  • 79
  • 296
  • 580
max630
  • 8,762
  • 3
  • 30
  • 55
  • Interestingly enough, when the Git repo does not rely on LFS, the `:@` is not needed. But it is a must when LFS is involved. – mark Nov 16 '18 at 13:41