diff --git a/backend/check_ldap_user.py b/backend/check_ldap_user.py new file mode 100644 index 00000000..ebdda65f --- /dev/null +++ b/backend/check_ldap_user.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python +""" +Скрипт для проверки записи пользователя в LDAP +""" +import sys +from ldap3 import Server, Connection, ALL, SUBTREE, Tls +import ssl + +# Данные для подключения из .env (закомментированные строки) +LDAP_URI = "ldaps://DCII.robotail.local:636" +LDAP_BIND_DN = "corp@robotail.local" +LDAP_BIND_PASSWORD = "change-me-redacted-secret" +LDAP_BASE_DN = "DC=robotail,DC=local" +LDAP_USERS_BASE = "OU=Users,OU=company,DC=robotail,DC=local" +LDAP_CA_CERT = "C:\\ca\\corp-ca.pem" + +# Email пользователя для поиска +USER_EMAIL = "nadein-igor-vladimirovich@05-04-1999.ru" + +def main(): + print(f"=" * 80) + print(f"Подключение к LDAP: {LDAP_URI}") + print(f"Bind DN: {LDAP_BIND_DN}") + print(f"=" * 80) + + try: + # Настройка TLS + tls = Tls( + ca_certs_file=LDAP_CA_CERT, + validate=ssl.CERT_REQUIRED + ) + + # Подключение к серверу + server = Server( + "DCII.robotail.local", + port=636, + use_ssl=True, + tls=tls, + get_info=ALL + ) + + conn = Connection( + server, + user=LDAP_BIND_DN, + password=change-me-redacted-secret + auto_bind=True + ) + + print(f"✅ Успешное подключение к LDAP") + print(f"Server info: {server.info}") + print(f"\n" + "=" * 80) + print(f"Поиск пользователя с email: {USER_EMAIL}") + print(f"=" * 80) + + # Поиск пользователя по email + search_filter = f"(&(objectClass=user)(mail={USER_EMAIL}))" + + conn.search( + search_base=LDAP_BASE_DN, + search_filter=search_filter, + search_scope=SUBTREE, + attributes=['*'] # Получаем все атрибуты + ) + + if not conn.entries: + print(f"❌ Пользователь с email {USER_EMAIL} не найден в LDAP") + + # Попробуем поиск по userPrincipalName + print(f"\nПоиск по userPrincipalName...") + upn_filter = f"(&(objectClass=user)(userPrincipalName=*{USER_EMAIL.split('@')[0]}*))" + conn.search( + search_base=LDAP_BASE_DN, + search_filter=upn_filter, + search_scope=SUBTREE, + attributes=['*'] + ) + + if not conn.entries: + print(f"❌ Не найдено по userPrincipalName") + + # Поиск по sAMAccountName + print(f"\nПоиск по sAMAccountName...") + sam_filter = f"(&(objectClass=user)(sAMAccountName=*nadein*))" + conn.search( + search_base=LDAP_BASE_DN, + search_filter=sam_filter, + search_scope=SUBTREE, + attributes=['*'] + ) + + if not conn.entries: + print(f"❌ Не найдено записей с 'nadein' в sAMAccountName") + else: + print(f"\n✅ Найдено записей: {len(conn.entries)}") + else: + print(f"\n✅ Найдено записей: {len(conn.entries)}") + else: + print(f"\n✅ Найдено записей: {len(conn.entries)}") + + # Выводим все найденные записи + for idx, entry in enumerate(conn.entries, 1): + print(f"\n{'=' * 80}") + print(f"ЗАПИСЬ #{idx}") + print(f"{'=' * 80}") + print(f"DN: {entry.entry_dn}") + print(f"\nАтрибуты:") + print(f"-" * 80) + + # Основные атрибуты + important_attrs = [ + 'cn', 'givenName', 'sn', 'displayName', 'mail', + 'userPrincipalName', 'sAMAccountName', 'objectGUID', + 'telephoneNumber', 'mobile', 'userAccountControl', + 'whenCreated', 'whenChanged', 'memberOf', 'thumbnailPhoto' + ] + + for attr in important_attrs: + if hasattr(entry, attr): + value = getattr(entry, attr).value + if attr == 'thumbnailPhoto' and value: + print(f" {attr:25}: ") + elif attr == 'memberOf' and value: + print(f" {attr:25}:") + if isinstance(value, list): + for group in value: + print(f" - {group}") + else: + print(f" - {value}") + elif attr == 'objectGUID' and value: + # Преобразуем GUID в читаемый формат + guid_bytes = value + if isinstance(guid_bytes, bytes): + guid_str = '-'.join([ + guid_bytes[3::-1].hex(), + guid_bytes[5:3:-1].hex(), + guid_bytes[7:5:-1].hex(), + guid_bytes[8:10].hex(), + guid_bytes[10:].hex() + ]) + print(f" {attr:25}: {guid_str}") + else: + print(f" {attr:25}: {value}") + else: + print(f" {attr:25}: {value}") + + # Дополнительные атрибуты + print(f"\n Все остальные атрибуты:") + for attr_name in entry.entry_attributes: + if attr_name not in important_attrs: + value = entry[attr_name].value + if isinstance(value, bytes): + print(f" {attr_name:23}: ") + else: + print(f" {attr_name:23}: {value}") + + conn.unbind() + print(f"\n{'=' * 80}") + print(f"✅ Проверка завершена") + print(f"{'=' * 80}") + + except Exception as e: + print(f"\n❌ Ошибка: {type(e).__name__}") + print(f" {str(e)}") + import traceback + traceback.print_exc() + return 1 + + return 0 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/backend/eusrr_backend/settings.py b/backend/eusrr_backend/settings.py index 58993fe9..072a510c 100644 --- a/backend/eusrr_backend/settings.py +++ b/backend/eusrr_backend/settings.py @@ -322,8 +322,8 @@ LDAP_USER_BASE = os.getenv("LDAP_USER_BASE", "OU=company,DC=robotail,DC=local") LDAP_USERS_BASE = os.getenv("LDAP_USERS_BASE", LDAP_USER_BASE) # Базовый DN для операций создания (если не указан department_dn) LDAP_BASE_DN = os.getenv("LDAP_BASE_DN", LDAP_USERS_BASE) -# UPN-суффикс для создания пользователей (userPrincipalName) -LDAP_UPN_SUFFIX = os.getenv("LDAP_USER_UPN_SUFFIX", "@robotail.local") +# UPN-суффикс для создания пользователей (userPrincipalName) - домен БЕЗ @ +LDAP_UPN_SUFFIX = os.getenv("LDAP_USER_UPN_SUFFIX", "robotail.local") LDAP_USER_FILTER = os.getenv( "LDAP_USER_FILTER", "(&(objectCategory=person)(objectClass=user))" @@ -356,8 +356,8 @@ LDAP_WRITE_DN = os.getenv("LDAP_WRITE_DN", LDAP_BIND_DN) LDAP_WRITE_PASSWORD = os.getenv("LDAP_WRITE_PASSWORD", LDAP_BIND_PASSWORD) LDAP_WRITE_TIMEOUT = int(os.getenv("LDAP_WRITE_TIMEOUT", "5")) -# UPN суффикс для создания пользователей (например, @robotail.local) -LDAP_UPN_SUFFIX = os.getenv("LDAP_USER_UPN_SUFFIX", "@robotail.local") +# UPN суффикс для создания пользователей (домен БЕЗ @, например robotail.local) +LDAP_UPN_SUFFIX = os.getenv("LDAP_USER_UPN_SUFFIX", "robotail.local") # Белый список: локальные поля -> LDAP-атрибуты LDAP_WRITE_ATTRS = {