Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Log onto TeamCity server using REST API without passing credentials in the url

As a follow up to a previous question I asked: How to pass username and password in TeamCity REST API, I'd like to check on something.

Can someone tell me if it's possible to access the TeamCity REST API in a more secure way, rather then passing the username and password in the url?

It just seems crazy to me that passing credentials in the url is the only way, since it's so easy for a sniffer to get their hands on the url and use the credentials themselves.

like image 838
Jason Evans Avatar asked Jun 13 '12 17:06

Jason Evans


People also ask

How do I use REST API on TeamCity?

TeamCity REST API It allows accessing resources via URL paths. You can start working with the REST API by opening the http://<TeamCity Server host>:<port>/app/rest/server URL in your browser: this page gives several pointers to explore the API. To learn more, proceed to the dedicated TeamCity REST API Help.

How do I pass login details in REST API?

The client must create a POST call and pass the user name, password, and authString in the Request headers using the /x-www-form-urlencoded content type. The AR System server then performs the normal authentication mechanisms to validate the credentials.

How do I login to TeamCity server?

To login as superuser navigate to your TeamCity login screen (http://<teamcity-server-url>/login.html ) leave the username field blank and enter the security token as the password. Once logged in you will have full administrator privileges.


3 Answers

We faced the same problem and I spent some time to see how could we solve this problem and found a way:

You do a get in the initial screen (/ntlmLogin.html) - you'll be able to identify the user using NTLM.
Then you save the cookie that TeamCity provides to you.
Now you use the cookie to reach the API.

See https://github.com/eduaquiles/TeamCityNtlmApiWrapper with a very simple example on how to do this.

like image 159
Eduardo Aquiles Avatar answered Nov 08 '22 05:11

Eduardo Aquiles


I've done some more digging around with this and it does not look too promising.

I found the following thread on the TeamCity community forums:

Rest API Authentication Integrated

http://devnet.jetbrains.net/message/5461520#5461520

Another user had asked a similar question to mine and the response was that basic HTTP authentication is currently the only option. Although you can use NTLM authentication, that is tailored towards the front end web UI, not the REST API.

I have asked on the forum whether using NTLM via the REST API is possible. I've not had a reply, but I can imagine that it's not possible, which would be expected in this case.

like image 26
Jason Evans Avatar answered Nov 08 '22 03:11

Jason Evans


As per Eduardo Aquiles, if you configure your TeamCity server to support HTTP NTLM authentication (TeamCity 8.x NTLM HTTP Authentication), you can get a session cookie (TCSESSIONID) from the /ntlmLogin.html url and use that to authenticate against the REST API.

I've just had to do something similar to get the pinned state of builds. Here's the PowerShell I used:

function Get-TeamCityNtlmAuthCookie()
{
    param( [string] $serverUrl )
    $url = "$serverUrl/ntlmLogin.html";
    $cookies = new-object System.Net.CookieContainer;
    $request = [System.Net.WebRequest]::Create($url);
    $request.CookieContainer = $cookies;
    $request.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials;
    $request.PreAuthenticate = $true;
    $response = $request.GetResponse();
    return $cookies;
}

function Get-TeamCityBuildPinnedState()
{
    param( [string] $serverUrl, [string] $buildTypeId)
    # get a session cookie to use with the rest api
    $cookies = Get-TeamCityNtlmAuthCookie $serverUrl;
    # query the rest api using the session cookie for authentication
    $url = "$serverUrl/httpAuth/app/rest/builds/id:$buildTypeId/pin/";
    $request = [System.Net.WebRequest]::Create($url);
    $request.CookieContainer = $cookies;
    $response = $request.GetResponse();
    $stream = $response.GetResponseStream();
    $reader = new-object System.IO.StreamReader($stream);
    $text = $reader.ReadToEnd();
    $reader.Close();
    return [bool]::Parse($text);
}

$myServerUrl = "http://myTeamCityServer";
$myBuildId = "6";

$pinned = Get-TeamCityBuildPinnedState $myServerUrl $myBuildId;
write-host $pinned;

Note: I'm not sure if this is officially supported by JetBrains, so you might find it breaks in a future version of TeamCity, but it currently works against version 8.0.2 (build 27482).

like image 39
mclayton Avatar answered Nov 08 '22 04:11

mclayton