Практикум по LDAP или повесть о «первичной группе»
Автор: menzoberranzann
|
![]() |
Я думаю каждый, кто сталкивался с той или иной реализацией LDAP, а тем более с его настройкой, знакомо понятие «первичной группы». Вроде бы все стандартно, цифровой идентификатор группы (gidNumber), определяющий принадлежность пользователя к той или иной группе. Но что, если учетной записи пользователя назначено несколько групп? О том, какие могут возникнуть проблемы и как их решить, в сегодняшнем блоге.
Намедни пришлось участвовать в настройке LDAP аутентификации для некоторого серверного окружения. LDAP-сервер поднят на OpenLDAP, используются в том числе стандартные схемы, такие как nis, cosine, inetorgperson; со стороны client-серверов настроен sssd, кому это уже интересно, тот меня поймет. Аутентификация пользователей проходит на ура, никаких проблем не предвидится. Но, как обычно бывает, вдруг, откуда ни возьмись…alarm.
Дело в том, что за время существования каждая учетная запись пользователя обрастает некоторым количеством групп, к которым она привязывается. С помощью групп выдается доступ на те или иные сервера и так далее. Но, в зависимости от профессиональной истории сотрудника, учетные записи двух сотрудников в LDAP, работающих в одном департаменте, могут содержать разные первичные группы и некоторый набор других групп. Вот тут и наступает казус. Ограничение прав доступа по группе не одинаково ограничивают права обоих пользователей. Все дело именно в первичной группе, она то у них разная. Как минимум, при аутентификации на сервере у двух пользователей различные группы домашнего каталога. Но основная проблема в решении оной. Как переназначить первичную группу в зависимости от серверного окружения. Просто установить двум учетным записям одинаковые первичные группы нельзя, поломаются правила на других серверных окружениях. Это уже вопросы не ко мне, не я смотрящий LDAP-а. Облазил весь рунет, иностранные известные и неизвестные ресурсы, официальные руководства – даже ни намека на возможное решение.
И тут я почувствовал себя мультяшным героем, у которого в голове засветилась лампочка
А почему нет, подумал я и принялся реализовывать идею. Собственно идея заключалась в использовании параметра ldap_user_gid_number конфигурационного файла sssd.conf. Официальная документация http://linux.die.net/man/5/sssd-ldap говорит нам, что с помощью этого параметра указывается атрибут (наименование), который в учетной записи LDAP пользователя содержит идентификатор первичной группы (primary group id). По умолчанию используется именно gidNumber, который менять нельзя. Но кто сказал, что нам нельзя добавить в работающую схему еще один подобный параметр и указать в нем идентификатор необходимой иной первичной группы. На стороне client-сервера добавляем строку ldap_user_gid_number = gidPNumber в sssd.conf (gidPNumber – именно тот еще один подобный параметр) в раздел описания LDAP-домена:
[domain/LDAP]
…
ldap_user_gid_number =gidPNumber
…
Остается дело за малым, ввести в описание LDAP схемы новый атрибут и добавить его в описание учетной записи. Поскольку в реализации LDAP, с которой столкнулся я, для описания учетной записи используется схема nis, необходимо добавить в нее новый атрибут и изменить описание класса объекта (objectClass) posixAccount.
Далее приводятся исключительно пошаговые действия в виде bash-copy-paste с комментариями. Для ясности: ldap-server и ldap-client – OpenLDAP-сервер и любой client-сервер соответственно с sssd-демоном.
Было вот так:
[root@ldap-client sssd]# id testuser
uid=1005(testuser) gid=1001(dev) groups=1001(dev),1002(test)
[root@ldap-client sssd]# ls -la /home/
total 16
drwxr-xr-x. 4 root root 4096 Nov 27 10:56 .
dr-xr-xr-x. 25 root root 4096 Nov 27 05:52 ..
drwxr-xr-x 4 testuser dev 4096 Nov 27 10:56 testuser
[root@ldap-server azapravdin]# ldapsearch -xWD "cn=admin,dc=mydomain,dc=com" -b 'dc=mydomain,dc=com'
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <dc=mydomain,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
...
# dev, groups, mydomain.com
dn: cn=dev,ou=groups,dc=mydomain,dc=com
objectClass: posixGroup
cn: dev
gidNumber: 1001
memberUid: testuser
# test, groups, mydomain.com
dn: cn=test,ou=groups,dc=mydomain,dc=com
objectClass: posixGroup
cn: test
gidNumber: 1002
memberUid: testuser
# testuser, people, mydomain.com
dn: uid=testuser,ou=people,dc=mydomain,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
objectClass: hostObject
uid: testuser
sn: testuser
givenName: testuser
cn: testuser
displayName: testuser
uidNumber: 1005
gidNumber: 1001
userPassword:: e2NyeXB0fSQ2JFJodU9yT3BydGZtckh4UjMkUTJTL1M0VVE4MlVtZmlrQ0ZvdXc
0U2dhREJjZGtSMm53OVovaWFSVkhLNHQuMzkvNUlGV3lFTU9HOVYvUS8vNEZtbWlZek94NVNEQmh4
Rll5cG1xSS4=
gecos: testuser
loginShell: /bin/bash
homeDirectory: /home/testuser
shadowExpire: 364
shadowFlag: 0
shadowWarning: 7
shadowMin: 0
shadowMax: 99999
shadowLastChange: 16374
host: ldap-client.mydomain.com
...
Необходимые изменения:
Создаем файл описания нового атрибута gidPNumber в схеме nis:
[root@ldap-server azapravdin]# cat add_attr_to_nis.ldif
dn: cn={2}nis,cn=schema,cn=config
changetype: modify
add: olcAttributeTypes
olcAttributeTypes: ( 1.3.6.1.1.1.1.28 NAME 'gidPNumber' DESC 'An integer primary group' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE)
Вносим изменения в схему nis:
[root@ldap-server azapravdin]# ldapmodify -Y EXTERNAL -H ldapi:/// -f add_attr_to_nis.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn={2}nis,cn=schema,cn=config"
Создаем файл описания класса объекта PosixAccount для схемы nis:
[root@ldap-server azapravdin]# cat change_nis.ldif
dn: cn={2}nis,cn=schema,cn=config
changetype: modify
delete: olcObjectClasses
olcObjectClasses: {0}( 1.3.6.1.1.1.2.0 NAME 'posixAccount' DESC 'Abstraction of an account with POSIX attributes' SUP top AUXILIARY MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) MAY ( userPassword $ loginShell $ gecos $ description ) )
-
add: olcObjectClasses
olcObjectClasses: {0}( 1.3.6.1.1.1.2.0 NAME 'posixAccount' DESC 'Abstraction of an account with POSIX attributes' SUP top AUXILIARY MUST ( cn $ uid $ uidNumber $ gidNumber $ gidPNumber $ homeDirectory ) MAY ( userPassword $ loginShell $ gecos $ description ) )
Вносим изменения в схему nis:
[root@ldap-server azapravdin]# ldapmodify -Y EXTERNAL -H ldapi:/// -f change_nis.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn={2}nis,cn=schema,cn=config"
Создаем файл для добавления атрибута gidPNumber в описание учетной записи:
[root@ldap-server azapravdin]# cat add_attr_to_user.ldif
dn: uid=testuser,ou=people,dc=mydomain,dc=com
changetype: modify
add: gidPNumber
gidPNumber: 1002
Изменяем описание учетной записи:
[root@ldap-server azapravdin]# ldapmodify -xWD "cn=admin,dc=mydomain,dc=com" -f add_attr_to_user.ldif
Enter LDAP Password:
modifying entry "uid=testuser,ou=people,dc=mydomain,dc=com"
На client-сервере добавляем запись в /etc/sssd/sssd.conf файл в раздел [domain/LDAP]:
ldap_user_gid_number = gidPNumber
и перезагружаем sssd демон.
И стало вот так:
[root@ldap-client sssd]# ls -la /home/
total 16
drwxr-xr-x. 4 root root 4096 Nov 27 12:24 .
dr-xr-xr-x. 25 root root 4096 Nov 27 05:52 ..
drwxr-xr-x 4 testuser test 4096 Nov 27 12:24 testuser
[root@ldap-server azapravdin]# ldapsearch -xWD "cn=admin,dc=mydomain,dc=com" -b 'dc=mydomain,dc=com'
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <dc=mydomain,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
...
# testuser, people, mydomain.com
dn: uid=testuser,ou=people,dc=mydomain,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
objectClass: hostObject
uid: testuser
sn: testuser
givenName: testuser
cn: testuser
displayName: testuser
uidNumber: 1005
gidNumber: 1001
userPassword:: e2NyeXB0fSQ2JFJodU9yT3BydGZtckh4UjMkUTJTL1M0VVE4MlVtZmlrQ0ZvdXc
0U2dhREJjZGtSMm53OVovaWFSVkhLNHQuMzkvNUlGV3lFTU9HOVYvUS8vNEZtbWlZek94NVNEQmh4
Rll5cG1xSS4=
gecos: testuser
loginShell: /bin/bash
homeDirectory: /home/testuser
shadowExpire: 364
shadowFlag: 0
shadowWarning: 7
shadowMin: 0
shadowMax: 99999
shadowLastChange: 16374
host: ldap-client.mydomain.com
gidPNumber: 1002
...
То есть, теперь, при прохождении LDAP авторизации, первичная группа для учетной записи меняется на ту, которую мы установим. Для каждого серверного окружения, а их не так уже и много, можно создать свой атрибут и, в зависимости от окружения, на client-сервере использовать необходимый.
Надеюсь, данное руководство будет полезным. На авторские права не претендую, отдаю в массы
И помните, нет нерешаемых задач, но «костыль» - не вариант.
Постараюсь ответить на любые вопросы. Спасибо за внимание.
P.S. У тех, кто ждет продолжение блога про Cobbler, прошу прощение, не расстраивайтесь. Материал готовится, уж очень объемная тема, не хочется публиковать сырой материал.
Намедни пришлось участвовать в настройке LDAP аутентификации для некоторого серверного окружения. LDAP-сервер поднят на OpenLDAP, используются в том числе стандартные схемы, такие как nis, cosine, inetorgperson; со стороны client-серверов настроен sssd, кому это уже интересно, тот меня поймет. Аутентификация пользователей проходит на ура, никаких проблем не предвидится. Но, как обычно бывает, вдруг, откуда ни возьмись…alarm.
Дело в том, что за время существования каждая учетная запись пользователя обрастает некоторым количеством групп, к которым она привязывается. С помощью групп выдается доступ на те или иные сервера и так далее. Но, в зависимости от профессиональной истории сотрудника, учетные записи двух сотрудников в LDAP, работающих в одном департаменте, могут содержать разные первичные группы и некоторый набор других групп. Вот тут и наступает казус. Ограничение прав доступа по группе не одинаково ограничивают права обоих пользователей. Все дело именно в первичной группе, она то у них разная. Как минимум, при аутентификации на сервере у двух пользователей различные группы домашнего каталога. Но основная проблема в решении оной. Как переназначить первичную группу в зависимости от серверного окружения. Просто установить двум учетным записям одинаковые первичные группы нельзя, поломаются правила на других серверных окружениях. Это уже вопросы не ко мне, не я смотрящий LDAP-а. Облазил весь рунет, иностранные известные и неизвестные ресурсы, официальные руководства – даже ни намека на возможное решение.
И тут я почувствовал себя мультяшным героем, у которого в голове засветилась лампочка

[domain/LDAP]
…
ldap_user_gid_number =gidPNumber
…
Остается дело за малым, ввести в описание LDAP схемы новый атрибут и добавить его в описание учетной записи. Поскольку в реализации LDAP, с которой столкнулся я, для описания учетной записи используется схема nis, необходимо добавить в нее новый атрибут и изменить описание класса объекта (objectClass) posixAccount.
Далее приводятся исключительно пошаговые действия в виде bash-copy-paste с комментариями. Для ясности: ldap-server и ldap-client – OpenLDAP-сервер и любой client-сервер соответственно с sssd-демоном.
Было вот так:
[root@ldap-client sssd]# id testuser
uid=1005(testuser) gid=1001(dev) groups=1001(dev),1002(test)
[root@ldap-client sssd]# ls -la /home/
total 16
drwxr-xr-x. 4 root root 4096 Nov 27 10:56 .
dr-xr-xr-x. 25 root root 4096 Nov 27 05:52 ..
drwxr-xr-x 4 testuser dev 4096 Nov 27 10:56 testuser
[root@ldap-server azapravdin]# ldapsearch -xWD "cn=admin,dc=mydomain,dc=com" -b 'dc=mydomain,dc=com'
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <dc=mydomain,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
...
# dev, groups, mydomain.com
dn: cn=dev,ou=groups,dc=mydomain,dc=com
objectClass: posixGroup
cn: dev
gidNumber: 1001
memberUid: testuser
# test, groups, mydomain.com
dn: cn=test,ou=groups,dc=mydomain,dc=com
objectClass: posixGroup
cn: test
gidNumber: 1002
memberUid: testuser
# testuser, people, mydomain.com
dn: uid=testuser,ou=people,dc=mydomain,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
objectClass: hostObject
uid: testuser
sn: testuser
givenName: testuser
cn: testuser
displayName: testuser
uidNumber: 1005
gidNumber: 1001
userPassword:: e2NyeXB0fSQ2JFJodU9yT3BydGZtckh4UjMkUTJTL1M0VVE4MlVtZmlrQ0ZvdXc
0U2dhREJjZGtSMm53OVovaWFSVkhLNHQuMzkvNUlGV3lFTU9HOVYvUS8vNEZtbWlZek94NVNEQmh4
Rll5cG1xSS4=
gecos: testuser
loginShell: /bin/bash
homeDirectory: /home/testuser
shadowExpire: 364
shadowFlag: 0
shadowWarning: 7
shadowMin: 0
shadowMax: 99999
shadowLastChange: 16374
host: ldap-client.mydomain.com
...
Необходимые изменения:
Создаем файл описания нового атрибута gidPNumber в схеме nis:
[root@ldap-server azapravdin]# cat add_attr_to_nis.ldif
dn: cn={2}nis,cn=schema,cn=config
changetype: modify
add: olcAttributeTypes
olcAttributeTypes: ( 1.3.6.1.1.1.1.28 NAME 'gidPNumber' DESC 'An integer primary group' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE)
Вносим изменения в схему nis:
[root@ldap-server azapravdin]# ldapmodify -Y EXTERNAL -H ldapi:/// -f add_attr_to_nis.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn={2}nis,cn=schema,cn=config"
Создаем файл описания класса объекта PosixAccount для схемы nis:
[root@ldap-server azapravdin]# cat change_nis.ldif
dn: cn={2}nis,cn=schema,cn=config
changetype: modify
delete: olcObjectClasses
olcObjectClasses: {0}( 1.3.6.1.1.1.2.0 NAME 'posixAccount' DESC 'Abstraction of an account with POSIX attributes' SUP top AUXILIARY MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) MAY ( userPassword $ loginShell $ gecos $ description ) )
-
add: olcObjectClasses
olcObjectClasses: {0}( 1.3.6.1.1.1.2.0 NAME 'posixAccount' DESC 'Abstraction of an account with POSIX attributes' SUP top AUXILIARY MUST ( cn $ uid $ uidNumber $ gidNumber $ gidPNumber $ homeDirectory ) MAY ( userPassword $ loginShell $ gecos $ description ) )
Вносим изменения в схему nis:
[root@ldap-server azapravdin]# ldapmodify -Y EXTERNAL -H ldapi:/// -f change_nis.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn={2}nis,cn=schema,cn=config"
Создаем файл для добавления атрибута gidPNumber в описание учетной записи:
[root@ldap-server azapravdin]# cat add_attr_to_user.ldif
dn: uid=testuser,ou=people,dc=mydomain,dc=com
changetype: modify
add: gidPNumber
gidPNumber: 1002
Изменяем описание учетной записи:
[root@ldap-server azapravdin]# ldapmodify -xWD "cn=admin,dc=mydomain,dc=com" -f add_attr_to_user.ldif
Enter LDAP Password:
modifying entry "uid=testuser,ou=people,dc=mydomain,dc=com"
На client-сервере добавляем запись в /etc/sssd/sssd.conf файл в раздел [domain/LDAP]:
ldap_user_gid_number = gidPNumber
и перезагружаем sssd демон.
И стало вот так:
[root@ldap-client sssd]# ls -la /home/
total 16
drwxr-xr-x. 4 root root 4096 Nov 27 12:24 .
dr-xr-xr-x. 25 root root 4096 Nov 27 05:52 ..
drwxr-xr-x 4 testuser test 4096 Nov 27 12:24 testuser
[root@ldap-server azapravdin]# ldapsearch -xWD "cn=admin,dc=mydomain,dc=com" -b 'dc=mydomain,dc=com'
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <dc=mydomain,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
...
# testuser, people, mydomain.com
dn: uid=testuser,ou=people,dc=mydomain,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
objectClass: hostObject
uid: testuser
sn: testuser
givenName: testuser
cn: testuser
displayName: testuser
uidNumber: 1005
gidNumber: 1001
userPassword:: e2NyeXB0fSQ2JFJodU9yT3BydGZtckh4UjMkUTJTL1M0VVE4MlVtZmlrQ0ZvdXc
0U2dhREJjZGtSMm53OVovaWFSVkhLNHQuMzkvNUlGV3lFTU9HOVYvUS8vNEZtbWlZek94NVNEQmh4
Rll5cG1xSS4=
gecos: testuser
loginShell: /bin/bash
homeDirectory: /home/testuser
shadowExpire: 364
shadowFlag: 0
shadowWarning: 7
shadowMin: 0
shadowMax: 99999
shadowLastChange: 16374
host: ldap-client.mydomain.com
gidPNumber: 1002
...
То есть, теперь, при прохождении LDAP авторизации, первичная группа для учетной записи меняется на ту, которую мы установим. Для каждого серверного окружения, а их не так уже и много, можно создать свой атрибут и, в зависимости от окружения, на client-сервере использовать необходимый.
Надеюсь, данное руководство будет полезным. На авторские права не претендую, отдаю в массы

Постараюсь ответить на любые вопросы. Спасибо за внимание.
P.S. У тех, кто ждет продолжение блога про Cobbler, прошу прощение, не расстраивайтесь. Материал готовится, уж очень объемная тема, не хочется публиковать сырой материал.
Комментарии
Отправить комментарий