Первый шаг по расширению схемы данных — указание флага --use-rfc2307
при инициализации samba:
# samba-tool domain provision <...> --use-rfc2307
Сразу необходимо отметить, что этот процесс необратим, то есть удалить добавленный набор схемы нельзя (по крайней мере, я пока не нашёл, как это сделать). Поэтому, прежде чем вносить изменения в схему данных, надо чётко сформулировать себе цель, для достижения которой это делается.
Кроме того, расширение схемы — потенциально опасная операция, лучше создать резервную копию.
Цель: Интеграция каталога samba4 с почтовыми системами (postfix, qmail, courier, exim и другие).
Задача: Добавить к учётной записи пользователя вспомогательный объектный класс qmailUser
из набора схемы qmail.schema
и несколько атрибутов из этого объектного класса. Другими словами, применить к учётной записи пользователя следующий ldif-файл (/tmp/user_update.ldif
):
dn: CN=Test User,CN=Users,DC=samba4,DC=lab changetype: modify add: objectClass objectClass: qmailUser - add: mail mail: test_user@samba4.lab - add: mailAlternateAddress mailAlternateAddress: test_user@somewhere.else.ru - add: mailMessageStore mailMessageStore: samba4lab/test_user - add: deliveryProgramPath deliveryProgramPath: /var/mail
Порядок действий:
Берём где-либо требуемый набор схемы в формате .schema
(не .ldif
!) и копируем его в доступную нам директорию файловой системы. Пусть, для определённости, это будет директория /tmp.
Выполняем преобразование набора с помощью утилиты oLschema2ldif
из набора samba4:
# oLschema2ldif -b DC=samba4,DC=lab -I /tmp/qmail.schema -O /tmp/qmail.samba4.ldif Converted 41 records with 0 failures
Аргументы командной строки тут достаточно прозрачны: -b
определяет DN базовой записи каталога, а -I
и -O
— входной и выходной файлы.
Возможная ошибка:
Invalid entry attributetype ( <...> ), closing braces needs to be preceeded by a spaceговорит о том, что в неряшливо составленном файле набора схемы нет пробела перед последней закрывающейся скобкой в определении типа атрибута. Нужно найти это определение, добавить необходимый пробел и выполнить преобразование заново.
Набор схемы есть, самое время его добавить. Здесь необходимо отметить, что по умолчанию модификация схемы данных в samba4 запрещена, но разрешить её довольно просто. Первый путь — указать соответствующую директиву в секции [global]
файла smb.conf
:
[global] <...> dsdb:schema update allowed = yes <...>Альтернативный путь — указать ту же самую директиву в качестве опции при вызове инструмента работы с базой данных LDB:
# ldbmodify <...> --option="dsdb:schema update allowed"=true
Мне больше нравится второй способ: защита от непреднамеренных ошибок (что-то вроде флага --yes-i-know-what-i-am-doing
в некоторых программах).
Вопреки официальному руководству сразу добавить сформированный набор схемы данных в каталог мне не удалось:
# ldbadd -H /opt/samba-4.1.2/private/sam.ldb /tmp/qmail.samba4.ldif --option="dsdb:schema update allowed"=true Unable to find attribute mailMessageStore in the schema ERR: Invalid attribute syntax : "objectclass_attrs: attribute 'mayContain' on entry 'CN=qmailUser,CN=Schema,CN=Configuration,DC=samba4,DC=lab' contains at least one invalid value!" on DN CN=qmailUser,CN=Schema,CN=Configuration,DC=samba4,DC=lab at block before line 520 Added 38 records successfully
Попросту говоря, при добавлении объектного класса не найдены только что добавленные типы атрибутов (38 records). Пришлось разбивать полученный набор схемы на две части: отдельно определение типов атрибутов, отдельно определение объектных классов. Для этого можно воспользоваться любым текстовым редактором или придумать что-то более замороченное в стиле unix-way:
# perl -00 -wne 'print if /attributeSchema/' /tmp/qmail.samba4.ldif > /tmp/qmail.samba4-at.ldif # perl -00 -wne 'print if /classSchema/' /tmp/qmail.samba4.ldif > /tmp/qmail.samba4-oc.ldif
Поскольку типы атрибутов у нас уже добавлены, остаётся добавить объектные классы:
# ldbadd -H /opt/samba-4.1.2/private/sam.ldb /tmp/qmail.samba4-oc.ldif --option="dsdb:schema update allowed"=true Added 3 records successfully
Вроде бы всё, схема расширена. Но, на самом деле, есть ещё один тонкий момент. Попробуем расширить учётку пользователя вновь добавленными атрибутами, применив наш тестовый файл /tmp/user_update.ldif
:
# ldapmodify -U Administrator -f /tmp/user_update.ldif modifying entry "CN=Test User,CN=Users,DC=samba4,DC=lab" ldap_modify: Object class violation (65) additional info: 00002014: objectclass_attrs: attribute 'mailAlternateAddress' on entry 'CN=Test User,CN=Users,DC=samba4,DC=lab' does not exist in the specified objectclasses!
Ошибка, более того, из описания не понятно, чем именно она вызвана. Подводный камень скрыт в концепции взаимоотношений объектных классов каталога samba4. Дело в том, что требуемый нам объектный класс qmailUser
— вспомогательный, а чтобы добавить вспомогательный класс к структурному (в нашем случае — user), структурный класс должен "знать" о его существовании. Звучит мудрёно, проще показать это в виде LDIF (/tmp/qmail.samba4-update-user-oc.ldif
):
dn: CN=User,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: auxiliaryClass auxiliaryClass: qmailUser
Применим наш LDIF с помощью ldbmodify
(мы же вносим изменения в схему данных!):
# ldbmodify -H /opt/samba-4.1.2/private/sam.ldb /tmp/qmail.samba4-update-user-oc.ldif --option="dsdb:schema update allowed"=true Modified 1 records successfully
Попробуем ещё раз расширить учётку пользователя:
# ldapmodify -U Administrator -f /tmp/user_update.ldif modifying entry "CN=Test User,CN=Users,DC=samba4,DC=lab" # ldapsearch -LLL -U Administrator -b 'CN=Test User,CN=Users,DC=samba4,DC=lab' mail mailAlternateAddress mailMessageStore deliveryProgramPath dn: CN=Test User,CN=Users,DC=samba4,DC=lab mail: test_user@samba4.lab mailAlternateAddress: test_user@somewhere.else.ru mailMessageStore: samba4lab/test_user deliveryProgramPath: /var/mail
Всё, учётка пользователя расширена. Казалось бы, желаемый результат достигнут и можно приступать к интеграции. Но тут мы сталкиваемся с очередным подвохом: вспомогательный объектный класс "приклеивается" с своему структурному. Теперь все атрибуты из класса qmailUser
можно использовать в записях, основанных на объектном классе User
, даже без прямого указания в записи класса qmailUser
. С одной стороны, ничего страшного в этом нет, но, с другой стороны, атрибут mail
, обязательный для qmailUser
, становится обязательным и для User
. В связи с этим добавить пользователя через RSAT становится невозможным, поскольку в мастере добавления не предусмотрено поле для ввода адреса электронной почты. Для настоящих индейцев это, конечно же, не проблема:
# samba-tool user add test_user_2 Passw0rd --given-name=Test --surname='User 2' --mail-address=test_user_2@samba4.lab User 'test_user_2' created successfully
Тем не менее, хотелось бы сохранить в рабочем состоянии "удобный интерфейс для белых людей", к тому же почтовый ящик может быть не у всех пользователей. Поразмыслив немного, я решил сделать атрибут mail
необязательным (согласен, что решение не самое элегантное и противоречит всем канонам LDAP, но это же samba4 и приходится идти на компромиссы). LDIF-файл (/tmp/qmail.samba4-qmailUser-downgrade.ldif
):
dn: CN=qmailUser,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify delete: mustContain mustContain: mail - add: mayContain mayContain: mail
Применим его с помощью ldbmodify
:
# ldbmodify -H /opt/samba-4.1.2/private/sam.ldb /tmp/qmail.samba4-qmailUser-downgrade.ldif --option="dsdb:schema update allowed"=true Modified 1 records successfully
Теперь у нас есть нужные нам атрибуты и добавление пользователей через RSAT работает штатно.
Резюме:
Преобразование "стандартного" набора схемы данных производится штатной утилитой oLschema2ldif
, модификация схемы данных — штатными утилитами ldbadd
и ldbmodify
из набора samba4.
Расширение схемы производится в два этапа: сначала добавляются типы атрибутов, потом — объектные классы.
Требуемые вспомогательные объектные классы необходимо прописать как auxiliaryClass
в основной объектный класс для учётной записи пользователя user
. Побочный эффект: все атрибуты (обязательные и необязательные) вспомогательного объектного класса "приклеиваются" к основному. В связи с этим нужно следить за обязательными атрибутами вспомогательного класса, чтобы сохранить в работоспособном состоянии RSAT.
Штатными графическими средствами администрирования AD (RSAT) редактировать добавленные атрибуты не удастся — придётся придумывать какой-то другой способ.
Цель: Интеграция каталога samba4 с сервером ISC dhcpd.
Задача: Добавить в каталог записи со структурными объектными классами из набора схемы dhcp.schema
. В виде LDIF это будет выглядеть так (/tmp/dhcp-init.ldif
):
dn: CN=DHCP,DC=samba4,DC=lab objectClass: container cn: DHCP dn: CN=ads,CN=DHCP,DC=samba4,DC=lab objectClass: dhcpServer cn: ads dhcpServiceDN: CN=service,CN=DHCP,DC=samba4,DC=lab dn: CN=service,CN=DHCP,DC=samba4,DC=lab objectClass: dhcpService cn: service dhcpPrimaryDN: CN=ads,CN=DHCP,DC=samba4,DC=lab dhcpStatements: default-lease-time 86400 dn: CN=192.168.1.0,CN=service,CN=DHCP,DC=samba4,DC=lab objectClass: dhcpSubnet cn: 192.168.1.0 dhcpNetMask: 24 dhcpRange: 192.168.1.21 192.168.1.254 dhcpOption: routers 192.168.1.1 dhcpOption: domain-name "samba4.lab" dhcpOption: domain-name-servers 192.168.1.7 dhcpOption: netbios-name-servers 192.168.1.7 dhcpOption: netbios-dd-server 192.168.1.7 dhcpOption: netbios-node-type 8
В основном порядок расширения схемы аналогичен тому, что приведён в примере 1, поэтому подробности мы опустим, за исключением "тонких" мест.
Порядок действий:
Берём где-либо набор схемы dhcp.schema
и копируем его в директорию /tmp
.
Преобразуем его в LDIF для samba4:
# oLschema2ldif -b DC=samba4,DC=lab -I /tmp/dhcp.schema -O /tmp/dhcp.samba4.ldif Unknown Definition: X-NDS_CONTAINMENT <...> Converted 76 records with 0 failuresВыдаваемые предупреждения
Unknown Definition: X-NDS_CONTAINMENTможно проигнорировать (пока).
Отделяем описания типов атрибутов от объектных классов и поочерёдно добавляем их в схему данных:
# perl -00 -wne 'print if /attributeSchema/' /tmp/dhcp.samba4.ldif > /tmp/dhcp.samba4-at.ldif # perl -00 -wne 'print if /classSchema/' /tmp/dhcp.samba4.ldif > /tmp/dhcp.samba4-oc.ldif # ldbadd -H /opt/samba-4.1.2/private/sam.ldb /tmp/dhcp.samba4-at.ldif --option="dsdb:schema update allowed"=true Added 58 records successfully # ldbadd -H /opt/samba-4.1.2/private/sam.ldb /tmp/dhcp.samba4-oc.ldif --option="dsdb:schema update allowed"=true Added 18 records successfully
Попытаемся добавить требуемый нам LDIF:
# ldapadd -U Administrator -f /tmp/dhcp-init.ldif adding new entry "CN=DHCP,DC=samba4,DC=lab" adding new entry "CN=ads,CN=DHCP,DC=samba4,DC=lab" ldap_add: Naming violation (64) additional info: 00002037: structural objectClass dhcpServer is not a valid child class for CN=DHCP,DC=samba4,DC=labОшибка! Но на этот раз описание сразу наводит на мысль, что объектный класс нужно куда-то прописать в качестве "child class". А если точнее, в описание самого объектного класса
dhcpServer
нужно поместить информацию об объектных классах, на которых, возможно, будет строиться родительская (по отношению к добавляемой) запись. Опять же, звучит мудрёно, проще показать в виде LDIF, для нашего случая это:
dn: CN=dhcpServer,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: containerЛогично предположить, что подобную процедуру потребуется повторить для каждого добавляемого структурного объектного класса. Чтобы не делать одно и тоже несколько раз, я сразу сделал LDIF для всех нужных мне объектных классов (
/tmp/dhcp.samba4-oc-update.ldif
):
n: CN=dhcpService,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: container dn: CN=dhcpSharedNetwork,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpService dn: CN=dhcpSubnet,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpService possSuperiors: dhcpSharedNetwork dn: CN=dhcpPool,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpSharedNetwork possSuperiors: dhcpGroup dn: CN=dhcpGroup,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpSubnet possSuperiors: dhcpService dn: CN=dhcpHost,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpSubnet possSuperiors: dhcpService possSuperiors: dhcpGroup dn: CN=dhcpClass,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpSubnet possSuperiors: dhcpService dn: CN=dhcpSubClass,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpClass dn: CN=dhcpOptions,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpService possSuperiors: dhcpSharedNetwork possSuperiors: dhcpSubnet possSuperiors: dhcpPool possSuperiors: dhcpGroup possSuperiors: dhcpHost possSuperiors: dhcpClass dn: CN=dhcpLeases,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpService possSuperiors: dhcpSubnet possSuperiors: dhcpPool dn: CN=dhcpLog,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpLeases possSuperiors: dhcpPool possSuperiors: dhcpSubnet possSuperiors: dhcpSharedNetwork possSuperiors: dhcpService dn: CN=dhcpServer,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: container dn: CN=dhcpTSigKey,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpService possSuperiors: dhcpSharedNetwork possSuperiors: dhcpSubnet dn: CN=dhcpDnsZone,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpService possSuperiors: dhcpSharedNetwork possSuperiors: dhcpSubnet dn: CN=dhcpFailOverPeer,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpService possSuperiors: dhcpSharedNetwork possSuperiors: dhcpSubnet dn: CN=dhcpLocator,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: container dn: CN=dhcpSubnet6,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpService possSuperiors: dhcpSharedNetwork dn: CN=dhcpPool6,CN=Schema,CN=Configuration,DC=samba4,DC=lab changetype: modify add: possSuperiors possSuperiors: dhcpSubnet possSuperiors: dhcpSharedNetworkПри составлении этого файла "родительские" классы были взяты из первоначального файла
dhcp.schema
(те самые определения X-NDS_CONTAINMENT, на которые жаловалась утилита oLschema2ldif
на шаге 2). Но это, скорее, исключение, при добавлении других наборов схемы придётся проявлять смекалку. Применим файл:
# ldbmodify -H /opt/samba-4.1.2/private/sam.ldb /tmp/dhcp.samba4-oc-update.ldif --option="dsdb:schema update allowed"=true Modified 18 records successfullyДобавляем наши записи (предварительно удалив уже добавленную):
# ldapdelete -U Administrator 'CN=DHCP,DC=samba4,DC=lab' # ldapadd -U Administrator -f /tmp/dhcp-init.ldif adding new entry "CN=DHCP,DC=samba4,DC=lab" adding new entry "CN=ads,CN=DHCP,DC=samba4,DC=lab" adding new entry "CN=service,CN=DHCP,DC=samba4,DC=lab" adding new entry "CN=192.168.1.0,CN=service,CN=DHCP,DC=samba4,DC=lab" # ldapsearch -LLL -U Administrator -b 'CN=DHCP,DC=samba4,DC=lab' 1.1 dn: CN=DHCP,DC=samba4,DC=lab dn: CN=service,CN=DHCP,DC=samba4,DC=lab dn: CN=192.168.1.0,CN=service,CN=DHCP,DC=samba4,DC=lab dn: CN=ads,CN=DHCP,DC=samba4,DC=lab
Всё, можно настраивать dhcpd на интеграцию с каталогом.
Резюме:
Преобразование "стандартного" набора схемы данных производится штатной утилитой oLschema2ldif
, модификация схемы данных — штатными утилитами ldbadd
и ldbmodify
из набора samba4.
Расширение схемы производится в два этапа: сначала добавляются типы атрибутов, потом — объектные классы.
Для структурных объектных классов дополнительно нужно указывать в качестве значения атрибута possSuperiors
те объектные классы, на которых построены непосредственно вышестоящие записи.