|
a/Allura/allura/lib/plugin.py |
|
b/Allura/allura/lib/plugin.py |
1 |
'''
|
1 |
'''
|
2 |
Allura plugins for authentication and project registration
|
2 |
Allura plugins for authentication and project registration
|
3 |
'''
|
3 |
'''
|
|
|
4 |
import re
|
|
|
5 |
import os
|
4 |
import logging
|
6 |
import logging
|
5 |
import re
|
7 |
import subprocess
|
6 |
|
8 |
|
7 |
from random import randint
|
9 |
from random import randint
|
8 |
from hashlib import sha256
|
10 |
from hashlib import sha256
|
9 |
from base64 import b64encode
|
11 |
from base64 import b64encode
|
10 |
from datetime import datetime
|
12 |
from datetime import datetime
|
11 |
|
13 |
|
12 |
import ldap
|
14 |
import ldap
|
|
|
15 |
from ldap import modlist
|
13 |
import pkg_resources
|
16 |
import pkg_resources
|
14 |
from tg import config
|
17 |
from tg import config
|
15 |
from pylons import g, c
|
18 |
from pylons import g, c
|
16 |
from webob import exc
|
19 |
from webob import exc
|
17 |
|
20 |
|
|
... |
|
... |
78 |
raise NotImplementedError, 'by_username'
|
81 |
raise NotImplementedError, 'by_username'
|
79 |
|
82 |
|
80 |
def set_password(self, user, old_password, new_password):
|
83 |
def set_password(self, user, old_password, new_password):
|
81 |
raise NotImplementedError, 'set_password'
|
84 |
raise NotImplementedError, 'set_password'
|
82 |
|
85 |
|
|
|
86 |
def upload_sshkey(self, username, pubkey):
|
|
|
87 |
raise NotImplemented, 'upload_sshkey'
|
|
|
88 |
|
83 |
class LocalAuthenticationProvider(AuthenticationProvider):
|
89 |
class LocalAuthenticationProvider(AuthenticationProvider):
|
84 |
|
90 |
|
85 |
def register_user(self, user_doc):
|
91 |
def register_user(self, user_doc):
|
86 |
from allura import model as M
|
92 |
from allura import model as M
|
87 |
return M.User(**user_doc)
|
93 |
return M.User(**user_doc)
|
|
... |
|
... |
121 |
|
127 |
|
122 |
class LdapAuthenticationProvider(AuthenticationProvider):
|
128 |
class LdapAuthenticationProvider(AuthenticationProvider):
|
123 |
|
129 |
|
124 |
def register_user(self, user_doc):
|
130 |
def register_user(self, user_doc):
|
125 |
from allura import model as M
|
131 |
from allura import model as M
|
126 |
password = user_doc.pop('password', None)
|
132 |
password = user_doc['password'].encode('utf-8')
|
127 |
result = M.User(**user_doc)
|
133 |
result = M.User(**user_doc)
|
128 |
dn = 'uid=%s,%s' % (user_doc['username'], config['auth.ldap.suffix'])
|
134 |
dn_u = 'uid=%s,%s' % (user_doc['username'], config['auth.ldap.suffix'])
|
|
|
135 |
uid = str(M.AuthGlobals.get_next_uid())
|
129 |
try:
|
136 |
try:
|
130 |
con = ldap.initialize(config['auth.ldap.server'])
|
137 |
con = ldap.initialize(config['auth.ldap.server'])
|
131 |
con.bind_s(config['auth.ldap.admin_dn'],
|
138 |
con.bind_s(config['auth.ldap.admin_dn'],
|
132 |
config['auth.ldap.admin_password'])
|
139 |
config['auth.ldap.admin_password'])
|
133 |
ldap_info = dict(
|
140 |
uname = user_doc['username'].encode('utf-8')
|
134 |
uid=user_doc['username'],
|
|
|
135 |
displayName=user_doc['display_name'],
|
141 |
display_name = user_doc['display_name'].encode('utf-8')
|
136 |
cn=user_doc['display_name'],
|
142 |
ldif_u = modlist.addModlist(dict(
|
|
|
143 |
uid=uname,
|
137 |
userPassword=password,
|
144 |
userPassword=password,
|
138 |
objectClass=['inetOrgPerson'],
|
145 |
objectClass=['account', 'posixAccount' ],
|
139 |
givenName=user_doc['display_name'].split()[0],
|
146 |
cn=display_name,
|
140 |
sn=user_doc['display_name'].split()[-1])
|
147 |
uidNumber=uid,
|
141 |
ldap_info = dict((k,v) for k,v in ldap_info.iteritems()
|
148 |
gidNumber='10001',
|
142 |
if v is not None)
|
149 |
homeDirectory='/home/' + uname,
|
|
|
150 |
loginShell='/bin/bash',
|
|
|
151 |
gecos=uname,
|
|
|
152 |
description='SCM user account'))
|
143 |
try:
|
153 |
try:
|
144 |
con.add_s(dn, ldap_info.items())
|
154 |
con.add_s(dn_u, ldif_u)
|
145 |
except ldap.ALREADY_EXISTS:
|
155 |
except ldap.ALREADY_EXISTS:
|
146 |
con.modify_s(dn, [(ldap.MOD_REPLACE, k, v)
|
156 |
log.exception('Trying to create existing user %s', uname)
|
147 |
for k,v in ldap_info.iteritems()])
|
157 |
raise
|
148 |
con.unbind_s()
|
158 |
con.unbind_s()
|
|
|
159 |
argv = ('schroot -d / -c %s -u root /ldap-userconfig.py init %s' % (
|
|
|
160 |
config['auth.ldap.schroot_name'], user_doc['username'])).split()
|
|
|
161 |
p = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
|
162 |
rc = p.wait()
|
|
|
163 |
if rc != 0:
|
|
|
164 |
log.error('Error creating home directory for %s',
|
|
|
165 |
user_doc['username'])
|
149 |
except:
|
166 |
except:
|
150 |
raise
|
167 |
raise
|
151 |
return result
|
168 |
return result
|
152 |
|
169 |
|
|
|
170 |
def upload_sshkey(self, username, pubkey):
|
|
|
171 |
argv = ('schroot -d / -c %s -u root /ldap-userconfig.py upload %s' % (
|
|
|
172 |
config['auth.ldap.schroot_name'], username)).split() + [ pubkey ]
|
|
|
173 |
p = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
|
174 |
rc = p.wait()
|
|
|
175 |
if rc != 0:
|
|
|
176 |
errmsg = p.stdout.read()
|
|
|
177 |
log.exception('Error uploading public SSH key for %s: %s',
|
|
|
178 |
username, errmsg)
|
|
|
179 |
assert False, errmsg
|
|
|
180 |
|
153 |
def by_username(self, username):
|
181 |
def by_username(self, username):
|
154 |
from allura import model as M
|
182 |
from allura import model as M
|
155 |
return M.User.query.get(username=username)
|
183 |
return M.User.query.get(username=username)
|
156 |
|
184 |
|
157 |
def set_password(self, user, old_password, new_password):
|
185 |
def set_password(self, user, old_password, new_password):
|
158 |
try:
|
186 |
try:
|
|
|
187 |
import pdb; pdb.set_trace()
|
159 |
dn = 'uid=%s,%s' % (self.username, config['auth.ldap.suffix'])
|
188 |
dn = 'uid=%s,%s' % (user.username, config['auth.ldap.suffix'])
|
160 |
con = ldap.initialize(config['auth.ldap.server'])
|
189 |
con = ldap.initialize(config['auth.ldap.server'])
|
161 |
con.bind_s(dn, old_password)
|
190 |
con.bind_s(dn, old_password.encode('utf-8'))
|
162 |
con.modify_s(dn, [(ldap.MOD_REPLACE, 'userPassword', new_password)])
|
191 |
con.modify_s(dn, [(ldap.MOD_REPLACE, 'userPassword', new_password.encode('utf-8'))])
|
163 |
con.unbind_s()
|
192 |
con.unbind_s()
|
164 |
except ldap.INVALID_CREDENTIALS:
|
193 |
except ldap.INVALID_CREDENTIALS:
|
165 |
raise exc.HTTPUnauthorized()
|
194 |
raise exc.HTTPUnauthorized()
|
166 |
|
195 |
|
167 |
def _login(self):
|
196 |
def _login(self):
|
|
... |
|
... |
299 |
32: 'images/ext_32.png',
|
328 |
32: 'images/ext_32.png',
|
300 |
48: 'images/ext_48.png'
|
329 |
48: 'images/ext_48.png'
|
301 |
}
|
330 |
}
|
302 |
}
|
331 |
}
|
303 |
|
332 |
|
|
|
333 |
@LazyProperty
|
|
|
334 |
def password_change_form(self):
|
|
|
335 |
from allura.lib.widgets.forms import PasswordChangeForm
|
|
|
336 |
return PasswordChangeForm(action='/auth/prefs/change_password')
|
|
|
337 |
|
|
|
338 |
@LazyProperty
|
|
|
339 |
def upload_key_form(self):
|
|
|
340 |
from allura.lib.widgets.forms import UploadKeyForm
|
|
|
341 |
return UploadKeyForm(action='/auth/prefs/upload_sshkey')
|
|
|
342 |
|
304 |
@property
|
343 |
@property
|
305 |
def master(self):
|
344 |
def master(self):
|
306 |
return self.master_template
|
345 |
return self.master_template
|
307 |
|
346 |
|
308 |
@classmethod
|
347 |
@classmethod
|
|
... |
|
... |
326 |
app_class = ep.load()
|
365 |
app_class = ep.load()
|
327 |
return app_class.icon_url(size)
|
366 |
return app_class.icon_url(size)
|
328 |
else:
|
367 |
else:
|
329 |
return app.icon_url(size)
|
368 |
return app.icon_url(size)
|
330 |
|
369 |
|
331 |
|
|
|
332 |
class LocalProjectRegistrationProvider(ProjectRegistrationProvider):
|
370 |
class LocalProjectRegistrationProvider(ProjectRegistrationProvider):
|
333 |
pass
|
371 |
pass
|