##// END OF EJS Templates
auth: refactor code and simplified instructions....
marcink -
r1454:01fbc7af default
parent child Browse files
Show More
@@ -627,3 +627,21 b' def authenticate(username, password, env'
627 log.debug("User `%s` failed to authenticate against %s",
627 log.debug("User `%s` failed to authenticate against %s",
628 display_user, plugin.get_id())
628 display_user, plugin.get_id())
629 return None
629 return None
630
631
632 def chop_at(s, sub, inclusive=False):
633 """Truncate string ``s`` at the first occurrence of ``sub``.
634
635 If ``inclusive`` is true, truncate just after ``sub`` rather than at it.
636
637 >>> chop_at("plutocratic brats", "rat")
638 'plutoc'
639 >>> chop_at("plutocratic brats", "rat", True)
640 'plutocrat'
641 """
642 pos = s.find(sub)
643 if pos == -1:
644 return s
645 if inclusive:
646 return s[:pos+len(sub)]
647 return s[:pos]
@@ -28,10 +28,9 b' import base64'
28 import logging
28 import logging
29 import urllib2
29 import urllib2
30
30
31 from pylons.i18n.translation import lazy_ugettext as _
31 from rhodecode.translation import _
32 from sqlalchemy.ext.hybrid import hybrid_property
32 from rhodecode.authentication.base import (
33
33 RhodeCodeExternalAuthPlugin, hybrid_property)
34 from rhodecode.authentication.base import RhodeCodeExternalAuthPlugin
35 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
34 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
36 from rhodecode.authentication.routes import AuthnPluginResourceBase
35 from rhodecode.authentication.routes import AuthnPluginResourceBase
37 from rhodecode.lib.colander_utils import strip_whitespace
36 from rhodecode.lib.colander_utils import strip_whitespace
@@ -21,15 +21,14 b''
21 import colander
21 import colander
22 import logging
22 import logging
23
23
24 from sqlalchemy.ext.hybrid import hybrid_property
24 from rhodecode.translation import _
25
25 from rhodecode.authentication.base import (
26 from rhodecode.authentication.base import RhodeCodeExternalAuthPlugin
26 RhodeCodeExternalAuthPlugin, hybrid_property)
27 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
27 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
28 from rhodecode.authentication.routes import AuthnPluginResourceBase
28 from rhodecode.authentication.routes import AuthnPluginResourceBase
29 from rhodecode.lib.colander_utils import strip_whitespace
29 from rhodecode.lib.colander_utils import strip_whitespace
30 from rhodecode.lib.utils2 import str2bool, safe_unicode
30 from rhodecode.lib.utils2 import str2bool, safe_unicode
31 from rhodecode.model.db import User
31 from rhodecode.model.db import User
32 from rhodecode.translation import _
33
32
34
33
35 log = logging.getLogger(__name__)
34 log = logging.getLogger(__name__)
@@ -30,10 +30,9 b' import rhodecode'
30 import urllib
30 import urllib
31 import urllib2
31 import urllib2
32
32
33 from pylons.i18n.translation import lazy_ugettext as _
33 from rhodecode.translation import _
34 from sqlalchemy.ext.hybrid import hybrid_property
34 from rhodecode.authentication.base import (
35
35 RhodeCodeExternalAuthPlugin, hybrid_property)
36 from rhodecode.authentication.base import RhodeCodeExternalAuthPlugin
37 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
36 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
38 from rhodecode.authentication.routes import AuthnPluginResourceBase
37 from rhodecode.authentication.routes import AuthnPluginResourceBase
39 from rhodecode.lib.colander_utils import strip_whitespace
38 from rhodecode.lib.colander_utils import strip_whitespace
@@ -27,10 +27,9 b' import colander'
27 import logging
27 import logging
28 import traceback
28 import traceback
29
29
30 from pylons.i18n.translation import lazy_ugettext as _
30 from rhodecode.translation import _
31 from sqlalchemy.ext.hybrid import hybrid_property
31 from rhodecode.authentication.base import (
32
32 RhodeCodeExternalAuthPlugin, chop_at, hybrid_property)
33 from rhodecode.authentication.base import RhodeCodeExternalAuthPlugin
34 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
33 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
35 from rhodecode.authentication.routes import AuthnPluginResourceBase
34 from rhodecode.authentication.routes import AuthnPluginResourceBase
36 from rhodecode.lib.colander_utils import strip_whitespace
35 from rhodecode.lib.colander_utils import strip_whitespace
@@ -72,14 +71,15 b' class LdapSettingsSchema(AuthnPluginSett'
72 host = colander.SchemaNode(
71 host = colander.SchemaNode(
73 colander.String(),
72 colander.String(),
74 default='',
73 default='',
75 description=_('Host of the LDAP Server'),
74 description=_('Host of the LDAP Server \n'
75 '(e.g., 192.168.2.154, or ldap-server.domain.com'),
76 preparer=strip_whitespace,
76 preparer=strip_whitespace,
77 title=_('LDAP Host'),
77 title=_('LDAP Host'),
78 widget='string')
78 widget='string')
79 port = colander.SchemaNode(
79 port = colander.SchemaNode(
80 colander.Int(),
80 colander.Int(),
81 default=389,
81 default=389,
82 description=_('Port that the LDAP server is listening on'),
82 description=_('Custom port that the LDAP server is listening on. Default: 389'),
83 preparer=strip_whitespace,
83 preparer=strip_whitespace,
84 title=_('Port'),
84 title=_('Port'),
85 validator=colander.Range(min=0, max=65536),
85 validator=colander.Range(min=0, max=65536),
@@ -87,7 +87,9 b' class LdapSettingsSchema(AuthnPluginSett'
87 dn_user = colander.SchemaNode(
87 dn_user = colander.SchemaNode(
88 colander.String(),
88 colander.String(),
89 default='',
89 default='',
90 description=_('User to connect to LDAP'),
90 description=_('Optional user DN/account to connect to LDAP if authentication is required. \n'
91 'e.g., cn=admin,dc=mydomain,dc=com, or '
92 'uid=root,cn=users,dc=mydomain,dc=com, or admin@mydomain.com'),
91 missing='',
93 missing='',
92 preparer=strip_whitespace,
94 preparer=strip_whitespace,
93 title=_('Account'),
95 title=_('Account'),
@@ -95,7 +97,7 b' class LdapSettingsSchema(AuthnPluginSett'
95 dn_pass = colander.SchemaNode(
97 dn_pass = colander.SchemaNode(
96 colander.String(),
98 colander.String(),
97 default='',
99 default='',
98 description=_('Password to connect to LDAP'),
100 description=_('Password to authenticate for given user DN.'),
99 missing='',
101 missing='',
100 preparer=strip_whitespace,
102 preparer=strip_whitespace,
101 title=_('Password'),
103 title=_('Password'),
@@ -117,7 +119,9 b' class LdapSettingsSchema(AuthnPluginSett'
117 base_dn = colander.SchemaNode(
119 base_dn = colander.SchemaNode(
118 colander.String(),
120 colander.String(),
119 default='',
121 default='',
120 description=_('Base DN to search (e.g., dc=mydomain,dc=com)'),
122 description=_('Base DN to search. Dynamic bind is supported. Add `$login` marker '
123 'in it to be replaced with current user credentials \n'
124 '(e.g., dc=mydomain,dc=com, or ou=Users,dc=mydomain,dc=com)'),
121 missing='',
125 missing='',
122 preparer=strip_whitespace,
126 preparer=strip_whitespace,
123 title=_('Base DN'),
127 title=_('Base DN'),
@@ -125,22 +129,25 b' class LdapSettingsSchema(AuthnPluginSett'
125 filter = colander.SchemaNode(
129 filter = colander.SchemaNode(
126 colander.String(),
130 colander.String(),
127 default='',
131 default='',
128 description=_('Filter to narrow results (e.g., ou=Users, etc)'),
132 description=_('Filter to narrow results \n'
133 '(e.g., (&(objectCategory=Person)(objectClass=user)), or \n'
134 '(memberof=cn=rc-login,ou=groups,ou=company,dc=mydomain,dc=com)))'),
129 missing='',
135 missing='',
130 preparer=strip_whitespace,
136 preparer=strip_whitespace,
131 title=_('LDAP Search Filter'),
137 title=_('LDAP Search Filter'),
132 widget='string')
138 widget='string')
139
133 search_scope = colander.SchemaNode(
140 search_scope = colander.SchemaNode(
134 colander.String(),
141 colander.String(),
135 default=search_scope_choices[0],
142 default=search_scope_choices[2],
136 description=_('How deep to search LDAP'),
143 description=_('How deep to search LDAP. If unsure set to SUBTREE'),
137 title=_('LDAP Search Scope'),
144 title=_('LDAP Search Scope'),
138 validator=colander.OneOf(search_scope_choices),
145 validator=colander.OneOf(search_scope_choices),
139 widget='select')
146 widget='select')
140 attr_login = colander.SchemaNode(
147 attr_login = colander.SchemaNode(
141 colander.String(),
148 colander.String(),
142 default='',
149 default='uid',
143 description=_('LDAP Attribute to map to user name'),
150 description=_('LDAP Attribute to map to user name (e.g., uid, or sAMAccountName)'),
144 preparer=strip_whitespace,
151 preparer=strip_whitespace,
145 title=_('Login Attribute'),
152 title=_('Login Attribute'),
146 missing_msg=_('The LDAP Login attribute of the CN must be specified'),
153 missing_msg=_('The LDAP Login attribute of the CN must be specified'),
@@ -148,7 +155,7 b' class LdapSettingsSchema(AuthnPluginSett'
148 attr_firstname = colander.SchemaNode(
155 attr_firstname = colander.SchemaNode(
149 colander.String(),
156 colander.String(),
150 default='',
157 default='',
151 description=_('LDAP Attribute to map to first name'),
158 description=_('LDAP Attribute to map to first name (e.g., givenName)'),
152 missing='',
159 missing='',
153 preparer=strip_whitespace,
160 preparer=strip_whitespace,
154 title=_('First Name Attribute'),
161 title=_('First Name Attribute'),
@@ -156,7 +163,7 b' class LdapSettingsSchema(AuthnPluginSett'
156 attr_lastname = colander.SchemaNode(
163 attr_lastname = colander.SchemaNode(
157 colander.String(),
164 colander.String(),
158 default='',
165 default='',
159 description=_('LDAP Attribute to map to last name'),
166 description=_('LDAP Attribute to map to last name (e.g., sn)'),
160 missing='',
167 missing='',
161 preparer=strip_whitespace,
168 preparer=strip_whitespace,
162 title=_('Last Name Attribute'),
169 title=_('Last Name Attribute'),
@@ -164,7 +171,9 b' class LdapSettingsSchema(AuthnPluginSett'
164 attr_email = colander.SchemaNode(
171 attr_email = colander.SchemaNode(
165 colander.String(),
172 colander.String(),
166 default='',
173 default='',
167 description=_('LDAP Attribute to map to email address'),
174 description=_('LDAP Attribute to map to email address (e.g., mail).\n'
175 'Emails are a crucial part of RhodeCode. \n'
176 'If possible add a valid email attribute to ldap users.'),
168 missing='',
177 missing='',
169 preparer=strip_whitespace,
178 preparer=strip_whitespace,
170 title=_('Email Attribute'),
179 title=_('Email Attribute'),
@@ -182,7 +191,7 b' class AuthLdap(object):'
182 def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='',
191 def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='',
183 tls_kind='PLAIN', tls_reqcert='DEMAND', ldap_version=3,
192 tls_kind='PLAIN', tls_reqcert='DEMAND', ldap_version=3,
184 search_scope='SUBTREE', attr_login='uid',
193 search_scope='SUBTREE', attr_login='uid',
185 ldap_filter='(&(objectClass=user)(!(objectClass=computer)))'):
194 ldap_filter=None):
186 if ldap == Missing:
195 if ldap == Missing:
187 raise LdapImportError("Missing or incompatible ldap library")
196 raise LdapImportError("Missing or incompatible ldap library")
188
197
@@ -236,14 +245,13 b' class AuthLdap(object):'
236 server.start_tls_s()
245 server.start_tls_s()
237
246
238 if self.LDAP_BIND_DN and self.LDAP_BIND_PASS:
247 if self.LDAP_BIND_DN and self.LDAP_BIND_PASS:
239 log.debug('Trying simple_bind with password and given DN: %s',
248 log.debug('Trying simple_bind with password and given login DN: %s',
240 self.LDAP_BIND_DN)
249 self.LDAP_BIND_DN)
241 server.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS)
250 server.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS)
242
251
243 return server
252 return server
244
253
245 def get_uid(self, username):
254 def get_uid(self, username):
246 from rhodecode.lib.helpers import chop_at
247 uid = username
255 uid = username
248 for server_addr in self.SERVER_ADDRESSES:
256 for server_addr in self.SERVER_ADDRESSES:
249 uid = chop_at(username, "@%s" % server_addr)
257 uid = chop_at(username, "@%s" % server_addr)
@@ -292,8 +300,11 b' class AuthLdap(object):'
292 self.BASE_DN, self.SEARCH_SCOPE, filter_)
300 self.BASE_DN, self.SEARCH_SCOPE, filter_)
293
301
294 if not lobjects:
302 if not lobjects:
303 log.debug("No matching LDAP objects for authentication "
304 "of UID:'%s' username:(%s)", uid, username)
295 raise ldap.NO_SUCH_OBJECT()
305 raise ldap.NO_SUCH_OBJECT()
296
306
307 log.debug('Found matching ldap object, trying to authenticate')
297 for (dn, _attrs) in lobjects:
308 for (dn, _attrs) in lobjects:
298 if dn is None:
309 if dn is None:
299 continue
310 continue
@@ -304,15 +315,13 b' class AuthLdap(object):'
304 break
315 break
305
316
306 else:
317 else:
307 log.debug("No matching LDAP objects for authentication "
308 "of '%s' (%s)", uid, username)
309 raise LdapPasswordError('Failed to authenticate user '
318 raise LdapPasswordError('Failed to authenticate user '
310 'with given password')
319 'with given password')
311
320
312 except ldap.NO_SUCH_OBJECT:
321 except ldap.NO_SUCH_OBJECT:
313 log.debug("LDAP says no such user '%s' (%s), org_exc:",
322 log.debug("LDAP says no such user '%s' (%s), org_exc:",
314 uid, username, exc_info=True)
323 uid, username, exc_info=True)
315 raise LdapUsernameError()
324 raise LdapUsernameError('Unable to find user')
316 except ldap.SERVER_DOWN:
325 except ldap.SERVER_DOWN:
317 org_exc = traceback.format_exc()
326 org_exc = traceback.format_exc()
318 raise LdapConnectionError(
327 raise LdapConnectionError(
@@ -447,7 +456,7 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
447 'email': get_ldap_attr('attr_email') or email,
456 'email': get_ldap_attr('attr_email') or email,
448 'admin': admin,
457 'admin': admin,
449 'active': active,
458 'active': active,
450 "active_from_extern": None,
459 'active_from_extern': None,
451 'extern_name': user_dn,
460 'extern_name': user_dn,
452 'extern_type': extern_type,
461 'extern_type': extern_type,
453 }
462 }
@@ -17,6 +17,7 b''
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20 """
21 """
21 RhodeCode authentication library for PAM
22 RhodeCode authentication library for PAM
22 """
23 """
@@ -29,10 +30,9 b' import pwd'
29 import re
30 import re
30 import socket
31 import socket
31
32
32 from pylons.i18n.translation import lazy_ugettext as _
33 from rhodecode.translation import _
33 from sqlalchemy.ext.hybrid import hybrid_property
34 from rhodecode.authentication.base import (
34
35 RhodeCodeExternalAuthPlugin, hybrid_property)
35 from rhodecode.authentication.base import RhodeCodeExternalAuthPlugin
36 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
36 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
37 from rhodecode.authentication.routes import AuthnPluginResourceBase
37 from rhodecode.authentication.routes import AuthnPluginResourceBase
38 from rhodecode.lib.colander_utils import strip_whitespace
38 from rhodecode.lib.colander_utils import strip_whitespace
@@ -25,9 +25,8 b' RhodeCode authentication plugin for buil'
25 import logging
25 import logging
26
26
27 from pylons.i18n.translation import lazy_ugettext as _
27 from pylons.i18n.translation import lazy_ugettext as _
28 from sqlalchemy.ext.hybrid import hybrid_property
29
28
30 from rhodecode.authentication.base import RhodeCodeAuthPluginBase
29 from rhodecode.authentication.base import RhodeCodeAuthPluginBase, hybrid_property
31 from rhodecode.authentication.routes import AuthnPluginResourceBase
30 from rhodecode.authentication.routes import AuthnPluginResourceBase
32 from rhodecode.lib.utils2 import safe_str
31 from rhodecode.lib.utils2 import safe_str
33 from rhodecode.model.db import User
32 from rhodecode.model.db import User
@@ -24,10 +24,9 b' RhodeCode authentication token plugin fo'
24
24
25 import logging
25 import logging
26
26
27 from sqlalchemy.ext.hybrid import hybrid_property
28
29 from rhodecode.translation import _
27 from rhodecode.translation import _
30 from rhodecode.authentication.base import RhodeCodeAuthPluginBase, VCS_TYPE
28 from rhodecode.authentication.base import (
29 RhodeCodeAuthPluginBase, VCS_TYPE, hybrid_property)
31 from rhodecode.authentication.routes import AuthnPluginResourceBase
30 from rhodecode.authentication.routes import AuthnPluginResourceBase
32 from rhodecode.model.db import User, UserApiKeys
31 from rhodecode.model.db import User, UserApiKeys
33
32
@@ -40,10 +40,11 b' class AuthnPluginSettingsSchemaBase(cola'
40 cache_ttl = colander.SchemaNode(
40 cache_ttl = colander.SchemaNode(
41 colander.Int(),
41 colander.Int(),
42 default=0,
42 default=0,
43 description=_('Amount of seconds to cache the authentication '
43 description=_('Amount of seconds to cache the authentication response'
44 'call for this plugin. Useful for long calls like '
44 'call for this plugin. \n'
45 'LDAP to improve the responsiveness of the '
45 'Useful for long calls like LDAP to improve the '
46 'authentication system (0 means disabled).'),
46 'performance of the authentication system '
47 '(0 means disabled).'),
47 missing=0,
48 missing=0,
48 title=_('Auth Cache TTL'),
49 title=_('Auth Cache TTL'),
49 validator=colander.Range(min=0, max=None),
50 validator=colander.Range(min=0, max=None),
@@ -57,7 +57,12 b' class RhodecodeEvent(object):'
57 def actor(self):
57 def actor(self):
58 auth_user = self.auth_user
58 auth_user = self.auth_user
59 if auth_user:
59 if auth_user:
60 return auth_user.get_instance()
60 instance = auth_user.get_instance()
61 if not instance:
62 return AttributeDict(dict(
63 username=auth_user.username
64 ))
65
61 return SYSTEM_USER
66 return SYSTEM_USER
62
67
63 @property
68 @property
@@ -61,6 +61,7 b''
61 .help-block {
61 .help-block {
62 display: block;
62 display: block;
63 margin-left: @label-width;
63 margin-left: @label-width;
64 white-space: pre;
64 }
65 }
65
66
66 .action_button {
67 .action_button {
@@ -116,7 +117,7 b''
116 float: none;
117 float: none;
117 margin-left: @label-width;
118 margin-left: @label-width;
118
119
119 .help-block{
120 .help-block {
120 margin-left: 0;
121 margin-left: 0;
121 }
122 }
122 }
123 }
@@ -111,6 +111,7 b''
111 $("#tls_kind").select2(select2Options);
111 $("#tls_kind").select2(select2Options);
112 $("#tls_reqcert").select2(select2Options);
112 $("#tls_reqcert").select2(select2Options);
113 $("#search_scope").select2(select2Options);
113 $("#search_scope").select2(select2Options);
114 $("#group_extraction_type").select2(select2Options);
114 });
115 });
115 </script>
116 </script>
116 </%def>
117 </%def>
General Comments 0
You need to be logged in to leave comments. Login now