Samba/idmapldap

Материал из ALT Linux Wiki
Freesource-logo.png Blue Glass Arrow.svg MediaWiki logo.png
Эта страница была перемещена с freesource.info.
Эта страница наверняка требует чистки и улучшения — смело правьте разметку и ссылки.
Просьба по окончанию убрать этот шаблон со страницы.


задача: получить единые uidnumber/gidnumber на PDC и рядовых серверах домена.

в openldap находится база пользователей: ou=People и ou=Groups. на PDC пользователей в систему поставляет nss_ldap, samba использует ldap passdb backend.

замечание: ab@ утверждает что nss_winbind уже способен работать на pdc и поставлять пользователей из ldap backend в систему. Однако, мне вообще не удалось заставить winbind работать на pdc в 3.0.14 и последней 3.0.21rc1.

На domain members штатно предлагается использовать winbind для трансляции SID'ов в uid, и nss_winbind как поставщик uid'ов в систему. он выделяет uid из idmap uid range (допустим, 10000-20000).

пусть существует учетная запись uid=kolya,ou=People, o=example. У нее есть uidNumber: 510, и objectclass: posixAccount, sambaSAMAccount. При подключении под этим логином по сети: - на pdc - smbd euid будет 510 (account из nss_ldap) - на domain member с winbind - "какой-то" uid, предоставленный nss_winbind, полученный из заданного диапазона (очевидно, отличающийся от 510).

(далее под словом сервер понимается domain member server)

Предположим, что на PDC включена опция unix extensions = yes, и монтируем сетевой ресур по cifs (а не smbfs). В этом случае, будут виден настоящий owner uid (510), который не имеет никакого смысла для member не использующего nss_ldap.

Используя idmap backend = ldap, можно добиться единых uid'ов на всех серверах входящих в домен - кроме pdc. Это приемлемо только если сам pdc не предоставляет сетевых ресурсов.

Я вижу проблему: winbind выделяет числовые uid непредсказуемо (хотя возможно и постоянные). Не существует способа гарантировать что выделенный uid будет равен gidNumber, заданному в uid=kolya,ou=People; даже наверняка будет не равен. Существуют idmap_rid. Однако его алгоритм хотя и предсказуем, но страдает тем же.

Я предположил что можно на всех машинах входящих в домен использовать nss_ldap, поместив его в nsswitch.conf. Этим мы добьемся того, что на каждом сервере будут существовать kolya с uid 510 (из nss_ldap) и еще один kolya с uid 10021 (из nss_winbind). Для смонтированных ресурсов - будут видны настоящие имена пользователей, но это ничего не даст для member server предоставляющего ресурсы: по прежнему подключения к нему будут работать с "левым" uid полученным от nss_winbind/idmap.

Сделаем еще один шаг: уберем winbind из nsswitch.conf.

passwd:     files ldap db nisplus nis
shadow:     tcb files ldap db nisplus nis
group:      files ldap db nisplus nis

Теперь подключиться к серверу под доменной учетной записью вообще нельзя. В логах winbind при этом:

[2005/11/28 16:14:39, 1] nsswitch/winbindd_sid.c:winbindd_gid_to_sid(474)
  Could not convert gid 513 to sid

угу. Дальше изучаем исходники в районе nsswitch/winbindd_util.c и sam/idmap_ldap.c и пытаемся понять как это работает. Думаем еще, смотрим лдап-клиентом на ветку idmap. В голову приходит синхронизировать uid/gid в Idmap с ветками Groups.

.... еще смотрим на исходники и логи slapd и наконец понимаем: idmap_ldap ищет objectClass: sambaIdmapEntry, и создает новую запись если не находит. Причем в запросе стоит: (sambaSID="XXXX") - для sid_to_gid, (uidNumber=XXX) - для uid_to_sid, и т.д. Причем все аттрибуты: SID и необязательные uidnumber/gidnumber - уже содержатся в записи для каждой группы и каждого пользователя.

задаем idmap suffix = (пустой) и пробуем еще раз. Это не работает как хотелось, но теперь все уже понятно: в "листьях" ldap, представляющих пользователей (objectclass: posixaccount) и группы (objectclass: posixgroup) пишем дополнительный objectClass: sambaIdmapEntry. После этого обманутый idmap смотрит в корень ldap-дерева и делает запрос. И таки находит ;) uid/gid в них - те же самые которые видит nss_ldap, а SID - по определению правильный.

чтобы теперь так было всегда, smbldap-{user,group}add из smbldap-tools учим добавлять одну строчку: objectClass=sambaIdmapEntry.

[root@vault root]# diff -Naur /usr/sbin/smbldap-useradd.orig /usr/sbin/smbldap-useradd
--- /usr/sbin/smbldap-useradd.orig      2005-11-29 17:15:42 +0200
+++ /usr/sbin/smbldap-useradd   2005-11-29 20:34:41 +0200
@@ -382,7 +382,7 @@

     my $modify = $ldap_master->modify ( "uid=$userName,$config{usersdn}",
                                        changes => [
-                                                   add => [objectClass => 'sambaSAMAccount'],
+                                                   add => [objectClass => ['sambaSAMAccount', 'sambaIdmapEntry']],
                                                    add => [sambaPwdLastSet => "$valpwdlastset"],
                                                    add => [sambaLogonTime => '0'],
                                                    add => [sambaLogoffTime => '2147483647'],

Теперь nss_winbind выдает в точности такие uid как nss_ldap. Я не до конца разобрался, почему без nss_winbind wbinfo какой-то неполноценный, но вообще можно отказаться от nss_ldap на domain member в пользу nss_winbind (однако pam_winbind для моих задач не подходит - на рабочих станциях линуксы, и нужна авторизация входа на каждый хост).

хинт: экспериментируя с idmap, всегда удаляйте /var/lib/samba/winbindd_cache.tdb и /var/lib/samba/winbindd_idmap.tdb. В некоторых случаях даже при наличии idmapentry в ldap, используется сохраненный мапинг из winbindd_cache.tdb.

хинт2: скрипт smbldap-populate из smbldap-tools создает не все группы из BUILTIN (SID S-1-5-32-xxx). В частности, не создаются группы System Operators, Guests, Users, Power Users. Но в выводе wbinfo -g (или getent group, если winbind используется в nss) они присутствуют с gid в духе 20001,20002; причем idmap затем записывает этот мапинг в ldap в ветке idmap suffix (т.е. в нашем случае - в корень). Лучше их все же создать заранее в Groups и выдать нормальные gid вручную.

на самом деле, записи для этих групп есть в smbldap-populate, но закомментированы (?). В "местной" сборке 0.9.1 я их вернул.

хинт3: хотя мы сделали стабильный маппинг, все же idmap gid / idmap uid продолжают действовать: в нашем случае они ограничивают допустимый диапазон uid/gid, и если указанные в ldap не попадают в него, winbind назначает "левые". В частности, Administrator (uid=0) у меня имеет локально uid 20001. Задать же range с нуля невозможно : в логе будет "idmap range missing or invalid". Исправить это можно только захачив проверку диапазона:

param/loadparm.c:2875

if (idmap_uid_low == 0 || idmap_uid_high == 0)
     return False;

param/loadparm.c:2889

if (idmap_gid_low == 0 || idmap_gid_high == 0)
                return False;

... но подумав, я согласился что это фича - в самом деле, зачем работать под рутом/админом? ;) Можно сразу задать Администратору "правильный" uid/gid, это не помешает вводить машины в домен (начиная с 3.0.11pre2 samba использует систему привилегий). А больше ни для чего root не нужен ;)

внеклассное чтение: http://samba.org/samba/docs/man/Samba-HOWTO-Collection/idmapper.html

обсуждение ldapsam:trusted:

Yes you still need it [nss_ldap] as Samba is going to use it. I'll look
into modifying smbd so that all getpwXXX calls go via passdb
and thus take advantage of LDAP if that's configured directly.
That'll have to be for 3.0.21+ though.

Jeremy Allison

You still need ldap in /etc/nsswitch.conf, be it only for the
other unix programs running. The major optimizations come from the assumption
that all accounts relevant to Samba are in LDAP and both the posix and samba
object classes are on the same LDAP entry.

Volker Lendecke