blob: 2cd2b132e1364b1186c2c5955bc462f19c80c673 [file] [log] [blame]
aroben@apple.com280e4812011-12-01 19:58:49 +00001# Copyright (C) 2011 Apple Inc. All rights reserved.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions
5# are met:
6# 1. Redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer.
8# 2. Redistributions in binary form must reproduce the above copyright
9# notice, this list of conditions and the following disclaimer in the
10# documentation and/or other materials provided with the distribution.
11#
12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
13# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
16# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
18# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
19# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
20# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
21# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22
23"""An implementation of buildbot.status.web.auth.IAuth for authenticating WebKit committers"""
24
25import ConfigParser
26import buildbot.status.web.auth
27import json
28import zope.interface
29
rniwa@webkit.org07df2382013-02-01 04:01:57 +000030from htdigestparser import HTDigestParser
aroben@apple.com280e4812011-12-01 19:58:49 +000031
32
33class Error(Exception):
34 pass
35
36
37class CommitterAuth(buildbot.status.web.auth.AuthBase):
38 zope.interface.implements(buildbot.status.web.auth.IAuth)
39
40 def __init__(self, auth_json_filename):
41 self._auth_json_filename = auth_json_filename
42
43 def auth_json(self):
44 try:
45 with self.open_auth_json_file() as f:
46 return json.load(f)
annulen@yandex.ru549ab042017-12-10 21:11:18 +000047 except IOError as e:
aroben@apple.com280e4812011-12-01 19:58:49 +000048 raise Error('Error opening auth.json file: {0}'.format(e.strerror))
annulen@yandex.ru549ab042017-12-10 21:11:18 +000049 except ValueError as e:
aroben@apple.com280e4812011-12-01 19:58:49 +000050 raise Error('Error parsing auth.json file: {0}'.format(e.message))
51
52 def auth_json_filename(self):
53 return self._auth_json_filename
54
55 def authenticate(self, username, password):
56 try:
57 return self.is_webkit_committer(username) and self.is_webkit_trac_user(username, password)
annulen@yandex.ru549ab042017-12-10 21:11:18 +000058 except Error as e:
lforschler@apple.com410c0fe2017-03-24 19:41:38 +000059 self.err = e.args[0]
aroben@apple.com280e4812011-12-01 19:58:49 +000060 return False
61
62 def is_webkit_committer(self, username):
63 try:
64 if username not in self.webkit_committers():
65 self.err = 'Invalid username/password'
66 return False
67 return True
68 except ConfigParser.Error:
69 raise Error('Error parsing WebKit committers file')
annulen@yandex.ru549ab042017-12-10 21:11:18 +000070 except IOError as e:
aroben@apple.com280e4812011-12-01 19:58:49 +000071 raise Error('Error opening WebKit committers file: {0}'.format(e.strerror))
72
73 def is_webkit_trac_user(self, username, password):
74 try:
75 with self.open_trac_credentials_file() as f:
76 htdigest = HTDigestParser(f)
annulen@yandex.ru549ab042017-12-10 21:11:18 +000077 except IOError as e:
aroben@apple.com280e4812011-12-01 19:58:49 +000078 raise Error('Error opening Trac credentials file: {0}'.format(e.strerror))
79
80 if not htdigest.entries():
81 raise Error('Error parsing Trac credentials file')
82
83 if not htdigest.authenticate(username, 'Mac OS Forge', password):
84 self.err = 'Invalid username/password'
85 return False
86
87 return True
88
89 # These three methods exist for ease of testing.
90 def open_auth_json_file(self):
91 return open(self.auth_json_filename())
92
93 def open_trac_credentials_file(self):
94 return open(self.trac_credentials_filename())
95
96 def open_webkit_committers_file(self):
97 return open(self.webkit_committers_filename())
98
99 def trac_credentials_filename(self):
100 try:
101 return self.auth_json()['trac_credentials']
102 except KeyError:
103 raise Error('auth.json file is missing "trac_credentials" key')
104
105 def webkit_committers(self):
106 config = ConfigParser.RawConfigParser()
107 with self.open_webkit_committers_file() as f:
108 config.readfp(f)
109 return config.get('groups', 'webkit').split(',')
110
111 def webkit_committers_filename(self):
112 try:
113 return self.auth_json()['webkit_committers']
114 except KeyError:
115 raise Error('auth.json file is missing "webkit_committers" key')