Что такое код ldap_get_option

Содержание

Пример работы с LDAP-каталогом с помощью php API

Левинца Егор, 06 апреля 2012 года.

В порядке эксперимента, а также чтобы оказать помощь человеку в его затруднении, решил написать небольшую утилитку для отображения пользователей (а точнее, учётных записей пользователей), хранящихся в каталоге LDAP, по группам. Эксперимент состоял в том, чтобы обратиться к каталогу и получить из него данные через php API, чего я раньше не делал. Зная общие принципы взаимодействия с LDAP-каталогами и имея опыт написания подобных программ на perl API (с использованием модуля Net::LDAP), сделать это оказалось несложно. Все же я решил описать свою работу — возможно, она поможет кому-нибудь в разработке php-программ, взаимодействующих с LDAP-каталогом.

Исходные данные: имеется каталог (базовый DN dc=mycompany,dc=ru) со «стандартной» структурой для интеграции с samba: сведения об учётных записях пользователей хранятся в ветке ou=Users,dc=myconpany,dc=ru, сведения о группах пользователей — в ветке ou=Groups,dc=mycompany,dc=ru. Основная задача: отобразить нестандартную древовидную структуру: на первом уровне список групп, на втором — принадлежащие этим группам пользователи. Факультативная задача: при выборе пользователя из списка вывести некоторые сведения по нему.

Для упрощения примера подразумевается, что группы строятся на структурном объектном классе posixGroup , атрибут членства в группе — memberUid , значение которого совпадает с атрибутом uid учётной записи пользователя. Если у Вас за членство в группах и учётные записи пользователей отвечают другие атрибуты — измените код программы под Ваши настройки.

LDAP — относительно простой протокол с небольшим количеством операций. В нашем примере мы не собираемся изменять содержимое каталога (осуществляем доступ только для чтения), поэтому вся работа с каталогом будет выполнена за 4 операции: соединение с сервером каталога (connect), подключение к каталогу (bind), выполнение поиска необходимых нам данных (search) с выводом результатов, и, наконец, отключение от сервера (unbind). Все эти операции реализованы в php функциями с «говорящими» названиями: ldap_connect() , ldap_bind() , ldap_search() и ldap_unbind() . Эти и другие функции работы с LDAP в php описаны в соответствующей странице документации по php. Описаны, кстати, довольно неплохо, с хорошими примерами.

Поскольку при выполнении основной и факультативной задач осуществляются абсолютно одинаковые операции соединения, подключения и отключения от сервера, я решил вынести их в основную часть программы, а различающиеся операции поиска и отображения полученных в результате поиска данных — в отдельные функции. В первой функции get_main() производится поиск сведений о группах в ветке ou=Groups,dc=mycompany,dc=ru. Найденные группы, а также члены каждой из групп сортируются по алфавиту и выводится html-страница с древовидной структурой. Чтобы не изобретать велосипедов с отображением древовидной структуры, я воспользовался готовым модулем dhtmlxTree библиотеки компонентов dhtmlx. Вызов второй функции get_userinfo() выполняется при обращении к программе из ajax-запроса, генерируемого при нажатии на пользователя — члена группы в выведенной в браузер html-странице. В этой функции выполняется поиск в ветке ou=Users,dc=myconpany,dc=ru на совпадение имени пользователя с содержимым атрибута uid. Выбранные в результате поиска атрибуты записи пользователя оформляются в виде таблицы и загружаются в соответствующее информационное поле на html-странице.

‘; // Вывод таблицы с запрашиваемыми данными echo ‘

‘; foreach($LDAP[‘Attrs’] as $attr=>$desc) < echo '

‘; > echo ‘

‘ . $desc . ‘ ‘; if(isset($entries[0][$attr])) < array_shift($entries[0][$attr]); echo join('
‘, $entries[0][$attr]); > echo ‘

‘; > ?>

Выглядит это так:

Код программы с библиотеками dhtmlx и набором иконок можно скачать одним архивом здесь (

active directory — Получить количество ошибок AD с LDAP и PHP (функция ldap возвращает неточную ошибку)

Я делаю приложение с использованием PHP для подключения к Active Directory (AD), используя протокол LDAP.

Работает нормально, моя проблема в том, как перехватить конкретные ошибки, если не удается выполнить вход в систему. Сегодня приложение показывает только, сработал ли вход в систему, например: предположим, что срок действия имени пользователя истек в AD, система покажет, что «имя пользователя / пароль недействительны», потому что мы не проверяем конкретные возвраты LDAP.

Хорошо, давайте перейдем к самой проблеме, ниже приведен мой код, который я ожидаю отлавливать конкретные ошибки.

Эта функция, ldap_errno, возвращает мне номер того, что произошло, основываясь на этой таблице:

(Есть еще, см ссылку ниже)

48 LDAP_INAPPROPRIATE_AUTH
49 LDAP_INVALID_CREDENTIALS
49 / 52e AD_INVALID ПОЛНОМОЧИЯ
49/525 ПОЛЬЗОВАТЕЛЬ НЕ НАЙДЕН
49/530 NOT_PERMITTED_TO_LOGON_AT_THIS_TIME
49/531 RESTRICTED_TO_SPECIFIC_MACHINES
49/532 PASSWORD_EXPIRED
49/533 ACCOUNT_DISABLED
49/568 ERROR_TOO_MANY_CONTEXT_IDS
49/701 ACCOUNT_EXPIRED
49/773 ПОЛЬЗОВАТЕЛЬ ДОЛЖЕН СБРОСИТЬ ПАРОЛЬ
50 LDAP_INSUFFICIENT_ACCESS

Хорошо, проблема в том, что PHP всегда возвращает мне только 49 (LDAP_INVALID_CREDENTIALS), независимо от ситуации (ситуации, в которой есть связь с логином). Например, если срок действия моей учетной записи истек, PHP возвращает мне 49, я хочу вернуть 49/701, как мне найти 701? Это другая функция?

И как мне показать пользователю, если его пароль ИЛИ его имя пользователя неверно, а не оба? Я знаю, что с точки зрения безопасности показывать, что оба недействительны, но мы решили, что лучше показать, что не так, если имя пользователя или пароль — это можно узнать с помощью LDAP?

Версия PHP 5.4.31

РЕДАКТИРОВАТЬ

Я нашел проблему, которая может быть полезна:

Любой знает, как сделать ldap_search таким образом:

Я не знаю, как сделать этот поиск с помощью PHP ldap_search() функция

Решение

Потратив много часов на поиски, я нашел решение!

в основном вы должны определить новую постоянную переменную под названием LDAP_OPT_DIAGNOSTIC_MESSAGE

При этом LDAP выдаст вам расширенную ошибку, и вы сможете узнать, что на самом деле произошло, значение будет помещено в $ extended_error.

ldap_get_option

(PHP 4 >= 4.0.4, PHP 5, PHP 7)

ldap_get_option — Get the current value for given option

Description

Sets retval to the value of the specified option.

Parameters

The parameter option can be one of:

Option Type
LDAP_OPT_DEREF integer
LDAP_OPT_SIZELIMIT integer
LDAP_OPT_TIMELIMIT integer
LDAP_OPT_NETWORK_TIMEOUT integer
LDAP_OPT_PROTOCOL_VERSION integer
LDAP_OPT_ERROR_NUMBER integer
LDAP_OPT_REFERRALS bool
LDAP_OPT_RESTART bool
LDAP_OPT_HOST_NAME string
LDAP_OPT_ERROR_STRING string
LDAP_OPT_MATCHED_DN string
LDAP_OPT_SERVER_CONTROLS array
LDAP_OPT_CLIENT_CONTROLS array

This will be set to the option value.

Return Values

Returns TRUE on success or FALSE on failure.

Examples

Example #1 Check protocol version

Notes

This function is only available when using OpenLDAP 2.x.x OR Netscape Directory SDK x.x.

See Also

User Contributed Notes

Here is how to tell if an Active Directory user account expired:

ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($conn, LDAP_OPT_REFERRALS, 0);

$bind = ldap_bind($conn, $user, $pass);

ldap_get_option($conn, LDAP_OPT_DIAGNOSTIC_MESSAGE, $extended_error);

if (!empty($extended_error))
<
$errno = explode(‘,’, $extended_error)[2];
$errno = explode(‘ ‘, $errno)[2];
$errno = intval($errno);

if ($errno == 532)
$err = ‘Unable to login: Password expired.’;
>

Ответ OpenLDAP ldap_get_option ()

Я работаю над реализацией политики паролей OpenLDAP для приложения. Я пытаюсь получить пароль истекает, истек срок действия пароля из OpenLDAP.

Я устанавливаю текущее значение

с ldap_set_option() для LDAP_OPT_SERVER_CONTROLS (управление политикой паролей)

Я все еще не получаю ответ политики паролей от ldap_get_option() .

Что я узнал, что API OpenLDAP C не реализовал случай LDAP_OPT_SERVER_CONTROLS в методе ldap_get_option (). Проверка пакетов на Wireshark показывает реакцию ppolicy, привязанную к пакету.

Есть ли какое-либо обходное решение, чтобы вытащить ответ политики паролей из OpenLDAP с помощью PHP или API OpenLDAP C?

Аутентификация клиентов при помощи LDAP на сервере Ubuntu 12.04

LDAP (или Lightweight Directory Access Protocol) – это протокол, позволяющий хранить данные аутентификации в одном централизованном месте. В предыдущей статье было показано, как настроить сервер LDAP на Ubuntu 12.04.

Данная статья поможет настроить удалённую аутентификацию клиентских машин.

Примечание: Для выполнения руководства нужны предварительно настроенный сервер Ubuntu 12.04 и установленный сервер LDAP. Также понадобится ещё один сервер Ubuntu 12.04, который будет использован в качестве клиента.

Установка пакетов клиента

На клиентскую машину нужно установить несколько пакетов для корректной поддержки аутентификации LDAP.

Чтобы загрузить эти пакеты из стандартного репозитория Ubuntu, используйте следующие команды:

sudo apt-get update
sudo apt-get install libpam-ldap nscd

Система задаст несколько стандартных вопросов и запросит некоторые данные, а именно:

    Uniform Resource >Если вы допустили ошибку и хотите её исправить, можете вернуться в это меню при помощи команды:

sudo dpkg-reconfigure ldap-auth-config

Настройка клиента

Теперь нужно отредактировать некоторые настройки, чтобы файлы аутентификации могли обращаться к серверу LDAP за информацией.

Для начала отредактируйте файл /etc/nsswitch.conf. Он позволяет настроить изменение учетных данных LDAP при запуске пользователями определённых команд аутентификации.

sudo nano /etc/nsswitch.conf

Найдите в файле строки passwd, group и shadow и отредактируйте их следующим образом:

passwd: ldap compat
group: ldap compat
shadow: ldap compat

Затем нужно добавить некоторые значения в настройки PAM.

PAM (или Pluggable Authentication Modules) – это система, которая соединяет приложения, обеспечивающие аутентификацию в тех приложениях, которые требуют проверки подлинности.

Система PAM внедрена по умолчанию на большинстве компьютеров, работает в фоновом режиме и не требует вмешательства пользователя. После установки модуля PAM для LDAP большая часть необходимой информации была добавлена в конфигурационные файлы.

Отредактируйте файл /etc/pam.d/common-session:

sudo nano /etc/pam.d/common-session

В конец файла добавьте строку:

session required pam_mkhomedir.so skel=/etc/skel umask=0022

Это создаст на клиентской машине домашний каталог при подключении пользователя LDAP, у которого нет такого каталога.

Чтобы обновить настройки, перезапустите сервис:

sudo /etc/init.d/nscd restart

Права доступа

Как помните, во время настройки сервера LDAP была создана группа admin. Это название выбрано не случайно. Оно совпадает с названием группы, созданной на машине Ubuntu по умолчанию.

Пользователи LDAP, добавленные в группу admin, получают доступ к команде sudo согласно настройкам файла /etc/sudoers.

Отредактируйте этот файл:

%admin ALL=(ALL) ALL

Все записи, начинающиеся с символа %, обозначают группу, а не пользователя. Чтобы отключить доступ пользователей к команде sudo или передать права доступа только определённым пользователям, закомментируйте эту строку:

#%admin ALL=(ALL) ALL

Вход пользователя LDAP

Теперь клиентская машина настроена и может подключиться в качестве пользователя LDAP. Этот пользователь не должен существовать на клиентском компьютере.

В новом окне терминала создайте SSH-подключение к клиентскому компьютеру, используя учетные данные пользователя LDAP.

Примечание: Рекомендуется оставить исходное окно терминала на случай ошибок в конфигурации.

Пользователь должен подключиться так, будто он был создан локально. Запросите рабочий каталог:

Команда вернёт домашний каталог, созданный при входе этого пользователя.

Попробуйте выйти и войти снова как другой пользователь LDAP. На сервере появится ещё один домашний каталог пользователя:

ls /home
user1 user2

Если пользователь входит в группу admin, и вы не отключили доступ к sudo в предыдущем разделе, то тот пользователь сможет запускать команды с sudo.

Запустите команду passwd, чтобы изменить пароль. Как видите, сервер LDAP позволяет изменить учётные данные:

passwd
Enter login(LDAP) password:

Ограничение доступа по группам

Чтобы возможность войти на данный компьютер была только у членов определенных групп, можно отредактировать файлы PAM.

Откройте для редактирования с правами root:

sudo nano /etc/pam.d/common-auth

В конце файла нужно указать, что система PAM должна проверять файлы доступа, прежде чем пропустить пользователя.

auth required pam_access.so

Сохраните и закройте файл.

Файл, к которому обращается PAM за информацией о доступе — /etc/security/access.conf. Откройте его:

sudo nano /etc/security/access.conf

В конец этого файла нужно добавить правило.

Символ тире в начале строки значит, что это ограничение. Между символами двоеточия указывается само правило.

В данном случае правило касается всех пользователей, кроме root и членов группы admin. Группы указываются в скобках.

После второго символа двоеточия уточняется, при каких обстоятельствах правило должно применяться. В данном примере ограничение будет применяться во всех случаях, кроме локальных подключений.

-:ALL EXCEPT root (admin):ALL EXCEPT LOCAL

Внимание: Это правило применяется ко всем пользователям, а не только к пользователям LDAP. Потому любой пользователь, созданный на клиентской машине, должны входить в одну из указанных в правиле групп, чтобы получить доступ.

Заключение

Теперь сервер LDAP позволяет аутентифицировать клиентов. Пользователи LDAP с валидными учётными данными смогут пользоваться всеми машинами, доступ к которым не заблокирован.

Такой подход позволяет предотвратить рассредоточение, дублирование и потерю контроля над данными. Аутентификация LDAP особенно важна в случаях, когда количество пользователей, имеющих доступ к серверам и проектам, постоянно растет.

OpenLDAP ldap_get_option() response

I’m working on OpenLDAP password policy implementation to app. I’m trying to get password is expiring, password expired notifications from OpenLDAP.

I set the current value

with ldap_set_option() for LDAP_OPT_SERVER_CONTROLS (password policy control)

I still don’t get the password policy response from ldap_get_option() .

What I have learned, that OpenLDAP C API hasn’t implemented LDAP_OPT_SERVER_CONTROLS case on ldap_get_option() method. Checking the packets on Wireshark shows the ppolicy response hooked to the packet.

Is there any workaround to pull the password policy response from OpenLDAP using PHP or OpenLDAP C API?

OTRS: LDAP аутентификация, авторизация и синхронизация (FreeIPA, AD)

OTRS — система обработки заявок с открытым кодом (Open-source Ticket Request System), написанная на Perl.

Существует в двух вариантах:

  • OTRS Business Solution — платная версия
  • ((OTRS)) Community Edition — бесплатная версия

Перечислю немного из того фукционала, который поддерживает эта система:

  • модуль ITSM (Service Level Management, Change Management, Configuration Management, CMDB)
  • адаптивный веб-интерфейс
  • API
  • SLA и сервисы
  • мультитенантность
  • эскалации
  • аутентификация: DB, LDAP, HTTPBasicAuth, Radius
  • поддержка MySQL, MariaDB, PostgreSQL, Oracle

И если искать в ней недостатки — так это непривычность интерфейса и сложность в настройке. Под катом — об основах авторизации (группы, RBAC, поддержка нескольких компаний-клиентов), аутентификации и синхронизации метаданных (ФИО, телефона и прочего), используя различные каталоги LDAP

Клиенты, очереди, агенты и группы

После установки OTRS у вас сразу будут доступны:

  • клиенты — могут создавать заявки, отправив письмо или используя веб-доступ
  • очереди — каждая заявка попадает в одну из очередей заявок
  • агенты — ИТ специалисты, работающие над выполнением заявок из доступных им очередей
  • группы — сущность, связывающая между собой очереди, клиентов и агентов, а также задающая права агентов — например, только чтение, изменение приоритета заявки и т. п.

Стандартные группы

После установки системы вы увидите три созданные группы:

  • admin — члены группы могут администрировать (настраивать) OTRS
  • stats — возможность настраивать и запускать отчеты
  • users — стандартная группа для клиентов, очередей и агентов

Права, связанные с группами

Основные права

Основные права, которые можно настроить в группе, ограничивающие действия агентов:

  • только чтение — права только на чтение заявки в данной группе/очереди
  • переместить — права на перемещение заявок в эту группу/очередь
  • создание — права на создание заявок в этой группе/очереди
  • заметка — права на добавление заметок в заявки в этой группе/очереди
  • владелец — права на смену владельца заявок в этой группе/очереди
  • приоритет — права на смену приоритета заявок в этой группе/очереди
  • чтение/запись — полные права на чтение и запись для заявок в данной группе/очереди

Дополнительные права

Также существуют и дополнительные права, отображение которых можно включить в настройках (System::Permission):

  • отчеты — предоставляет доступ к странице отчетов
  • перенаправить — право перенаправить/bounce почтовое сообщение (ссылка перенаправить/bounce в ticketZoom)
  • создать — право составления ответа на заявку
  • клиент — право изменить клиента для этой заявки
  • переслать — право пересылать сообщения (с помощью кнопки Переслать)
  • в ожидании — право перевести заявку в ожидание
  • телефон — право добавить содержание звонка клиента к заявке в виде сообщения/заметки
  • ответственный — Право изменить ответственного за заявку

Рассмотрим это более подробно:

  • каждый клиент может быть включен в одну или несколько групп, изначально все клиенты входят в группу users
  • каждая очередь заявок связывается с какой-либо одной из групп
  • через веб-интерфейс клиент может делать заявки в тех очередях, к которым имеют доступ группы, в которые он включен
  • при отправке клиентом заявки по электронной почте существует возможность на основании анализа атрибутов письма (например, адреса отправителя или заголовка письма) изменять характеристики заявки, в том числе и очередь, в которую попадет заявка
  • если клиент позвонил по телефону, агент может завести заявку вручную, выбрав любую из доступных агенту очередей
  • желательно, чтобы заявка клиента всегда была в очередях, доступных клиенту, иначе он не сможет получить доступ к ней через веб-интерфейс
  • агенты могут производить действия в заявками в соответствии с правами на очередь, в которой находится заявка

Аутентификация с использованием базы данных

Стандартный способ аутентификации и авторизации агентов и клиентов — это база данных.

Например, настройки аутентификации агентов, используя базу данных, выглядит так:

Мы также оставим этот способ аутентификации и добавим в дополнение с нему аутентификацию через LDAP.

Роли и компании

Так же мы расширим возможности авторизации, добавив роли и компании:

  • роли — позволяют более гибко управлять доступами, связывая между собой группы и агентов
  • компании — позволяют изолировать заявки различных клиентов (будь то разные отделы или компании)

Постановка задачи

Вы — администратор системы OTRS в компании my-it-company.com, предоставляющей сервисные услуги другим компаниям (или подразделениям внутри вашего холдинга).

Вам очень бы не хотелось заводить учетные записи новых агентов и клиентов вручную, а также заполнять дополнительную информацию, такую как адрес электронной почты, телефон, должность, адрес и номер кабинета — ведь это все уже есть в каталогах LDAP.

И ваша компания также получит очевидные плюсы — единый пароль сотрудника во все системы, блокировка учетной записи в LDAP заблокирует доступ и во все остальные сервисы.

my-it-company.com работает на Linux и использует в качестве сервера каталогов Red Hat FreeIPA, а обслуживаемые вами подразделения — различные леса Microsoft Active Directory, с которыми у вас нет федерации, но есть возможность подключения к контроллерам домена.

Вам нужно разделить потоки заявок от различных клиентов, а также реализовать различные уровни доступа агентов к очередям — менеджеры должны иметь возможность менять приоритет задач в системе.

Сотрудники вашей компании так же могут ставить задачи в системе для внутренних нужд my-it-company.com, иногда являясь и агентами, и клиентами одновременно (а иногда и нет).

Подготовка

Учетные записи для просмотра LDAP

Если запрещен анонимный просмотр дерева каталогов, то создадим в доменах my-it-company.com, pear.com и macrohard.com учетные записи, прав которых нам хватит, чтобы делать запросы к LDAP (назовем их, например, ldap-bot)

Группы FreeIPA для синхронизации с ролями OTRS

Заведем на FreeIPA три группы пользователей, которые будут синхронизироваться с нашими ролями OTRS, например:

  • otrs-sa — члены этой группы получат доступ к администрированию OTRS, но доступ к очередям давать не будем, чтобы не было желания всегда работать под администратором),
  • otrs-admins — наши менеджеры, имеющие право изменения приоритета заявок) и
  • otrs-helpdesk — учетные записи наших специалистов

Атрибут, определяющий принадлежность к компании

Выберем атрибут, по которому будем определять принадлежность к компании. Пусть это будет атрибут «Организация». Например, у вас все получилось организационно и технически, и все пользователи во всех доменах всегда имеют значение в поле «Организация»:

  • my-it-company — для сотрудников my-it-company.com
  • pear-company — для сотрудников pear.com
  • macrohard-company — для сотрудников macrohard.com

Определим атрибуты пользователя, используемые FreeIPA

Изучим схему FreeIPA, выяснив названия атрибутов, которые нам понадобятся для синхронизации (ФИО, логин, телефон и т. п.).

dn: u > uid: laptevs
givenname: Stanislav
sn: Laptev
cn: Laptev Stanislav
mail: laptevs@MY-IT-COMPANY.COM
l: Moscow
telephonenumber: +7(863)999-99-99
mobile: +7(999)999-99-99
ou: My-it-company
title: SysAdm

Настройка конфигурации OTRS

Файлы конфигурации

Настройка агентов

Аутентификация агентов

Синхронизация агентов (групп LDAP с ролями OTRS)

Если вы решили, что роли вам не подходят, и вы хотите только группы, приведу два примера синхронизации групп LDAP с группами OTRS — упрощенный и с настройкой прав по каждой группе.

/привет/мир/etc

Периодические заметки о программировании

четверг, 31 октября 2013 г.

Что такое LDAP и с чем его едят

Эта статья — кратчайшее введение в LDAP и службы каталогов. Для иллюстрации излагаемого материала я буду пользоваться инструментом Softerra LDAP Browser, который можно свободно скачать с сайта производителя.

Концепцию служб каталогов и требования к их реализации определяет серия стандартов X.500 ITU-T. Здесь каталог — это специализированная база данных, оптимизированная для поиска и извлечения информации, также поддерживающая добавление и изменение данных.

Среди реализаций служб каталогов наиболее известные — OpenLDAP и MS Active Directory. Клиентами каталогов являются адресные книги почтовых клиентов, сетевые службы, такие как DNS, SMTP, корпоративные приложения и информационные системы.

Как правило, служба каталогов

  • реализует протокол для взаимодействия с клиентами,
  • поддерживает разграничение доступа,
  • поддерживает репликацию каталогов,
  • не поддерживает механизм транзакций.

Для взаимодействия со службами каталогов X.500 широко используется протокол LDAP (Lightweight Directory Access Protocol), специфицированный в RFC4510. LDAP работает поверх TCP/IP и является легковесной альтернативой протокола DAP (Directory Access Protocol), весьма требовательного к вычислительным ресурсам.

LDAP реализует протокол взаимодействия со службой каталогов и задает модель данных, соответствующую X.500. Эта модель данных такова:

  • В каталоге хранятся записи (entry).
  • Запись — это коллекция атрибутов (attribute), имеющая уникальное имя (Distinguished Name, DN).
  • Каждый атрибут имеет тип (type) и одно или несколько значений. Синтаксис значений зависит от типа.
  • Атрибут objectClass позволяет контролировать, какие атрибуты обязательны и какие допустимы в записи. Таким образом, записи, как и атрибуты, имеют тип (object class).
  • Записи в каталоге организованы иерархически в виде дерева.
  • Определения типов записей (object classes) и типов атрибутов сами являются записями в каталоге, в специальном поддереве, известном как schema.

Запустим Softerra LDAP Browser и откроем одну из публичных служб каталогов, параметры соединения с которыми предустановлены по умолчанию. (Настроив соединение с MS Active Directory или OpenLDAP в вашей корпоративной сети, вы можете исследовать структуру и содержимое корпоративного каталога.)

Иерархическая организация данных в каталоге часто отражает географическую или организационную структуру. Записи на верхнем уровне могут представлять страны, на нижних — области стран и организации, еще ниже — отделы внутри организаций, людей, оборудование, ресурсы. А можно построить дерево по доменным именам Internet.

Текущая выбранная запись в каталоге Carnegie Mellon University (см. картинку выше) имеет уникальное имя DN o=CMRI,o=CMU,dc=cmu,dc=edu . Компоненты DN — имена узлов иерархической структуры от корневого до текущего (справа налево). Самый левый компонент DN называется относительным уникальным именем (Relative Distinguished Name, RDN). Таким образом, DN o=CMRI,o=CMU,dc=cmu,dc=edu состоит из RDN o=CMRI и DN родительской записи o=CMU,dc=cmu,dc=edu .

Можно рассматривать DN как абсолютный путь к файлу (по аналогии с файловой системой) или как первичный ключ записи в таблице (по аналогии с реляционной БД).

В рассматриваемом DN o=CMRI,o=CMU,dc=cmu,dc=edu два верхних уровня названы по доменным именам Internet. А уровнем ниже текущей записи располагаются записи, идентифицируемые значением атрибута ou (см. картинку выше). Здесь имена атрибутов, идентифицирующие записи разных уровней, имеют следующие значения:

dc аббревиатура от domain component o аббревиатура от organization ou аббревиатура от organizational unit

Эти имена, как и десятки других, — имена стандартных атрибутов, специфицированных в RFC 2256 и предназначенных для использования в объектных классах, описывающих людей, организации, их подразделения и т.п. Все реализациии LDAP поддерживают эти стандартные типы атрибутов. Вот еще несколько примеров: telephoneNumber , name , givenName , postalAddress , sn (аббревиатура от surname).

В рассматриваемой записи с DN o=CMRI,o=CMU,dc=cmu,dc=edu имеются три атрибута, objectClass , o и businessCategory , по каждому из которых можно искать эту запись в каталоге.

Для поиска записей в LDAP-каталоге задаются три компонента:

base DN (базовое уникальное имя) показывает, откуда в иерархии начать поиск scope (область поиска) показывает область поиска, одно из:

  • одна запись, идентифицированная base DN
  • записи уровнем ниже base DN, т.е. дочерние, но не внучатые
  • поддерево с корнем base DN, включая корень

filter (фильтр) задает условие отбора записей

Например, поиск по условию

вернет все записи из поддерева с корнем o=CMU,dc=cmu,dc=edu , удовлетворяющие фильтру (синтаксис фильтра в этом примере легко читаемый, но неправильный, см. далее).

На заметку: cуществуют специальные базовые DN для запроса информации о возможностях сервера, для доступа к схеме (schema) и данным мониторинга.

В Softerra LDAP Browser по Ctrl+F3 вызывается окно поиска, в котором удобно экспериментировать с параметрами поиска LDAP:

В фильтре можно использовать следующие проверки для атрибутов (атрибут ou взят для примера):

Заметьте, что отсутствуют проверки > и . Проверка на приближенное равенство

= использует фонетические сравнение. Расширенная проверка для сравнения образца со значением атрибута использует реализованное LDAP-сервером правило, идентификатор которого указан после двоеточия. Примеры выражений для проверки наличия подстроки (звездочка означает 0 или более символов):

Проверки в фильтре можно комбинировать при помощи логических операторов:

Внимание! Последний фильтр с NOT вернет также записи, не содержащие атрибута cn .

Формируя запрос, можно указать типы атрибутов, которые должны быть включены сервером каталога в ответ. Если список типов атрибутов пуст, то окно поиска LDAP Browser отображает идентифицирующие атрибуты найденных записей (это RDN) и DN родительских записей — вместе они образуют DN найденных записей. Поиск LDAP всегда возвращает DN найденных записей, помимо и независимо от списка атрибутов. Зададим явно список атрибутов, которые мы хотим видеть и повторим запрос (несуществующие типы атрибутов в списке игнорируются сервером и не приводят к ошибке):

Чтобы хорошо освоить синтаксис фильтра, попробуйте разные проверки и их логические комбинации.

Как уже упоминалось, служба каталогов позволяет не только извлекать, но также добавлять и модифицировать записи. Softerra LDAP Browser поддерживает только просмотр данных в каталоге, поэтому для внесения изменений в каталог необходим другой инструмент (например, платный Softerra LDAP Administrator).

Для работы с LDAP практически из любого языка программирования можно воспользоваться существующими библиотекми для этого языка. В будущих статьях, посвященных LDAP, я рассмотрю работу с MS Active Directory в Oracle PL/SQL и в языке программирования Python.

XLIX. Функции LDAP

LDAP это Lightweight Directory Access Protocol — протокол, используемый для доступа к «Directory Servers». Directory это особый вид базы данных, которая содержит информацию как древовидную структуру.

Концепция аналогична структуре директорий жёсткого диска, но в данном контексте root/корневая директория это «The world/Земной шар», а первый уровень поддиректорий это «countries/страны». Ещё ниже идут уровни структуры директорий, содержащие вхождения для companies/компаний, organisations/организаций или мест, а ещё ниже находятся вхождения директорий для people/людей и, возможно, оборудования или документов.

Чтобы обратиться к файлу в поддиректории на жёстком диске, вы вводите что-нибудь вроде

Слэш отделяет каждое подразделение ссылки, а последовательность читается слева направо.

Эквивалентом для полной квалифицированной ссылки на файл в LDAP является «distinguished name/различительное имя», называемое просто «dn». Примером dn может быть:

cn=John Smith,ou=Accounts,o=My Company,c=US

Запятая работает как слэш, а последовательность читается справа налево. Вы можете прочитать это dn как .

country = US
organization = My Company
organizationalUnit = Accounts
commonName = John Smith

Точно так же, поскольку нет твёрдых правил организации структуры директорий на жёстком диске, directory server manager (менеждер сервера директорий) может настроить любую структуру, необходимую для осуществления поставленных задач. Однако есть некоторые соглашения, которые при этом используются: вы не можете записать код для доступа к серверу директорий, если не знаете его структуру, хотя можете использовать БД без знания того, что доступно.

Полный пример кода

Запрашиваем информацию для всех вхождений, где фамилия начинается с «S», с сервера директорий и отображаем их с именем и email-адресом.

Пример 1. Пример поиска LDAP

Использование вызовов PHP LDAP

Вам нужно получить и скомпилировать клиентские библиотеки LDAP из пакета ldap-3.3 University of Michigan или Netscape Directory SDK 3.0. Вам нужно также перекомпилировать PHP с включённой поддержкой LDAP, прежде чем вызовы PHP к LDAP заработают.

Прежде чем начать использование вызовов LDAP, вам необходимо знать:


Имя или адрес сервера директорий, который вы будете использовать

«base dn» сервера (часть world-директории, которая содержится на этом сервере, которая может быть «o=My Company,c=US»)

Нужен ли вам пароль для доступа к этому серверу (многие серверы предоставляют доступ для чтения для «anonymous bind», но требуют пароля для других действий)

Типичная последовательность вызова LDAP в вашем приложении будет соответствовать такому патэрну:

ldap_connect() // установить соединение с сервером
|
ldap_bind() // anonymous/анонимный или аутентифицированный «login»
|
сделать что-нибудь типа поиска или обновления директории
и вывести результаты
|
ldap_close() // «logout»

Дополнительная информация

Большое количество информации о LDAP можно найти на:

Netscape SDK содержит хороший Programmer’s Guide в формате .html.

как прокомментировать php родные ldap fuctions, такие как lda_connect, ldap_get_entries, ldap_search и ldap_read

У меня есть класс ниже, чтобы подключиться к серверу ldap, чтобы проверить, принадлежит ли пользователь группе или нет. Я хочу написать unit тест для этого класса. как мне это достичь. как издеваться над собственными функциями ldap php. может кто-то, пожалуйста, помогите мне с немного пример кода.

Взгляните на uopz — этот пакет позволяет переопределить собственные функции в PHP.

Пример использования ниже (см. Документы в Github, поскольку есть изменения между PHP 5 и 7).

uopz-2.0.x

uopz-5.0.x

Примечание: будьте осторожны с той версией, которую вы устанавливаете. >=5.x поддерживает PHP 7.x и поддерживает PHP 5.3.x

Обычно вам не нужно издеваться над этими функциями. Издевательство над ними на самом деле означает, что вы будете имитировать поведение сервера, которое может быть громоздким. У вас может быть недостаток в вашей реализации, который не работает с конкретным сервером ldap (настройка) или у вас есть недостаток в использовании вашего класса LdapAuthentication.

Это также связано с тем, что LdapAuthentication — это оболочка расширения PHP Ldap, что является хорошей практикой, поскольку вы защищаете остальную часть вашего приложения от конкретной библиотеки, чтобы вы могли менять ее с течением времени (например, обрабатывать некоторые различия в настройках и изменениях с течением времени).

Одна из стратегий для этого — тестирование интерфейса. У LdapAuthentication есть открытый интерфейс, который вы используете в своем приложении. Чтобы проверить правильность вашего интерфейса приложения с типом, вы должны издеваться над этим классом. Это будет охватывать публичный интерфейс.

С другой стороны, вы хотели бы проверить, работает ли аутентификатор с экземпляром сервера ldap. Для этого требуется набор test-, который предоставляет все функции, представляемые публичным интерфейсом, на конкретном сервере. Это эффективно проверяет интерфейс сервера. В Phpunit это могут быть два случая test-. Один для интерфейса открытого класса и один для тестирования интеграции для конфигурации (lnap-server) (test-).

Два интерфейса для тестирования:

С точки зрения вашего приложения, издевательство над внутренними функциями PHP (через расширение PHP Ldap) не должно быть необходимым для тестирования вашего приложения.

Чтобы протестировать интерфейс сервера Ldap, вам не нужно также имитировать эти функции, так как в этом случае вы действительно хотите проверить, работают ли все по-настоящему, а не в макете. Поэтому из этого теста интерфейса вы даже не хотите издеваться над этими внутренними функциями, вы действительно хотите их использовать.

Как издевательский класс, представляющий взаимодействие с сервером, может быть сложным и динамически настраивать макеты для таких интенсивных типов взаимодействия, может быть громоздким, вам стоит подумать о том, чтобы написать макет объекта LdapAuthentication в простой PHP-кодировке краткую функциональность, которую вы ожидаете от этого класса с примерами данных.

То есть вы пишете вторую реализацию LdapAuthentication, давайте назовите ее LdapAuthenticationMock, которая ведет себя так, как вы ожидаете. Обычно он размещается рядом с модульным тестом, который находится в том же каталоге, что и LdapAuthenticationTest (блок test-).

Но прежде чем вы сможете создать такой макет, который удовлетворяет общему интерфейсу LdapAuthentication, сначала нужно выполнить некоторую рефакторингу. Хорошая его часть заключается в том, что ваше общее применение выиграет от этого, а не только для тестирования.

Эта дополнительная работа заключается в извлечении интерфейса из LdapAuthentication. Извлечение интерфейса означает, что вы создаете интерфейс (см. PHP-интерфейсы) с тем же именем, который содержит те общедоступные методы, которые вы используете в своем приложении:

Теперь, поскольку вы не можете иметь интерфейсы и классы с одинаковым именем, вы переименуете свой класс LdapAuthentication в другое имя, реализующее интерфейс:

(Пожалуйста, обратите внимание, что имя просто образцовое, вы должны быть в состоянии лучше подойти)

Главное преимущество этого заключается в том, что теперь вы можете программировать против интерфейса вместо конкретного типа. Если вы называете интерфейс, как вы назвали класс в вашем текущем коде (так сказать, как вы его назвали ранее), ваш существующий код автоматически переходит от программирования к конкретному типу к программированию с интерфейсом. Например, подсказки типа теперь принимают любую реализацию.

Это позволяет вам обменивать реализацию (т.е. Вы можете вносить изменения в подклассы или переписывать реализацию даже в новом классе, например, тот, который использует другую библиотеку ldap или для другого типа ldap-сервера без нарушая остальную часть вашего кода).

Одна из таких новых реализаций, например, станет LdapAuthenticationMock:

Затем вы можете передать его в тестах, чтобы проверить код приложения без использования ldap-сервера или даже этого расширения ldap PHP. Благодаря интерфейсу PHP уведомит вас, если вы его не внедрили полностью.

Рядом с тестом mock (который работает больше, чем вы записываете, как вы ожидаете, что этот класс будет работать, часто тесты записывают спецификацию в кодовом порядке), вам также нужен интеграционный тест конкретной реализации, который у вас есть против Ldap (test-), FooLdapAuthenticationTest.

Написание этих тестов поможет вам написать аутентификацию Ldap в изолированных случаях test- без запуска всего вашего приложения. Затем приложение — благодаря программированию против интерфейсов — может быть записано без дополнительной информации о деталях реализации FooLdapAuthentication или любой другой LdapAuthentication.

Таким образом, при тестировании интерфейса вы можете тестировать как свои классы приложений, так и сервер, и вы можете вносить изменения в том месте, где они принадлежат (или обрабатывать изменения в интерфейсе сервера без необходимости изменения всего приложения).

Имея макет как конкретный класс PHP, также имеет то преимущество, что вам не нужно настраивать его интенсивно снова и снова для других тестов, которые должны взаимодействовать с LdapAuthentication, вы просто вводите этот макет.

Если вы правильно настроили автозагрузчик, это довольно просто. Никакое громоздкое издевательство над внутренними функциями, легкое для написания модульных тестов, которым требуется LdapAuthentication для работы и всестороннего тестирования интеграции с интерфейсом сервера, возможно таким образом.

Это один из способов преодоления проблем, которые создают интеграционные тесты:

Покрытие: часто не хватает тестов интеграции (покрываемых через интерфейс PHP, любая реализация должна выполнить интерфейс 100%, иначе он не запустится)

Сложность: тесты интеграции не показывают точной причины ошибки (вы замечаете проблему с сервером где-то в вашем коде приложения, а код приложения просто ожидает, что ваша реализация выполнит работу, а не ошибку)

В более продвинутой настройке test- весь серверный интерфейс на уровне сетевого протокола также будет абстрагирован, чтобы вы могли протестировать конкретный сервер, чтобы он соответствовал ожидаемому интерфейсу в обоих направлениях. То же самое для клиентской стороны, снова и снова. Однако это, несомненно, оставит область PHP здесь. С учетом моего предложения вы по крайней мере отделите свое приложение от интерфейса сервера, введя интерфейс PHP между ними. У вас все еще будет интеграционный тест для конкретного (test-) сервера, поэтому общая проблема теста интеграции будет уменьшена и ограничена (более конкретной) интеграцией test-. Поскольку вы часто зависите от более или менее конкретного сервера, я думаю, что этот ярлык подходит, пока вы не обнаружите дальнейшие (регрессионные) потребности в тестировании.

Илон Маск рекомендует:  Поиск уязвимостей в программах с помощью анализаторов кода
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL