Connect to geonode with LDAP account
Web app crash when user submit login and password
TypeError at /account/login/
sequence item 0: expected str instance, bytes found
Request Method: POST
Request URL: http://geonode-dev.aesn.fr/account/login/?next=/
Django Version: 2.2.12
Exception Type: TypeError
Exception Value:
sequence item 0: expected str instance, bytes found
Exception Location: /usr/local/lib/python3.7/site-packages/geonode_ldap/utils.py in get_ldap_groups_map, line 56
Python Executable: /usr/local/bin/uwsgi
Python Version: 3.7.6
Python Path:
['/usr/src/app',
'.',
'',
'/usr/local/lib/python37.zip',
'/usr/local/lib/python3.7',
'/usr/local/lib/python3.7/lib-dynload',
'/usr/local/lib/python3.7/site-packages',
'/usr/src/app']
Server time: ven, 6 Nov 2020 12:54:20 +0000
When I change line 55 in /usr/local/lib/python3.7/site-packages/geonode_ldap/utils.py like this:
Before
group_name = " ".join(
attributes[settings.LDAP_GROUP_NAME_ATTRIBUTE])
After
group_name = b" ".join(
attributes[settings.LDAP_GROUP_NAME_ATTRIBUTE])
Everything work fine (I have an error but it's my config : Group matching query does not exist. )
@naub1n thanks, I pushed your patch to geonode-contribs module
https://github.com/GeoNode/geonode-contribs/commit/ecb41e6319f00dd9308739463547ab5b78f22e1d
@afabiani wait! I have strange behavior
With original utils.py file.
When I login for the first time, web app crash.
But when I return to main page and I try again to login, everything is OK
When I logout and then loggin, it's OK.
I don't understand ...
Anything from the geonode logs?
I change the code like this:
Before:
group_name = " ".join(
attributes[settings.LDAP_GROUP_NAME_ATTRIBUTE])
After:
group_name = b" ".join(attributes[settings.LDAP_GROUP_NAME_ATTRIBUTE])
And I have the same error but not on the same line:
TypeError at /account/login/
sequence item 0: expected str instance, bytes found
Request Method: POST
Request URL: http://geonode-dev.aesn.fr/account/login/?next=/
Django Version: 2.2.12
Exception Type: TypeError
Exception Value:
sequence item 0: expected str instance, bytes found
Exception Location: /usr/local/lib/python3.7/site-packages/geonode_ldap/utils.py in get_ldap_groups_map, line 56
Python Executable: /usr/local/bin/uwsgi
Python Version: 3.7.6
Python Path:
['/usr/src/app',
'.',
'',
'/usr/local/lib/python37.zip',
'/usr/local/lib/python3.7',
'/usr/local/lib/python3.7/lib-dynload',
'/usr/local/lib/python3.7/site-packages',
'/usr/src/app']
Server time: ven, 6 Nov 2020 14:31:38 +0000
The geonode logs :
search_s('ou=agents,dc=aesn,dc=fr', 2, '(&(uid=%(user)s)(objectClass=person))') returned 1 objects: cn=nicolas aubin,ou=agents,dc=aesn,dc=fr
cn=nicolas aubin,ou=agents,dc=aesn,dc=fr does not have a value for the attribute mailPrimaryAddress
sequence item 0: expected str instance, bytes found while authenticating aubin_ni
Internal Server Error: /account/login/
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python3.7/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.7/site-packages/django/views/generic/base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/django/utils/decorators.py", line 45, in _wrapper
return bound_method(*args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/django/views/decorators/debug.py", line 76, in sensitive_post_parameters_wrapper
return view(request, *args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/allauth/account/views.py", line 138, in dispatch
return super(LoginView, self).dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/allauth/account/views.py", line 81, in dispatch
**kwargs)
File "/usr/local/lib/python3.7/site-packages/django/views/generic/base.py", line 97, in dispatch
return handler(request, *args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/allauth/account/views.py", line 103, in post
if form.is_valid():
File "/usr/local/lib/python3.7/site-packages/django/forms/forms.py", line 185, in is_valid
return self.is_bound and not self.errors
File "/usr/local/lib/python3.7/site-packages/django/forms/forms.py", line 180, in errors
self.full_clean()
File "/usr/local/lib/python3.7/site-packages/django/forms/forms.py", line 382, in full_clean
self._clean_form()
File "/usr/local/lib/python3.7/site-packages/django/forms/forms.py", line 409, in _clean_form
cleaned_data = self.clean()
File "/usr/local/lib/python3.7/site-packages/allauth/account/forms.py", line 179, in clean
**credentials)
File "/usr/local/lib/python3.7/site-packages/allauth/account/adapter.py", line 489, in authenticate
user = authenticate(request, **credentials)
File "/usr/local/lib/python3.7/site-packages/django/contrib/auth/__init__.py", line 73, in authenticate
user = backend.authenticate(request, **credentials)
File "/usr/local/lib/python3.7/site-packages/django_auth_ldap/backend.py", line 153, in authenticate
user = self.authenticate_ldap_user(ldap_user, password)
File "/usr/local/lib/python3.7/site-packages/geonode_ldap/backend.py", line 114, in authenticate_ldap_user
self._get_or_create_user(ldap_user)
File "/usr/local/lib/python3.7/site-packages/geonode_ldap/backend.py", line 184, in _get_or_create_user
self._mirror_groups(ldap_user)
File "/usr/local/lib/python3.7/site-packages/geonode_ldap/backend.py", line 194, in _mirror_groups
slug_map = utils.get_ldap_groups_map(user)
File "/usr/local/lib/python3.7/site-packages/geonode_ldap/utils.py", line 56, in get_ldap_groups_map
sanitized_name = sanitize_group_name(group_name)
TypeError: sequence item 0: expected str instance, bytes found
[pid: 996|app: 0|req: 14/172] 10.0.9.11 () {62 vars in 1339 bytes} [Fri Nov 6 14:31:38 2020] POST /account/login/?next=/ => generated 204586 bytes in 375 msecs (HTTP/1.1 500) 7 headers in 252 bytes (1 switches on core 0)
worker 9 lifetime reached, it was running for 3601 second(s)
worker 10 lifetime reached, it was running for 3601 second(s)
worker 11 lifetime reached, it was running for 3601 second(s)
worker 12 lifetime reached, it was running for 3601 second(s)
worker 13 lifetime reached, it was running for 3601 second(s)
worker 14 lifetime reached, it was running for 3601 second(s)
worker 15 lifetime reached, it was running for 3601 second(s)
worker 16 lifetime reached, it was running for 3601 second(s)
Respawned uWSGI worker 10 (new pid: 1254)
Respawned uWSGI worker 9 (new pid: 1255)
Respawned uWSGI worker 11 (new pid: 1256)
Respawned uWSGI worker 12 (new pid: 1257)
Respawned uWSGI worker 13 (new pid: 1258)
Respawned uWSGI worker 14 (new pid: 1259)
Respawned uWSGI worker 15 (new pid: 1260)
Respawned uWSGI worker 16 (new pid: 1261)
Try changing
sanitized_name = sanitize_group_name(group_name)
to
sanitized_name = sanitize_group_name(group_name.decode('UTF-8'))
I suspect docker volume.
I mount only local_settings.py from host file instead of mount /usr/src/app folder from samba share.
Everythings seems to work fine. No error when loggin for the first time.
However, there are another strange thing.
Django ignore variable LDAP_GROUP_PROFILE_MEMBER_ATTR=uniqueMember
geonode.log:
search_s('ou=agents,dc=aesn,dc=fr', 2, '(&(uid=%(user)s)(objectClass=person))') returned 1 objects: cn=nicolas aubin,ou=agents,dc=aesn,dc=fr
search_s('ou=groupes,dc=aesn,dc=fr', 2, '(&(cn=geonode)(|(member=cn=nicolas aubin,ou=agents,dc=aesn,dc=fr)))') returned 0 objects:
I will create a new issue for this.
cn=nicolas aubin,ou=agents,dc=aesn,dc=fr does not have a value for the attribute mailPrimaryAddress
sequence item 0: expected str instance, bytes found while authenticating aubin_ni
Any way to debug the contrib app? LDAP Auth is complicated and it is hard to see if the error resides in the geonode contrib code / the django LDAP code / or the LDAP directory you map to. For example there is no value for mailPrimaryAddress, which could lead null values and errors in the profile creation process.
@gannebamm this is not an error, it's like a Warning.
There is no mailPrimaryAddress in my LDAP test database. But it's not a problem, geonode can work without this value.
I will try new test this week when i will have little free time.
I did other tests:
staticsand dbdatavolumes/usr/src/app/usr/src/app/geonode/local_settings.pyEverything work fine with LDAP connexion.
CIFS volume was the problem.
Don't do that (where appis CIFS volume):
volumes:
- app:/usr/src/app
EDIT : mount CIFS is not a problem
@afabiani , I found other problem in utils.py
LDAPS groups no have same name in geonode after GeoNode/geonode-contribs@ecb41e6.
This is actual result:
>>> conn = ldap.initialize("ldap://openldap:389/")
>>> conn.simple_bind_s("cn=admin,dc=aesn,dc=fr","password")
(97, [], 1, [])
>>> remote_groups = conn.search_s(base="ou=groupes,dc=aesn,dc=fr",scope=ldap.SCOPE_SUBTREE,filterstr="(cn=geonode_admin)")
>>> print(remote_groups)
[('cn=geonode_admin,ou=groupes,dc=aesn,dc=fr', {'cn': [b'geonode_admin'], 'objectClass': [b'groupOfUniqueNames', b'top'], 'uniqueMember': [b'cn=Nicolas AUBIN,ou=agents,dc=aesn,dc=fr']})]
>>> result = {}
>>> for cn, attributes in remote_groups:
... group_name = b" ".join(attributes["cn"])
... sanitized_name = sanitize_group_name(group_name)
... result[slugify(sanitized_name)] = {"original": group_name,"sanitized": sanitized_name,}
...
>>> print(result)
{'bgeonode_admin': {'original': b'geonode_admin', 'sanitized': b'geonode_admin'}}
>>>
resultis a byte value and slugify(sanitized_name) have bad value ( bgeonode_admin)
To correct this problem, you can had .decode("utf-8") to group_name like this:
>>> conn = ldap.initialize("ldap://openldap:389/")
>>> conn.simple_bind_s("cn=admin,dc=aesn,dc=fr","password")
(97, [], 1, [])
>>> remote_groups = conn.search_s(base="ou=groupes,dc=aesn,dc=fr",scope=ldap.SCOPE_SUBTREE,filterstr="(cn=geonode_admin)")
>>> print(remote_groups)
[('cn=geonode_admin,ou=groupes,dc=aesn,dc=fr', {'cn': [b'geonode_admin'], 'objectClass': [b'groupOfUniqueNames', b'top'], 'uniqueMember': [b'cn=Nicolas AUBIN,ou=agents,dc=aesn,dc=fr']})]
>>> result = {}
>>> for cn, attributes in remote_groups:
... group_name = b" ".join(attributes["cn"]).decode("utf-8")
... sanitized_name = sanitize_group_name(group_name)
... result[slugify(sanitized_name)] = {"original": group_name,"sanitized": sanitized_name,}
...
>>> print(result)
{'geonode_admin': {'original': 'geonode_admin', 'sanitized': 'geonode_admin'}}
result is now a string value and LDAP groups names are correct in geonode
@naub1n it is sufficient to remove the 'b' in front of join
group_name = " ".join(attributes["cn"])
@afabiani no because remote_groups have bytes values and join can't work with string value.
>>> print(remote_groups)
[('cn=geonode_admin,ou=groupes,dc=aesn,dc=fr', {'cn': [b'geonode_admin'], 'objectClass': [b'groupOfUniqueNames', b'top'], 'uniqueMember': [b'cn=Nicolas AUBIN,ou=agents,dc=aesn,dc=fr']})]
This is why I had my first message error: TypeError: sequence item 0: expected str instance, bytes found
>>> conn = ldap.initialize("ldap://openldap:389/")
>>> conn.simple_bind_s("cn=admin,dc=aesn,dc=fr","password")
(97, [], 1, [])
>>> remote_groups = conn.search_s(base="ou=groupes,dc=aesn,dc=fr",scope=ldap.SCOPE_SUBTREE,filterstr="(cn=geonode_admin)")
>>> print(remote_groups)
[('cn=geonode_admin,ou=groupes,dc=aesn,dc=fr', {'cn': [b'geonode_admin'], 'objectClass': [b'groupOfUniqueNames', b'top'], 'uniqueMember': [b'cn=Nicolas AUBIN,ou=agents,dc=aesn,dc=fr']})]
>>> result = {}
>>> for cn, attributes in remote_groups:
... group_name = " ".join(attributes["cn"])
... sanitized_name = sanitize_group_name(group_name)
... result[slugify(sanitized_name)] = {"original": group_name,"sanitized": sanitized_name,}
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: sequence item 0: expected str instance, bytes found
>>> print(result)
{}
I see... pushing the change accordingly. Thanks for checking.
After testing, everything works fine.
mount CIFS volume /usr/src/app is not a problem
very good