Try ERPNext Buy Support Partners Foundation Foundation Members

Ldap3 type error after upgrade to Erpnext v11.1.42

Hello,

After upgrade to 11.1.42, the ldap connexion is not functionnal.(no problem with the previous version)

Softwares version
frappe@srv-web02:~/frappe-bench$ ./env/bin/pip3 list | grep ldap
Server Linux Debian Buster
ldap3 2.5.1
python3-ldap 0.9.8.4
ERPNext: v11.1.42 (master)
Frappe Framework: v11.1.37 (master)
frappe@srv-web02:~/frappe-bench$ python --version
Python 2.7.16

Ldap settings
Url du serveur LDAP : ldaps://dc1.domain.fr
“Distinguished Name” (DN) de base : cn=administrator,cn=users,dc=domain,dc=fr
Mot de passe pour la base DN : *************
Organizational Unit for Users : ou=domain,dc=domain,dc=fr
Champ Prénom LDAP : givenName
Default Role on Creation : Employee
LDAP Middle Name Field :
Chaine de recherche LDAP : userPrincipalName={0}
LDAP Last Name Field :
Champ Email LDAP : mail
LDAP Phone Field :
Champ Nom d’utilisateur LDAP : userPrincipalName
LDAP Mobile Field
SSL/TLS Mode : Off
Path to private Key File :
Require Trusted Certificate : Non
Path to Server Certificate :
Path to CA Certs File :
LDAP Group Field :

Logs frappe.log :

[ERROR] 2019-07-01 14:48:41,318 | /home/frappe/frappe-bench/apps/frappe/frappe/app.py:
Site: erp.domain.fr
Form Dict: {
“cmd”: “frappe.integrations.doctype.ldap_settings.ldap_settings.login”,
“device”: “desktop”,
“pwd”: “*********”,
“usr”: "lastname@domain.fr"
}
Request Error
Traceback (most recent call last):
File “/home/frappe/frappe-bench/apps/frappe/frappe/app.py”, line 61, in application
response = frappe.handler.handle()
File “/home/frappe/frappe-bench/apps/frappe/frappe/handler.py”, line 21, in handle
data = execute_cmd(cmd)
File “/home/frappe/frappe-bench/apps/frappe/frappe/handler.py”, line 56, in execute_cmd
return frappe.call(method, **frappe.form_dict)
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 1036, in call
return fn(*args, **newargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/integrations/doctype/ldap_settings/ldap_settings.py”, line 200, in login
user = ldap.authenticate(frappe.as_unicode(args.usr), frappe.as_unicode(args.pwd))
File “/home/frappe/frappe-bench/apps/frappe/frappe/integrations/doctype/ldap_settings/ldap_settings.py”, line 166, in authenticate
return self.create_or_update_user(self.convert_ldap_entry_to_dict(user), groups=groups)
File “/home/frappe/frappe-bench/apps/frappe/frappe/integrations/doctype/ldap_settings/ldap_settings.py”, line 120, in create_or_update_user
self.sync_roles(user, groups)
File “/home/frappe/frappe-bench/apps/frappe/frappe/integrations/doctype/ldap_settings/ldap_settings.py”, line 88, in sync_roles
lower_groups = [g.lower() for g in additional_groups]
TypeError: ‘NoneType’ object is not iterable
[ERROR] 2019-07-01 14:48:41,322 | /home/frappe/frappe-bench/apps/frappe/frappe/utils/error.py:
Could not take error snapshot: startswith first arg must be str or a tuple of str, not bytes
Traceback (most recent call last):
File “/home/frappe/frappe-bench/apps/frappe/frappe/app.py”, line 61, in application
response = frappe.handler.handle()
File “/home/frappe/frappe-bench/apps/frappe/frappe/handler.py”, line 21, in handle
data = execute_cmd(cmd)
File “/home/frappe/frappe-bench/apps/frappe/frappe/handler.py”, line 56, in execute_cmd
return frappe.call(method, **frappe.form_dict)
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 1036, in call
return fn(*args, **newargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/integrations/doctype/ldap_settings/ldap_settings.py”, line 200, in login
user = ldap.authenticate(frappe.as_unicode(args.usr), frappe.as_unicode(args.pwd))
File “/home/frappe/frappe-bench/apps/frappe/frappe/integrations/doctype/ldap_settings/ldap_settings.py”, line 166, in authenticate
return self.create_or_update_user(self.convert_ldap_entry_to_dict(user), groups=groups)
File “/home/frappe/frappe-bench/apps/frappe/frappe/integrations/doctype/ldap_settings/ldap_settings.py”, line 120, in create_or_update_user
self.sync_roles(user, groups)
File “/home/frappe/frappe-bench/apps/frappe/frappe/integrations/doctype/ldap_settings/ldap_settings.py”, line 88, in sync_roles
lower_groups = [g.lower() for g in additional_groups]
TypeError: ‘NoneType’ object is not iterable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/error.py”, line 36, in make_error_snapshot
snapshot = get_snapshot(exception)
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/error.py”, line 131, in get_snapshot
# render multilingual string properly
TypeError: startswith first arg must be str or a tuple of str, not bytes
[DEBUG] 2019-07-01 14:48:42,154 | /home/frappe/frappe-bench/apps/frappe/frappe/utils/scheduler.py:

Thank you

Try a

bench clear-cache

Not sure if you’ll need to run the update again, but that is easy enough to try out if the cache is not helping

Hello trentmu,

Thank you, but I have already try this command :

frappe@srv-web02:~/frappe-bench$ bench clear-cache
Traceback (most recent call last):
File “/home/frappe/frappe-bench/env/lib/python3.7/site-packages/werkzeug/local.py”, line 72, in getattr
return self.storage[self.ident_func()][name]
KeyError: ‘conf’

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “/usr/lib/python3.7/runpy.py”, line 193, in _run_module_as_main
main”, mod_spec)
File “/usr/lib/python3.7/runpy.py”, line 85, in _run_code
exec(code, run_globals)
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/bench_helper.py”, line 97, in
main()
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/bench_helper.py”, line 18, in main
click.Group(commands=commands)(prog_name=‘bench’)
File “/home/frappe/frappe-bench/env/lib/python3.7/site-packages/click/core.py”, line 764, in call
return self.main(*args, **kwargs)
File “/home/frappe/frappe-bench/env/lib/python3.7/site-packages/click/core.py”, line 717, in main
rv = self.invoke(ctx)
File “/home/frappe/frappe-bench/env/lib/python3.7/site-packages/click/core.py”, line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File “/home/frappe/frappe-bench/env/lib/python3.7/site-packages/click/core.py”, line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File “/home/frappe/frappe-bench/env/lib/python3.7/site-packages/click/core.py”, line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File “/home/frappe/frappe-bench/env/lib/python3.7/site-packages/click/core.py”, line 555, in invoke
return callback(*args, **kwargs)
File “/home/frappe/frappe-bench/env/lib/python3.7/site-packages/click/decorators.py”, line 17, in new_func
return f(get_current_context(), *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/commands/init.py”, line 25, in _func
ret = f(frappe._dict(ctx.obj), *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/commands/utils.py”, line 47, in clear_cache
frappe.connect(site)
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 187, in connect
local.db = Database(user=db_name or local.conf.db_name)
File “/home/frappe/frappe-bench/env/lib/python3.7/site-packages/werkzeug/local.py”, line 74, in getattr
raise AttributeError(name)
AttributeError: conf

This command runs without error but does not correct the problem :
frappe@srv-web02:~/frappe-bench$ bench --site all clear-cache
frappe@srv-web02:~/frappe-bench$

I’m having the same issue with v11.1.42. Standard login is working but LDAP fails with the same error.

I have found a solution. I think it is a bug. You can’t have empty LDAP Group Field in LDAP Settings. I’m not sure what is a valid value here. I get a different error if I put gidNumber that is integer:

File "/home/frappe/frappe-bench/apps/frappe/frappe/integrations/doctype/ldap_settings/ldap_settings.py", line 88, in sync_roles
 lower_groups = [g.lower() for g in additional_groups]

It’s doing .lower() conversion here, so my guess is that accepts strings only.

I put cn as LDAP Group Field, as I know this is a string, although probably the wrong one.

Can someone give a hint what this value should be?
We use OpenLDAP server with
ou=groups, cn=[group name], memberUid - a list of users that are members of this group

ou=users, there is an attribute gidNumber (id of default group).

I would like to use this feature and assign roles according to LDAP Group the users belongs to.

Hello bab1ch,

Thank you very much, you’re right.
Like you, I put “cn” as LDAP Group Field (very generic attribute)
Adding the role associated with the group does not activate the role to the LDAP user.

Hi there, see https://user-images.githubusercontent.com/3469512/58928456-1db03c80-8785-11e9-800d-1d2d532745e6.gif for an example, I haven’t got around to updating the docs yet.
Using an atrribute like cn isn’t how it works, what your looking for is the attribute that holds all the groups the user is in. For example in Active Directory it is memberOf.
Then you specify the DN of the group, and then it will match…

PS Openldap seems to be named the same
It seems you may need to enable some stuff (or this may be old info)
https://www.adimian.com/blog/2014/10/how-to-enable-memberof-using-openldap/

Hello,
In ADSI Edit the attribute memberOf is not present in the user’s properties (AD Samba version 4.5.12-Debian)
But ldapsearch work with the filter memberOf :
ldapsearch -T /tmp -h dc.domain.fr -Y GSSAPI -U ‘administrator@domain.fr’ -b “ou=entity,dc=domain,dc=fr” “(&(CN=*)(memberOf=CN=group1,OU=groups,OU=entity,DC=domain,DC=fr))” cn

cn : user1
cn : user2

So I add memberOf in the LDAP Group Field and “CN=group1,OU=groups,OU=entity,DC=domain,DC=fr” like LDAP Group associated with a test ERPNext Role.
I disable all user’s previous privileges defined in ERPNext and everythings works as expected.

pgx,

What were the changes you made to run erpnext on debian 10?
I would love to upgrade to buster.

NoobieWanKenobie,

My Erpnext server is installed on a vm KVM with mariadb on the same server.
Don’t forget to backup your server before upgrade or better yet create a new vm for testing.
I encountered a compatibility problem between ldap and python :