From 38c5cf680f552d1613d88c1dfeabb13ccc8d1533 Mon Sep 17 00:00:00 2001
From: Benoit Sigoure <tsuna@lrde.epita.fr>
Date: Thu, 15 Nov 2007 23:23:25 +0100
Subject: [PATCH v4 11/12] Allow authentication to work with .htpasswd-style files.
* NEWS: Mention the change.
* buildbot/status/web/authentication.py (HTPasswdAuth): New class.
* docs/buildbot.texinfo (WebStatus Configuration Parameters):
Document the new feature.
Signed-off-by: Benoit Sigoure <tsuna@lrde.epita.fr>
---
NEWS | 3 +-
buildbot/status/web/authentication.py | 40 ++++++++++++++++++++++++++++++++-
docs/buildbot.texinfo | 6 +++++
3 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/NEWS b/NEWS
index 7fdcd11..2a87f27 100644
|
a
|
b
|
that start builds on all Builders at once. |
| 13 | 13 | *** Password protected WebStatus |
| 14 | 14 | The WebStatus constructor can take an instance of IAuth (from |
| 15 | 15 | status.web.authentication). The class BasicAuth accepts a `userpass' keyword |
| 16 | | argument in pretty much the same way as Try_Userpass does. |
| | 16 | argument in pretty much the same way as Try_Userpass does. The class |
| | 17 | HTPasswdAuth authenticate users with a .htpasswd-style file. |
| 17 | 18 | Only users with a valid login/password can then force/stop builds from the |
| 18 | 19 | WebStatus. |
| 19 | 20 | |
diff --git a/buildbot/status/web/authentication.py b/buildbot/status/web/authentication.py
index c8c6875..1c36d78 100644
|
a
|
b
|
|
| 1 | | |
| | 1 | import os |
| 2 | 2 | from zope.interface import Interface, implements |
| 3 | 3 | |
| 4 | 4 | class IAuth(Interface): |
| … |
… |
class BasicAuth(AuthBase): |
| 45 | 45 | return True |
| 46 | 46 | self.err = "Invalid login or password" |
| 47 | 47 | return False |
| | 48 | |
| | 49 | class HTPasswdAuth(AuthBase): |
| | 50 | implements(IAuth) |
| | 51 | """Implement an authentication against an .htpasswd-style file.""" |
| | 52 | |
| | 53 | file = "" |
| | 54 | """Path to the .htpasswd-style file to use.""" |
| | 55 | |
| | 56 | def __init__(self, file): |
| | 57 | """C{file} is a path to an .htpasswd-style file.""" |
| | 58 | assert os.path.exists(file) |
| | 59 | self.file = file |
| | 60 | |
| | 61 | def authenticate(self, login, password): |
| | 62 | """Authenticate C{login} and C{password} against a .htpasswd-style |
| | 63 | file""" |
| | 64 | if not os.path.exists(self.file): |
| | 65 | self.err = "No such file: " + self.file |
| | 66 | return False |
| | 67 | # Fetch the lines from the .htpasswd file and split them in a |
| | 68 | # [login, password] array. |
| | 69 | lines = [l.rstrip().split(':', 1) |
| | 70 | for l in file(self.file).readlines()] |
| | 71 | # Keep only the line for this login |
| | 72 | lines = [l for l in lines if l[0] == login] |
| | 73 | if not lines: |
| | 74 | self.err = "Invalid login" |
| | 75 | return False |
| | 76 | # This is the DES-hash of the password. The first two characters are |
| | 77 | # the salt used to introduce disorder in the DES algorithm. |
| | 78 | hash = lines[0][1] |
| | 79 | from crypt import crypt |
| | 80 | res = hash == crypt(password, hash[0:2]) |
| | 81 | if res: |
| | 82 | self.err = "" |
| | 83 | else: |
| | 84 | self.err = "Invalid password" |
| | 85 | return res |
diff --git a/docs/buildbot.texinfo b/docs/buildbot.texinfo
index 278cf4a..e16ee40 100644
|
a
|
b
|
current builds, in that case you can pass an instance of |
| 6127 | 6127 | @code{status.web.authentication.IAuth} as a @code{auth} keyword argument. |
| 6128 | 6128 | The class @code{BasicAuth} implements a basic authentication mechanism |
| 6129 | 6129 | using a list of login/password pairs provided from the configuration file. |
| | 6130 | The class @code{HTPasswdAuth} implements an authentication against an |
| | 6131 | @file{.htpasswd}-style file. |
| 6130 | 6132 | |
| 6131 | 6133 | @example |
| 6132 | 6134 | from buildbot.status.html import WebStatus |
| 6133 | 6135 | from buildbot.status.web.authentication import BasicAuth |
| 6134 | 6136 | users = [('login', 'password'), ('bob', 'secret-pass')] |
| 6135 | 6137 | c['status'].append(WebStatus(http_port=8080, auth=BasicAuth(users))) |
| | 6138 | |
| | 6139 | from buildbot.status.web.authentication import HTPasswdAuth |
| | 6140 | file = '/path/to/file' |
| | 6141 | c['status'].append(WebStatus(http_port=8080, auth=HTPasswdAuth(file))) |
| 6136 | 6142 | @end example |
| 6137 | 6143 | |
| 6138 | 6144 | |