Предпосылки: В организации, сведения о которой ведутся в нашем каталоге, два отдела: Developers и Designers. Информация о принадлежности пользователя отделу фиксируется как значение атрибута ou
в учётной записи каждого пользователя. Разграничение доступа на сервере VPN-подключений организации решено выполнить на основании принадлежности пользователей POSIX-группам соответствующих отделов.
Задача: Требуется создать POSIX-группы, постоянно отражающие актуальную структуру организации.
Как мы помним, POSIX-группы представляют собой записи-списки, в которых в значениях атрибута memberUid
перечислены текстовые имена учётных записей пользователей UNIX, соответствующие тем, которые указываются в значении атрибута uid
записей пользователей в каталоге. Как видно, имена атрибутов, содержащих нужную нам информацию, в записях пользователей и записях-списках не совпадают, и напрямую построить динамический список нужного формата не получится. Но наложение dynlist
позволяет при построении динамических списков выполнять перезапись имён атрибутов, чем мы и воспользуемся.
Начинать, как всегда, будем с исходного положения каталога. В данном примере порядок работы будет такой: настройка наложения, добавление записей динамических списков, модификация записей пользователей.
Первым делом нужно подгрузить модуль нашего наложения в работающий сервер slapd
. Для этого требуется внести изменения в запись cn=module{0},cn=config
:
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: dynlist.la
Подгрузим наш модуль и убедимся, что он загружен:
$ ldapmodify -x -D cn=config -W -f ./101-add_dynlist_module.ldif Enter LDAP Password: modifying entry "cn=module{0},cn=config" $ ldapsearch -xLLL -D cn=config -W -b cn=module{0},cn=config olcModuleLoad Enter LDAP Password: dn: cn=module{0},cn=config olcModuleLoad: {0}back_mdb.la olcModuleLoad: {1}dynlist.la
Переходим к настройкам наложения. Для данного примера мы сформируем такую запись наложения с объектным классом olcDynamicList
(дочернюю по отношению к рабочей базе данных):
dn: olcOverlay=dynlist,olcDatabase={1}mdb,cn=config
objectClass: olcDynamicList
olcOverlay: dynlist
olcDLattrSet: posixGroup labeledURI memberUid:uid
Параметры работы наложения задаются значением атрибута olcDLattrSet
(строка 4). В данном случае у нас три разделённых пробелами параметра: имя объектного класса (posixGroup
), имя типа атрибута (labeledURI
), а также определение правила перезаписи имени атрибута (memberUid:uid
). Назначение первых двух параметров мы подробно разбирали в предыдущем примере: это объектный класс и тип атрибута, по которым наложение dynlist
отбирает среди результирующего набора операции поиска LDAP те записи, которые требуется дополнить динамическим содержимым. Обратите внимание, что для данного примера мы выбрали "нетипичные" для наложения dynlist
класс и тип атрибута. Отчасти это сделано для того, чтобы продемонстрировать, что с наложением dynlist
можно использовать любые известные серверу slapd
классы и типы атрибутов. Другая же причина в том, что многие приложения, проверяющие права пользователей на основе сведений из каталога, понимают класс posixGroup
как "стандартный", к тому же на нём как раз и строятся POSIX-группы.
Наиболее интересен для нас третий параметр настройки наложения. В данном примере он представляет собой два имени атрибута, разделённых символом двоеточия. Такой синтаксис говорит о том, что наложению задаётся правило перезаписи имён атрибутов, которое формулируется так: если среди атрибутов, возвращаемых в результате вторичного поискового запроса, выполняемого с целью сбора динамического содержимого записи, будут возвращены атрибуты типа uid
, то в них имя атрибута будет заменено на memberUid
. Значение же атрибута останется неизменным. Простое действие, которое позволит сформировать запись-список, полностью отвечающий условию нашей задачи.
Следует отметить, что в настройках наложения dynlist
можно задавать несколько таких правил перезаписи, отделяя их друг от друга пробелом. Но для нашей задачи это не требуется.
Итак, добавим нашу запись с настройками наложения и убедимся в её наличии:
$ ldapadd -x -D cn=config -W -f ./102-add_dynlist_overlay.ldif Enter LDAP Password: adding new entry "olcOverlay=dynlist,olcDatabase={1}mdb,cn=config" $ ldapsearch -xLLL -D cn=config -W -b olcDatabase={1}mdb,cn=config -s one Enter LDAP Password: dn: olcOverlay={0}dynlist,olcDatabase={1}mdb,cn=config objectClass: olcDynamicList olcOverlay: {0}dynlist olcDlAttrSet: {0}posixGroup labeledURI memberUid:uid
Наложение стало первым (индекс 0) для нашей рабочей базы данных. Пора переходить к следующему этапу.
По условиям задачи составим определения динамических списков (POSIX-групп) для наших отделов Developers и Designers, поместив их в отдельный контейнер с именем PosixGroups:
dn: ou=PosixGroups,dc=mycompany,dc=ru
objectClass: organizationalUnit
ou: PosixGroups
dn: cn=Developers,ou=PosixGroups,dc=mycompany,dc=ru
objectClass: posixGroup
objectClass: labeledURIObject
cn: Developers
gidNumber: 10001
labeledURI: ldap:///ou=People,dc=mycompany,dc=ru?uid?one?(&(objectClass=inetOrgPerson)(ou=Developers))
dn: cn=Designers,ou=PosixGroups,dc=mycompany,dc=ru
objectClass: posixGroup
objectClass: labeledURIObject
cn: Designers
gidNumber: 10002
labeledURI: ldap:///ou=People,dc=mycompany,dc=ru?uid?one?(&(objectClass=inetOrgPerson)(ou=Designers))
Записи POSIX-групп строятся на структурном объектном классе posixGroup
, его обязательные атрибуты cn
(который мы использовали для формирования RDN) и gidNumber
(наследие NIS для хранения числового идентификатора группы в UNIX). Условия для поиска динамического содержимого оформлены в виде LDAP URI в значениях атрибутов labeledURI
динамических записей (строки 10 и 17). Поскольку тип атрибута labeledURI
не входит в число обязательных или допустимых атрибутов класса posixGroup
, для включения таких атрибутов в наши записи мы воспользовались вспомогательным объектным классом labeledURIObject
, содержащим этот тип атрибута и позволяющим включить его в запись.
Сами LDAP URI мало чем отличаются от подробно разобранных нами в предыдущем примере URI: согласно указанных в них критериев поиска, среди записей пользователей будут отобраны те, у которых есть признак принадлежности к конкретному отделу. Отличается только список возвращаемых атрибутов (4-й компонент URI): в данном случае из найденных записей будут извлекаться только атрибуты uid
.
Добавим наши записи в каталог:
$ ldapadd -D cn=manager,ou=System,dc=mycompany,dc=ru -W -f ./002-add_posix_groups.ldif Enter LDAP Password: adding new entry "ou=PosixGroups,dc=mycompany,dc=ru" adding new entry "cn=Developers,ou=PosixGroups,dc=mycompany,dc=ru" adding new entry "cn=Designers,ou=PosixGroups,dc=mycompany,dc=ru"
Посмотрим, что получилось:
$ ldapsearch -xLLL -b dc=mycompany,dc=ru -o ldif-wrap=no '(objectClass=posixGroup)' dn: cn=Developers,ou=PosixGroups,dc=mycompany,dc=ru objectClass: posixGroup objectClass: labeledURIObject cn: Developers gidNumber: 10001 labeledURI: ldap:///ou=People,dc=mycompany,dc=ru?uid?one?(&(objectClass=inetOrgPerson)(ou=Developers)) dn: cn=Designers,ou=PosixGroups,dc=mycompany,dc=ru objectClass: posixGroup objectClass: labeledURIObject cn: Designers gidNumber: 10002 labeledURI: ldap:///ou=People,dc=mycompany,dc=ru?uid?one?(&(objectClass=inetOrgPerson)(ou=Designers))
А где же, собственно, атрибуты принадлежности списку memberUid
, то есть динамическое содержимое записей? Что-то пошло не так и наложение dynlist
не сработало? Да нет, всё так, просто в наших записях пользователей ещё нет признака принадлежности отделу.
Дополним записи пользователей признаком принадлежности к отделам. Для этого сформируем такой LDIF-файл:
dn: uid=antonova,ou=People,dc=mycompany,dc=ru
changetype: modify
add: ou
ou: Designers
dn: uid=ivanov,ou=People,dc=mycompany,dc=ru
changetype: modify
add: ou
ou: Developers
dn: uid=petrov,ou=People,dc=mycompany,dc=ru
changetype: modify
add: ou
ou: Developers
dn: uid=sidorov,ou=People,dc=mycompany,dc=ru
changetype: modify
add: ou
ou: Designers
Применим его к нашему каталогу и посмотрим, в каком состоянии будут наши учётки после модификации:
$ ldapmodify -x -D cn=manager,ou=System,dc=mycompany,dc=ru -W -f ./003-add_users_attributes.ldif Enter LDAP Password: modifying entry "uid=antonova,ou=People,dc=mycompany,dc=ru" modifying entry "uid=ivanov,ou=People,dc=mycompany,dc=ru" modifying entry "uid=petrov,ou=People,dc=mycompany,dc=ru" modifying entry "uid=sidorov,ou=People,dc=mycompany,dc=ru" $ ldapsearch -xLLL -b ou=People,dc=mycompany,dc=ru -s one dn: uid=ivanov,ou=People,dc=mycompany,dc=ru objectClass: inetOrgPerson uid: ivanov cn: Ivan Ivanov sn: Ivanov ou: Developers dn: uid=petrov,ou=People,dc=mycompany,dc=ru objectClass: inetOrgPerson uid: petrov cn: Petr Petrov sn: Petrov ou: Developers dn: uid=sidorov,ou=People,dc=mycompany,dc=ru objectClass: inetOrgPerson uid: sidorov cn: Sidor Sidorov sn: Sidorov ou: Designers dn: uid=antonova,ou=People,dc=mycompany,dc=ru objectClass: inetOrgPerson uid: antonova cn: Antonina Antonova sn: Antonova ou: Designers
Всё в порядке. А теперь ещё раз запросим наши POSIX-группы:
$ ldapsearch -xLLL -b dc=mycompany,dc=ru -o ldif-wrap=no '(objectClass=posixGroup)' dn: cn=Developers,ou=PosixGroups,dc=mycompany,dc=ru objectClass: posixGroup objectClass: labeledURIObject cn: Developers gidNumber: 10001 labeledURI: ldap:///ou=People,dc=mycompany,dc=ru?uid?one?(&(objectClass=inetOrgPerson)(ou=Developers)) memberUid: ivanov memberUid: petrov dn: cn=Designers,ou=PosixGroups,dc=mycompany,dc=ru objectClass: posixGroup objectClass: labeledURIObject cn: Designers gidNumber: 10002 labeledURI: ldap:///ou=People,dc=mycompany,dc=ru?uid?one?(&(objectClass=inetOrgPerson)(ou=Designers)) memberUid: antonova memberUid: sidorov
Как видно, наше наложение успешно справилось и с задачей наполнения записей динамическим содержимым, и с перезаписью имён атрибутов: у нас получились корректные POSIX-группы с нужными атрибутами членства в них.
У наложения dynlist
есть ещё один параметр настройки, с помощью которого можно ограничить область действия наложения. Чтобы не нарушать очерёдность перечисления параметров наложения, мы будем называть его промежуточным параметром, поскольку, при необходимости, его можно указать между первым (имя объектного класса, на который срабатывает наложение) и вторым параметром (имя атрибута, в котором указаны критерии вторичного поиска). То есть, если вслед за первым параметром в настройках наложения вместо имени атрибута указан LDAP URI, то наложение будет воспринимать его как тот самый промежуточный параметр.
Итак, промежуточный параметр представляет собой LDAP URI, с помощью компонентов которого (базовой записи, поискового диапазона и фильтра отбора) задаётся область действия наложения. При указании промежуточного параметра наложение будет применяться не ко всем записям, попавшим в результирующий набор первоначальной операции поиска, а только к подмножеству этих записей, удовлетворяющих условиям, заданным в URI этого параметра.
Разберём применение промежуточного параметра на примере. Допустим, в ветку ou=Groups,dc=mycompany,dc=ru также добавляются записи, на которые будет реагировать наложение dynlist
с указанными нами настройками:
dn: cn=Developers2,ou=Groups,dc=mycompany,dc=ru
objectClass: posixGroup
objectClass: labeledURIObject
cn: Developers2
gidNumber: 10011
labeledURI: ldap:///ou=People,dc=mycompany,dc=ru?uid?one?(&(objectClass=inetOrgPerson)(ou=Developers))
dn: cn=Designers2,ou=Groups,dc=mycompany,dc=ru
objectClass: posixGroup
objectClass: labeledURIObject
cn: Designers2
gidNumber: 10012
labeledURI: ldap:///ou=People,dc=mycompany,dc=ru?uid?one?(&(objectClass=inetOrgPerson)(ou=Designers))
Добавим эти записи в каталог:
$ ldapadd -D cn=manager,ou=System,dc=mycompany,dc=ru -W -f ./004-add_posix_groups2.ldif Enter LDAP Password: adding new entry "cn=Developers2,ou=Groups,dc=mycompany,dc=ru" adding new entry "cn=Designers2,ou=Groups,dc=mycompany,dc=ru"
Проверим работу наложения dynlist
:
$ ldapsearch -xLLL -b dc=mycompany,dc=ru -o ldif-wrap=no '(objectClass=posixGroup)' memberUid dn: cn=Developers,ou=PosixGroups,dc=mycompany,dc=ru memberUid: ivanov memberUid: petrov dn: cn=Designers,ou=PosixGroups,dc=mycompany,dc=ru memberUid: antonova memberUid: sidorov dn: cn=Developers2,ou=Groups,dc=mycompany,dc=ru memberUid: ivanov memberUid: petrov dn: cn=Designers2,ou=Groups,dc=mycompany,dc=ru memberUid: antonova memberUid: sidorov
Наложение отработало великолепно: все четыре наших POSIX-группы дополнились динамическим содержимым.
А теперь попытаемся ограничить область действия наложения так, чтобы динамическим содержимым дополнялись только записи в ветке ou=PosixGroups,dc=mycompany,dc=ru. Дополним настройки наложения промежуточным параметром:
dn: olcOverlay={0}dynlist,olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcDLattrSet
olcDLattrSet: posixGroup ldap:///ou=PosixGroups,dc=mycompany,dc=ru??one? labeledURI memberUid:uid
Интересующие нас изменения представлены в строке 4. В параметрах наложения между именем объектного класса (posixGroup
) и именем типа атрибута (labeledURI
) мы поместили LDAP URI — тот самый промежуточный параметр. Согласно критериям, заданным компонентами этого URI, наложение будет обрабатывать только записи, непосредственно дочерние (диапазон one) записи ou=PosixGroups,dc=mycompany,dc=ru. Поисковый фильтр не задан, поэтому будут рассматриваться все записи, отвечающие первым двум критериям.
Применим наши изменения и проверим:
$ ldapmodify -x -D cn=config -W -f ./103-modify_dynlist_overlay.ldif Enter LDAP Password: modifying entry "olcOverlay={0}dynlist,olcDatabase={1}mdb,cn=config" $ ldapsearch -xLLL -D cn=config -W -b olcDatabase={1}mdb,cn=config -s one -o ldif-wrap=no Enter LDAP Password: dn: olcOverlay={0}dynlist,olcDatabase={1}mdb,cn=config objectClass: olcDynamicList olcOverlay: {0}dynlist olcDlAttrSet: {0}posixGroup ldap:///ou=PosixGroups,dc=mycompany,dc=ru??one? labeledURI memberUid:uid
Теперь посмотрим, как это повлияло на работу нашего наложения:
$ ldapsearch -xLLL -b dc=mycompany,dc=ru -o ldif-wrap=no '(objectClass=posixGroup)' memberUid dn: cn=Developers,ou=PosixGroups,dc=mycompany,dc=ru memberUid: ivanov memberUid: petrov dn: cn=Designers,ou=PosixGroups,dc=mycompany,dc=ru memberUid: antonova memberUid: sidorov dn: cn=Developers2,ou=Groups,dc=mycompany,dc=ru dn: cn=Designers2,ou=Groups,dc=mycompany,dc=ru
Как видно, записи в ветке ou=Groups,dc=mycompany,dc=ru не получили динамического содержимого, следовательно, наши ограничения работают.
В ходе этого урока мы познакомились с одним из вариантов третьего параметра настроек наложения dynlist
, отвечающим за перезапись имён атрибутов при построении динамического содержимого. Кроме того, была рассмотрена возможность установки ограничений на область действия наложения с помощью промежуточного параметра в настройках. Итоговые настройки каталога dc=mycompany,dc=ru выглядят так:
$ ldapsearch -xLLL -o ldif-wrap=no -D cn=config -W -b olcDatabase={1}mdb,cn=config Enter LDAP Password: dn: olcDatabase={1}mdb,cn=config objectClass: olcMdbConfig olcDatabase: {1}mdb olcDbDirectory: /var/lib/ldap/dc=mycompany,dc=ru olcSuffix: dc=mycompany,dc=ru olcAccess: {0}to attrs=userPassword by self write by anonymous auth by * none olcAccess: {1}to * by self write by * read olcRootDN: cn=manager,ou=System,dc=mycompany,dc=ru olcRootPW: {SSHA}PKFrwbIL/zLd3gabPPLxn1vNq2jQHj4g olcDbIndex: objectClass eq olcDbIndex: cn eq,sub,subinitial dn: olcOverlay={0}dynlist,olcDatabase={1}mdb,cn=config objectClass: olcDynamicList olcOverlay: {0}dynlist olcDlAttrSet: {0}posixGroup ldap:///ou=PosixGroups,dc=mycompany,dc=ru??one? labeledURI memberUid:uid