Skip to content
This repository has been archived by the owner on Sep 15, 2021. It is now read-only.

Commit

Permalink
bug 738000: enable CSRF protection in existing balrog code - use a di…
Browse files Browse the repository at this point in the history
…fferent url to retrieve data_version/csrf_token. r=rail
  • Loading branch information
bhearsum committed Jun 7, 2012
1 parent 534aab0 commit e9dcdd5
Showing 1 changed file with 24 additions and 1 deletion.
25 changes: 24 additions & 1 deletion lib/python/balrog/client/api.py
Expand Up @@ -14,8 +14,29 @@ def is_csrf_token_expired(token):
return False

class API(object):
"""A class that knows how to make requests to a Balrog server, including
pre-retrieving CSRF tokens and data versions.
url_template: The URL to submit to when request() is called. Standard
Python string interpolation can be used here in
combination with the url_template_vars argument to
request().
prerequest_url_template: Before submitting the real request, a HEAD
operation will be done on this URL. If the
HEAD request succeeds, it is expected that
there will be X-CSRF-Token and X-Data-Version
headers in the response. If the HEAD request
results in a 404, another HEAD request to
/csrf_token will be made in attempt to get a
CSRF Token. This URL can use string
interpolation the same way url_template can.
In some cases this may be the same as the
url_template.
"""
verify = False
auth = None
url_template = None
prerequest_url_template = None

def __init__(self, api_root='https://balrog.build.mozilla.org',
auth=None, ca_certs=CA_BUNDLE, timeout=60, raise_exceptions=True):
Expand Down Expand Up @@ -45,13 +66,14 @@ def __init__(self, api_root='https://balrog.build.mozilla.org',

def request(self, data=None, method='GET', url_template_vars={}):
url = self.api_root + self.url_template % url_template_vars
prerequest_url = self.api_root + self.prerequest_url_template % url_template_vars
# If we'll be modifying things, do a GET first to get a CSRF token
# and possibly a data_version.
if method != 'GET' and method != 'HEAD':
# Use the URL of the resource we're going to modify first,
# because we'll need its data_version if it exists.
try:
res = self.do_request(url, None, 'HEAD', {})
res = self.do_request(prerequest_url, None, 'HEAD', {})
data['data_version'] = res.headers['X-Data-Version']
# We may already have a non-expired CSRF token, but it's
# faster/easier just to set it again even if we do, since
Expand Down Expand Up @@ -84,6 +106,7 @@ def do_request(self, url, data, method, url_template_vars):

class SingleLocale(API):
url_template = '/releases/%(name)s/builds/%(build_target)s/%(locale)s'
prerequest_url_template = '/releases/%(name)s'

def update_build(self, name, product, version, build_target, locale,
buildData, copyTo=None):
Expand Down

0 comments on commit e9dcdd5

Please sign in to comment.