LDAP Linux Auth: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
(не показано 6 промежуточных версий этого же участника) | |||
Строка 319: | Строка 319: | ||
==Groups== |
==Groups== |
||
− | Контейнер для групп. |
+ | Контейнер для групп и для пользователей. |
<PRE> |
<PRE> |
||
0001_Groups |
0001_Groups |
||
Строка 326: | Строка 326: | ||
dn: ou=Group,dc=customer_organization,dc=fuel_domain |
dn: ou=Group,dc=customer_organization,dc=fuel_domain |
||
ou: Group |
ou: Group |
||
+ | objectClass: top |
||
+ | objectClass: organizationalUnit |
||
+ | |||
+ | dn: ou=People,dc=customer_organization,dc=fuel_domain |
||
+ | ou: People |
||
objectClass: top |
objectClass: top |
||
objectClass: organizationalUnit |
objectClass: organizationalUnit |
||
Строка 672: | Строка 677: | ||
</PRE> |
</PRE> |
||
+ | ==Test user== |
||
− | ==9902_User_test_user== |
||
+ | Пользователь который добавляется для демонстрации - изначально не имеет прав sudo. |
||
<PRE> |
<PRE> |
||
Строка 710: | Строка 716: | ||
description: Fuel Users |
description: Fuel Users |
||
memberUid: test1 |
memberUid: test1 |
||
− | </PRE> |
||
− | |||
− | =1= |
||
− | |||
− | ==Organization Units People and Groups== |
||
− | <PRE> |
||
− | # 06_people |
||
− | dn: ou=People,dc=customer_organization,dc=fuel_domain |
||
− | ou: People |
||
− | objectClass: top |
||
− | objectClass: organizationalUnit |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | # 07_groups |
||
− | dn: ou=Group,dc=customer_organization,dc=fuel_domain |
||
− | ou: Group |
||
− | objectClass: top |
||
− | objectClass: organizationalUnit |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | ldapadd < 06_people |
||
− | adding new entry "ou=People,dc=customer_organization,dc=fuel_domain" |
||
− | |||
− | root@node-3:~/ldap# ldapadd < 07_groups |
||
− | adding new entry "ou=Group,dc=customer_organization,dc=fuel_domain" |
||
− | </PRE> |
||
− | =="Живые Люди"== |
||
− | Добавить пользователя. Обратить внимание - пароль такой же как в /etc/shadow <BR>(Как его генерировать я не знаю пока) |
||
− | <PRE> |
||
− | dn: uid=sirmax,ou=People,dc=customer_organization,dc=fuel_domain |
||
− | objectClass: top |
||
− | objectClass: person |
||
− | objectClass: organizationalPerson |
||
− | objectClass: inetOrgPerson |
||
− | objectClass: posixAccount |
||
− | objectClass: shadowAccount |
||
− | uid: sirmax |
||
− | cn: Max Mazur |
||
− | sn: Mazur |
||
− | givenName: Mazur |
||
− | title: Max Mazur |
||
− | telephoneNumber: +38 067 341 80 70 |
||
− | mobile: +38 067 341 80 70 |
||
− | postalAddress: AddressLine1$AddressLine2$AddressLine3 |
||
− | userPassword: {CRYPT}$6$DS/mzad5$EB.cNCLE7KB7OCPK1nU6aEA8HnQDLY1FPd3KaWPVqaNBtWhmh/4cOUgD1I8tQSFu41yy7jMXDrg9TDqlAbuLX. |
||
− | labeledURI: http://wiki.sirmax.noname.com.ua/ |
||
− | loginShell: /usr/bin/sudosh |
||
− | uidNumber: 9999 |
||
− | gidNumber: 9999 |
||
− | homeDirectory: /home/sirmax/ |
||
− | description: This is an example user |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | ldapadd < 08_user1 |
||
− | adding new entry "uid=sirmax,ou=People,dc=customer_organization,dc=fuel_domain" |
||
− | </PRE> |
||
− | |||
− | |||
− | Обратить внимание на <B>loginShell: /usr/bin/sudosh</B> - если не используется запись сессий то шелл будет другим. |
||
− | <BR> |
||
− | Остальные пользователи создаются полностью аналогично. |
||
− | |||
− | |||
− | ==Groups== |
||
− | 2 группы |
||
− | * группа пользователя (для каждого пользователя) |
||
− | * группа fuel_users которой будет разрешено делвть sudo |
||
− | |||
− | <PRE> |
||
− | dn: cn=sirmax,ou=Group,dc=example_organization,dc=fuel |
||
− | changetype: add |
||
− | cn: fuel users |
||
− | objectClass: posixGroup |
||
− | gidNumber: 9999 |
||
− | description: Fuel Users |
||
− | memberUid: sirmax |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | dn: cn=fuel_users,ou=Group,dc=example_organization,dc=fuel |
||
− | changetype: add |
||
− | cn: fuel_users |
||
− | objectClass: posixGroup |
||
− | gidNumber: 109999 |
||
− | description: Fuel Users |
||
− | memberUid: sirmax |
||
− | </PRE> |
||
− | |||
− | Добавить: |
||
− | <PRE> |
||
− | ldapadd < 09_group_for_user1 |
||
− | adding new entry "cn=sirmax,ou=Group,dc=customer_organization,dc=fuel_domain" |
||
− | |||
− | ldapadd < 10_group_fuel_users |
||
− | adding new entry "cn=fuel_users,ou=Group,dc=customer_organization,dc=fuel_domain" |
||
− | |||
</PRE> |
</PRE> |
||
Строка 815: | Строка 722: | ||
http://wiki.sirmax.noname.com.ua/index.php/LDAP_Linux_Auth_Client |
http://wiki.sirmax.noname.com.ua/index.php/LDAP_Linux_Auth_Client |
||
− | |||
− | =Securing LDAP= |
||
− | В этой секции описывается создание служебных пользователей и групп и ограничение их привелегий. |
||
− | <BR> |
||
− | Эти пользователи будут использоваться на node-1 .. node-4 в файлах |
||
− | * /etc/ldap.conf (node-3) |
||
− | <PRE> |
||
− | uri ldap://10.20.0.3/ |
||
− | base dc=fuel_domain |
||
− | ldap_version 3 |
||
− | rootbinddn uid=nssproxy-node3,ou=service_users,dc=customer_organization,dc=fuel_domain |
||
− | pam_password md5 |
||
− | </PRE> |
||
− | * /etc/ldap.secret (пароль для node-1 - "node1", аналогично для остальных нод) |
||
− | <PRE> |
||
− | node3 |
||
− | </PRE> |
||
− | * /etc/sudo-ldap.conf |
||
− | <PRE> |
||
− | BASE dc=customer_organization,dc=fuel_domain |
||
− | URI ldap://10.20.0.3 |
||
− | BINDDN uid=nssproxy-node3,ou=service_users,dc=customer_organization,dc=fuel_domain |
||
− | BINDPW node3 |
||
− | TIMELIMIT 15 |
||
− | TIMEOUT 20 |
||
− | SUDOERS_BASE ou=sudo,ou=services,dc=customer_organization,dc=fuel_domain |
||
− | </PRE> |
||
− | |||
− | ==Служебные пользователи== |
||
− | |||
− | Для того что бы не делать анонимных запросов я создаю для каждого из своих серверов своего пользователя nssproxy-node{X}, например nssproxy-node1. Все пользователи помещаются в отдельный OU. |
||
− | <BR> |
||
− | Отдельный юнит для этих пользователей |
||
− | <PRE> |
||
− | dn: ou=service_users,dc=customer_organization,dc=fuel_domain |
||
− | ou: service_users |
||
− | objectClass: top |
||
− | objectClass: organizationalUnit |
||
− | </PRE> |
||
− | |||
− | Пользователь: |
||
− | <PRE> |
||
− | dn: uid=nssproxy-node1,ou=service_users,dc=customer_organization,dc=fuel_domain |
||
− | uid: nssproxy-node1 |
||
− | gecos: Network Service Switch Proxy User |
||
− | objectClass: top |
||
− | #objectClass: account |
||
− | objectClass: posixAccount |
||
− | objectClass: shadowAccount |
||
− | objectClass: organizationalPerson |
||
− | objectClass: inetOrgPerson |
||
− | userPassword: {SSHA}RsAMqOI3647qg1gAZF3x2BKBnp0sEVfa |
||
− | cn: node1 |
||
− | sn: node1 |
||
− | shadowLastChange: 15140 |
||
− | shadowMin: 0 |
||
− | shadowMax: 99999 |
||
− | shadowWarning: 7 |
||
− | loginShell: /bin/false |
||
− | uidNumber: 801 |
||
− | gidNumber: 801 |
||
− | homeDirectory: /home/nssproxy |
||
− | </PRE> |
||
− | <BR>и т. д. до node4 |
||
− | <BR> |
||
− | Обратить внимаение - нужно менять не только имя но и UID |
||
− | |||
− | ==Установка паролей== |
||
− | Меняем пароли для всех пользователей, задавая соответвенно node1, node2, node3, node4. |
||
− | <PRE> |
||
− | ldappasswd -S uid=nssproxy-node1,ou=service_users,dc=customer_organization,dc=fuel_domain |
||
− | ldappasswd -S uid=nssproxy-node2,ou=service_users,dc=customer_organization,dc=fuel_domain |
||
− | ldappasswd -S uid=nssproxy-node3,ou=service_users,dc=customer_organization,dc=fuel_domain |
||
− | ldappasswd -S uid=nssproxy-node4,ou=service_users,dc=customer_organization,dc=fuel_domain |
||
− | </PRE> |
||
− | |||
− | ==Служебные Группы== |
||
− | Для служебных пользователей создаем отдельную группу, на которую будем назначать привелегии. <BR> |
||
− | Важно отметить, что эта группа имеет тип <B>groupOfNames</B> а не posixGroup, и содержит не список ID а список dn=<BR> |
||
− | Для posixGroup не работает конструкция <B> by group.exact="cn= ... " read </B> в списках контроля доступа. |
||
− | |||
− | <PRE> |
||
− | dn: cn=nssproxy,ou=Group,dc=customer_organization,dc=fuel_domain |
||
− | cn: nssproxy1 |
||
− | objectClass: groupOfNames |
||
− | objectClass: top |
||
− | member: uid=nssproxy-node1,ou=service_users,dc=customer_organization,dc=fuel_domain |
||
− | member: uid=nssproxy-node2,ou=service_users,dc=customer_organization,dc=fuel_domain |
||
− | member: uid=nssproxy-node3,ou=service_users,dc=customer_organization,dc=fuel_domain |
||
− | member: uid=nssproxy-node4,ou=service_users,dc=customer_organization,dc=fuel_domain |
||
− | </PRE> |
||
− | |||
− | Добавлять пользователей в группу отдельно не надо - группа изначально создается содержащей всех необходимых пользователей. |
||
− | |||
− | |||
− | ==Назначение прав== |
||
− | Пока у пользователя нет прав то он не может получить криптованый пароль так как настройка ACL по умолчанию это запрещает: |
||
− | <PRE> |
||
− | olcAccess: {0}to attrs=userPassword,shadowLastChange |
||
− | by self write |
||
− | by anonymous auth |
||
− | by dn="cn=admin,dc=fuel_domain" write |
||
− | by * none |
||
− | </PRE> |
||
− | Тут можно видеть, что просмотр паролей (хешей) разрешен только администратору "cn=admin,dc=fuel_domain" |
||
− | <BR> |
||
− | Соответвенно утилита getent не может получить доступа к паролю так-как использует пользователя nssproxy-node{N} |
||
− | <PRE> |
||
− | getent shadow sirmax |
||
− | sirmax:*::::::: |
||
− | </PRE> |
||
− | Вообще-то для того что бы работал логин пароль знать не обязательно - с ним можно авторизоваться через PAM (pam_ldap). |
||
− | <BR> но для того что бы работал nss без pam_ldap а только с pam_unix нужно что бы можно было получить хеш пароля. |
||
− | |||
− | Проверим текущие разрешения: |
||
− | <BR> |
||
− | Обратить внимание - у меня 2 базы данных потому <B>{2}</B> |
||
− | <PRE> |
||
− | \ldapsearch -Y EXTERNAL -H ldapi:/// -b "olcDatabase={2}hdb,cn=config" |
||
− | </PRE> |
||
− | Вывод поформатирован: |
||
− | <PRE> |
||
− | # {2}hdb, config |
||
− | dn: olcDatabase={2}hdb,cn=config |
||
− | objectClass: olcDatabaseConfig |
||
− | objectClass: olcHdbConfig |
||
− | |||
− | olcDatabase: {2}hdb |
||
− | olcDbDirectory: /var/lib/ldap_fuel_domain/ |
||
− | olcSuffix: dc=fuel_domain |
||
− | |||
− | olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=fuel_domain" write by * none |
||
− | olcAccess: {1}to dn.base="" by * read |
||
− | olcAccess: {2}to * by dn="cn=admin,dc=fuel_domain" write by * read |
||
− | |||
− | olcLastMod: TRUE |
||
− | |||
− | olcRootDN: cn=admin,dc=fuel_domain |
||
− | olcRootPW: {SSHA}bxQpFzYmIkILSbDEL3cVl+nf03mdra/t |
||
− | |||
− | olcDbCheckpoint: 512 30 |
||
− | olcDbConfig: {0}set_cachesize 0 2097152 0 |
||
− | olcDbConfig: {1}set_lk_max_objects 1500 |
||
− | olcDbConfig: {2}set_lk_max_locks 1500 |
||
− | olcDbConfig: {3}set_lk_max_lockers 1500 |
||
− | olcDbIndex: objectClass eq |
||
− | </PRE> |
||
− | |||
− | Нас интересует секция |
||
− | <PRE> |
||
− | olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=fuel_domain" write by * none |
||
− | olcAccess: {1}to dn.base="" by * read |
||
− | olcAccess: {2}to * by dn="cn=admin,dc=fuel_domain" write by * read |
||
− | </PRE> |
||
− | |||
− | Тут видно что права на чтения и запись пароля есть только у dn="cn=admin,dc=fuel_domain |
||
− | <BR> |
||
− | |||
− | |||
− | Требуется добавить разрешение для группы nsswitch |
||
− | <PRE> |
||
− | # 21_acl |
||
− | dn: olcDatabase={2}hdb,cn=config |
||
− | changetype: modify |
||
− | replace: olcAccess |
||
− | olcAccess: {0}to attrs=userPassword,shadowLastChange |
||
− | by self write |
||
− | by anonymous auth |
||
− | by dn="cn=admin,dc=fuel_domain" write |
||
− | by group.exact="cn=nssproxy,ou=Group,dc=customer_organization,dc=fuel_domain" read |
||
− | by * none |
||
− | olcAccess: {1}to dn.base="" |
||
− | by * read |
||
− | olcAccess: {2}to * |
||
− | by dn="cn=admin,dc=fuel_domain" write |
||
− | by * read |
||
− | </PRE> |
||
− | <PRE> |
||
− | \ldapmodify -Y EXTERNAL -H ldapi:/// < 21_acl |
||
− | </PRE> |
||
− | |||
− | После назначение прав можно увидеть что getent может получить хеш пароля: |
||
− | <PRE> |
||
− | getent shadow sirmax |
||
− | sirmax:$6$DS/mzad5$EB.cNCLE7KB7OCPK1nU6aEA8HnQDLY1FPd3KaWPVqaNBtWhmh/4cOUgD1I8tQSFu41yy7jMXDrg9TDqlAbuLX. |
||
− | </PRE> |
||
− | |||
− | Следующим шагом следует разрешить чтение всего что касается sudo всем кроме группы nssproxy |
||
− | <PRE> |
||
− | dn: olcDatabase={2}hdb,cn=config |
||
− | changetype: modify |
||
− | replace: olcAccess |
||
− | olcAccess: {0}to attrs=userPassword,shadowLastChange |
||
− | by self write |
||
− | by anonymous auth |
||
− | by dn="cn=admin,dc=fuel_domain" write |
||
− | by group.exact="cn=nssproxy,ou=Group,dc=customer_organization,dc=fuel_domain" read |
||
− | by * none |
||
− | olcAccess: {1}to dn.subtree="ou=sudo,ou=services,dc=customer_organization,dc=fuel_domain" |
||
− | by dn="cn=admin,dc=fuel_domain" write. |
||
− | by group.exact="cn=nssproxy,ou=Group,dc=customer_organization,dc=fuel_domain" read |
||
− | by anonymous auth |
||
− | by * none |
||
− | olcAccess: {2}to dn.base="" |
||
− | by * read |
||
− | olcAccess: {3}to * |
||
− | by dn="cn=admin,dc=fuel_domain" write |
||
− | by * read |
||
− | </PRE> |
||
− | dn.subtree="ou=sudo,ou=services,dc=customer_organization,dc=fuel_domain" - указать что все поддерево доступно только группе cn=nssproxy,ou=Group,dc=customer_organization,dc=fuel_domain |
||
− | |||
− | <BR>Проверить то, что доступ к поддереву ограничен можно следующим образом: |
||
− | * Создать алиас для простоты использования, который использует "обычного" пользователя. |
||
− | <PRE> |
||
− | alias ldapsearch_sirmax='\ldapsearch -D "uid=sirmax,ou=People,dc=customer_organization,dc=fuel_domain" -w r00tme' |
||
− | </PRE> |
||
− | <PRE> |
||
− | ldapsearch -x -b 'dc=fuel_domain' '(objectclass=*)' | grep sudo |
||
− | </PRE> |
||
− | Вывод (часть строк удалена так как вывод длиный) |
||
− | <PRE> |
||
− | loginShell: /usr/bin/sudosh |
||
− | dn: cn=defaults,ou=sudo,ou=services,dc=customer_organization,dc=fuel_domain |
||
− | objectClass: sudoRole |
||
− | description: Default sudoOption's go here |
||
− | sudoOption: env_reset |
||
− | sudoOption: mail_badpass |
||
− | sudoOption: secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sb |
||
− | sudoOrder: 1 |
||
− | ... |
||
− | dn: cn=root,ou=sudo,ou=services,dc=customer_organization,dc=fuel_domain |
||
− | objectClass: sudoRole |
||
− | sudoUser: root |
||
− | sudoHost: ALL |
||
− | sudoRunAsUser: ALL |
||
− | sudoRunAsGroup: ALL |
||
− | sudoCommand: ALL |
||
− | sudoOrder: 2 |
||
− | # %admin, sudo, services, customer_organization.fuel_domain |
||
− | dn: cn=%admin,ou=sudo,ou=services,dc=customer_organization,dc=fuel_domain |
||
− | objectClass: sudoRole |
||
− | sudoUser: %admin |
||
− | sudoHost: ALL |
||
− | sudoRunAsUser: ALL |
||
− | sudoCommand: ALL |
||
− | sudoOrder: 3 |
||
− | </PRE> |
||
− | Для сравнения тот же запрос с использованием "обычного" пользователя не показывает информации о sudo |
||
− | <PRE> |
||
− | ldapsearch_sirmax -x -b 'dc=fuel_domain' '(objectclass=*)' | grep sudo |
||
− | </PRE> |
||
− | <PRE> |
||
− | loginShell: /usr/bin/sudosh |
||
− | loginShell: /usr/bin/sudosh |
||
− | loginShell: /usr/bin/sudosh |
||
− | </PRE> |
||
=SUDO= |
=SUDO= |
Текущая версия на 15:49, 30 мая 2016
Введение
Соглашения и умолчания
Везде в документе приняты следующие соглашения:
- пароль, если не указан - r00tme
- все пароли заведомо простые так как использовались для отладки. В реальной инсталляции рекомендую использовать более сложные пароли.
- изначально настройка не безопасна (используется "админская" учетная запись, и перенастройка на более безопасную конфигурацию описываетсяв отдельной секции.
- использование шифрования описывается в отдельной секции, изначальная настройка не использует шифрование.
- OS: Ubuntu 14.04
- Вся настройка делается для конкретной цели и ОС установлена Fuel-ом (Base OS) для OpenStack и конфигурация может отличаться (незначительно) от обычной установки Ubuntu.
Для простоты и скорости работы я создаю алиасы для утилит, что бы не вписывать логин и пароль каждый раз.
По этой причине команды указаны БЕЗ пароля.
alias ldappasswd='ldappasswd -D "cn=admin,dc=fuel_domain" -w r00tme' alias ldapsearch='ldapsearch -D "cn=admin,dc=fuel_domain" -w r00tme' alias ldapmodify='ldapmodify -D "cn=admin,dc=fuel_domain" -w r00tme' alias ldapadd='ldapadd -D "cn=admin,dc=fuel_domain" -w r00tme'
Если требуется ввести другой пароль то команда обычно предваряется символом \ (unalias), например
\ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config"
Репликация
В моей инсталляции фигурируют 2 сервера, сначала настраивается 1 потом дополняется репликацией.
Для простоты я использую алиасы через /etc/hosts
10.20.0.6 ldap2 10.20.0.3 ldap1
Прокси для Active-Backup конфигурации - на виртуальном IP который (не реализовано) будет перемещаться между нодами. (В примере - перенос осуществляется в ручном режиме)
10.20.0.100 ldap
Запись сессии
В статье встечаются ссылки на утилиту sudosh - это утилита для записи сессии пользователя. Отмечу что в моей конфигурации она установлена и используется, потому на нее иногда будут ссылки
dpkg -i <path>/sudosh2_2.0.1-1_amd64.deb
mkdir /var/log/sudosh; chmod a+w /var/log/sudosh chmod +r /etc/sudosh.conf
LDAP Server Installation
"Тихая" установка (на ldap 1)
DEBIAN_FRONTEND=noninteractive apt-get install slapd ldap-utils
Современные дистрибутивы OpenLDAP используют сам LDAP как хранилище конфигурации. cn=config. По-умолчанию настроен доступ без пароля для локального рута.
Посмотреть содержимое можно так:
ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config"
Create database
Создать отдельную базу данных для своих объектов.
Внимательно проверить права на директорию - она должна существовать и быть доступна серверу на запись (/var/lib/ldap_fuel_domain/)
0002_createDatabase.ldif
dn: olcDatabase={2}hdb,cn=config objectClass: olcDatabaseConfig objectClass: olcHdbConfig olcDatabase: {2}hdb olcDbDirectory: /var/lib/ldap_fuel_domain/ olcSuffix: dc=fuel_domain olcAccess: {0}to * by * write olcLastMod: TRUE olcRootDN: cn=admin,dc=fuel_domain olcRootPW: {SSHA}bxQpFzYmIkILSbDEL3cVl+nf03mdra/t olcDbCheckpoint: 512 30 olcDbConfig: {0}set_cachesize 0 2097152 0 olcDbConfig: {1}set_lk_max_objects 1500 olcDbConfig: {2}set_lk_max_locks 1500 olcDbConfig: {3}set_lk_max_lockers 1500 olcDbIndex: objectClass eq
Обратить внимание на
olcAccess: {0}to * by * write
Изначально я даю полный доступ всем на все, изменю его позже.
В строке цифра 2 в строке dn: olcDatabase={2}hdb,cn=config обозначает что это 2-я база, ту что существует можно как удалить так и оставить "на потом"
Создание: (подключение через -H ldapi:/// в установке по умолчанию доступно руту без пароля.
mkdir -p /var/lib/ldap_fuel_domain/ chown openldap:openldap /var/lib/ldap_fuel_domain/
ldapadd -Y EXTERNAL -H ldapi:/// < 0002_createDatabase.ldif
adding new entry "olcDatabase={2}hdb,cn=config"
Если права на директорию неправильные ИЛИ не настроен apparmor возникает ошибка:
adding new entry "olcDatabase={2}hdb,cn=config" ldap_add: Other (e.g., implementation specific) error (80) additional info: olcDbDirectory: value #0: invalid path: Permission denied
В логах:
apparmor="DENIED" operation="mknod" profile="/usr/sbin/slapd" name="/var/lib/ldap_fuel_domain/DUMMY" pid=26365 comm="slapd" requested_mask="c" denied_mask="c" fsuid=107 ouid=107
Исправить:
/etc/apparmor.d/usr.sbin.slapd
## /var/lib/ldap*/ rwk, /var/lib/ldap** rwk,
и перезапустить apparmor
/etc/init.d/apparmor restart
Some info:
Populate Database
Для работы создаем свой домен куда будем помещать все объекты.
- domain
0010_create_comain.ldiff
dn: dc=fuel_domain objectClass: top objectClass: dcObject objectClass: organization o: fuel_users
- domain_admin
0011_fuel_domain_admin.ldiff
dn: cn=admin,dc=fuel_domain objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator userPassword: {SSHA}bxQpFzYmIkILSbDEL3cVl+nf03mdra/t
Пароль пользователя генерируется утилитой ldappasswd, в моем примере это 'r00tme'
Загрузить объекты:
ldapadd -Y EXTERNAL -H ldapi:/// < 0010_create_comain.ldiff <PRE> <PRE> adding new entry "dc=fuel_domain"
ldapadd -Y EXTERNAL -H ldapi:/// < 0011_fuel_domain_admin.ldiff
adding new entry "cn=admin,dc=fuel_domain"
Check connection
Проверить, подключившись с ново-созданным пользователем
ldapsearch -LL -D "cn=admin,dc=fuel_domain" -w 'r00tme' -b 'dc=fuel_domain' '(objectclass=*)'
- -D - "логин"
- -w - пароль
- -b - base, ветка дерева в которой искать
- '(objectclass=*)' - "что искать", в примере - "все"
Результат поиска:
dn: dc=fuel_domain objectClass: top objectClass: dcObject objectClass: organization o: fuel_users dc: fuel_domain dn: cn=admin,dc=fuel_domain objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator userPassword:: e1NTSEF9YnhRcEZ6WW1Ja0lMU2JERUwzY1ZsK25mMDNtZHJhL3Q=
Fix permmissions
Исправить права на базу.
0022_fix_database_permissions.ldif
dn: olcDatabase={2}hdb,cn=config changetype: modify replace: olcAccess olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break olcAccess: {1}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=fuel_domain" write by * none olcAccess: {2}to dn.base="" by * read olcAccess: {3}to * by dn="cn=admin,dc=fuel_domain" write by * read
ldapmodify -Y EXTERNAL -H ldapi:/// < 0021_fix_database_permissions.ldif
modifying entry "olcDatabase={2}hdb,cn=config"
Download configuration and check it
Проверить права можно например скачав весь конфиг:
ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" > all_config
Результат
На этом шаге - рабочий LDAP сервер с минимальными настройками и без шифрования.
Шифрование
Настройка шифрования вынесена на отдельную страницу
На данный момент настроено шифрование.
Репликация
Перед началом настройки репликации - настроить на обоих серверах шифрования. Конфигурация аналогичная за исключением сертификата и хостнейма
http://wiki.sirmax.noname.com.ua/index.php/LDAP_Linux_Replication
PHP LDAP Addmin
Опционально можно поставить phpldapadmin
apt-get install phpldapadmin
Настройки минимальны и ограничиваются указанием домена пользователя
diff /etc/phpldapadmin/config.php /etc/phpldapadmin/config.php.original 300c300 < $servers->setValue('server','base',array('dc=fuel_domain')); --- > $servers->setValue('server','base',array('dc=example,dc=com')); 326c326 < $servers->setValue('login','bind_id','cn=admin,dc=fuel_domain'); --- > $servers->setValue('login','bind_id','cn=admin,dc=example,dc=com');
Если нужно шифрование то
apt-get install php5-sasl
И конфигурация будет выглядеть так:
$servers->setValue('server','host','ldaps://127.0.0.1:636'); $servers->setValue('server','port',0);
В файле /etc/ldap/ldap.conf должны быть правильные настройки
TLS_CACERT /etc/ssl/certs/rootca.crt TLS_REQCERT allow TIMELIMIT 15 TIMEOUT 20
Populate LDAP
Customers_Organization
Контейнер для всех остальных объектов
0000_Customers_Organization
dn: dc=customer_organization,dc=fuel_domain dc: customer_organization o: Example Organization objectClass: dcObject objectClass: organization
Groups
Контейнер для групп и для пользователей.
0001_Groups
dn: ou=Group,dc=customer_organization,dc=fuel_domain ou: Group objectClass: top objectClass: organizationalUnit dn: ou=People,dc=customer_organization,dc=fuel_domain ou: People objectClass: top objectClass: organizationalUnit
User sirmax (мой пользователь)
Первый пользователь и его группа, который сможет логиниться на ноды.
0002_User_sirmax
dn: uid=sirmax,ou=People,dc=customer_organization,dc=fuel_domain objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount uid: sirmax cn: Max Mazur sn: Mazur givenName: Mazur title: Max Mazur telephoneNumber: +38 067 341 80 70 mobile: +38 067 341 80 70 postalAddress: AddressLine1$AddressLine2$AddressLine3 userPassword: {CRYPT}$6$DS/mzad5$EB.cNCLE7KB7OCPK1nU6aEA8HnQDLY1FPd3KaWPVqaNBtWhmh/4cOUgD1I8tQSFu41yy7jMXDrg9TDqlAbuLX. labeledURI: http://wiki.sirmax.noname.com.ua/ loginShell: /usr/bin/sudosh uidNumber: 9999 gidNumber: 9999 homeDirectory: /home/sirmax description: This is me :) dn: cn=sirmax,ou=Group,dc=customer_organization,dc=fuel_domain changetype: add cn: sirmax objectClass: posixGroup gidNumber: 9999 description: Fuel Users memberUid: sirmax
Group Fuel_Users
Группа пользователей которая используется для sudo
0004_GroupFuelUsers
dn: cn=fuel_users,ou=Group,dc=customer_organization,dc=fuel_domain changetype: add cn: fuel_users objectClass: posixGroup gidNumber: 109999 description: Fuel Users memberUid: sirmax
ServiceOU and Sudoers
Создать контейнеры для сервисных объектов и поместить в него контейнер для sudo.
0005_ServiceOU_and_Sudoers
dn: ou=services,dc=customer_organization,dc=fuel_domain ou: Services objectClass: top objectClass: organizationalUnit description: Group all services under this OU dn: ou=sudo,ou=services,dc=customer_organization,dc=fuel_domain objectClass: organizationalUnit description: sudo objectClass: top
ServieUsersOU
Контейнер для служебных пользователей
0006_ServieUsersOU
dn: ou=service_users,dc=customer_organization,dc=fuel_domain ou: service_users objectClass: top objectClass: organizationalUnit
nssproxy_group
Группа для служебных пользователей, пользователям этой группы будет разрешено читать хеши пароля и пользователи этой группы используются для nss, pam и ldap-sudo
0007_nssproxy_group
dn: cn=nssproxy,ou=Group,dc=customer_organization,dc=fuel_domain cn: nssproxy objectClass: groupOfNames objectClass: top member: uid=nssproxy-node1,ou=service_users,dc=customer_organization,dc=fuel_domain member: uid=nssproxy-node2,ou=service_users,dc=customer_organization,dc=fuel_domain member: uid=nssproxy-node3,ou=service_users,dc=customer_organization,dc=fuel_domain member: uid=nssproxy-node4,ou=service_users,dc=customer_organization,dc=fuel_domain
0008_nssProxyUsers
Служебные пользователи (4 по числу серверов)
0008_nssProxyUsers
dn: uid=nssproxy-node1,ou=service_users,dc=customer_organization,dc=fuel_domain uid: nssproxy-node1 gecos: Network Service Switch Proxy User objectClass: top #objectClass: account objectClass: posixAccount objectClass: shadowAccount objectClass: organizationalPerson objectClass: inetOrgPerson userPassword: {SSHA}RsAMqOI3647qg1gAZF3x2BKBnp0sEVfa cn: node1 sn: node1 shadowLastChange: 15140 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 loginShell: /bin/false uidNumber: 801 gidNumber: 801 homeDirectory: /home/nssproxy dn: uid=nssproxy-node2,ou=service_users,dc=customer_organization,dc=fuel_domain uid: nssproxy-node2 gecos: Network Service Switch Proxy User objectClass: top #objectClass: account objectClass: posixAccount objectClass: shadowAccount objectClass: organizationalPerson objectClass: inetOrgPerson userPassword: {SSHA}RsAMqOI3647qg1gAZF3x2BKBnp0sEVfa cn: node2 sn: node2 shadowLastChange: 15140 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 loginShell: /bin/false uidNumber: 802 gidNumber: 801 homeDirectory: /home/nssproxy dn: uid=nssproxy-node3,ou=service_users,dc=customer_organization,dc=fuel_domain uid: nssproxy-node3 gecos: Network Service Switch Proxy User objectClass: top #objectClass: account objectClass: posixAccount objectClass: shadowAccount objectClass: organizationalPerson objectClass: inetOrgPerson userPassword: {SSHA}RsAMqOI3647qg1gAZF3x2BKBnp0sEVfa cn: node3 sn: node3 shadowLastChange: 15140 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 loginShell: /bin/false uidNumber: 803 gidNumber: 801 homeDirectory: /home/nssproxy dn: uid=nssproxy-node4,ou=service_users,dc=customer_organization,dc=fuel_domain uid: nssproxy-node4 gecos: Network Service Switch Proxy User objectClass: top #objectClass: account objectClass: posixAccount objectClass: shadowAccount objectClass: organizationalPerson objectClass: inetOrgPerson userPassword: {SSHA}RsAMqOI3647qg1gAZF3x2BKBnp0sEVfa cn: node4 sn: node4 shadowLastChange: 15140 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 loginShell: /bin/false uidNumber: 804 gidNumber: 801 homeDirectory: /home/nssproxy
Fix Permissions: Alow NSS Read Passwords
Добавляем группе nss права на чтение паролей/хешей паролей
0009_FixPermissionsAlowNSSReadPAsswords.ldif
dn: olcDatabase={2}hdb,cn=config changetype: modify replace: olcAccess olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break olcAccess: {1}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=fuel_domain" write. by group.exact="cn=nssproxy,ou=Group,dc=customer_organization,dc=fuel_domain" read by * none olcAccess: {2}to dn.subtree="ou=sudo,ou=services,dc=customer_organization,dc=fuel_domain" by dn="cn=admin,dc=fuel_domain" write. by group.exact="cn=nssproxy,ou=Group,dc=customer_organization,dc=fuel_domain" read by anonymous auth by * none olcAccess: {3}to dn.base="" by * read olcAccess: {4}to * by dn="cn=admin,dc=fuel_domain" write by * read
Вносить исправление через ldapi:///
ldapmodify -Y EXTERNAL -H ldapi:/// < 0009_FixPermissionsAlowNSSReadPAsswords.ldif
Sudo Scheme
Cхема для sudo (как ее генерировать описано в отдельном разделе)
0010_SudoScheme.ldif
dn: cn=sudo,cn=schema,cn=config objectClass: olcSchemaConfig cn: sudo olcAttributeTypes: {0}( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: {1}( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' DESC 'Host(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: {2}( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' DESC 'Command(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: {3}( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User(s)impersonated by sudo (deprecated)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: {4}( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption' DESC 'Options(s) followed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: {5}( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'User(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: {6}( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoRunAsGroup' DESC 'Group(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) olcAttributeTypes: {7}( 1.3.6.1.4.1.15953.9.1.8 NAME 'sudoNotBefore' DESC 'Start of time interval for which the entry is valid' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 ) olcAttributeTypes: {8}( 1.3.6.1.4.1.15953.9.1.9 NAME 'sudoNotAfter' DESC 'End of time interval for which the entry is valid' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 ) olcAttributeTypes: {9}( 1.3.6.1.4.1.15953.9.1.10 NAME 'sudoOrder' DESC 'an integer to order the sudoRole entries' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) olcObjectClasses: {0}( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' DESC 'Sudoer Entries' SUP top STRUCTURAL MUST cn MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoOrder $ sudoNotBefore $ sudoNotAfter $ description ) )
Sudoers
Файл sudoers (как его генерировать описано в отдельном разделе)
0010_sudoers.ldif
dn: cn=defaults,ou=sudo,ou=services,dc=customer_organization,dc=fuel_domain objectClass: top objectClass: sudoRole cn: defaults description: Default sudoOption's go here sudoOption: env_reset sudoOption: mail_badpass sudoOption: secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" sudoOrder: 1 dn: cn=root,ou=sudo,ou=services,dc=customer_organization,dc=fuel_domain objectClass: top objectClass: sudoRole cn: root sudoUser: root sudoHost: ALL sudoRunAsUser: ALL sudoRunAsGroup: ALL sudoCommand: ALL sudoOrder: 2 dn: cn=%admin,ou=sudo,ou=services,dc=customer_organization,dc=fuel_domain objectClass: top objectClass: sudoRole cn: %admin sudoUser: %admin sudoHost: ALL sudoRunAsUser: ALL sudoCommand: ALL sudoOrder: 3 dn: cn=%sudo,ou=sudo,ou=services,dc=customer_organization,dc=fuel_domain objectClass: top objectClass: sudoRole cn: %sudo sudoUser: %sudo sudoHost: ALL sudoRunAsUser: ALL sudoRunAsGroup: ALL sudoCommand: ALL sudoOrder: 4 dn: cn=%fuel_users,ou=sudo,ou=services,dc=customer_organization,dc=fuel_domain objectClass: top objectClass: sudoRole cn: %fuel_users sudoUser: %fuel_users sudoHost: ALL sudoRunAsUser: ALL sudoRunAsGroup: ALL sudoCommand: ALL sudoOrder: 5
Сброс паролей для служебных пользователей
Пароли всем пользователям ставлю (для теста) - по номеру ноды, например для node-1 пользователь будет nssproxy-node1 с паролем '1111'
0011_setPaswordsAndCheck.sh
for N in `seq 1 4` do echo user=nssproxy-node${N} ldappasswd -H ldaps://ldap -s ${N}${N}${N}${N} uid=nssproxy-node${N},ou=service_users,dc=customer_organization,dc=fuel_domain -D "cn=admin,dc=fuel_domain" -w 'r00tme' ldapsearch -D "uid=nssproxy-node${N},ou=service_users,dc=customer_organization,dc=fuel_domain" -w ${N}${N}${N}${N} -b 'dc=fuel_domain' -H ldaps://ldap '(objectclass=*)' done
Test user
Пользователь который добавляется для демонстрации - изначально не имеет прав sudo.
9902_User_test_user
dn: uid=test1,ou=People,dc=customer_organization,dc=fuel_domain objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount uid: test1 cn: test1 test1 sn: test1 givenName: test1 title: test user for demo telephoneNumber: +38 067 341 80 70 mobile: +38 067 341 80 70 postalAddress: AddressLine1$AddressLine2$AddressLine3 userPassword: {CRYPT}$6$DS/mzad5$EB.cNCLE7KB7OCPK1nU6aEA8HnQDLY1FPd3KaWPVqaNBtWhmh/4cOUgD1I8tQSFu41yy7jMXDrg9TDqlAbuLX. labeledURI: http://wiki.test1.noname.com.ua/ loginShell: /usr/bin/sudosh uidNumber: 9998 gidNumber: 9998 homeDirectory: /home/test1 description: This is me :) dn: cn=test1,ou=Group,dc=customer_organization,dc=fuel_domain changetype: add cn: test1 objectClass: posixGroup gidNumber: 9998 description: Fuel Users memberUid: test1
Настройка клиента
Вынесено в отдельный документ:
http://wiki.sirmax.noname.com.ua/index.php/LDAP_Linux_Auth_Client
SUDO
http://wiki.sirmax.noname.com.ua/index.php/LDAP_Linux_LDAP_SUDO
Ссылки
- ВВедение в PAM https://www.ibm.com/developerworks/ru/library/l-pam/
PAM
PAM vs NSS
http://serverfault.com/questions/538383/understand-pam-and-nss
http://pro-ldap.ru/tr/zytrax/ch6/slapd-config.html
https://wiki.archlinux.org/index.php/LDAP_authentication
RUS
http://www.bog.pp.ru/work/LDAP.html
http://pro-ldap.ru/tr/zytrax/ch6/slapd-config.html
http://xgu.ru/wiki/man:ldapmodify
https://rtfm.co.ua/openldap-migraciya-s-slapd-conf-na-cnconfig-olc/
http://www.slashroot.in/how-are-passwords-stored-linux-understanding-hashing-shadow-utils