powershellteamcityntlmpowershell-3.0teamcity-7.0

How do I download a protected file using PowerShell?


I am trying to download a file using PowerShell 3.0 from my TeamCity build server. I have configured TeamCity to use NTLM authentication but I cannot download the file directly and get redirected to login.

I am trying to use the following PowerShell code to download the file.

$artifacts = "http://teamcity/repository/download/bt1/.lastSuccessful/%7Bbuild.number%7D.zip"
Invoke-WebRequest -Uri $artifacts -UseDefaultCredentials

My response from the request is a redirection to the login page.


Solution

  • Here is the code for the final solution.


    $artifacts = "http://teamcity/repository/download/bt1/.lastSuccessful/%7Bbuild.number%7D.zip"
    $login = "http://teamcity/ntlmLogin.html"
    $dest = "Artifacts.zip"
    
    $TeamCitySession = New-Object Microsoft.PowerShell.Commands.WebRequestSession
    Invoke-WebRequest -Uri $login -WebSession $TeamCitySession -UseDefaultCredentials -UseBasicParsing
    Invoke-WebRequest -Uri $artifacts -WebSession $TeamCitySession -UseBasicParsing -OutFile $dest
    

    In order to figure out what was happening I needed to use Fiddler to trace what a successful request looks like and also trace what was happening in PowerShell. In order to do that I had to make my PowerShell request use it. The following is how I turned on Fiddler tracing from within PowerShell.

    Invoke-WebRequest -Uri $artifacts -UseDefaultCredentials -Proxy http://localhost:8888/
    

    By adding the -Proxy argument to the command it told he command to use Fiddler as a proxy server.

    From here I saw that TeamCity was redirecting me to the login page. Since I have NTLM authentication turned on there is a special page that you browse to in order to login. So what I wanted to do from here was to visit this login page and then download the file using the cookies that I get back as TeamCity uses a cookie to track authentication status.

    It also turns out that the Invoke-WebRequest cmdlets also allow you to connect them using a web session. There are two ways of accomplishing this using either the -WebSession or the -SessionVariable parameter. After some trial and error it turns out that if you use the -SessionVariable parameter it will overwrite the session variable after each request, so that it doesn't actually share the state. Clearly this is not the behavior I am looking for. Instead I had to use the -WebSession parameter and then I could chain together the login and the download of the file. Once I did this then everything started working.