Навигация
Главная »  IBM 

Работа с данными Active Directory c помощью сценариев: Часть 2. Совместное использование Bourne Shell и утилиты ldapsearch


Источник: ibm
Рашид Ачилов
Введение

В данной статье мы попробуем решить конкретную задачу: с помощью программы Sarg сформировать так называемый usertab-файл, в котором определяется соответствие учетных записей пользователей, использованных в процессе аутентификации в squid, и их настоящих имен. В результате должен быть получен отчет примерно такого вида:

ivanov-iv		Иванов Иван petrov-pp		Петров Петр root			Администратор 

Для этого потребуется выполнить действия, практически аналогичные действиям, выполнявшимся в предыдущей статье вручную:

  1. подключение к LDAP с соответствующим фильтром и списком полей;
  2. получение и вывод данных;
  3. преобразование полученной информации и сохранение её в виде файла.
Подготовка к работе

Нас интересуют только поля displayName и sAMAccountName. Сценарий будет называться ldapshtest. Так как это демонстрационный сценарий, а не полная версия (которая должна содержать больше элементов и исполняться в соответствующем окружении), то некоторые фрагменты будут опущены и рассматриваться будут только те фрагменты, которые непосредственно отвечают за выполнение интересующих действий. Данный сценарий будет использовать конфигурационный файл типового формата, показанный в листинге 1, в котором собраны настройки подключения к LDAP.

Листинг 1. Конфигурационный файл сценария ldapshtest
ldap_server=192.168.50.1 ldap_basedn="dc=shelton,dc=int" ldap_binddn=ldapread@SHELTON.INT ldap_password="cXdlcnR5YXNkZgo 1" ldap_common_filter="(&(sAMAccountName=*)(sAMAccountType=805306368)(telephoneNumber=*))" etcdir=/usr/local/etc sargdir=sarg2 sargfile=sargusers 

В листинге 6 все должно быть понятно кроме пароля. Он записан в таком странном формате по нескольким причинам. Конечно, не следует хранить пароли в открытом виде. Но в то же время трудно найти обратимую функцию, чтобы надежно зашифровать пароль и потом также надежно его расшифровать. Поэтому был выбран компромисс - простейшее преобразование формата, а не шифр. Точнее говоря, это преобразование Base64, у которого отброшены заполнители и вместо них проставлено их количество. Этот пароль можно привести к исходному состоянию с помощью несложной процедуры, приведенной в листинге 2.

Листинг 2. Процедура обратного преобразования пароля
# обратное преобразование строки пароля # вход:		$1 enconved (строка)    	- пароль из файла конфигурации # выход:		_passwd			- пароль в текстовом виде demux_passwd() { local _ideconv _iadd _ifill _ifill="=" _ideconv=$1 if [ ! $2 -eq 0 ]; then _iadd=$2 while [ $_iadd -gt 0 ]; do _ideconv=$_ideconv$_ifill _iadd=$(($_iadd-1)) done fi _passwd=`echo $_ideconv / $util_mmencode -u` } 

Особых пояснений этот код тоже не требует: если второй параметр не нуль, то циклом в конец строки дописывается столько символов заполнителей, сколько было передано во втором параметре, а затем строка декодируется. Внешняя переменная $util_mmencode содержит путь к программе mmencode.

Алгоритм работы создаваемого сценария состоит из нескольких этапов. После предварительной части (загрузка конфигурационного файла, разбор командной строки, поиск необходимых программ) сценарий "расшифровывает" пароль и создает временный каталог для работы. Потом выполняется подключение к LDAP, откуда загружаются учетные записи и имена пользователей, которые сохраняются во временных файлах. Часть кода опущена, ссылку на полную версию можно найти в разделе "Материалы для скачивания". В листинге 3 приведен только код, представляющий интерес.

Листинг 3. Основная процедура сценария
safe_logger "LDAPQuery ver. $revisionNumber started" # обратное преобразование пароля demux_passwd $ldap_password _ldap_pwd=$_passwd # создать временный каталог, если он еще не создан и перейти в него make_tempdir # выполнить поиск учетных записей пользователей в LDAP и сохранить результат ldap_data_query sAMAccountName $tempdir/users.ldif # преобразовать данные в читаемый вид ldap_data_deconvert $tempdir/users.ldif $tempdir/users.list # выполнить поиск имен пользователей в LDAP и сохранить результат ldap_data_query displayName $tempdir/names.ldif # преобразовать данные в читаемый вид ldap_data_deconvert $tempdir/names.ldif $tempdir/names.list # сравнить списки и добавить в файл sargusers отсутствующие учетные записи ldapusers=`cat $tempdir/users.list` sargusers=`cat $etcdir/$sargdir/$sarglist / awk '{print $1}'` IFS=$newline _added=0 # внешний цикл по списку пользователей из LDAP for _oneldapuser in $ldapusers do _togo=0 # внутренний цикл по списку пользователей Sarg for _onesarguser in $sargusers do # если пользователь найден, то прервать внутренний и внешний циклы # и перейти к следующей записи внешнего цикла if [ $_oneldapuser = $_onesargluser ]; then continue 2 fi done # если мы находимся здесь - пользователь LDAP не найден в списке пользователей Sarg. # следует записать в список пользователей Sarg # строку с учетной записью из users.list и именем пользователя из names.list _oneusername=`cat $tempdir/names.list / tail -n +$_togo / head -n 1` echo -e "$_oneldapuser \t$_oneusername\n" >> $etcdir/$sargdir/$sarglist _togo=$(($_togo+1)) _added=$(($_added+1)) done 

Код до начала сравнения списков интуитивно понятен: идут вызовы процедур для получения данных из LDAP и их последующего преобразования. Далее выполняются два вложенных цикла для сравнения двух списков. Первый список - это список полученных из LDAP учетных записей, второй - список учетных записей пользователей, уже присутствующих в файле. Он получается с помощью простейшей команды на awk. Суть его в том, что оба списка считываются в переменные, затем берется один элемент "внешнего" списка и последовательно сравнивается со всеми элементами "внутреннего" списка. Когда находится совпадение, выполняются необходимые действия, потом внешний цикл (в Bourne Shell можно указать оператору break или continue число уровней вложенности, на которые он одновременно воздействует) переходит к следующему элементу.

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

Основной интерес представляют процедуры ldap_data_query() и ldap_data_deconvert(). Первая процедура всего лишь вызывает утилиту ldapsearch, передавая ей все необходимые параметры из конфигурационного файла и список переданных параметров. Единственное, что выполняется перед вызовом ldapsearch - это замена запятых в списке запрашиваемых полей на пробелы. Код процедуры ldap_data_query() приведен в листинге 4.

Листинг 4. Процедура ldap_data_query()
# запросить некоторые данные у LDAP сервера # вход:	$1 fieldname (строка) 	- имя атрибута(ов), запрашиваемых в AD #		$2 outfile (строка) - имя файла для сохранения полученных данных # выход:	none ldap_data_query() { local _ldapfield _outfile _ldapfield=`echo $1 / sed -e "s:,: :g"` _outfile=$2 # выполнить запрос к LDAP и сохранить результат $util_ldapsearch -T $tempdir -D $ldap_binddn -w $_ldap_pwd -LLL                    -h $ldap_server -b $ldap_basedn -P 3                    -a always $ldap_common_filter $_ldapfield > $_outfile   # проверить код возврата status=$? if [ $status -ne 0 ]; then safe_logger "Unable to complete LDAP request to get $_ldapfield from AD" exit fi } 

В листинге 5 приведены вспомогательные процедуры unspace() и make_tempdir().

Листинг 5. Процедуры unspace() и make_tempdir()
# удалить пробелы и строки комментариев из файла # вход:	$1 source (строка)		- имя исходного файла #		$2 destination (строка) 	- имя файла результата # выход:	none _unspace() { cat $1 / grep -v ^# / sed -e "s: ::g" > $2 } # создать временный каталог, если он еще не был создан и перейти в него # вход:		none # выход:		tempdir (строка) 	- имя временного каталога make_tempdir() { if [ ${#tempdir} -eq 0 ]; then tempdir=`mktemp -d /tmp/adphones.XXXXXX` fi cd $tempdir } 

Процедура unspace() удаляет из файла, заданного первым параметром, все пробелы и все строки, начинающиеся с символа "#". В итоге на выходе будут только строки вывода ldapsearch. Процедура make_tempdir() создает временный каталог с уникальным именем, если такового еще не было создано. Сделано это для удобства использования данного сценария из других сценариев, чтобы избежать гонок (race condition).

Заключение

В данной статье был рассмотрен основной алгоритм выполнения запросов к LDAP через сценарии оболочки с помощью утилиты ldapsearch. В следующей статье мы рассмотрим дополнительные аспекты обращения к LDAP из сценариев Bourne Shell.

Загрузка

Имя Размер Метод загрузки
ldapshtst.tar.bz2 5KB HTTP 


 

 Гибкая разработка программного обеспечения с применением уже имеющихся инструментов CCM.
 Решение IBM Rational для разработки технических систем
и встраиваемого ПО.

 Какой ты программист?.
 Пять полезных советов по использованию гибких методов при разработке критически важных систем.
 IBM Business Process Manager Standard.


Главная »  IBM 

© 2018 Team.Furia.Ru.
Частичное копирование материалов разрешено.