Cory Kramer
Cory Kramer

Reputation: 117876

POST build to TeamCity queue

I am trying to use the TeamCity REST API to add a build to the queue but am running into some difficulty with authorization.

I have the url to our teamcity server defined, and have generated an authorization token through the admin page

TEAMCITY_URL = 'http://teamcity.somedomain.com'
BEARER_TOKEN = 'SOMELONGTOKEN'

With this URL and token I can successfully make GET requests

import json
import requests

session = requests.Session()
session.headers.update({
    'Accept': 'application/json',
    'Authorization': f'Bearer {BEARER_TOKEN}',
})

response = session.get(f'{TEAMCITY_URL}/app/rest/projects/example/buildTypes')
assert(response.status_code == requests.codes.ok)  # this succeeds, can parse response fine later

but then if I try to POST a build to the queue I get a 403

payload = {
    'branchName': 'master',
    'buildType': {
        'id': buildID  # assume this was already defined
    }
}

response = session.post(f'{TEAMCITY_URL}/app/rest/buildQueue', json=payload)
assert(response.status_code == requests.codes.ok)  # fails with 403

the latter response.text is

'403 Forbidden: Responding with 403 status code due to failed CSRF check: authenticated POST request is made, but neither tc-csrf-token parameter nor X-TC-CSRF-Token header are provided.. For a temporary workaround, you can set internal property teamcity.csrf.paranoid=false and provide valid Origin={teamcity_url} header with your request\n'

How can I correctly use this bearer token to perform a POST request?

Upvotes: 2

Views: 896

Answers (1)

Cory Kramer
Cory Kramer

Reputation: 117876

The fix for this was I needed to first make a GET request for a CSRF token. I could then use this token to update the session headers with a 'X-TC-CSRF-Token' as follows

response = session.get(f'{TEAMCITY_URL}/authenticationTest.html?csrf')
assert(response.status_code == requests.codes.ok)
csrf_token = response.text
session.headers.update({
    'X-TC-CSRF-Token': csrf_token
})

then the subsequent POST would succeed. More details in official docs.

Upvotes: 1

Related Questions