LDAP Linux Auth: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
 
(не показано 117 промежуточных версий этого же участника)
Строка 1: Строка 1:
 
[[Категория:LDAP]]
 
[[Категория:LDAP]]
 
[[Категория:Linix]]
 
[[Категория:Linix]]
  +
[[Категория:HA]]
  +
[[Категория:SSL]]
 
[[Категория:Pam]]
 
[[Категория: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 который (не реализовано) будет перемещаться между нодами. (В примере - перенос осуществляется в ручном режиме)
getent passwd
 
  +
<PRE>
getent group
 
  +
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 Server Installation=
   
"Тихая" установка
+
"Тихая" установка (на ldap 1)
 
<PRE>
 
<PRE>
 
DEBIAN_FRONTEND=noninteractive apt-get install slapd ldap-utils
 
DEBIAN_FRONTEND=noninteractive apt-get install slapd ldap-utils
 
</PRE>
 
</PRE>
   
Современные дистрибутивы OpenLDAP используют сам LDAP как хранилище конфигурации.
+
Современные дистрибутивы OpenLDAP используют сам LDAP как хранилище конфигурации. <B>cn=config</B>. По-умолчанию настроен доступ без пароля для локального рута.
   
 
<BR>
 
<BR>
Строка 24: Строка 71:
 
ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config"
 
ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config"
 
</PRE>
 
</PRE>
  +
==Create database==
 
 
Создать отдельную базу данных для своих объектов.
 
Создать отдельную базу данных для своих объектов.
 
<BR>
 
<BR>
 
Внимательно проверить права на директорию - она должна существовать и быть доступна серверу на запись (/var/lib/ldap_fuel_domain/)
 
Внимательно проверить права на директорию - она должна существовать и быть доступна серверу на запись (/var/lib/ldap_fuel_domain/)
  +
  +
<PRE>
  +
0002_createDatabase.ldif
  +
</PRE>
  +
 
<PRE>
 
<PRE>
 
dn: olcDatabase={2}hdb,cn=config
 
dn: olcDatabase={2}hdb,cn=config
Строка 53: Строка 105:
 
Изначально я даю полный доступ всем на все, изменю его позже.
 
Изначально я даю полный доступ всем на все, изменю его позже.
 
<BR>
 
<BR>
  +
Создание: (подключение через -H ldapi:/// в установке по умолчанию доступно руту без пароля.
 
  +
В строке цифра 2 в строке <B>dn: olcDatabase={2}hdb,cn=config</B> обозначает что это 2-я база, ту что существует можно как удалить так и оставить "на потом"
<PRE>
 
  +
ldapadd -Y EXTERNAL -H ldapi:/// < database
 
  +
Создание: (подключение через <B>-H ldapi:///</B> в установке по умолчанию доступно руту без пароля.
SASL/EXTERNAL authentication started
 
  +
<PRE>
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
 
  +
mkdir -p /var/lib/ldap_fuel_domain/
SASL SSF: 0
 
  +
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"
 
adding new entry "olcDatabase={2}hdb,cn=config"
 
</PRE>
 
</PRE>
Строка 64: Строка 124:
 
Если права на директорию неправильные ИЛИ не настроен apparmor возникает ошибка:
 
Если права на директорию неправильные ИЛИ не настроен apparmor возникает ошибка:
 
<PRE>
 
<PRE>
root@node-3:~/ldap# ldapadd -Y EXTERNAL -H ldapi:/// < database
 
SASL/EXTERNAL authentication started
 
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
 
SASL SSF: 0
 
 
adding new entry "olcDatabase={2}hdb,cn=config"
 
adding new entry "olcDatabase={2}hdb,cn=config"
 
ldap_add: Other (e.g., implementation specific) error (80)
 
ldap_add: Other (e.g., implementation specific) error (80)
 
additional info: olcDbDirectory: value #0: invalid path: Permission denied
 
additional info: olcDbDirectory: value #0: invalid path: Permission denied
 
</PRE>
 
</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>
 
<PRE>
 
/etc/apparmor.d/usr.sbin.slapd
 
/etc/apparmor.d/usr.sbin.slapd
  +
</PRE>
 
  +
<PRE>
 
##
 
##
  +
/var/lib/ldap*/ rwk,
 
/var/lib/ldap** rwk,
 
/var/lib/ldap** rwk,
 
</PRE>
 
</PRE>
* http://ubuntuforums.org/showthread.php?t=1492043
 
   
  +
и перезапустить apparmor
   
  +
<PRE>
  +
/etc/init.d/apparmor restart
  +
</PRE>
  +
  +
Some info:
  +
* http://ubuntuforums.org/showthread.php?t=1492043
  +
  +
==Populate Database==
 
Для работы создаем свой домен куда будем помещать все объекты.
 
Для работы создаем свой домен куда будем помещать все объекты.
 
* domain
 
* domain
 
<PRE>
 
<PRE>
  +
0010_create_comain.ldiff
# fuel_domain
 
  +
</PRE>
  +
<PRE>
 
dn: dc=fuel_domain
 
dn: dc=fuel_domain
 
objectClass: top
 
objectClass: top
Строка 95: Строка 168:
 
* domain_admin
 
* domain_admin
 
<PRE>
 
<PRE>
  +
0011_fuel_domain_admin.ldiff
# admin
 
  +
</PRE>
  +
<PRE>
 
dn: cn=admin,dc=fuel_domain
 
dn: cn=admin,dc=fuel_domain
 
objectClass: simpleSecurityObject
 
objectClass: simpleSecurityObject
Строка 107: Строка 182:
 
Загрузить объекты:
 
Загрузить объекты:
 
<PRE>
 
<PRE>
ldapadd -Y EXTERNAL -H ldapi:/// < domain
+
ldapadd -Y EXTERNAL -H ldapi:/// < 0010_create_comain.ldiff
  +
<PRE>
ldapadd -Y EXTERNAL -H ldapi:/// < domain_admin
 
  +
<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>
 
</PRE>
   
  +
==Check connection==
 
Проверить, подключившись с ново-созданным пользователем
 
Проверить, подключившись с ново-созданным пользователем
  +
 
<PRE>
 
<PRE>
ldapsearch -D "cn=admin,dc=fuel_domain" -w 'r00tme' -b 'dc=fuel_domain' '(objectclass=*)'
+
ldapsearch -LL -D "cn=admin,dc=fuel_domain" -w 'r00tme' -b 'dc=fuel_domain' '(objectclass=*)'
 
</PRE>
 
</PRE>
  +
 
* -D - "логин"
 
* -D - "логин"
 
* -w - пароль
 
* -w - пароль
Строка 123: Строка 209:
   
 
<PRE>
 
<PRE>
# extended LDIF
 
#
 
# LDAPv3
 
# base <dc=fuel_domain> with scope subtree
 
# filter: (objectclass=*)
 
# requesting: ALL
 
#
 
 
# fuel_domain
 
 
dn: dc=fuel_domain
 
dn: dc=fuel_domain
 
objectClass: top
 
objectClass: top
Строка 139: Строка 216:
 
dc: fuel_domain
 
dc: fuel_domain
   
# admin, fuel_domain
 
 
dn: cn=admin,dc=fuel_domain
 
dn: cn=admin,dc=fuel_domain
 
objectClass: simpleSecurityObject
 
objectClass: simpleSecurityObject
Строка 146: Строка 222:
 
description: LDAP administrator
 
description: LDAP administrator
 
userPassword:: e1NTSEF9YnhRcEZ6WW1Ja0lMU2JERUwzY1ZsK25mMDNtZHJhL3Q=
 
userPassword:: e1NTSEF9YnhRcEZ6WW1Ja0lMU2JERUwzY1ZsK25mMDNtZHJhL3Q=
 
# search result
 
search: 2
 
result: 0 Success
 
 
# numResponses: 3
 
# numEntries: 2
 
 
</PRE>
 
</PRE>
   
  +
==Fix permmissions==
 
Исправить права на базу:
+
Исправить права на базу.
  +
<PRE>
  +
0022_fix_database_permissions.ldif
  +
</PRE>
 
<PRE>
 
<PRE>
 
dn: olcDatabase={2}hdb,cn=config
 
dn: olcDatabase={2}hdb,cn=config
 
changetype: modify
 
changetype: modify
 
replace: olcAccess
 
replace: olcAccess
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=fuel_domain" write by * none
+
olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break
olcAccess: {1}to dn.base="" by * read
+
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 * by dn="cn=admin,dc=fuel_domain" write by * read
+
olcAccess: {2}to dn.base="" by * read
  +
olcAccess: {3}to * by dn="cn=admin,dc=fuel_domain" write by * read
 
</PRE>
 
</PRE>
   
 
<PRE>
 
<PRE>
ldapmodify -Y EXTERNAL -H ldapi:/// < 03_fix_permissions
+
ldapmodify -Y EXTERNAL -H ldapi:/// < 0021_fix_database_permissions.ldif
  +
</PRE>
SASL/EXTERNAL authentication started
 
  +
<PRE>
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
 
SASL SSF: 0
 
 
modifying entry "olcDatabase={2}hdb,cn=config"
 
modifying entry "olcDatabase={2}hdb,cn=config"
 
</PRE>
 
</PRE>
   
  +
==Download configuration and check it==
 
Проверить права можно например скачав весь конфиг:
 
Проверить права можно например скачав весь конфиг:
 
<PRE>
 
<PRE>
 
ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" > all_config
 
ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" > all_config
 
</PRE>
 
</PRE>
  +
==Результат==
   
  +
На этом шаге - рабочий LDAP сервер с минимальными настройками и без шифрования.
=LDAP Configuration=
 
==Aliases==
 
Для простоты я создаю алиасы что бы не вводить пароль каждый раз
 
<PRE>
 
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>
 
   
  +
=Шифрование=
  +
Настройка шифрования вынесена на отдельную страницу
   
  +
* http://wiki.sirmax.noname.com.ua/index.php/LDAP_Linux_LDAP_TLS
   
  +
На данный момент настроено шифрование.
==Organization==
 
  +
=Репликация=
Добавить организацию
 
  +
Перед началом настройки репликации - настроить на обоих серверах шифрования. Конфигурация аналогичная за исключением сертификата и хостнейма
Обратить внимание - <B>dn: dc=customer_organization,dc=fuel_domain</B> - порядок важен. dc В КОТОРЫЙ добавляется должен быть последним.
 
   
  +
  +
http://wiki.sirmax.noname.com.ua/index.php/LDAP_Linux_Replication
  +
  +
=PHP LDAP Addmin=
  +
Опционально можно поставить phpldapadmin
 
<PRE>
 
<PRE>
  +
apt-get install phpldapadmin
# 04_customer_organization
 
dn: dc=customer_organization,dc=fuel_domain
 
dc: customer_organization
 
o: Example Organization
 
objectClass: dcObject
 
objectClass: organization
 
 
</PRE>
 
</PRE>
  +
Настройки минимальны и ограничиваются указанием домена пользователя
Добавить организацию:
 
 
<PRE>
 
<PRE>
  +
diff /etc/phpldapadmin/config.php /etc/phpldapadmin/config.php.original
ldapadd < 04_customer_organization
 
  +
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>
  +
Результат:
 
  +
Если нужно шифрование то
 
<PRE>
 
<PRE>
  +
apt-get install php5-sasl
ldapadd < 04_customer_organization
 
adding new entry "dc=customer_organization,dc=fue_domain"
 
ldap_add: Server is unwilling to perform (53)
 
additional info: no global superior knowledge
 
 
root@node-3:~/ldap# ldapadd < 04_customer_organization
 
adding new entry "dc=customer_organization,dc=fuel_domain"
 
 
</PRE>
 
</PRE>
   
  +
И конфигурация будет выглядеть так:
 
==Manager Role==
 
 
<PRE>
 
<PRE>
  +
$servers->setValue('server','host','ldaps://127.0.0.1:636');
# 05_manager
 
  +
$servers->setValue('server','port',0);
dn: cn=Manager,dc=customer_organization,dc=fuel_domain
 
  +
</PRE>
cn: Manager
 
  +
В файле /etc/ldap/ldap.conf должны быть правильные настройки
description: LDAP administrator
 
  +
<PRE>
objectClass: organizationalRole
 
  +
TLS_CACERT /etc/ssl/certs/rootca.crt
objectClass: top
 
  +
TLS_REQCERT allow
roleOccupant: dc=customer_organization,dc=fuel_domain
 
  +
TIMELIMIT 15
  +
TIMEOUT 20
 
</PRE>
 
</PRE>
   
  +
=Populate LDAP=
  +
==Customers_Organization==
  +
Контейнер для всех остальных объектов
 
<PRE>
 
<PRE>
  +
0000_Customers_Organization
ldapadd < 05_manager
 
adding new entry "cn=Manager,dc=customer_organization,dc=fuel_domain"
 
 
</PRE>
 
</PRE>
   
==Organization Units People and Groups==
 
 
<PRE>
 
<PRE>
  +
dn: dc=customer_organization,dc=fuel_domain
# 06_people
 
dn: ou=People,dc=customer_organization,dc=fuel_domain
+
dc: customer_organization
  +
o: Example Organization
ou: People
 
objectClass: top
+
objectClass: dcObject
objectClass: organizationalUnit
+
objectClass: organization
 
</PRE>
 
</PRE>
   
  +
==Groups==
  +
Контейнер для групп и для пользователей.
  +
<PRE>
  +
0001_Groups
  +
</PRE>
 
<PRE>
 
<PRE>
# 07_groups
 
 
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
 
</PRE>
 
</PRE>
   
  +
==User sirmax (мой пользователь)==
  +
Первый пользователь и его группа, который сможет логиниться на ноды.
 
<PRE>
 
<PRE>
  +
0002_User_sirmax
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>
 
</PRE>
   
==Users==
 
 
<PRE>
 
<PRE>
dn: uid=sirmax,ou=People,dc=example_organization,dc=fuel
+
dn: uid=sirmax,ou=People,dc=customer_organization,dc=fuel_domain
 
objectClass: top
 
objectClass: top
 
objectClass: person
 
objectClass: person
Строка 272: Строка 353:
 
sn: Mazur
 
sn: Mazur
 
givenName: Mazur
 
givenName: Mazur
title: test user
+
title: Max Mazur
 
telephoneNumber: +38 067 341 80 70
 
telephoneNumber: +38 067 341 80 70
 
mobile: +38 067 341 80 70
 
mobile: +38 067 341 80 70
 
postalAddress: AddressLine1$AddressLine2$AddressLine3
 
postalAddress: AddressLine1$AddressLine2$AddressLine3
  +
userPassword: {CRYPT}$6$DS/mzad5$EB.cNCLE7KB7OCPK1nU6aEA8HnQDLY1FPd3KaWPVqaNBtWhmh/4cOUgD1I8tQSFu41yy7jMXDrg9TDqlAbuLX.
userPassword: {SSHA}pNCOaigx9LpjZp80yG4lDd/LPI2sZj7K
 
 
labeledURI: http://wiki.sirmax.noname.com.ua/
 
labeledURI: http://wiki.sirmax.noname.com.ua/
loginShell: /bin/bash
+
loginShell: /usr/bin/sudosh
 
uidNumber: 9999
 
uidNumber: 9999
 
gidNumber: 9999
 
gidNumber: 9999
homeDirectory: /home/sirmax/
+
homeDirectory: /home/sirmax
description: This is an example user
+
description: This is me :)
</PRE>
 
   
=2=
 
Пароль криптуется с помощью slappasswd
 
   
  +
dn: cn=sirmax,ou=Group,dc=customer_organization,dc=fuel_domain
<BR>
 
  +
changetype: add
Проверить (\ - отключить алиас) (настройки безопасности - отдельная тема, http://www.openldap.org/doc/admin24/access-control.html )
 
  +
cn: sirmax
 
  +
objectClass: posixGroup
<PRE>
 
  +
gidNumber: 9999
\ldapsearch -x -b 'dc=example_organization,dc=fuel' '(objectclass=*)'
 
  +
description: Fuel Users
  +
memberUid: sirmax
 
</PRE>
 
</PRE>
   
  +
==Group Fuel_Users==
  +
Группа пользователей которая используется для <b>sudo</b>
 
<PRE>
 
<PRE>
  +
0004_GroupFuelUsers
\ldapsearch -D "uid=sirmax,ou=People,dc=example_organization,dc=fuel" -w r00tme -b 'dc=example_organization,dc=fuel' '(uid=sirmax)'
 
 
</PRE>
 
</PRE>
   
 
<PRE>
 
<PRE>
dn: cn=sirmax,ou=Group,dc=example_organization,dc=fuel
+
dn: cn=fuel_users,ou=Group,dc=customer_organization,dc=fuel_domain
 
changetype: add
 
changetype: add
cn: fuel users
+
cn: fuel_users
 
objectClass: posixGroup
 
objectClass: posixGroup
gidNumber: 9999
+
gidNumber: 109999
 
description: Fuel Users
 
description: Fuel Users
 
memberUid: sirmax
 
memberUid: sirmax
 
</PRE>
 
</PRE>
  +
  +
==ServiceOU and Sudoers==
  +
  +
Создать контейнеры для сервисных объектов и поместить в него контейнер для sudo.
  +
   
 
<PRE>
 
<PRE>
  +
0005_ServiceOU_and_Sudoers
dn: cn=fuel_users,ou=Group,dc=example_organization,dc=fuel
 
  +
</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
 
changetype: add
cn: fuel users
+
cn: test1
 
objectClass: posixGroup
 
objectClass: posixGroup
gidNumber: 109999
+
gidNumber: 9998
 
description: Fuel Users
 
description: Fuel Users
memberUid: sirmax
+
memberUid: test1
 
</PRE>
 
</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/
 
* ВВедение в PAM https://www.ibm.com/developerworks/ru/library/l-pam/

Текущая версия на 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

PAM vs 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


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