##// END OF EJS Templates
feat(configs): deprecared old hooks protocol and ssh wrapper....
feat(configs): deprecared old hooks protocol and ssh wrapper. New defaults are now set on v2 keys, so previous installation are automatically set to new keys. Fallback mode is still available.

File last commit:

r5397:46138ab9 default
r5496:cab50adf default
Show More
auth_ldap.py
550 lines | 20.4 KiB | text/x-python | PythonLexer
copyrights: updated for 2023
r5088 # Copyright (C) 2010-2023 RhodeCode GmbH
project: added all source files and assets
r1 #
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
"""
RhodeCode authentication plugin for LDAP
"""
import logging
import traceback
ldap: use connection ping only in case of single server specifed.
r2736 import colander
auth: refactor code and simplified instructions....
r1454 from rhodecode.translation import _
from rhodecode.authentication.base import (
ldap: use connection ping only in case of single server specifed.
r2736 RhodeCodeExternalAuthPlugin, AuthLdapBase, hybrid_property)
feat(2fa): added 2fa for more auth plugins and moved 2fa forced functionality to ee edition. Fixes: RCCE-68
r5397 from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase, TwoFactorAuthnPluginSettingsSchemaMixin
project: added all source files and assets
r1 from rhodecode.authentication.routes import AuthnPluginResourceBase
authn: Add whitespace stripping to authentication plugin settings.
r55 from rhodecode.lib.colander_utils import strip_whitespace
project: added all source files and assets
r1 from rhodecode.lib.exceptions import (
LdapConnectionError, LdapUsernameError, LdapPasswordError, LdapImportError
)
authentication: fixed for python3 migrations
r5057 from rhodecode.lib.str_utils import safe_str
project: added all source files and assets
r1 from rhodecode.model.db import User
from rhodecode.model.validators import Missing
log = logging.getLogger(__name__)
try:
import ldap
except ImportError:
ldap-auth: fixed wrong Missing check
r126 # means that python-ldap is not installed, we use Missing object to mark
# ldap lib is Missing
ldap = Missing
project: added all source files and assets
r1
ldap: enable connection recycling on LDAP plugin.
r2575 class LdapError(Exception):
pass
email: added help block on where to change email settings
r2725
auth: add better logging for ldap related attributes to help track problems
r3271 def plugin_factory(plugin_id, *args, **kwargs):
project: added all source files and assets
r1 """
Factory function that is called during plugin discovery.
It returns the plugin instance.
"""
plugin = RhodeCodeAuthPlugin(plugin_id)
return plugin
class LdapAuthnResource(AuthnPluginResourceBase):
pass
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 class AuthLdap(AuthLdapBase):
default_tls_cert_dir = '/etc/openldap/cacerts'
ldap: changed plugin to help with debugging and error handling....
r4303 scope_labels = {
ldap.SCOPE_BASE: 'SCOPE_BASE',
ldap.SCOPE_ONELEVEL: 'SCOPE_ONELEVEL',
ldap.SCOPE_SUBTREE: 'SCOPE_SUBTREE',
}
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='',
tls_kind='PLAIN', tls_reqcert='DEMAND', tls_cert_file=None,
tls_cert_dir=None, ldap_version=3,
search_scope='SUBTREE', attr_login='uid',
ldap_filter='', timeout=None):
if ldap == Missing:
raise LdapImportError("Missing or incompatible ldap library")
self.debug = False
self.timeout = timeout or 60 * 5
self.ldap_version = ldap_version
self.ldap_server_type = 'ldap'
self.TLS_KIND = tls_kind
if self.TLS_KIND == 'LDAPS':
ldap: fixed ldaps port example to correct number.
r4296 port = port or 636
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 self.ldap_server_type += 's'
OPT_X_TLS_DEMAND = 2
self.TLS_REQCERT = getattr(ldap, 'OPT_X_TLS_%s' % tls_reqcert, OPT_X_TLS_DEMAND)
self.TLS_CERT_FILE = tls_cert_file or ''
self.TLS_CERT_DIR = tls_cert_dir or self.default_tls_cert_dir
# split server into list
self.SERVER_ADDRESSES = self._get_server_list(server)
self.LDAP_SERVER_PORT = port
# USE FOR READ ONLY BIND TO LDAP SERVER
self.attr_login = attr_login
self.LDAP_BIND_DN = safe_str(bind_dn)
self.LDAP_BIND_PASS = safe_str(bind_pass)
self.SEARCH_SCOPE = getattr(ldap, 'SCOPE_%s' % search_scope)
self.BASE_DN = safe_str(base_dn)
self.LDAP_FILTER = safe_str(ldap_filter)
def _get_ldap_conn(self):
if self.debug:
ldap.set_option(ldap.OPT_DEBUG_LEVEL, 255)
if self.TLS_CERT_FILE and hasattr(ldap, 'OPT_X_TLS_CACERTFILE'):
ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, self.TLS_CERT_FILE)
elif hasattr(ldap, 'OPT_X_TLS_CACERTDIR'):
ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, self.TLS_CERT_DIR)
if self.TLS_KIND != 'PLAIN':
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, self.TLS_REQCERT)
ldap.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF)
ldap.set_option(ldap.OPT_RESTART, ldap.OPT_ON)
# init connection now
ldap_servers = self._build_servers(
self.ldap_server_type, self.SERVER_ADDRESSES, self.LDAP_SERVER_PORT)
log.debug('initializing LDAP connection to:%s', ldap_servers)
ldap_conn = ldap.initialize(ldap_servers)
ldap_conn.set_option(ldap.OPT_NETWORK_TIMEOUT, self.timeout)
ldap_conn.set_option(ldap.OPT_TIMEOUT, self.timeout)
ldap_conn.timeout = self.timeout
if self.ldap_version == 2:
ldap_conn.protocol = ldap.VERSION2
else:
ldap_conn.protocol = ldap.VERSION3
if self.TLS_KIND == 'START_TLS':
ldap_conn.start_tls_s()
if self.LDAP_BIND_DN and self.LDAP_BIND_PASS:
auth: add better logging for ldap related attributes to help track problems
r3271 log.debug('Trying simple_bind with password and given login DN: %r',
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 self.LDAP_BIND_DN)
ldap_conn.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS)
ldap: logging fixes
r4244 log.debug('simple_bind successful')
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 return ldap_conn
ldap: changed plugin to help with debugging and error handling....
r4303 def fetch_attrs_from_simple_bind(self, ldap_conn, dn, username, password):
scope = ldap.SCOPE_BASE
scope_label = self.scope_labels.get(scope)
ldap_filter = '(objectClass=*)'
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 try:
ldap: changed plugin to help with debugging and error handling....
r4303 log.debug('Trying authenticated search bind with dn: %r SCOPE: %s (and filter: %s)',
dn, scope_label, ldap_filter)
ldap_conn.simple_bind_s(dn, safe_str(password))
response = ldap_conn.search_ext_s(dn, scope, ldap_filter, attrlist=['*', '+'])
ldap: logging fixes
r4244
ldap: changed plugin to help with debugging and error handling....
r4303 if not response:
log.error('search bind returned empty results: %r', response)
return {}
else:
_dn, attrs = response[0]
return attrs
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235
except ldap.INVALID_CREDENTIALS:
ldap: changed plugin to help with debugging and error handling....
r4303 log.debug("LDAP rejected password for user '%s': %s, org_exc:",
username, dn, exc_info=True)
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235
def authenticate_ldap(self, username, password):
"""
Authenticate a user via LDAP and return his/her LDAP properties.
Raises AuthenticationError if the credentials are rejected, or
EnvironmentError if the LDAP server can't be reached.
:param username: username
:param password: password
"""
uid = self.get_uid(username, self.SERVER_ADDRESSES)
user_attrs = {}
dn = ''
self.validate_password(username, password)
self.validate_username(username)
ldap: changed plugin to help with debugging and error handling....
r4303 scope_label = self.scope_labels.get(self.SEARCH_SCOPE)
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235
ldap_conn = None
try:
ldap_conn = self._get_ldap_conn()
ldap: small fixes and improvements over ldap authentication
r5140 filter_ = '(&{}({}={}))'.format(
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 self.LDAP_FILTER, self.attr_login, username)
ldap: changed plugin to help with debugging and error handling....
r4303 log.debug("Authenticating %r filter %s and scope: %s",
self.BASE_DN, filter_, scope_label)
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235
ldap: changed plugin to help with debugging and error handling....
r4303 ldap_objects = ldap_conn.search_ext_s(
self.BASE_DN, self.SEARCH_SCOPE, filter_, attrlist=['*', '+'])
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235
ldap: changed plugin to help with debugging and error handling....
r4303 if not ldap_objects:
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 log.debug("No matching LDAP objects for authentication "
"of UID:'%s' username:(%s)", uid, username)
raise ldap.NO_SUCH_OBJECT()
ldap: changed plugin to help with debugging and error handling....
r4303 log.debug('Found %s matching ldap object[s], trying to authenticate on each one now...', len(ldap_objects))
for (dn, _attrs) in ldap_objects:
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 if dn is None:
continue
user_attrs = self.fetch_attrs_from_simple_bind(
ldap_conn, dn, username, password)
ldap: changed plugin to help with debugging and error handling....
r4303
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 if user_attrs:
ldap: changed plugin to help with debugging and error handling....
r4303 log.debug('Got authenticated user attributes from DN:%s', dn)
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 break
else:
raise LdapPasswordError(
authentication: run modernize for python3
r5094 f'Failed to authenticate user `{username}` with given password')
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235
except ldap.NO_SUCH_OBJECT:
log.debug("LDAP says no such user '%s' (%s), org_exc:",
uid, username, exc_info=True)
raise LdapUsernameError('Unable to find user')
except ldap.SERVER_DOWN:
org_exc = traceback.format_exc()
raise LdapConnectionError(
ldap: changed plugin to help with debugging and error handling....
r4303 "LDAP can't access authentication server, org_exc:%s" % org_exc)
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 finally:
if ldap_conn:
log.debug('ldap: connection release')
try:
ldap_conn.unbind_s()
except Exception:
# for any reason this can raise exception we must catch it
# to not crush the server
pass
return dn, user_attrs
feat(2fa): added 2fa for more auth plugins and moved 2fa forced functionality to ee edition. Fixes: RCCE-68
r5397 class LdapSettingsSchema(TwoFactorAuthnPluginSettingsSchemaMixin, AuthnPluginSettingsSchemaBase):
project: added all source files and assets
r1 tls_kind_choices = ['PLAIN', 'LDAPS', 'START_TLS']
tls_reqcert_choices = ['NEVER', 'ALLOW', 'TRY', 'DEMAND', 'HARD']
search_scope_choices = ['BASE', 'ONELEVEL', 'SUBTREE']
host = colander.SchemaNode(
colander.String(),
default='',
auth-plugins: updated description on auth_ldap plugin servers.
r1772 description=_('Host[s] of the LDAP Server \n'
'(e.g., 192.168.2.154, or ldap-server.domain.com.\n '
'Multiple servers can be specified using commas'),
authn: Add whitespace stripping to authentication plugin settings.
r55 preparer=strip_whitespace,
project: added all source files and assets
r1 title=_('LDAP Host'),
widget='string')
port = colander.SchemaNode(
colander.Int(),
default=389,
auth-plugins: updated description on auth_ldap plugin servers.
r1772 description=_('Custom port that the LDAP server is listening on. '
ldap: fixed ldaps port example to correct number.
r4296 'Default value is: 389, use 636 for LDAPS (SSL)'),
authn: Add whitespace stripping to authentication plugin settings.
r55 preparer=strip_whitespace,
project: added all source files and assets
r1 title=_('Port'),
validator=colander.Range(min=0, max=65536),
widget='int')
auth-ldap: added connection pinning and timeout option to ldap plugin
r2654
timeout = colander.SchemaNode(
colander.Int(),
default=60 * 5,
description=_('Timeout for LDAP connection'),
preparer=strip_whitespace,
title=_('Connection timeout'),
validator=colander.Range(min=1),
widget='int')
project: added all source files and assets
r1 dn_user = colander.SchemaNode(
colander.String(),
default='',
auth: refactor code and simplified instructions....
r1454 description=_('Optional user DN/account to connect to LDAP if authentication is required. \n'
'e.g., cn=admin,dc=mydomain,dc=com, or '
'uid=root,cn=users,dc=mydomain,dc=com, or admin@mydomain.com'),
project: added all source files and assets
r1 missing='',
authn: Add whitespace stripping to authentication plugin settings.
r55 preparer=strip_whitespace,
ldap: logging fixes
r4244 title=_('Bind account'),
project: added all source files and assets
r1 widget='string')
dn_pass = colander.SchemaNode(
colander.String(),
default='',
auth: refactor code and simplified instructions....
r1454 description=_('Password to authenticate for given user DN.'),
project: added all source files and assets
r1 missing='',
authn: Add whitespace stripping to authentication plugin settings.
r55 preparer=strip_whitespace,
ldap: logging fixes
r4244 title=_('Bind account password'),
project: added all source files and assets
r1 widget='password')
tls_kind = colander.SchemaNode(
colander.String(),
default=tls_kind_choices[0],
description=_('TLS Type'),
title=_('Connection Security'),
validator=colander.OneOf(tls_kind_choices),
widget='select')
tls_reqcert = colander.SchemaNode(
colander.String(),
default=tls_reqcert_choices[0],
ldap: addedn info about custom certificates option
r1744 description=_('Require Cert over TLS?. Self-signed and custom '
'certificates can be used when\n `RhodeCode Certificate` '
'found in admin > settings > system info page is extended.'),
project: added all source files and assets
r1 title=_('Certificate Checks'),
validator=colander.OneOf(tls_reqcert_choices),
widget='select')
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 tls_cert_file = colander.SchemaNode(
colander.String(),
default='',
description=_('This specifies the PEM-format file path containing '
'certificates for use in TLS connection.\n'
'If not specified `TLS Cert dir` will be used'),
title=_('TLS Cert file'),
missing='',
widget='string')
tls_cert_dir = colander.SchemaNode(
colander.String(),
default=AuthLdap.default_tls_cert_dir,
description=_('This specifies the path of a directory that contains individual '
'CA certificates in separate files.'),
title=_('TLS Cert dir'),
widget='string')
project: added all source files and assets
r1 base_dn = colander.SchemaNode(
colander.String(),
default='',
auth: refactor code and simplified instructions....
r1454 description=_('Base DN to search. Dynamic bind is supported. Add `$login` marker '
ldap: logging fixes
r4244 'in it to be replaced with current user username \n'
auth: refactor code and simplified instructions....
r1454 '(e.g., dc=mydomain,dc=com, or ou=Users,dc=mydomain,dc=com)'),
project: added all source files and assets
r1 missing='',
authn: Add whitespace stripping to authentication plugin settings.
r55 preparer=strip_whitespace,
project: added all source files and assets
r1 title=_('Base DN'),
widget='string')
filter = colander.SchemaNode(
colander.String(),
default='',
auth: refactor code and simplified instructions....
r1454 description=_('Filter to narrow results \n'
'(e.g., (&(objectCategory=Person)(objectClass=user)), or \n'
'(memberof=cn=rc-login,ou=groups,ou=company,dc=mydomain,dc=com)))'),
project: added all source files and assets
r1 missing='',
authn: Add whitespace stripping to authentication plugin settings.
r55 preparer=strip_whitespace,
project: added all source files and assets
r1 title=_('LDAP Search Filter'),
widget='string')
auth: refactor code and simplified instructions....
r1454
project: added all source files and assets
r1 search_scope = colander.SchemaNode(
colander.String(),
auth: refactor code and simplified instructions....
r1454 default=search_scope_choices[2],
description=_('How deep to search LDAP. If unsure set to SUBTREE'),
project: added all source files and assets
r1 title=_('LDAP Search Scope'),
validator=colander.OneOf(search_scope_choices),
widget='select')
attr_login = colander.SchemaNode(
colander.String(),
auth: refactor code and simplified instructions....
r1454 default='uid',
description=_('LDAP Attribute to map to user name (e.g., uid, or sAMAccountName)'),
authn: Add whitespace stripping to authentication plugin settings.
r55 preparer=strip_whitespace,
project: added all source files and assets
r1 title=_('Login Attribute'),
auth-ldap: added flag to set debug mode for LDAP connections.
r499 missing_msg=_('The LDAP Login attribute of the CN must be specified'),
project: added all source files and assets
r1 widget='string')
auth-plugins: updated some code for better unicode compat.
r3256 attr_email = colander.SchemaNode(
colander.String(),
default='',
description=_('LDAP Attribute to map to email address (e.g., mail).\n'
'Emails are a crucial part of RhodeCode. \n'
'If possible add a valid email attribute to ldap users.'),
missing='',
preparer=strip_whitespace,
title=_('Email Attribute'),
widget='string')
project: added all source files and assets
r1 attr_firstname = colander.SchemaNode(
colander.String(),
default='',
auth: refactor code and simplified instructions....
r1454 description=_('LDAP Attribute to map to first name (e.g., givenName)'),
project: added all source files and assets
r1 missing='',
authn: Add whitespace stripping to authentication plugin settings.
r55 preparer=strip_whitespace,
project: added all source files and assets
r1 title=_('First Name Attribute'),
widget='string')
attr_lastname = colander.SchemaNode(
colander.String(),
default='',
auth: refactor code and simplified instructions....
r1454 description=_('LDAP Attribute to map to last name (e.g., sn)'),
project: added all source files and assets
r1 missing='',
authn: Add whitespace stripping to authentication plugin settings.
r55 preparer=strip_whitespace,
project: added all source files and assets
r1 title=_('Last Name Attribute'),
widget='string')
class RhodeCodeAuthPlugin(RhodeCodeExternalAuthPlugin):
authentication: use registerd UID for plugin definition for more consistent loading of auth plugins.
r3246 uid = 'ldap'
project: added all source files and assets
r1 # used to define dynamic binding in the
DYNAMIC_BIND_VAR = '$login'
auth-plugins: define unsafe settings
r1623 _settings_unsafe_keys = ['dn_pass']
project: added all source files and assets
r1
def includeme(self, config):
config.add_authn_plugin(self)
config.add_authn_resource(self.get_id(), LdapAuthnResource(self))
config.add_view(
'rhodecode.authentication.views.AuthnPluginViewBase',
attr='settings_get',
templating: use .mako as extensions for template files.
r1282 renderer='rhodecode:templates/admin/auth/plugin_settings.mako',
project: added all source files and assets
r1 request_method='GET',
route_name='auth_home',
context=LdapAuthnResource)
config.add_view(
'rhodecode.authentication.views.AuthnPluginViewBase',
attr='settings_post',
templating: use .mako as extensions for template files.
r1282 renderer='rhodecode:templates/admin/auth/plugin_settings.mako',
project: added all source files and assets
r1 request_method='POST',
route_name='auth_home',
context=LdapAuthnResource)
def get_settings_schema(self):
return LdapSettingsSchema()
auth: allow custom name for plugins if defined in the settings.
r4545 def get_display_name(self, load_from_settings=False):
project: added all source files and assets
r1 return _('LDAP')
auth-plugins: expose docs and icon methods for authentication.
r3232 @classmethod
def docs(cls):
return "https://docs.rhodecode.com/RhodeCode-Enterprise/auth/auth-ldap.html"
project: added all source files and assets
r1 @hybrid_property
def name(self):
authentication: run modernize for python3
r5094 return "ldap"
project: added all source files and assets
r1
def use_fake_password(self):
return True
def user_activation_state(self):
users: make AuthUser propert a method, and allow override of params.
r1997 def_user_perms = User.get_default_user().AuthUser().permissions['global']
project: added all source files and assets
r1 return 'hg.extern_activate.auto' in def_user_perms
def try_dynamic_binding(self, username, password, current_args):
"""
Detects marker inside our original bind, and uses dynamic auth if
present
"""
org_bind = current_args['bind_dn']
passwd = current_args['bind_pass']
ldap: small fixes and improvements over ldap authentication
r5140 def has_bind_marker(_username):
if self.DYNAMIC_BIND_VAR in _username:
project: added all source files and assets
r1 return True
# we only passed in user with "special" variable
if org_bind and has_bind_marker(org_bind) and not passwd:
log.debug('Using dynamic user/password binding for ldap '
'authentication. Replacing `%s` with username',
self.DYNAMIC_BIND_VAR)
current_args['bind_dn'] = org_bind.replace(
self.DYNAMIC_BIND_VAR, username)
current_args['bind_pass'] = password
return current_args
def auth(self, userobj, username, password, settings, **kwargs):
"""
Given a user object (which may be null), username, a plaintext password,
and a settings object (containing all the keys needed as listed in
settings()), authenticate this user's login attempt.
Return None on failure. On success, return a dictionary of the form:
see: RhodeCodeAuthPluginBase.auth_func_attrs
This is later validated for correctness
"""
if not username or not password:
log.debug('Empty username or password skipping...')
return None
ldap_args = {
'server': settings.get('host', ''),
'base_dn': settings.get('base_dn', ''),
'port': settings.get('port'),
'bind_dn': settings.get('dn_user'),
'bind_pass': settings.get('dn_pass'),
'tls_kind': settings.get('tls_kind'),
'tls_reqcert': settings.get('tls_reqcert'),
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235 'tls_cert_file': settings.get('tls_cert_file'),
'tls_cert_dir': settings.get('tls_cert_dir'),
project: added all source files and assets
r1 'search_scope': settings.get('search_scope'),
'attr_login': settings.get('attr_login'),
'ldap_version': 3,
'ldap_filter': settings.get('filter'),
auth-ldap: added connection pinning and timeout option to ldap plugin
r2654 'timeout': settings.get('timeout')
project: added all source files and assets
r1 }
ldap_attrs = self.try_dynamic_binding(username, password, ldap_args)
log.debug('Checking for ldap authentication.')
try:
ldap: small fixes and improvements over ldap authentication
r5140 auth_ldap = AuthLdap(**ldap_args)
(user_dn, ldap_attrs) = auth_ldap.authenticate_ldap(username, password)
project: added all source files and assets
r1 log.debug('Got ldap DN response %s', user_dn)
ldap: small fixes and improvements over ldap authentication
r5140 def get_ldap_attr(k) -> str:
return safe_str(ldap_attrs.get(settings.get(k), [b''])[0])
project: added all source files and assets
r1
# old attrs fetched from RhodeCode database
admin = getattr(userobj, 'admin', False)
active = getattr(userobj, 'active', True)
email = getattr(userobj, 'email', '')
username = getattr(userobj, 'username', username)
firstname = getattr(userobj, 'firstname', '')
lastname = getattr(userobj, 'lastname', '')
extern_type = getattr(userobj, 'extern_type', '')
groups = []
auth: add better logging for ldap related attributes to help track problems
r3271
project: added all source files and assets
r1 user_attrs = {
'username': username,
ldap: small fixes and improvements over ldap authentication
r5140 'firstname': get_ldap_attr('attr_firstname') or firstname,
'lastname': get_ldap_attr('attr_lastname') or lastname,
project: added all source files and assets
r1 'groups': groups,
authentication: introduce a group sync flag for plugins....
r2495 'user_group_sync': False,
ldap: fixed email extraction typo. An empty...
r886 'email': get_ldap_attr('attr_email') or email,
project: added all source files and assets
r1 'admin': admin,
'active': active,
auth: refactor code and simplified instructions....
r1454 'active_from_extern': None,
project: added all source files and assets
r1 'extern_name': user_dn,
'extern_type': extern_type,
}
ldap: adde common ldap-ce na ldap-ee structure, and extend options...
r3235
authn: don't use formatted_json to log statements. It totally screws up...
r12 log.debug('ldap user: %s', user_attrs)
logging: expose extra metadata to various important logs for loki
r4816 log.info('user `%s` authenticated correctly', user_attrs['username'],
logging: changed module in logs extra as it is a reserved keyword
r4818 extra={"action": "user_auth_ok", "auth_module": "auth_ldap", "username": user_attrs["username"]})
project: added all source files and assets
r1
return user_attrs
except (LdapUsernameError, LdapPasswordError, LdapImportError):
log.exception("LDAP related exception")
return None
except (Exception,):
log.exception("Other exception")
return None
core: change from homebrew plugin system into pyramid machinery....
r3240
def includeme(config):
authentication: run modernize for python3
r5094 plugin_id = f'egg:rhodecode-enterprise-ce#{RhodeCodeAuthPlugin.uid}'
core: change from homebrew plugin system into pyramid machinery....
r3240 plugin_factory(plugin_id).includeme(config)