From 9e026a19f7d3d7acc3ac8a82a9fc56512d80452c Mon Sep 17 00:00:00 2001 From: Jonathon Jongsma Date: Thu, 10 Sep 2009 23:35:25 -0500 Subject: Add support for bugzilla installations that require http auth This patch should support http authentication credentials specified in url form (e.g. https://user:password@foo.com) or in a configuration file. The additional configure options are: - bz-tracker..authuser - bz-tracker..authpwd --- git-bz | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/git-bz b/git-bz index dbcd618..8f9e8dc 100755 --- a/git-bz +++ b/git-bz @@ -79,6 +79,7 @@ import traceback import xmlrpclib import urlparse from xml.etree.cElementTree import ElementTree +import base64 # Globals # ======= @@ -335,6 +336,18 @@ def tracker_get_path(tracker): return config['path'] return None +def tracker_get_auth_user(tracker): + config = get_config(tracker) + if 'path' in config: + return config['authuser'] + return None + +def tracker_get_auth_password(tracker): + config = get_config(tracker) + if 'path' in config: + return config['authpwd'] + return None + def get_default_fields(tracker): config = get_config(tracker) @@ -357,11 +370,13 @@ class BugParseError(Exception): # uniquely identifies a bug on a server, though until we try # to load it (and create a Bug) we don't know if it actually exists. class BugHandle: - def __init__(self, host, path, https, id): + def __init__(self, host, path, https, id, authuser=None, authpwd=None): self.host = host self.path = path self.https = https self.id = id + self.authuser = authuser + self.authpwd = authpwd # ensure that the path to the bugzilla installation is an absolute path # so that it will still work even if their config option specifies @@ -377,10 +392,23 @@ class BugHandle: self.host, self.id) + def needs_auth(self): + return self.authuser and self.authpwd + @staticmethod def parse(bug_reference): parseresult = urlparse.urlsplit (bug_reference) + user = parseresult.username + pwd = parseresult.password + # if the url did not specify http auth credentials in the form + # https://user:pwd@host.com, check to see whether the config file + # specifies any auth credentials for this host + if not user: + user = tracker_get_auth_user(parseresult.hostname) + if not pwd: + pwd = tracker_get_auth_password(parseresult.hostname) + # strip off everything after the last '/', so '/bugzilla/show_bug.cgi' # will simply become '/bugzilla' path = parseresult.path[:parseresult.path.rfind('/')] @@ -390,7 +418,9 @@ class BugHandle: return BugHandle(host=parseresult.hostname, path=path, https=parseresult.scheme=="https", - id=m.group(1)) + id=m.group(1), + authuser=user, + authpwd=pwd) colon = bug_reference.find(":") if colon > 0: @@ -406,11 +436,13 @@ class BugHandle: host = resolve_host_alias(tracker) https = tracker_uses_https(tracker) path = tracker_get_path(tracker) + authuser = tracker_get_auth_user(tracker) + authpwd = tracker_get_auth_password(tracker) if not re.match(r"^.*\.[a-zA-Z]{2,}$", host): raise BugParseError("'%s' doesn't look like a valid bugzilla host or alias" % host) - return BugHandle(host=host, path=path, https=https, id=id) + return BugHandle(host=host, path=path, https=https, id=id, authuser=authuser, authpwd=authpwd) @staticmethod def parse_or_die(str): @@ -712,6 +744,9 @@ def die(message): print >>sys.stderr, message sys.exit(1) +def http_auth_header(user, password): + return 'Basic ' + base64.encodestring("%s:%s" % (user, password)).strip() + # Classes for bug handling # ======================== @@ -737,10 +772,12 @@ def get_connection(host, https): return connections[identifier] class BugServer(object): - def __init__(self, host, path, https): + def __init__(self, host, path, https, authuser=None, authpwd=None): self.host = host self.path = path self.https = https + self.authuser = authuser + self.authpwd = authpwd self.cookies = get_bugzilla_cookies(host) @@ -754,6 +791,8 @@ class BugServer(object): headers = dict(headers) headers['Cookie'] = self.get_cookie_string() headers['User-Agent'] = "git-bz" + if self.authuser and self.authpwd: + headers['Authorization'] = http_auth_header(self.authuser, self.authpwd) if self.path: url = self.path + url @@ -880,6 +919,7 @@ class BugTransport(xmlrpclib.Transport): def send_request(self, connection, *args): xmlrpclib.Transport.send_request(self, connection, *args) connection.putheader("Cookie", self.server.get_cookie_string()) + connection.putheader("Authorization", http_auth_header(self.server.authuser, self.server.authpwd)) servers = {} @@ -887,10 +927,10 @@ servers = {} # host/https of the server to avoid doing too many redirections, and # so the host,https we connect to may be different than what we use # to look up the server. -def get_bug_server(host, path, https): +def get_bug_server(host, path, https, authuser, authpwd): identifier = (host, path, https) if not identifier in servers: - servers[identifier] = BugServer(host, path, https) + servers[identifier] = BugServer(host, path, https, authuser, authpwd) return servers[identifier] @@ -1138,7 +1178,7 @@ class Bug(object): @staticmethod def load(bug_reference, attachmentdata=False): - server = get_bug_server(bug_reference.host, bug_reference.path, bug_reference.https) + server = get_bug_server(bug_reference.host, bug_reference.path, bug_reference.https, bug_reference.authuser, bug_reference.authpwd) bug = Bug(server) bug._load(bug_reference.id, attachmentdata) @@ -1149,9 +1189,11 @@ class Bug(object): host = resolve_host_alias(tracker) https = tracker_uses_https(tracker) path = tracker_get_path(tracker) + authuser = tracker_get_auth_user(tracker) + authpwd = tracker_get_auth_password(tracker) default_fields = get_default_fields(tracker) - server = get_bug_server(host, path, https) + server = get_bug_server(host, path, https, authuser, authpwd) bug = Bug(server) bug._create(product, component, short_desc, comment, default_fields) -- cgit v1.2.3