@@ -257,6 +257,8 @@ def __init__(self, appbuilder):
257257 app .config .setdefault ("AUTH_LDAP_FIRSTNAME_FIELD" , "givenName" )
258258 app .config .setdefault ("AUTH_LDAP_LASTNAME_FIELD" , "sn" )
259259 app .config .setdefault ("AUTH_LDAP_EMAIL_FIELD" , "mail" )
260+ # Nested groups options
261+ app .config .setdefault ("AUTH_LDAP_USE_NESTED_GROUPS_FOR_ROLES" , False )
260262
261263 # Rate limiting
262264 app .config .setdefault ("AUTH_RATE_LIMITED" , False )
@@ -495,6 +497,10 @@ def auth_ldap_tls_certfile(self):
495497 def auth_ldap_tls_keyfile (self ):
496498 return self .appbuilder .get_app .config ["AUTH_LDAP_TLS_KEYFILE" ]
497499
500+ @property
501+ def auth_ldap_use_nested_groups_for_roles (self ):
502+ return self .appbuilder .get_app .config ["AUTH_LDAP_USE_NESTED_GROUPS_FOR_ROLES" ]
503+
498504 @property
499505 def openid_providers (self ):
500506 return self .appbuilder .get_app .config ["OPENID_PROVIDERS" ]
@@ -963,11 +969,36 @@ def _search_ldap(self, ldap, con, username):
963969 user_dn = search_result [0 ][0 ]
964970 # extract the other attributes
965971 user_info = search_result [0 ][1 ]
966- # return
967- return user_dn , user_info
968972 except (IndexError , NameError ):
969973 return None , None
970974
975+ # get nested groups for user
976+ if self .auth_ldap_use_nested_groups_for_roles :
977+ log .debug ("Nested groups for LDAP enabled." )
978+ # filter for microsoft active directory only
979+ nested_groups_filter_str = (
980+ f"(&(objectCategory=Group)(member:1.2.840.113556.1.4.1941:={ user_dn } ))"
981+ )
982+ nested_groups_request_fields = ["cn" ]
983+
984+ nested_groups_search_result = con .search_s (
985+ self .auth_ldap_search ,
986+ ldap .SCOPE_SUBTREE ,
987+ nested_groups_filter_str ,
988+ nested_groups_request_fields ,
989+ )
990+ log .debug ("LDAP search for nested groups returned: %s" , nested_groups_search_result )
991+
992+ nested_groups = [
993+ x [0 ].encode () for x in nested_groups_search_result if x [0 ] is not None
994+ ]
995+ log .debug ("LDAP nested groups for users: %s" , nested_groups )
996+
997+ user_info [self .auth_ldap_group_field ] = nested_groups
998+
999+ # return
1000+ return user_dn , user_info
1001+
9711002 def _ldap_calculate_user_roles (
9721003 self , user_attributes : Dict [str , bytes ]
9731004 ) -> List [str ]:
0 commit comments