Это старая версия документа.


OpenLDAP сервер

Легковесный протокол доступа к каталогам, или LDAP - это протокол запросов и изменений к сервису каталогов на базе X.500, работающий поверх TCP/IP. Текущая версия LDAP это LDAPv3, как определено в RFC4510, а реализация LDAP в Ubuntu - это OpenLDAP, текущей версии 2.4.25 (Oneiric) (2.4.28 для Precise - прим. переводчика).

Итак, этот протокол обеспечивает доступ к каталогам LDAP. Здесь приведены некоторые ключевые понятия и термины:

  1. LDAP каталог - это дерево данных в виде записей, иерархичных по своей натуре, называемое Дерево каталогов информации (DIT).

  2. Запись содержит набор атрибутов.

  3. Атрибут имеет тип (имя/описание) и одно или несколько значений.

  4. Каждый атрибут должен быть определен как минимум в одном objectClass.

  5. Атрибуты и объектные классы определяются в схемах (объектный класс фактически рассматривается как специальный вид атрибута).

  6. Каждая запись имеет уникальный идентификатор: свое Отличительное имя (DN или dn). Она состоит из своего Относительного отличительного имени (RDN), следующим за записью родительского DN.

  7. DN записи - это не атрибут. Оно не является рассматриваемой частью собственно записи.

Термины объект, контейнер и узел (node) имеют определенный подтекст, но они все по существу обозначают такую вещь, как запись, технически корректный термин.

Например, далее мы имеем одну запись, содержащую 11 атрибутов. Ее DN - это "cn=John Doe,dc=example,dc=com"; ее RND - это "cn=John Doe"; а родительский DN - "dc=example,dc=com".

 dn: cn=John Doe,dc=example,dc=com
 cn: John Doe
 givenName: John
 sn: Doe
 telephoneNumber: +1 888 555 6789
 telephoneNumber: +1 888 555 1232
 mail: john@example.com
 manager: cn=Larry Smith,dc=example,dc=com
 objectClass: inetOrgPerson
 objectClass: organizationalPerson
 objectClass: person
 objectClass: top

Вышеприведенная запись - это формат LDIF (формат обмена данными LDAP). Любая информация, которую вы помещаете в ваш DIT должна быть в таком формате. Это определено в RFC2849.

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

Установка

Установка сервиса сервера OpenLDAP и привычных утилит управления LDAP. Они находятся в пакетах slapd и ldap-utils соответственно.

Установка slapd создаст работающую конфигурацию. В частности она создаст экземпляр базы данных, которую вы можете использовать для хранения своих данных. Однако суффикс (или базовый DN) этого экземпляра будет определен из доменного имени localhost. Если вы хотите использовать что-то другое, отредактируйте /etc/hosts и замените доменное имя на подходящее. В качестве примера, если вам нужен суффикс dc=example,dc=com, то ваш файл должен иметь подобную строку:

127.0.1.1       hostname.example.com	hostname

Вы можете отменить изменения после установки пакета.

Это руководство будет использовать суффикс базы данных dc=example,dc=com.

Продолжим с установкой:

sudo apt-get install slapd ldap-utils

Начиная с Ubuntu 8.10 slapd проектируется, чтобы настраиваться самостоятельно, выделяя отдельный DIT для этой цели. Это позволяет динамически настраивать slapd без необходимости перестартовывать сервис. Эта конфигурационная база данных содержит коллекцию текстовых LDIF файлов, расположенных в /etc/ldap/slapd.d. Этот вариант работы известен под разными именами: метод slapd-config, RTC метод (настройка в реальном времени) или cn=config метод. Вы все еще можете использовать традиционный метод плоского файла (slapd.conf), но это не рекомендуется; данная функциональность в конечном счете будет убрана.

Ubuntu теперь использует метод slapd-config для настройки slapd и данное руководство это отражает.

Во время установки у вас будет запрос на информацию об администраторе. Это LDAP данные для rootDN вашего экземпляра базы данных. По умолчанию этот пользовательский DN cn=admin,dc=example,dc=com. Также по умолчанию не создаеется административного пользователя для базы данных slapd-config и вы, следовательно, будете вынуждены использовать внешнюю авторизацию LDAP для доступа к ней. Мы рассмотрим как это делается позднее.

Некоторые классические схемы (cosine, nis, inetorgperson) выпускаются теперь для slapd. Это также включает базовую (core) схему, которая предполагается для любой рабочей схемы.

Проверка после установки

Процесс установки создаст 2 DIT. Один для slapd-config и один для ваших данных (dc=example,dc=com). Давайте взглянем:

  • Здесь показано как выглядит дерево (DIT) базы данных slapd-config. Напомним, что эта база основана на LDIF и находится в /etc/ldap/slapd.d:

        /etc/ldap/slapd.d/

    	├── cn=config
    	│   ├── cn=module{0}.ldif
    	│   ├── cn=schema
    	│   │   ├── cn={0}core.ldif
    	│   │   ├── cn={1}cosine.ldif
    	│   │   ├── cn={2}nis.ldif
    	│   │   └── cn={3}inetorgperson.ldif
    	│   ├── cn=schema.ldif
    	│   ├── olcBackend={0}hdb.ldif
    	│   ├── olcDatabase={0}config.ldif
    	│   ├── olcDatabase={-1}frontend.ldif
    	│   └── olcDatabase={1}hdb.ldif
    	└── cn=config.ldif
Не редактируйте базу slapd-config напрямую. Вносите изменения через протокол LDAP (утилитами).
  • Здесь ппоказано как выглядит дерево slapd-config через LDAP протокол:

sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config dn
dn: cn=config
dn: cn=module{0},cn=config
dn: cn=schema,cn=config
dn: cn={0}core,cn=schema,cn=config
dn: cn={1}cosine,cn=schema,cn=config
dn: cn={2}nis,cn=schema,cn=config
dn: cn={3}inetorgperson,cn=schema,cn=config
dn: olcBackend={0}hdb,cn=config
dn: olcDatabase={-1}frontend,cn=config
dn: olcDatabase={0}config,cn=config
dn: olcDatabase={1}hdb,cn=config

Объяснение по записям:

  1. cn=config: глобальные настройки

  2. cn=module{0},cn=config: динамически загружаемый модуль

  3. cn=schema,cn=config: содержит жестко запрограммированную схему системного уровня

  4. cn={0}core,cn=schema,cn=config: жестко запрограммированная схема ядра (core)

  5. cn={1}cosine,cn=schema,cn=config: схема cosine

  6. cn={2}nis,cn=schema,cn=config: схема nis

  7. cn={3}inetorgperson,cn=schema,cn=config: схема inetorgperson

  8. olcBackend={0}hdb,cn=config: тип хранилища 'hdb' заднего плана

  9. olcDatabase={-1}frontend,cn=config: база переднего плана, настройка по умолчанию для других баз данных

  10. olcDatabase={0}config,cn=config: конфигурационная база slapd (cn=config)

  11. olcDatabase={1}hdb,cn=config: экземпляр вашей базы данных (dc=examle,dc=com)

  • А здесь показано как выглядит дерево dc=example,dc=com:

ldapsearch -x -LLL -H ldap:/// -b dc=example,dc=com dn
dn: dc=example,dc=com
dn: cn=admin,dc=example,dc=com

Объяснение по записям:

  1. dc=example,dc=com: базовый уровень вашего дерева (DIT)

  2. cn=admin,dc=example,dc=com: администратор (rootDN) данного дерева (заполняется в процессе установки пакета)

Изменение/заполнение вашей базы данных

Давайте введем некоторые данные в нашу базу. Мы добавим следующее:

  1. ноду с названием People (сохранять пользователей)

  2. ноду с названием Groups (сохранять группы)

  3. группу с названием miners

  4. пользователя с именем john

Создайте следующий LDIF файл и назовите его add_content.ldif:

dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: People

dn: ou=Groups,dc=example,dc=com
objectClass: organizationalUnit
ou: Groups

dn: cn=miners,ou=Groups,dc=example,dc=com
objectClass: posixGroup
cn: miners
gidNumber: 5000

dn: uid=john,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: john
sn: Doe
givenName: John
cn: John Doe
displayName: John Doe
uidNumber: 10000
gidNumber: 5000
userPassword: johnldap
gecos: John Doe
loginShell: /bin/bash
homeDirectory: /home/john
Важно, чтобы значения uid и gid в вашем каталоге не совпадали с локальными значениями. Используйте диапазон больших чисел, начинающийся, например, с 5000. Устанавливая значения uid и gid высокими для ldap, вы сможете проще контролировать что могут делать локальные пользователи, а что ldap. Подробнее далее.

Добавляем контент:

ldapadd -x -D cn=admin,dc=example,dc=com -W -f add_content.ldif
Enter LDAP Password: ********
adding new entry "ou=People,dc=example,dc=com"
adding new entry "ou=Groups,dc=example,dc=com"
adding new entry "cn=miners,ou=Groups,dc=example,dc=com"
adding new entry "uid=john,ou=People,dc=example,dc=com"

Мы можем проверить, что информация добавлена правильно с помощью утилиты ldapsearch:

ldapsearch -x -LLL -b dc=example,dc=com 'uid=john' cn gidNumber
dn: uid=john,ou=People,dc=example,dc=com
cn: John Doe
gidNumber: 5000

Объяснения по параметрам:

  1. -x: "простое" связывание; не будет использоваться метод SASL по умолчанию

  2. -LLL: отключить вывод посторонней информации

  3. uid=john: "фильтр" для нахождения пользователя john

  4. cn gidNumber: запрос на вывод определенных атрибутов (по умолчанию выводятся все атрибуты)

Изменение базы данных настройки slapd

Дерево (DIT) slapd-config также может запрашиваться и изменяться. Здесь приведено несколько примеров.

  • Используйте ldapmodify для добавления индекса (атрибут DbIndex) для вашей {1}hdb,cn=config базы (dc=example,dc=com). Создайте файл с названием uid_index.ldif следующего содержания:

    dn: olcDatabase={1}hdb,cn=config
    add: olcDbIndex
    olcDbIndex: uid eq,pres,sub

Затем выполните команду:

    sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f uid_index.ldif
    modifying entry "olcDatabase={1}hdb,cn=config"

Вы можете подтвердить изменения следующим способом:

    sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b \
    cn=config '(olcDatabase={1}hdb)' olcDbIndex

    dn: olcDatabase={1}hdb,cn=config
    olcDbIndex: objectClass eq
    olcDbIndex: uid eq,pres,sub
  • Давайте добавим схему. Это будет первый раз, когда потребуется конвертация в LDIF формат. Вы можете найти несконвертированные схемы в добавление к сконвертированным в каталоге /etc/ldap/schema.

  1. Удаление схемы из базы slapd-config - нетривиальная задача. Потренируйтесь добавлять схемы на тестовой системе.

  2. Перед добавлением любой схемы, вам следует проверить какие схемы уже установлены (показан вывод по умолчанию, для состояния "из коробки"):

        sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b \
        cn=schema,cn=config dn
        dn: cn=schema,cn=config
        dn: cn={0}core,cn=schema,cn=config
        dn: cn={1}cosine,cn=schema,cn=config    In the following example we'll add the CORBA schema.

        dn: cn={2}nis,cn=schema,cn=config
        dn: cn={3}inetorgperson,cn=schema,cn=config

В следующем примере мы добавим схему CORBA.

  • Создайте конфигурационный файл преобразования schema_convert.conf, содержащий следующие строки:

        include /etc/ldap/schema/core.schema
        include /etc/ldap/schema/collective.schema
        include /etc/ldap/schema/corba.schema
        include /etc/ldap/schema/cosine.schema
        include /etc/ldap/schema/duaconf.schema
        include /etc/ldap/schema/dyngroup.schema
        include /etc/ldap/schema/inetorgperson.schema
        include /etc/ldap/schema/java.schema
        include /etc/ldap/schema/misc.schema
        include /etc/ldap/schema/nis.schema
        include /etc/ldap/schema/openldap.schema
        include /etc/ldap/schema/ppolicy.schema
        include /etc/ldap/schema/ldapns.schema
        include /etc/ldap/schema/pmi.schema
  • Создайте каталог назначения ldif_output.

  • Определите индекс схемы:

        slapcat -f schema_convert.conf -F ldif_output -n 0 | grep corba,cn=schema
        cn={1}corba,cn=schema,cn=config
Когда slapd вводит объекты с тем же родительским DN, он создает индекс для этого объекта. Индекс обрамляется скобками: {X}.
  • Используйте slapcat для выполнения преобразования:

        slapcat -f schema_convert.conf -F ldif_output -n0 -H \
        ldap:///cn={1}corba,cn=schema,cn=config -l cn=corba.ldif

Сконвертированная (преобразованная) схема теперь в cn=corba.ldif

  • Редактируйте cn=corba.ldif, по достижении следующих атрибутов:

        dn: cn=corba,cn=schema,cn=config
        ...
        cn: corba

Также удалите следующие строки в конце:

        structuralObjectClass: olcSchemaConfig
        entryUUID: 52109a02-66ab-1030-8be2-bbf166230478
        creatorsName: cn=config
        createTimestamp: 20110829165435Z
        entryCSN: 20110829165435.935248Z#000000#000#000000
        modifiersName: cn=config
        modifyTimestamp: 20110829165435Z

Значения ваших атрибутов могут быть другими.

  • Наконец, используйте ldapadd для добавления новой схемы к дереву slapd-config:

        sudo ldapadd -Q -Y EXTERNAL -H ldapi:/// -f cn\=corba.ldif
        adding new entry "cn=corba,cn=schema,cn=config"
  • Проверьте текущую загруженную схему:

        sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=schema,cn=config dn
        dn: cn=schema,cn=config
        dn: cn={0}core,cn=schema,cn=config
        dn: cn={1}cosine,cn=schema,cn=config
        dn: cn={2}nis,cn=schema,cn=config
        dn: cn={3}inetorgperson,cn=schema,cn=config
        dn: cn={4}corba,cn=schema,cn=config
Для аутентификации с помощью LDAP внешних приложений и клиентов, они должны быть специфически настроены. Обратитесь к соответствующей документации по поводу деталей.

Ведение журналов

Ведение журнала активности для slapd обязательно, когда осуществляется решение на базе OpenLDAP, поэтому его требуется включить вручную после установки приложения. Иначе только элементарные сообщения будут доступны в журналах. Ведение журналов, как и другие настройки slapd, подключаются через базу данных slapd-config.

OpenLDAP поставляется с несколькими подсистемами (уровнями) журналирования, каждая из которых включает подчиненную (дополнительную). Хороший вариант, который стоит попробовать - это stats. Страница руководства slapd-config содержит больше информации по иным подсистемам.

Создайте файл logging.ldif со следующим содержимым:

dn: cn=config
changetype: modify
add: olcLogLevel
olcLogLevel: stats

Производим изменения:

sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f logging.ldif

Это породит значительный объем записи в журнал и вы захотите уменьшить уровень детализации когда ваша система станет боевой. С таким уровнем детализации система журналирования вашего хоста (rsyslog) может отнимать значительное время процессора, а также пропускать сообщения:

rsyslogd-2177: imuxsock lost 228 messages from pid 2547 due to rate-limiting

Вы можете решить изменить настройки rsyslog. В файл /etc/rsyslog.conf поместите следующее:

# Disable rate limiting
# (default is 200 messages in 5 seconds; below we make the 5 become 0)
$SystemLogRateLimitInterval 0

А затем перезапустите сервис rsyslog:

sudo service rsyslog restart

Репликация

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

Репликация доступна через механизм Syncrepl. Он позволят синхронизировать изменения используя модель Потребитель-Поставщик. Специфический вид репликации, который мы будем реализовывать в этом руководстве, является комбинацией следующих режимов: refreshAndPersist и delta-syncrepl. Это подразумевает что Потребитель передает измененные записи Поставщику, как только они появляются, но при этом посылаются только актуальные изменения, а не все записи.

Настройка Поставщика

Начнем с настройки Поставщика.

  • Создадим LDIF файл со следующим содержимым и назовем его provider_sync.ldif:

    # Add indexes to the frontend db.
    dn: olcDatabase={1}hdb,cn=config
    changetype: modify
    add: olcDbIndex
    olcDbIndex: entryCSN eq
    -
    add: olcDbIndex
    olcDbIndex: entryUUID eq

    #Load the syncprov and accesslog modules.
    dn: cn=module{0},cn=config
    changetype: modify
    add: olcModuleLoad
    olcModuleLoad: syncprov
    -
    add: olcModuleLoad
    olcModuleLoad: accesslog

    # Accesslog database definitions
    dn: olcDatabase={2}hdb,cn=config
    objectClass: olcDatabaseConfig
    objectClass: olcHdbConfig
    olcDatabase: {2}hdb
    olcDbDirectory: /var/lib/ldap/accesslog
    olcSuffix: cn=accesslog
    olcRootDN: cn=admin,dc=example,dc=com
    olcDbIndex: default eq
    olcDbIndex: entryCSN,objectClass,reqEnd,reqResult,reqStart

    # Accesslog db syncprov.
    dn: olcOverlay=syncprov,olcDatabase={2}hdb,cn=config
    changetype: add
    objectClass: olcOverlayConfig
    objectClass: olcSyncProvConfig
    olcOverlay: syncprov
    olcSpNoPresent: TRUE
    olcSpReloadHint: TRUE

    # syncrepl Provider for primary db
    dn: olcOverlay=syncprov,olcDatabase={1}hdb,cn=config
    changetype: add
    objectClass: olcOverlayConfig
    objectClass: olcSyncProvConfig
    olcOverlay: syncprov
    olcSpNoPresent: TRUE

    # accesslog overlay definitions for primary db
    dn: olcOverlay=accesslog,olcDatabase={1}hdb,cn=config
    objectClass: olcOverlayConfig
    objectClass: olcAccessLogConfig
    olcOverlay: accesslog
    olcAccessLogDB: cn=accesslog
    olcAccessLogOps: writes
    olcAccessLogSuccess: TRUE
    # scan the accesslog DB every day, and purge entries older than 7 days
    olcAccessLogPurge: 07+00:00 01+00:00

Замените rootDN в LDIF файле на соответствующий вашему каталогу.

  • Профиль apparmor для slapd нужно будет отрегулировать для расположения базы accesslog. Отредактируйте /etc/apparmor.d/local/usr.sbin.slapd, добавив следующее:

    /var/lib/ldap/accesslog/ r,
    /var/lib/ldap/accesslog/** rwk,

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

    sudo -u openldap mkdir /var/lib/ldap/accesslog
    sudo -u openldap cp /var/lib/ldap/DB_CONFIG /var/lib/ldap/accesslog
    sudo service apparmor reload
  • Добавляем новый контент и, поскольку изменили apparmor, перестартуем сервис:

    sudo ldapadd -Q -Y EXTERNAL -H ldapi:/// -f provider_sync.ldif
    sudo service slapd restart

Поставщик теперь настроен.

Настройка Потребителя

А теперь настроим Потребителя.

  • Установим программное обеспечение как указано в Установке. Убедитесь, что база slapd-config аналогична базе Поставщика. Особенно проверьте, что одинаковы схемы и суффикс базы.

  • Создайте LDIF файл со следующим содержимым и назовите его consumer_sync.ldif:

    dn: cn=module{0},cn=config
    changetype: modify
    add: olcModuleLoad
    olcModuleLoad: syncprov

    dn: olcDatabase={1}hdb,cn=config
    changetype: modify
    add: olcDbIndex
    olcDbIndex: entryUUID eq
    -
    add: olcSyncRepl
    olcSyncRepl: rid=0 provider=ldap://ldap01.example.com bindmethod=simple binddn="cn=admin,dc=example,dc=com" 
     credentials=secret searchbase="dc=example,dc=com" logbase="cn=accesslog" 
     logfilter="(&(objectClass=auditWriteObject)(reqResult=0))" schemachecking=on 
     type=refreshAndPersist retry="60 +" syncdata=accesslog
    -
    add: olcUpdateRef
    olcUpdateRef: ldap://ldap01.example.com

Убедитесь, что следующие атрибуты имеют корректные значения:

  1. provider (hostname сервера Поставщика - ldap01.example.com в этом примере - или IP адрес)

  2. binddn (DN администратора, которым вы пользуетесь)

  3. credentials (пароль для DN администратора, который вы используете)

  4. searchbase (суффикс базы, которую вы используете)

  5. olcUpdateRef (hostname сервера Поставщика или его IP адрес)

  6. rid (Replica ID, уникальное трехзначное число, идентифицирующее данную копию. Каждый Потребитель должен иметь минимум один rid)

  • Добавьте новый контент:

sudo ldapadd -Q -Y EXTERNAL -H ldapi:/// -f consumer_sync.ldif

Вы сделали это! Две базы (суффикс: dc=example,dc=com) будут теперь синхронизированы.

Проверка

Как только репликация стартует, вы можете отслеживать ее запустив:

ldapsearch -z1 -LLLQY EXTERNAL -H ldapi:/// -s base contextCSN

dn: dc=example,dc=com
contextCSN: 20120201193408.178454Z#000000#000#000000

как на Поставщике, так и на Потребителе. Как только вывод (20120201193408.178454Z#000000#000#000000 в примере выше) на обеих машинах совпадет, вы провели репликацию. Каждый раз, как происходят изменения на Поставщике, это значение будет изменяться и должно стать таким же на Поставщике.

Если ваше соединение медленное и/или ваша база LDAP велика, процесс приведения в соответствие contextCSN Потребителя и Поставщика может быть протяженным. Но, вы должны знать, что процесс запускается как только contextCSN Потребителя неизбежно увеличивается.

Если contextCSN Потребителя отсутствует или не совпадает со значением Поставщика, вы должны остановиться и понять причину проблемы перед тем как продолжить. Попробуйте проверить slapd (syslog - системный журнал) и файлы журналов авторизации Поставщика, чтобы увидеть удачны ли были запросы авторизации Потребителя и не возвращались ли ошибки в ответ на запросы данных (они будут видны как множество записей ldapsearch).

Чтобы проверить, что все работает, просто запросите на Потребителе DN из базы:

sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b dc=example,dc=com dn

Вы должны увидеть пользователя 'john' и группу 'miners', также как ноды 'People' и 'Groups'.

Контроль доступа

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

Когда мы устанавливаем пакет slapd различные ACL устанавливаются автоматически. Мы рассмотрим некоторые важные следствия этих умолчаний и, занимаясь этим, мы поймем идею того, как работают ACL и как их настраивать.

Для получения эффективных ACL для запроса LDAP нам надо посмотреть на ACL записи запрашиваемой базы данных также как и на записи специального экземпляра базы данных переднего плана. По умолчанию используются ACL, полученные последним действием, в случае, если они не совпадают с правилами из предыдущего варианта. База данных переднего плана опрашивается во вторую очередь и применяется ACL по первому совпадению среди этих двух источников ACL. Следующие команды покажут соответственно ACL базы hdb ("dc=example,dc=com") и они же из базы переднего плана:

FIXME оставлен оригинал предыдущего абзаца, поскольку не уверен, что правильно понял смысл:

To get the effective ACL for an LDAP query we need to look at the ACL entries of the database being queried as well as those of the special frontend database instance. The ACLs belonging to the latter act as defaults in case those of the former do not match. The frontend database is the second to be consulted and the ACL to be applied is the first to match («first match wins») among these 2 ACL sources. The following commands will give, respectively, the ACLs of the hdb database («dc=example,dc=com») and those of the frontend database:

sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b \
cn=config '(olcDatabase={1}hdb)' olcAccess

dn: olcDatabase={1}hdb,cn=config
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous
              auth by dn="cn=admin,dc=example,dc=com" write by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by self write by dn="cn=admin,dc=example,dc=com" write by *
  read
rootDN всегда имеет полный доступ к своей базе данных. Добавление их к ACL обеспечивает полную конфигурацию, но при этом становится причиной снижения быстродействия slapd.
sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b \
cn=config '(olcDatabase={-1}frontend)' olcAccess

dn: olcDatabase={-1}frontend,cn=config
olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,
              cn=external,cn=auth manage by * break
olcAccess: {1}to dn.exact="" by * read
olcAccess: {2}to dn.base="cn=Subschema" by * read

Самый первый ACL очень важен:

olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous
              auth by dn="cn=admin,dc=example,dc=com" write by * none

Это может быть представлено по-другому для лучшего понимания:

to attrs=userPassword
	by self write
	by anonymous auth
	by dn="cn=admin,dc=example,dc=com" write
	by * none

to attrs=shadowLastChange
	by self write
	by anonymous auth
	by dn="cn=admin,dc=example,dc=com" write
	by * none

Этот составной ACL (их два) предписывает следующее:

  1. Анонимный 'auth' доступ обеспечивается к атрибуту userPassword для осуществления изначального соединения. Возможно потребуется counter-intuitively для 'by anonymous auth' даже когда анонимный доступ к DIT не требуется. Как только удаленное соединение установлено, требуется авторизация (см. следующий пункт).

  2. Должна пройти авторизация, поскольку все пользователи имеют доступ на чтение (вследствие 'by self write') к атрибуту userPassword.

  3. Атрибут userPassword не доступен для всех других пользователей за исключением rootDN, который имеет полный доступ.

  4. Для того чтобы пользователи могли менять собственные пароли, используя passwd или иные утилиты, атрибут shadowLastChange должен быть доступен как только пользователь авторизовался.

Поиск по этому DIT может быть проведен анонимно из-за 'by * read' в данном ACL:

to *
	by self write
	by dn="cn=admin,dc=example,dc=com" write
	by * read

Если это нежелательно, то вам потребуется изменить набор ACL. Для принуждения к авторизации в процессе связывающего (bind) запроса в качестве альтернативы (или в комбинации с измененным ACL) вам надо использовать директиву 'olcRequire: authc'.

Как указывалось ранее, никаких административных пользователей не создается для базы slapd-config. Однако существует идентификация SASL, которая обеспечивает полный к ней доступ. Она подобна суперпользователю для localhost (root/sudo). Вот она:

dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth

Следующая команда покажет ACL базы slapd-config:

sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b \
cn=config '(olcDatabase={0}config)' olcAccess

dn: olcDatabase={0}config,cn=config
olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,
              cn=external,cn=auth manage by * break

Поскольку это SASL идентификация, нам потребуется механизм SASL, когда запрашивается LDAP утилита, о которой идет речь и мы увидим это много раз в данном руководстве. Это внешний (EXTERNAL) механизм. Смотрите предыдущую команду в качестве примера. Обратите внимание:

  1. Вы должны использовать sudo для идентификации как root чтобы ACL сработали.

  2. Механизм EXTERNAL работает через IPC (доменные сокеты UNIX). Это означает , что вы должны использовать ldapi формат адресации (URI).

Короткий путь для получения всех ACL выглядит следующим образом:

sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b \
cn=config '(olcAccess=*)' olcAccess olcSuffix

Есть еще много что сказать по контролю доступа. Смотрите страницу руководства по slapd.access.

TLS

Когда происходит аутентификация на OpenLDAP сервере, лучше всего это делать используя зашифрованную сессию. Это может быть достигнуто использованием транспортного уровня шифрования (TLS).

Здесь мы организуем свой собственный Центр сертификатов (Certificate Authority - CA) и затем создадим и подпишем сертификат нашего LDAP сервера от имени этого CA. Поскольку slapd скомпилирован с использованием библиотеки gnutls, мы будем использовать для выполнения этих задач утилиту certtool.

  • Устанавливаем пакеты gnutls-bin и ssl-cert:

sudo apt-get install gnutls-bin ssl-cert
  • Создаем секретный ключ Центра сертификатов:

sudo sh -c "certtool --generate-privkey > /etc/ssl/private/cakey.pem"
  • Создаем временный файл /etc/ssl/ca.info для оределения CA:

    cn = Example Company
    ca
    cert_signing_key
  • Создаем самоподписанный сертификат центра:

sudo certtool --generate-self-signed \
    --load-privkey /etc/ssl/private/cakey.pem \ 
    --template /etc/ssl/ca.info \
    --outfile /etc/ssl/certs/cacert.pem
  • Создаем секретный ключ для сервера:

sudo certtool --generate-privkey \
    --bits 1024 \
    --outfile /etc/ssl/private/ldap01_slapd_key.pem
Замените ldap01 в имени файла на имя вашего сервера (hostname). Имена сертификата и ключа для узла и сервиса, которые будут их использовать, помогут сохранять ясность понимания.
  • Создаем информационный файл /etc/ssl/ldap01.info, содержащий следующее:

    organization = Example Company
    cn = ldap01.example.com
    tls_www_server
    encryption_key
    signing_key
    expiration_days = 3650

Данный сертификат будет действителен 10 лет (3650 дней). Вы можете выбрать другое значение.

  • Создаем серверный сертификат:

sudo certtool --generate-certificate \
    --load-privkey /etc/ssl/private/ldap01_slapd_key.pem \
    --load-ca-certificate /etc/ssl/certs/cacert.pem \
    --load-ca-privkey /etc/ssl/private/cakey.pem \
    --template /etc/ssl/ldap01.info \
    --outfile /etc/ssl/certs/ldap01_slapd_cert.pem

Создайте файл certinfo.ldif со следующим содержимым (подставляйте свои значения, наш пример предполагает использование https://www.cacert.org):

dn: cn=config
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ssl/certs/cacert.pem
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ssl/certs/ldap01_slapd_cert.pem
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ssl/private/ldap01_slapd_key.pem

Используйте команду ldapmodify, чтобы сказать slapd о работе нашего TLS через базу данных slapd-config:

sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f /etc/ssl/certinfo.ldif

Вопреки распространенному мнению, вам не обязательно указывать ldaps:// в /etc/default/slapd чтобы использовать шифрование. Вам достаточно указать:

SLAPD_SERVICES="ldap:/// ldapi:///"
LDAP поверх TLS/SSL (ldaps://) осуждается в пользу StartTLS. Последний опирается на существующую LDAP сессию (прослушивание TCP порта 389), защищенную TLS/SSL в то время как LDAPS, подобно HTTPS, является другим защищенным-с-самого-начала протоколом, который работает через TCP порт 636.

Tighten up ownership and permissions:

sudo adduser openldap ssl-cert
sudo chgrp ssl-cert /etc/ssl/private/ldap01_slapd_key.pem
sudo chmod g+r /etc/ssl/private/ldap01_slapd_key.pem
sudo chmod o-r /etc/ssl/private/ldap01_slapd_key.pem

Restart OpenLDAP:

sudo service slapd restart

Check your host's logs (/var/log/syslog) to see if the server has started properly.

Репликация и TLS

If you have set up replication between servers, it is common practice to encrypt (StartTLS) the replication traffic to prevent evesdropping. This is distinct from using encryption with authentication as we did above. In this section we will build on that TLS-authentication work.

The assumption here is that you have set up replication between Provider and Consumer according to Replication and have configured TLS for authentication on the Provider by following TLS.

As previously stated, the objective (for us) with replication is high availablity for the LDAP service. Since we have TLS for authentication on the Provider we will require the same on the Consumer. In addition to this, however, we want to encrypt replication traffic. What remains to be done is to create a key and certificate for the Consumer and then configure accordingly. We will generate the key/certificate on the Provider, to avoid having to create another CA certificate, and then transfer the necessary material over to the Consumer.

  On the Provider,
  Create a holding directory (which will be used for the eventual transfer) and then the Consumer's private key:
  mkdir ldap02-ssl
  cd ldap02-ssl
  sudo certtool --generate-privkey \
  --bits 1024 \
  --outfile ldap02_slapd_key.pem
  Create an info file, ldap02.info, for the Consumer server, adjusting it's values accordingly:
  organization = Example Company
  cn = ldap02.example.com
  tls_www_server
  encryption_key
  signing_key
  expiration_days = 3650
  Create the Consumer's certificate:
  sudo certtool --generate-certificate \
  --load-privkey ldap02_slapd_key.pem \
  --load-ca-certificate /etc/ssl/certs/cacert.pem \
  --load-ca-privkey /etc/ssl/private/cakey.pem \
  --template ldap02.info \
  --outfile ldap02_slapd_cert.pem
  Get a copy of the CA certificate:
  cp /etc/ssl/certs/cacert.pem .
  We're done. Now transfer the ldap02-ssl directory to the Consumer. Here we use scp (adjust accordingly):
  cd ..
  scp -r ldap02-ssl user@consumer:
  On the Consumer,
  Configure TLS authentication:
  sudo apt-get install ssl-cert
  sudo adduser openldap ssl-cert
  sudo cp ldap02_slapd_cert.pem cacert.pem /etc/ssl/certs
  sudo cp ldap02_slapd_key.pem /etc/ssl/private
  sudo chgrp ssl-cert /etc/ssl/private/ldap02_slapd_key.pem
  sudo chmod g+r /etc/ssl/private/ldap02_slapd_key.pem
  sudo chmod o-r /etc/ssl/private/ldap02_slapd_key.pem
  Create the file /etc/ssl/certinfo.ldif with the following contents (adjust accordingly):
  dn: cn=config
  add: olcTLSCACertificateFile
  olcTLSCACertificateFile: /etc/ssl/certs/cacert.pem
  -
  add: olcTLSCertificateFile
  olcTLSCertificateFile: /etc/ssl/certs/ldap02_slapd_cert.pem
  -
  add: olcTLSCertificateKeyFile
  olcTLSCertificateKeyFile: /etc/ssl/private/ldap02_slapd_key.pem
  Configure the slapd-config database:
  sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f certinfo.ldif
  Configure /etc/default/slapd as on the Provider (SLAPD_SERVICES).
  On the Consumer,
  Configure TLS for Consumer-side replication. Modify the existing olcSyncrepl attribute by tacking on some TLS options. In so doing, we will see, for the first time, how to change an attribute's value(s).
  Create the file consumer_sync_tls.ldif with the following contents:
  dn: olcDatabase={1}hdb,cn=config
  replace: olcSyncRepl
  olcSyncRepl: rid=0 provider=ldap://ldap01.example.com bindmethod=simple
   binddn="cn=admin,dc=example,dc=com" credentials=secret searchbase="dc=example,dc=com"
   logbase="cn=accesslog" logfilter="(&(objectClass=auditWriteObject)(reqResult=0))"
   schemachecking=on type=refreshAndPersist retry="60 +" syncdata=accesslog
   starttls=critical tls_reqcert=demand
  The extra options specify, respectively, that the consumer must use StartTLS and that the CA certificate is required to verify the Provider's identity. Also note the LDIF syntax for changing the values of an attribute ('replace').
  Implement these changes:
  sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f consumer_sync_tls.ldif
  And restart slapd:
  sudo service slapd restart
  On the Provider,
  Check to see that a TLS session has been established. In /var/log/syslog, providing you have 'conns'-level logging set up, you should see messages similar to:
  slapd[3620]: conn=1047 fd=20 ACCEPT from IP=10.153.107.229:57922 (IP=0.0.0.0:389)
  slapd[3620]: conn=1047 op=0 EXT oid=1.3.6.1.4.1.1466.20037
  slapd[3620]: conn=1047 op=0 STARTTLS
  slapd[3620]: conn=1047 op=0 RESULT oid= err=0 text=
  slapd[3620]: conn=1047 fd=20 TLS established tls_ssf=128 ssf=128
  slapd[3620]: conn=1047 op=1 BIND dn="cn=admin,dc=example,dc=com" method=128
  slapd[3620]: conn=1047 op=1 BIND dn="cn=admin,dc=example,dc=com" mech=SIMPLE ssf=0
  slapd[3620]: conn=1047 op=1 RESULT tag=97 err=0 text

Установление подлинности через LDAP

Once you have a working LDAP server, you will need to install libraries on the client that will know how and when to contact it. On Ubuntu, this has been traditionally accomplishd by installing the libnss-ldap package. This package will bring in other tools that will assist you in the configuration step. Install this package now:

sudo apt-get install libnss-ldap

You will be prompted for details of your LDAP server. If you make a mistake you can try again using:

sudo dpkg-reconfigure ldap-auth-config

The results of the dialog can be seen in /etc/ldap.conf. If your server requires options not covered in the menu edit this file accordingly.

Now configure the LDAP profile for NSS:

sudo auth-client-config -t nss -p lac_ldap

Configure the system to use LDAP for authentication:

sudo pam-auth-update

From the menu, choose LDAP and any other authentication mechanisms you need.

You should now be able to log in using LDAP-based credentials.

LDAP clients will need to refer to multiple servers if replication is in use. In /etc/ldap.conf you would have something like:

uri ldap://ldap01.example.com ldap://ldap02.example.com

The request will time out and the Consumer (ldap02) will attempt to be reached if the Provider (ldap01) becomes unresponsive.

If you are going to use LDAP to store Samba users you will need to configure the Samba server to authenticate using LDAP. See Samba and LDAP for details.

An alternative to the libnss-ldap package is the libnss-ldapd package. This, however, will bring in the nscd package which is problably not wanted. Simply remove it afterwards.

Управление пользователями и группами

The ldap-utils package comes with enough utilities to manage the directory but the long string of options needed can make them a burden to use. The ldapscripts package contains wrapper scripts to these utilities that some people find easier to use.

Install the package:

sudo apt-get install ldapscripts

Then edit the file /etc/ldapscripts/ldapscripts.conf to arrive at something similar to the following:

SERVER=localhost BINDDN='cn=admin,dc=example,dc=com' BINDPWDFILE=«/etc/ldapscripts/ldapscripts.passwd» SUFFIX='dc=example,dc=com' GSUFFIX='ou=Groups' USUFFIX='ou=People' MSUFFIX='ou=Computers' GIDSTART=10000 UIDSTART=10000 MIDSTART=10000

Now, create the ldapscripts.passwd file to allow rootDN access to the directory:

sudo sh -c «echo -n 'secret' > /etc/ldapscripts/ldapscripts.passwd» sudo chmod 400 /etc/ldapscripts/ldapscripts.passwd

Replace “secret” with the actual password for your database's rootDN user.

The scripts are now ready to help manage your directory. Here are some examples of how to use them:

  Create a new user:
  sudo ldapadduser george example
  This will create a user with uid george and set the user's primary group (gid) to example
  Change a user's password:
  sudo ldapsetpasswd george
  Changing password for user uid=george,ou=People,dc=example,dc=com
  New Password: 
  New Password (verify): 
  Delete a user:
  sudo ldapdeleteuser george
  Add a group:
  sudo ldapaddgroup qa
  Delete a group:
  sudo ldapdeletegroup qa
  Add a user to a group:
  sudo ldapaddusertogroup george qa
  You should now see a memberUid attribute for the qa group with a value of george.
  Remove a user from a group:
  sudo ldapdeleteuserfromgroup george qa
  The memberUid attribute should now be removed from the qa group.
  The ldapmodifyuser script allows you to add, remove, or replace a user's attributes. The script uses the same syntax as the ldapmodify utility. For example:
  sudo ldapmodifyuser george
  # About to modify the following entry :
  dn: uid=george,ou=People,dc=example,dc=com
  objectClass: account
  objectClass: posixAccount
  cn: george
  uid: george
  uidNumber: 1001
  gidNumber: 1001
  homeDirectory: /home/george
  loginShell: /bin/bash
  gecos: george
  description: User account
  userPassword:: e1NTSEF9eXFsTFcyWlhwWkF1eGUybVdFWHZKRzJVMjFTSG9vcHk=
  # Enter your modifications here, end with CTRL-D.
  dn: uid=george,ou=People,dc=example,dc=com
  replace: gecos
  gecos: George Carlin
  The user's gecos should now be “George Carlin”.
  A nice feature of ldapscripts is the template system. Templates allow you to customize the attributes of user, group, and machine objectes. For example, to enable the user template edit /etc/ldapscripts/ldapscripts.conf changing:
  UTEMPLATE="/etc/ldapscripts/ldapadduser.template"
  There are sample templates in the /etc/ldapscripts directory. Copy or rename the ldapadduser.template.sample file to /etc/ldapscripts/ldapadduser.template:
  sudo cp /usr/share/doc/ldapscripts/examples/ldapadduser.template.sample \
  /etc/ldapscripts/ldapadduser.template
  Edit the new template to add the desired attributes. The following will create new users with an objectClass of inetOrgPerson:
  dn: uid=<user>,<usuffix>,<suffix>
  objectClass: inetOrgPerson
  objectClass: posixAccount
  cn: <user>
  sn: <ask>
  uid: <user>
  uidNumber: <uid>
  gidNumber: <gid>
  homeDirectory: <home>
  loginShell: <shell>
  gecos: <user>
  description: User account
  title: Employee
  Notice the <ask> option used for the sn attribute. This will make ldapadduser prompt you for it's value.

There are utilities in the package that were not covered here. Here is a complete list:

ldaprenamemachine ldapadduser ldapdeleteuserfromgroup ldapfinger ldapid ldapgid ldapmodifyuser ldaprenameuser lsldap ldapaddusertogroup ldapsetpasswd ldapinit ldapaddgroup ldapdeletegroup ldapmodifygroup ldapdeletemachine ldaprenamegroup ldapaddmachine ldapmodifymachine ldapsetprimarygroup ldapdeleteuser

Резервное копирование и восстановление

Now we have ldap running just the way we want, it is time to ensure we can save all of our work and restore it as needed.

What we need is a way to backup the ldap database(s), specifically the backend (cn=config) and frontend (dc=example,dc=com). If we are going to backup those databases into, say, /export/backup, we could use slapcat as shown in the following script, called /usr/local/bin/ldapbackup:

#!/bin/bash

BACKUP_PATH=/export/backup SLAPCAT=/usr/sbin/slapcat

nice ${SLAPCAT} -n 0 > ${BACKUP_PATH}/config.ldif nice ${SLAPCAT} -n 1 > ${BACKUP_PATH}/example.com.ldif nice ${SLAPCAT} -n 2 > ${BACKUP_PATH}/access.ldif chmod 640 ${BACKUP_PATH}/*.ldif

These files are uncompressed text files containing everything in your ldap databases including the tree layout, usernames, and every password. So, you might want to consider making /export/backup an encrypted partition and even having the script encrypt those files as it creates them. Ideally you should do both, but that depends on your security requirements.

Then, it is just a matter of having a cron script to run this program as often as we feel comfortable with. For many, once a day suffices. For others, more often is required. Here is an example of a cron script called /etc/cron.d/ldapbackup that is run every night at 22:45h:

MAILTO=backup-emails@domain.com 45 22 * * * root /usr/local/bin/ldapbackup

Now the files are created, they should be copied to a backup server.

Assuming we did a fresh reinstall of ldap, the restore process could be something like this:

sudo service slapd stop sudo mkdir /var/lib/ldap/accesslog sudo slapadd -F /etc/ldap/slapd.d -n 0 -l /export/backup/config.ldif sudo slapadd -F /etc/ldap/slapd.d -n 1 -l /export/backup/domain.com.ldif sudo slapadd -F /etc/ldap/slapd.d -n 2 -l /export/backup/access.ldif sudo chown -R openldap:openldap /etc/ldap/slapd.d/ sudo chown -R openldap:openldap /var/lib/ldap/ sudo service slapd start

Ссылки

  The primary resource is the upstream documentation: www.openldap.org
  There are many man pages that come with the slapd package. Here are some important ones, especially considering the material presented in this guide:
  slapd
  slapd-config
  slapd.access
  slapo-syncprov
  Other man pages:
  auth-client-config
  pam-auth-update
  Zytrax's LDAP for Rocket Scientists; a less pedantic but comprehensive treatment of LDAP
  A Ubuntu community OpenLDAP wiki page has a collection of notes
  O'Reilly's LDAP System Administration (textbook; 2003)
  Packt's Mastering OpenLDAP (textbook; 2007)