def to_django_settings(self): """Apply LDAP related parameters to Django settings. Doing so, we can use the django_auth_ldap module. """ try: import ldap from django_auth_ldap.config import ( LDAPSearch, PosixGroupType, GroupOfNamesType) ldap_available = True except ImportError: ldap_available = False values = dict(param_tools.get_global_parameters("core")) if not ldap_available or values["authentication_type"] != "ldap": return if not hasattr(settings, "AUTH_LDAP_USER_ATTR_MAP"): setattr(settings, "AUTH_LDAP_USER_ATTR_MAP", { "first_name": "givenName", "email": "mail", "last_name": "sn" }) ldap_uri = "ldaps://" if values["ldap_secured"] else "ldap://" ldap_uri += "%s:%s" % ( values["ldap_server_address"], values["ldap_server_port"]) setattr(settings, "AUTH_LDAP_SERVER_URI", ldap_uri) if values["ldap_group_type"] == "groupofnames": setattr(settings, "AUTH_LDAP_GROUP_TYPE", GroupOfNamesType()) searchfilter = "(objectClass=groupOfNames)" else: setattr(settings, "AUTH_LDAP_GROUP_TYPE", PosixGroupType()) searchfilter = "(objectClass=posixGroup)" setattr(settings, "AUTH_LDAP_GROUP_SEARCH", LDAPSearch( values["ldap_groups_search_base"], ldap.SCOPE_SUBTREE, searchfilter )) if values["ldap_auth_method"] == "searchbind": setattr(settings, "AUTH_LDAP_BIND_DN", values["ldap_bind_dn"]) setattr( settings, "AUTH_LDAP_BIND_PASSWORD", values["ldap_bind_password"] ) search = LDAPSearch( values["ldap_search_base"], ldap.SCOPE_SUBTREE, values["ldap_search_filter"] ) setattr(settings, "AUTH_LDAP_USER_SEARCH", search) else: setattr( settings, "AUTH_LDAP_USER_DN_TEMPLATE", values["ldap_user_dn_template"] ) if values["ldap_is_active_directory"]: if not hasattr(settings, "AUTH_LDAP_GLOBAL_OPTIONS"): setattr(settings, "AUTH_LDAP_GLOBAL_OPTIONS", { ldap.OPT_REFERRALS: False }) else: settings.AUTH_LDAP_GLOBAL_OPTIONS[ldap.OPT_REFERRALS] = False
def _apply_ldap_settings(self, values, backend): """Apply configuration for given backend.""" import ldap from django_auth_ldap.config import (LDAPSearch, PosixGroupType, GroupOfNamesType, ActiveDirectoryGroupType) if not hasattr(settings, backend.setting_fullname("USER_ATTR_MAP")): setattr(settings, backend.setting_fullname("USER_ATTR_MAP"), { "first_name": "givenName", "email": "mail", "last_name": "sn" }) ldap_uri = "ldaps://" if values["ldap_secured"] == "ssl" else "ldap://" ldap_uri += "%s:%s" % (values[backend.srv_address_setting_name], values[backend.srv_port_setting_name]) setattr(settings, backend.setting_fullname("SERVER_URI"), ldap_uri) if values["ldap_secured"] == "starttls": setattr(settings, backend.setting_fullname("START_TLS"), True) if values["ldap_is_active_directory"]: setattr(settings, backend.setting_fullname("GROUP_TYPE"), ActiveDirectoryGroupType()) searchfilter = "(objectClass=group)" elif values["ldap_group_type"] == "groupofnames": setattr(settings, backend.setting_fullname("GROUP_TYPE"), GroupOfNamesType()) searchfilter = "(objectClass=groupOfNames)" else: setattr(settings, backend.setting_fullname("GROUP_TYPE"), PosixGroupType()) searchfilter = "(objectClass=posixGroup)" setattr( settings, backend.setting_fullname("GROUP_SEARCH"), LDAPSearch(values["ldap_groups_search_base"], ldap.SCOPE_SUBTREE, searchfilter)) if values["ldap_auth_method"] == "searchbind": setattr(settings, backend.setting_fullname("BIND_DN"), values["ldap_bind_dn"]) setattr(settings, backend.setting_fullname("BIND_PASSWORD"), values["ldap_bind_password"]) search = LDAPSearch(values["ldap_search_base"], ldap.SCOPE_SUBTREE, values["ldap_search_filter"]) setattr(settings, backend.setting_fullname("USER_SEARCH"), search) else: setattr(settings, backend.setting_fullname("USER_DN_TEMPLATE"), values["ldap_user_dn_template"]) setattr(settings, backend.setting_fullname("BIND_AS_AUTHENTICATING_USER"), True) if values["ldap_is_active_directory"]: setting = backend.setting_fullname("GLOBAL_OPTIONS") if not hasattr(settings, setting): setattr(settings, setting, {ldap.OPT_REFERRALS: False}) else: getattr(settings, setting)[ldap.OPT_REFERRALS] = False
def test_posix_missing_attributes(self): self._init_settings( USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), GROUP_TYPE=PosixGroupType(), USER_FLAGS_BY_GROUP={'is_active': "cn=active_px,ou=groups,o=test"}) nobody = self.backend.authenticate(username='******', password='******') self.assertTrue(not nobody.is_active)
def test_group_mirroring(self): self._init_settings( USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE, '(objectClass=posixGroup)'), GROUP_TYPE=PosixGroupType(), MIRROR_GROUPS=True, ) self.assertEqual(Group.objects.count(), 0) alice = self.backend.authenticate(username='******', password='******') self.assertEqual(Group.objects.count(), 3) self.assertEqual(set(alice.groups.all()), set(Group.objects.all()))
def test_posix_group_permissions(self): self._init_settings( USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE, '(objectClass=posixGroup)'), GROUP_TYPE=PosixGroupType(), FIND_GROUP_PERMS=True ) self._init_groups() alice = User.objects.create(username='******') alice = self.backend.get_user(alice.pk) self.assertEqual(self.backend.get_group_permissions(alice), set(["auth.add_user", "auth.change_user"])) self.assertEqual(self.backend.get_all_permissions(alice), set(["auth.add_user", "auth.change_user"])) self.assertTrue(self.backend.has_perm(alice, "auth.add_user")) self.assertTrue(self.backend.has_module_perms(alice, "auth"))
def test_posix_group_permissions_no_gid(self): self._init_settings( USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE, '(objectClass=posixGroup)'), GROUP_TYPE=PosixGroupType(), FIND_GROUP_PERMS=True ) self._init_groups() self.ldapobj.modify_s(self.alice[0], [(ldap.MOD_DELETE, 'gidNumber', None)]) self.ldapobj.modify_s(self.active_px[0], [(ldap.MOD_ADD, 'memberUid', ['alice'])]) alice = User.objects.create(username='******') alice = self.backend.get_user(alice.pk) self.assertEqual(self.backend.get_group_permissions(alice), set(["auth.add_user", "auth.change_user"])) self.assertEqual(self.backend.get_all_permissions(alice), set(["auth.add_user", "auth.change_user"])) self.assertTrue(self.backend.has_perm(alice, "auth.add_user")) self.assertTrue(self.backend.has_module_perms(alice, "auth"))
def test_group_mirroring(self): self._init_settings( AUTH_LDAP_USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', AUTH_LDAP_GROUP_SEARCH=LDAPSearch('ou=groups,o=test', self.mock_ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)" ), AUTH_LDAP_GROUP_TYPE=PosixGroupType(), AUTH_LDAP_MIRROR_GROUPS=True, ) self.mock_ldap.set_return_value('search_s', ("ou=groups,o=test", 2, "(&(objectClass=posixGroup)(|(gidNumber=1000)(memberUid=alice)))", None, 0), [self.active_px, self.staff_px, self.superuser_px] ) self.assertEqual(Group.objects.count(), 0) alice = self.backend.authenticate(username='******', password='******') self.assertEqual(Group.objects.count(), 3) self.assertEqual(set(alice.groups.all()), set(Group.objects.all()))
def test_posix_membership(self): self._init_settings( USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', GROUP_SEARCH=LDAPSearch('ou=groups,o=test', ldap.SCOPE_SUBTREE), GROUP_TYPE=PosixGroupType(), USER_FLAGS_BY_GROUP={ 'is_active': "cn=active_px,ou=groups,o=test", 'is_staff': "cn=staff_px,ou=groups,o=test", 'is_superuser': "******" } ) alice = self.backend.authenticate(username='******', password='******') bob = self.backend.authenticate(username='******', password='******') self.assertTrue(alice.is_active) self.assertTrue(alice.is_staff) self.assertTrue(alice.is_superuser) self.assertTrue(not bob.is_active) self.assertTrue(not bob.is_staff) self.assertTrue(not bob.is_superuser)
def test_posix_group_permissions(self): self._init_settings( AUTH_LDAP_USER_DN_TEMPLATE='uid=%(user)s,ou=people,o=test', AUTH_LDAP_GROUP_SEARCH=LDAPSearch('ou=groups,o=test', self.mock_ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)" ), AUTH_LDAP_GROUP_TYPE=PosixGroupType(), AUTH_LDAP_FIND_GROUP_PERMS=True ) self._init_groups() self.mock_ldap.set_return_value('search_s', ("ou=groups,o=test", 2, "(&(objectClass=posixGroup)(|(gidNumber=1000)(memberUid=alice)))", None, 0), [self.active_px, self.staff_px, self.superuser_px] ) alice = User.objects.create(username='******') alice = self.backend.get_user(alice.pk) self.assertEqual(self.backend.get_group_permissions(alice), set(["auth.add_user", "auth.change_user"])) self.assertEqual(self.backend.get_all_permissions(alice), set(["auth.add_user", "auth.change_user"])) self.assert_(self.backend.has_perm(alice, "auth.add_user")) self.assert_(self.backend.has_module_perms(alice, "auth"))
# https://django-auth-ldap.readthedocs.io/ LDAP_BASE_DC = env("LDAP_BASE_DC") LDAP_BASE_OU = f"ou=groups,{LDAP_BASE_DC}" LDAP_BASE_GROUP = f"cn={env('LDAP_BASE_GROUP')},{LDAP_BASE_OU}" LDAP_PROJECT_GROUP = f"cn=radicalt,{LDAP_BASE_OU}" # Baseline configuration AUTH_LDAP_SERVER_URI = env("LDAP_SERVER_URI") AUTH_LDAP_BIND_DN = env("LDAP_BIND_DN", default="") AUTH_LDAP_BIND_PASSWORD = env("LDAP_BIND_PASSWORD", default="") AUTH_LDAP_USER_DN_TEMPLATE = "uid=%(user)s,ou=people," + LDAP_BASE_DC # Set up the basic group parameters AUTH_LDAP_GROUP_SEARCH = LDAPSearch(LDAP_BASE_OU, ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)") AUTH_LDAP_GROUP_TYPE = PosixGroupType(name_attr="cn") # Simple group restrictions AUTH_LDAP_REQUIRE_GROUP = LDAPGroupQuery(LDAP_BASE_GROUP) | LDAPGroupQuery( LDAP_PROJECT_GROUP) # Populate the Django user from the LDAP directory AUTH_LDAP_ALWAYS_UPDATE_USER = False AUTH_LDAP_USER_ATTR_MAP = { "first_name": env("LDAP_FIRST_NAME_FIELD"), "last_name": env("LDAP_LAST_NAME_FIELD"), "email": env("LDAP_EMAIL_FIELD"), } AUTH_LDAP_USER_FLAGS_BY_GROUP = {
AUTH_LDAP_BIND_PASSWORD = config('LDAP_BIND_PASSWORD', default='') AUTH_LDAP_USER_SEARCH = LDAPSearch( config('LDAP_USER_DN'), ldap.SCOPE_SUBTREE, config('LDAP_USER_FILTER', default='(&(objectClass=inetOrgPerson)(cn=%(user)s))')) AUTH_LDAP_GROUP_SEARCH = LDAPSearch( config('LDAP_GROUP_DN', default=''), ldap.SCOPE_SUBTREE, config('LDAP_GROUP_FILTER', default='(objectClass=groupOfUniqueNames)')) if config('LDAP_GROUP_TYPE', default='') == 'groupOfUniqueNames': AUTH_LDAP_GROUP_TYPE = GroupOfUniqueNamesType() elif config('LDAP_GROUP_TYPE', default='') == 'posixGroup': AUTH_LDAP_GROUP_TYPE = PosixGroupType() elif config('LDAP_GROUP_TYPE', default='') == 'nestedGroupOfNames': AUTH_LDAP_GROUP_TYPE = NestedGroupOfNamesType() AUTH_LDAP_REQUIRE_GROUP = config('LDAP_REQUIRE_GROUP', default=None) AUTH_LDAP_DENY_GROUP = config('LDAP_DENY_GROUP', default=None) AUTH_LDAP_USER_ATTR_MAP = { 'username': config('LDAP_SENTRY_USER_FIELD', default='mail'), 'name': config('LDAP_MAP_FULL_NAME', default='cn'), 'email': config('LDAP_MAP_MAIL', default='mail') } AUTH_LDAP_DEFAULT_SENTRY_ORGANIZATION = 'Locaweb' AUTH_LDAP_SENTRY_ORGANIZATION_ROLE_TYPE = 'member' AUTH_LDAP_FIND_GROUP_PERMS = False
AUTHENTICATION_BACKENDS = ( 'django_auth_ldap.backend.LDAPBackend', # ldap认证 'django.contrib.auth.backends.ModelBackend', # 本地默认的认证方式 ) AUTH_LDAP_SERVER_URI = LDAP_SERVER_IP # ldap服务器地址 AUTH_LDAP_BIND_DN = 'cn=%s,%s' % (LDAP_ADMIN, LDAP_DOMAIN ) # 可为空,也可以填写一个真实的ldap用户 AUTH_LDAP_BIND_PASSWORD = LDAP_PASS AUTH_LDAP_USER_SEARCH = LDAPSearch('ou=%s,%s' % (LDAP_OU, LDAP_DOMAIN), ldap.SCOPE_SUBTREE, "(cn=%(user)s)") # # 第一个参数是搜索的范围 #AUTH_LDAP_USER_ATTR_MAP = {"username": "******","email": "mail"} #从LDAP同步数据到本地数据库 AUTH_LDAP_ALWAYS_UPDATE_USER = True AUTH_LDAP_GROUP_SEARCH = LDAPSearch(LDAP_DOMAIN, ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)") AUTH_LDAP_GROUP_TYPE = PosixGroupType( name_attr="cn") # 组的DN是cn=员工,ou=Group,dc=ldap,dc=ssotest,dc=net,所以type是cn # ### log 配置部分BEGIN ### # LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': {#日志格式化 'simple': { 'format': '%(levelname)s %(name)s %(asctime)s %(message)s' }, 'verbose': { 'format': '%(levelname)s %(name)s %(asctime)s %(pathname)s %(module)s:%(funcName)s %(lineno)d %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S' }, 'django_request':{
# LDAP # ------------------------------------- LOGIN_URL = reverse_lazy('login') AUTH_LDAP_SERVER_URI = CARME_LDAP_SERVER_PROTO + CARME_LDAP_SERVER_IP AUTH_LDAP_BIND_DN = CARME_LDAP_BIND_DN AUTH_LDAP_BIND_PASSWORD = CARME_LDAP_SERVER_PW AUTH_LDAP_GROUP_SEARCH = LDAPSearch( "dc={},dc={}".format(CARME_LDAP_DC1, CARME_LDAP_DC2), # GroupOfUniqueNames)" ldap.SCOPE_SUBTREE, "(objectClass=PosixGroup)") AUTH_LDAP_GROUP_TYPE = PosixGroupType() # GroupOfUniqueNamesType() AUTH_LDAP_USER_FLAGS_BY_GROUP = { "is_active": ("cn={},ou={},dc={},dc={}".format(CARME_LDAPGROUP_1, CARME_LDAPINSTANZ_1, CARME_LDAP_DC1, CARME_LDAP_DC2), "cn={},ou={},dc={},dc={}".format(CARME_LDAPGROUP_2, CARME_LDAPINSTANZ_2, CARME_LDAP_DC1, CARME_LDAP_DC2), "cn={},ou={},dc={},dc={}".format(CARME_LDAPGROUP_3, CARME_LDAPINSTANZ_3, CARME_LDAP_DC1, CARME_LDAP_DC2), "cn={},ou={},dc={},dc={}".format(CARME_LDAPGROUP_4, CARME_LDAPINSTANZ_4, CARME_LDAP_DC1, CARME_LDAP_DC2), "cn={},ou={},dc={},dc={}".format(CARME_LDAPGROUP_5, CARME_LDAPINSTANZ_5, CARME_LDAP_DC1, CARME_LDAP_DC2)), "is_staff": ("cn={},ou={},dc={},dc={}".format(CARME_LDAPGROUP_1, CARME_LDAPINSTANZ_1,
# LDAP User Search settings. AUTH_LDAP_USER_SEARCH = LDAPSearch(RDRF_AUTH_LDAP_BIND_DC, ldap.SCOPE_SUBTREE, f"({RDRF_AUTH_LDAP_USER_SEARCH_ATTR}=%(user)s)") # Matching LDAP user group to user settings (superuser / active) AUTH_LDAP_USER_FLAGS_BY_GROUP = {} if RDRF_AUTH_LDAP_ALLOW_SUPERUSER: AUTH_LDAP_USER_FLAGS_BY_GROUP['is_superuser'] = RDRF_AUTH_LDAP_IS_SUPERUSER_GROUP if not RDRF_AUTH_LDAP_FORCE_ISACTIVE: AUTH_LDAP_USER_FLAGS_BY_GROUP['is_active'] = RDRF_AUTH_LDAP_IS_ACTIVE_GROUP # LDAP Group Search settings. AUTH_LDAP_GROUP_SEARCH = LDAPSearch(RDRF_AUTH_LDAP_BIND_GROUP, ldap.SCOPE_SUBTREE, f"({RDRF_AUTH_LDAP_GROUP_SEARCH_FIELD}={RDRF_AUTH_LDAP_GROUP_SEARCH_FIELD_VALUE})") if RDRF_AUTH_LDAP_GROUP_SEARCH_TYPE == "posix": AUTH_LDAP_GROUP_TYPE = PosixGroupType(name_attr=RDRF_AUTH_LDAP_GROUP_TYPE_ATTR) elif RDRF_AUTH_LDAP_GROUP_SEARCH_TYPE == "groupofnames": AUTH_LDAP_GROUP_TYPE = GroupOfNamesType(name_attr=RDRF_AUTH_LDAP_GROUP_TYPE_ATTR) elif RDRF_AUTH_LDAP_GROUP_SEARCH_TYPE == "activedirectory": AUTH_LDAP_GROUP_TYPE = ActiveDirectoryGroupType(name_attr=RDRF_AUTH_LDAP_GROUP_TYPE_ATTR) AUTH_LDAP_FIND_GROUP_PERMS = env.get("auth_ldap_find_group_perms", DEV_LDAP_GROUP_PERMS) AUTH_LDAP_CACHE_GROUPS = env.get("auth_ldap_cache_groups", DEV_LDAP_CACHE_GROUPS) AUTH_LDAP_GROUP_CACHE_TIMEOUT = env.get("auth_ldap_group_cache_timeout", DEV_LDAP_CACHE_TIMEOUT) # Security: set required LDAP group (user must be in this LDAP group to login in RDRF) AUTH_LDAP_REQUIRE_GROUP = env.get("auth_ldap_require_group", "") # these determine which authentication method to use # apps use modelbackend by default, but can be overridden here # see: https://docs.djangoproject.com/en/dev/ref/settings/#authentication-backends
def _dict_to_configs(self, new_configs): """ Turn given dictionary into self.configs. Clears all previous settings. :param new_configs: dictionary of new configs; values should be booleans or strings :return: """ self.configs = {} for k, v in new_configs.items(): k = k.upper() if v == "": continue if k == 'AUTH_LDAP_ENABLED': self.enabled = bool(v) # Also treat AUTH_LDAP_USER_FLAGS_BY_GROUP_IS_STAFF or _IS_SUPERUSER differently elif k == 'AUTH_LDAP_USER_FLAGS_BY_GROUP_IS_STAFF': group_flags = self.configs.get('AUTH_LDAP_USER_FLAGS_BY_GROUP', {}) group_flags['is_staff'] = v self.configs['AUTH_LDAP_USER_FLAGS_BY_GROUP'] = group_flags elif k == 'AUTH_LDAP_USER_FLAGS_BY_GROUP_IS_SUPERUSER': group_flags = self.configs.get('AUTH_LDAP_USER_FLAGS_BY_GROUP', {}) group_flags['is_superuser'] = v self.configs['AUTH_LDAP_USER_FLAGS_BY_GROUP'] = group_flags # AUTH_LDAP_GROUP_MAPPING and AUTH_LDAP_USER_ATTR_MAP should be imported as json elif k in LDAPSettings.JSON_FIELDS: try: self.configs[k] = json.loads(v) except json.JSONDecodeError: self.errors[k] = 'This field is not in json form' else: self.configs[k] = v if LDAPSettings.LDAP_IMPORT_SUCCESS: # Import AUTH_LDAP_USER_SEARCH as LDAPSearchUnion if "AUTH_LDAP_USER_SEARCH" in self.configs: temp = self.configs["AUTH_LDAP_USER_SEARCH"] ldap_searches = [] for el in temp: ldap_searches.append( LDAPSearch(el["search"], ldap.SCOPE_SUBTREE, el["filter"])) self.configs["AUTH_LDAP_USER_SEARCH"] = LDAPSearchUnion( *ldap_searches) # Import AUTH_LDAP_GROUP_SEARCH as LDAPSearch temp = new_configs.get('AUTH_LDAP_GROUP_TYPE', '').lower() group_type = None if temp == 'groupofnames': group_type = 'groupOfNames' elif temp == 'posixgroup': group_type = 'posixGroup' group_search_dn = new_configs.get('AUTH_LDAP_GROUP_SEARCH', None) if group_search_dn and group_type: self.configs['AUTH_LDAP_GROUP_SEARCH'] = LDAPSearch( group_search_dn, ldap.SCOPE_SUBTREE, "(objectClass={})".format(group_type)) # import AUTH_LDAP_GROUP_TYPE and AUTH_LDAP_GROUP_TYPE_NAME_ATTR as object name_attr = new_configs.get('AUTH_LDAP_GROUP_TYPE_NAME_ATTR', None) if group_type == 'groupOfNames': self.configs['AUTH_LDAP_GROUP_TYPE'] = GroupOfNamesType() \ if name_attr is None else GroupOfNamesType(name_attr=name_attr) elif group_type == 'posixGroup': self.configs['AUTH_LDAP_GROUP_TYPE'] = PosixGroupType() \ if name_attr is None else PosixGroupType(name_attr=name_attr) else: if 'AUTH_LDAP_GROUP_TYPE' in self.configs: del self.configs['AUTH_LDAP_GROUP_TYPE']