Работа со схемой данных LDAP-сервера Samba4

Содержание

Обзор схемы данных

В разработке

Расширение схемы данных

Первый шаг по расширению схемы данных — указание флага --use-rfc2307 при инициализации samba:

# samba-tool domain provision <...> --use-rfc2307
В разработке

Добавление пользовательского набора схемы данных

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

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

Пример 1. Новые типы атрибутов для учётных записей пользователей

Цель: Интеграция каталога 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

Порядок действий:

  1. Берём где-либо требуемый набор схемы в формате .schema (не .ldif!) и копируем его в доступную нам директорию файловой системы. Пусть, для определённости, это будет директория /tmp.

  2. Выполняем преобразование набора с помощью утилиты 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
    говорит о том, что в неряшливо составленном файле набора схемы нет пробела перед последней закрывающейся скобкой в определении типа атрибута. Нужно найти это определение, добавить необходимый пробел и выполнить преобразование заново.

  3. Набор схемы есть, самое время его добавить. Здесь необходимо отметить, что по умолчанию модификация схемы данных в 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
    
  4. Вроде бы всё, схема расширена. Но, на самом деле, есть ещё один тонкий момент. Попробуем расширить учётку пользователя вновь добавленными атрибутами, применив наш тестовый файл /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 работает штатно.

Резюме:

  1. Преобразование "стандартного" набора схемы данных производится штатной утилитой oLschema2ldif, модификация схемы данных — штатными утилитами ldbadd и ldbmodify из набора samba4.

  2. Расширение схемы производится в два этапа: сначала добавляются типы атрибутов, потом — объектные классы.

  3. Требуемые вспомогательные объектные классы необходимо прописать как auxiliaryClass в основной объектный класс для учётной записи пользователя user. Побочный эффект: все атрибуты (обязательные и необязательные) вспомогательного объектного класса "приклеиваются" к основному. В связи с этим нужно следить за обязательными атрибутами вспомогательного класса, чтобы сохранить в работоспособном состоянии RSAT.

  4. Штатными графическими средствами администрирования AD (RSAT) редактировать добавленные атрибуты не удастся — придётся придумывать какой-то другой способ.

Пример 2. Новые структурные объектные классы

Цель: Интеграция каталога 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, поэтому подробности мы опустим, за исключением "тонких" мест.

Порядок действий:

  1. Берём где-либо набор схемы dhcp.schema и копируем его в директорию /tmp.

  2. Преобразуем его в 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
    
    можно проигнорировать (пока).

  3. Отделяем описания типов атрибутов от объектных классов и поочерёдно добавляем их в схему данных:

    # 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
    

  4. Попытаемся добавить требуемый нам 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 на интеграцию с каталогом.

Резюме:

  1. Преобразование "стандартного" набора схемы данных производится штатной утилитой oLschema2ldif, модификация схемы данных — штатными утилитами ldbadd и ldbmodify из набора samba4.

  2. Расширение схемы производится в два этапа: сначала добавляются типы атрибутов, потом — объектные классы.

  3. Для структурных объектных классов дополнительно нужно указывать в качестве значения атрибута possSuperiors те объектные классы, на которых построены непосредственно вышестоящие записи.

Ссылки

  1. Samba AD schema extensions (официальное HOWTO)
  2. Пример расширения схемы данных вспомогательным объектным классом
  3. Поток из рассылки samba.org по поводу добавления dhcp.schema
Pro-LDAP.ru 2013-2014 г. Последнее изменение страницы — 20 января 2014 г.