LDAP Linux Auth: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
(не показаны 153 промежуточные версии этого же участника) | |||
Строка 1: | Строка 1: | ||
− | [[Категория:Linux]] |
||
[[Категория:LDAP]] |
[[Категория:LDAP]] |
||
+ | [[Категория:Linix]] |
||
+ | [[Категория:HA]] |
||
+ | [[Категория:SSL]] |
||
+ | [[Категория:Pam]] |
||
+ | =Введение= |
||
− | =1= |
||
+ | ==Соглашения и умолчания== |
||
+ | Везде в документе приняты следующие соглашения: |
||
+ | * пароль, если не указан - <B>r00tme</B> |
||
+ | * все пароли заведомо простые так как использовались для отладки. В реальной инсталляции рекомендую использовать более сложные пароли. |
||
+ | * изначально настройка не безопасна (используется "админская" учетная запись, и перенастройка на более безопасную конфигурацию описываетсяв отдельной секции. |
||
+ | * использование шифрования описывается в отдельной секции, изначальная настройка не использует шифрование. |
||
+ | * OS: Ubuntu 14.04 |
||
+ | * Вся настройка делается для конкретной цели и ОС установлена Fuel-ом (Base OS) для OpenStack и конфигурация может отличаться (незначительно) от обычной установки Ubuntu. |
||
+ | Для простоты и скорости работы я создаю алиасы для утилит, что бы не вписывать логин и пароль каждый раз. |
||
+ | <BR>По этой причине команды указаны БЕЗ пароля. |
||
+ | <PRE> |
||
+ | 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' |
||
+ | </PRE> |
||
+ | <BR>Если требуется ввести другой пароль то команда обычно предваряется символом <B>\</B> (unalias), например |
||
+ | <PRE> |
||
+ | \ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" |
||
+ | </PRE> |
||
+ | ==Репликация== |
||
+ | В моей инсталляции фигурируют 2 сервера, сначала настраивается 1 потом дополняется репликацией. |
||
+ | <BR> |
||
+ | Для простоты я использую алиасы через /etc/hosts |
||
+ | <PRE> |
||
+ | 10.20.0.6 ldap2 |
||
+ | 10.20.0.3 ldap1 |
||
+ | </PRE> |
||
+ | |||
+ | Прокси для Active-Backup конфигурации - на виртуальном IP который (не реализовано) будет перемещаться между нодами. (В примере - перенос осуществляется в ручном режиме) |
||
+ | <PRE> |
||
+ | 10.20.0.100 ldap |
||
+ | </PRE> |
||
+ | |||
+ | ==Запись сессии== |
||
+ | В статье встечаются ссылки на утилиту sudosh - это утилита для записи сессии пользователя. Отмечу что в моей конфигурации она установлена и используется, потому на нее иногда будут ссылки |
||
+ | |||
+ | * http://wiki.sirmax.noname.com.ua/index.php/Sudosh2 |
||
+ | |||
+ | <PRE> |
||
+ | dpkg -i <path>/sudosh2_2.0.1-1_amd64.deb |
||
+ | </PRE> |
||
+ | |||
+ | <PRE> |
||
+ | mkdir /var/log/sudosh; |
||
+ | chmod a+w /var/log/sudosh |
||
+ | chmod +r /etc/sudosh.conf |
||
+ | </PRE> |
||
+ | |||
+ | =LDAP Server Installation= |
||
+ | |||
+ | "Тихая" установка (на ldap 1) |
||
+ | <PRE> |
||
+ | DEBIAN_FRONTEND=noninteractive apt-get install slapd ldap-utils |
||
+ | </PRE> |
||
+ | |||
+ | Современные дистрибутивы OpenLDAP используют сам LDAP как хранилище конфигурации. <B>cn=config</B>. По-умолчанию настроен доступ без пароля для локального рута. |
||
+ | |||
+ | <BR> |
||
+ | Посмотреть содержимое можно так: |
||
+ | <PRE> |
||
+ | ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" |
||
+ | </PRE> |
||
+ | ==Create database== |
||
+ | Создать отдельную базу данных для своих объектов. |
||
+ | <BR> |
||
+ | Внимательно проверить права на директорию - она должна существовать и быть доступна серверу на запись (/var/lib/ldap_fuel_domain/) |
||
+ | |||
+ | <PRE> |
||
+ | 0002_createDatabase.ldif |
||
+ | </PRE> |
||
+ | |||
+ | <PRE> |
||
+ | 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 |
||
+ | </PRE> |
||
+ | |||
+ | Обратить внимание на |
||
+ | <PRE> |
||
+ | olcAccess: {0}to * by * write |
||
+ | </PRE> |
||
+ | Изначально я даю полный доступ всем на все, изменю его позже. |
||
+ | <BR> |
||
+ | |||
+ | В строке цифра 2 в строке <B>dn: olcDatabase={2}hdb,cn=config</B> обозначает что это 2-я база, ту что существует можно как удалить так и оставить "на потом" |
||
+ | |||
+ | Создание: (подключение через <B>-H ldapi:///</B> в установке по умолчанию доступно руту без пароля. |
||
+ | <PRE> |
||
+ | mkdir -p /var/lib/ldap_fuel_domain/ |
||
+ | chown openldap:openldap /var/lib/ldap_fuel_domain/ |
||
+ | </PRE> |
||
+ | |||
+ | <PRE> |
||
+ | ldapadd -Y EXTERNAL -H ldapi:/// < 0002_createDatabase.ldif |
||
+ | </PRE> |
||
+ | |||
+ | <PRE> |
||
+ | adding new entry "olcDatabase={2}hdb,cn=config" |
||
+ | </PRE> |
||
+ | |||
+ | Если права на директорию неправильные ИЛИ не настроен apparmor возникает ошибка: |
||
+ | <PRE> |
||
+ | 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 |
||
+ | </PRE> |
||
+ | В логах: |
||
+ | |||
+ | <PRE> |
||
+ | 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 |
||
+ | </PRE> |
||
+ | Исправить: |
||
+ | |||
+ | <PRE> |
||
+ | /etc/apparmor.d/usr.sbin.slapd |
||
+ | </PRE> |
||
+ | <PRE> |
||
+ | ## |
||
+ | /var/lib/ldap*/ rwk, |
||
+ | /var/lib/ldap** rwk, |
||
+ | </PRE> |
||
+ | |||
+ | и перезапустить apparmor |
||
+ | |||
+ | <PRE> |
||
+ | /etc/init.d/apparmor restart |
||
+ | </PRE> |
||
+ | |||
+ | Some info: |
||
+ | * http://ubuntuforums.org/showthread.php?t=1492043 |
||
+ | |||
+ | ==Populate Database== |
||
+ | Для работы создаем свой домен куда будем помещать все объекты. |
||
+ | * domain |
||
+ | <PRE> |
||
+ | 0010_create_comain.ldiff |
||
+ | </PRE> |
||
+ | <PRE> |
||
+ | dn: dc=fuel_domain |
||
+ | objectClass: top |
||
+ | objectClass: dcObject |
||
+ | objectClass: organization |
||
+ | o: fuel_users |
||
+ | </PRE> |
||
+ | * domain_admin |
||
+ | <PRE> |
||
+ | 0011_fuel_domain_admin.ldiff |
||
+ | </PRE> |
||
+ | <PRE> |
||
+ | dn: cn=admin,dc=fuel_domain |
||
+ | objectClass: simpleSecurityObject |
||
+ | objectClass: organizationalRole |
||
+ | cn: admin |
||
+ | description: LDAP administrator |
||
+ | userPassword: {SSHA}bxQpFzYmIkILSbDEL3cVl+nf03mdra/t |
||
+ | </PRE> |
||
+ | Пароль пользователя генерируется утилитой ldappasswd, в моем примере это 'r00tme' |
||
+ | |||
+ | Загрузить объекты: |
||
+ | <PRE> |
||
+ | ldapadd -Y EXTERNAL -H ldapi:/// < 0010_create_comain.ldiff |
||
+ | <PRE> |
||
+ | <PRE> |
||
+ | adding new entry "dc=fuel_domain" |
||
+ | </PRE> |
||
+ | <PRE> |
||
+ | ldapadd -Y EXTERNAL -H ldapi:/// < 0011_fuel_domain_admin.ldiff |
||
+ | </PRE> |
||
+ | <PRE> |
||
+ | adding new entry "cn=admin,dc=fuel_domain" |
||
+ | </PRE> |
||
+ | |||
+ | ==Check connection== |
||
+ | Проверить, подключившись с ново-созданным пользователем |
||
+ | |||
+ | <PRE> |
||
+ | ldapsearch -LL -D "cn=admin,dc=fuel_domain" -w 'r00tme' -b 'dc=fuel_domain' '(objectclass=*)' |
||
+ | </PRE> |
||
+ | |||
+ | * -D - "логин" |
||
+ | * -w - пароль |
||
+ | * -b - base, ветка дерева в которой искать |
||
+ | * '(objectclass=*)' - "что искать", в примере - "все" |
||
+ | |||
+ | Результат поиска: |
||
+ | |||
+ | <PRE> |
||
+ | 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= |
||
+ | </PRE> |
||
+ | |||
+ | ==Fix permmissions== |
||
+ | Исправить права на базу. |
||
+ | <PRE> |
||
+ | 0022_fix_database_permissions.ldif |
||
+ | </PRE> |
||
+ | <PRE> |
||
+ | 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 |
||
+ | </PRE> |
||
+ | |||
+ | <PRE> |
||
+ | ldapmodify -Y EXTERNAL -H ldapi:/// < 0021_fix_database_permissions.ldif |
||
+ | </PRE> |
||
+ | <PRE> |
||
+ | modifying entry "olcDatabase={2}hdb,cn=config" |
||
+ | </PRE> |
||
+ | |||
+ | ==Download configuration and check it== |
||
+ | Проверить права можно например скачав весь конфиг: |
||
+ | <PRE> |
||
+ | ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" > all_config |
||
+ | </PRE> |
||
+ | ==Результат== |
||
+ | |||
+ | На этом шаге - рабочий LDAP сервер с минимальными настройками и без шифрования. |
||
+ | |||
+ | =Шифрование= |
||
+ | Настройка шифрования вынесена на отдельную страницу |
||
+ | |||
+ | * http://wiki.sirmax.noname.com.ua/index.php/LDAP_Linux_LDAP_TLS |
||
+ | |||
+ | На данный момент настроено шифрование. |
||
+ | =Репликация= |
||
+ | Перед началом настройки репликации - настроить на обоих серверах шифрования. Конфигурация аналогичная за исключением сертификата и хостнейма |
||
+ | |||
+ | |||
+ | http://wiki.sirmax.noname.com.ua/index.php/LDAP_Linux_Replication |
||
+ | |||
+ | =PHP LDAP Addmin= |
||
+ | Опционально можно поставить phpldapadmin |
||
+ | <PRE> |
||
+ | apt-get install phpldapadmin |
||
+ | </PRE> |
||
+ | Настройки минимальны и ограничиваются указанием домена пользователя |
||
+ | <PRE> |
||
+ | 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'); |
||
+ | </PRE> |
||
+ | |||
+ | Если нужно шифрование то |
||
+ | <PRE> |
||
+ | apt-get install php5-sasl |
||
+ | </PRE> |
||
+ | |||
+ | И конфигурация будет выглядеть так: |
||
+ | <PRE> |
||
+ | $servers->setValue('server','host','ldaps://127.0.0.1:636'); |
||
+ | $servers->setValue('server','port',0); |
||
+ | </PRE> |
||
+ | В файле /etc/ldap/ldap.conf должны быть правильные настройки |
||
+ | <PRE> |
||
+ | TLS_CACERT /etc/ssl/certs/rootca.crt |
||
+ | TLS_REQCERT allow |
||
+ | TIMELIMIT 15 |
||
+ | TIMEOUT 20 |
||
+ | </PRE> |
||
+ | |||
+ | =Populate LDAP= |
||
+ | ==Customers_Organization== |
||
+ | Контейнер для всех остальных объектов |
||
+ | <PRE> |
||
+ | 0000_Customers_Organization |
||
+ | </PRE> |
||
+ | |||
+ | <PRE> |
||
+ | dn: dc=customer_organization,dc=fuel_domain |
||
+ | dc: customer_organization |
||
+ | o: Example Organization |
||
+ | objectClass: dcObject |
||
+ | objectClass: organization |
||
+ | </PRE> |
||
+ | |||
+ | ==Groups== |
||
+ | Контейнер для групп и для пользователей. |
||
+ | <PRE> |
||
+ | 0001_Groups |
||
+ | </PRE> |
||
+ | <PRE> |
||
+ | 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 |
||
+ | </PRE> |
||
+ | |||
+ | ==User sirmax (мой пользователь)== |
||
+ | Первый пользователь и его группа, который сможет логиниться на ноды. |
||
+ | <PRE> |
||
+ | 0002_User_sirmax |
||
+ | </PRE> |
||
+ | |||
+ | <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 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 |
||
+ | </PRE> |
||
+ | |||
+ | ==Group Fuel_Users== |
||
+ | Группа пользователей которая используется для <b>sudo</b> |
||
+ | <PRE> |
||
+ | 0004_GroupFuelUsers |
||
+ | </PRE> |
||
+ | |||
+ | <PRE> |
||
+ | 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 |
||
+ | </PRE> |
||
+ | |||
+ | ==ServiceOU and Sudoers== |
||
+ | |||
+ | Создать контейнеры для сервисных объектов и поместить в него контейнер для sudo. |
||
+ | |||
+ | |||
+ | <PRE> |
||
+ | 0005_ServiceOU_and_Sudoers |
||
+ | </PRE> |
||
+ | |||
+ | <PRE> |
||
+ | 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 |
||
+ | </PRE> |
||
+ | |||
+ | ==ServieUsersOU== |
||
+ | Контейнер для служебных пользователей |
||
+ | <PRE> |
||
+ | 0006_ServieUsersOU |
||
+ | </PRE> |
||
+ | |||
+ | <PRE> |
||
+ | dn: ou=service_users,dc=customer_organization,dc=fuel_domain |
||
+ | ou: service_users |
||
+ | objectClass: top |
||
+ | objectClass: organizationalUnit |
||
+ | </PRE> |
||
+ | |||
+ | ==nssproxy_group== |
||
+ | Группа для служебных пользователей, пользователям этой группы будет разрешено читать хеши пароля и пользователи этой группы используются для nss, pam и ldap-sudo |
||
+ | <PRE> |
||
+ | 0007_nssproxy_group |
||
+ | </PRE> |
||
+ | |||
+ | <PRE> |
||
+ | 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 |
||
+ | </PRE> |
||
+ | |||
+ | ==0008_nssProxyUsers== |
||
+ | |||
+ | Служебные пользователи (4 по числу серверов) |
||
+ | |||
+ | <PRE> |
||
+ | 0008_nssProxyUsers |
||
+ | </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 |
||
+ | |||
+ | |||
+ | 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 |
||
+ | </PRE> |
||
+ | |||
+ | == Fix Permissions: Alow NSS Read Passwords== |
||
+ | Добавляем группе nss права на чтение паролей/хешей паролей |
||
+ | |||
+ | <PRE> |
||
+ | 0009_FixPermissionsAlowNSSReadPAsswords.ldif |
||
+ | </PRE> |
||
+ | <PRE> |
||
+ | 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 |
||
+ | </PRE> |
||
+ | Вносить исправление через ldapi:/// |
||
+ | <PRE> |
||
+ | ldapmodify -Y EXTERNAL -H ldapi:/// < 0009_FixPermissionsAlowNSSReadPAsswords.ldif |
||
+ | </PRE> |
||
+ | |||
+ | ==Sudo Scheme== |
||
+ | Cхема для sudo (как ее генерировать описано в отдельном разделе) |
||
+ | |||
+ | <PRE> |
||
+ | 0010_SudoScheme.ldif |
||
+ | </PRE> |
||
+ | <PRE> |
||
+ | 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 ) ) |
||
+ | </PRE> |
||
+ | |||
+ | ==Sudoers== |
||
+ | Файл sudoers (как его генерировать описано в отдельном разделе) |
||
+ | <PRE> |
||
+ | 0010_sudoers.ldif |
||
+ | </PRE> |
||
+ | |||
+ | <PRE> |
||
+ | 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 |
||
+ | </PRE> |
||
+ | |||
+ | ==Сброс паролей для служебных пользователей== |
||
+ | |||
+ | Пароли всем пользователям ставлю (для теста) - по номеру ноды, например для node-1 пользователь будет nssproxy-node1 с паролем '1111' |
||
+ | |||
+ | <PRE> |
||
+ | 0011_setPaswordsAndCheck.sh |
||
+ | </PRE> |
||
+ | |||
+ | <PRE> |
||
+ | 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 |
||
+ | </PRE> |
||
+ | |||
+ | ==Test user== |
||
+ | Пользователь который добавляется для демонстрации - изначально не имеет прав sudo. |
||
+ | |||
+ | <PRE> |
||
+ | 9902_User_test_user |
||
+ | </PRE> |
||
+ | |||
+ | <PRE> |
||
+ | 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 |
||
+ | </PRE> |
||
+ | |||
+ | =Настройка клиента= |
||
+ | Вынесено в отдельный документ: |
||
+ | |||
+ | 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/ |
||
+ | |||
+ | |||
* http://www.mironovs.com/os/unix-os/debian-autentifikatsiya-i-avtorizatsiya-polzovateley-s-pomoschyu-ldap.html |
* http://www.mironovs.com/os/unix-os/debian-autentifikatsiya-i-avtorizatsiya-polzovateley-s-pomoschyu-ldap.html |
||
PAM |
PAM |
||
* https://www.opennet.ru/base/net/pam_linux.txt.html |
* https://www.opennet.ru/base/net/pam_linux.txt.html |
||
+ | PAM vs NSS |
||
+ | * http://serverfault.com/questions/538383/understand-pam-and-nss |
||
+ | http://serverfault.com/questions/538383/understand-pam-and-nss |
||
+ | |||
+ | http://skeletor.org.ua/?p=464 |
||
+ | |||
+ | http://pro-ldap.ru/tr/zytrax/ch6/slapd-config.html |
||
+ | |||
+ | https://wiki.archlinux.org/index.php/LDAP_authentication |
||
+ | |||
+ | <BR><B>RUS</B> |
||
+ | 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 |
Текущая версия на 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