Translate

неділя, 14 вересня 2014 р.

OpenLDAP Server. Part I: Setup And Configuration. phpLDAPadmin

Якщо серверів у компанія лиш декілька - можна просто додавати користувачів на кожен із них. Це просто, проте не далекоглядно. З часом видача прав доступу буде займати все більше часу. Тому в критичний час варто задуматись про аутентифікацію через через центральний сервер, який значно зменшить час на видачу доступів. У цій статті піде мове про установку і конфігурацію OpenLDAP серверу.

OpenLDAP - відкрита реалізація LDAP, розроблена однойменним проектом і поширюється під власною вільною ліцензією OpenLDAP Public License. LDAP — протокол, що використовує TCP/IP і дозволяє проводити операції авторизації (bind), пошуку (search) та порівняння (compare), а також операції додавання, зміни або видалення записів. У якості записів можуть бути різноманітні дані, наприклад, інформація щодо виверження вулкану (тобто зовсім різноманітна) чи перелік користувачів та їхніх даних. Стандарт LDAP не стандартизує як саме має зберігатись інформація в базі данних, тому кожен може реалізувати більшість аспектів серверу по-своєму, головне щоб зберігалась сумісність.

1. INSTALLATION OF OPENLDAP


Не вдаючись в теоретичні подробиці, перейдемо до налаштувань OpenLDAP серверу. Для власної конфігурації я використовую наступні параметри:

Operating System :  Debian 8 Server / Ubuntu LTS 16.04
Hostname         :  ldap.ipeacocks.info
IP Address       :  192.168.1.37

Отже, замініть їх на необхідні вам у наступних інструкціях.

Установлюємо пакети:

# apt-get install slapd ldap-utils

На протязі установки буде запитано пароль майбутнього адміністратора LDAP:


Виконунуємо переконфігурацію демона slapd, для чого відповідаємо на подальші питання:

# dpkg-reconfigure slapd

Обираємо "Ні":


Вводимо доменне ім'я, яким будемо користуватись:


Додаємо ім'я організації (назву компанії, в якій працюєте, чи щось на зразок цього):


Вводимо пароль, котрий вводили раніше або ж новий, та підтверджуємо його:


Обираємо базу даних для бекенду. Про їхню різницю можна почитати тут. Найшвидша - MDB, проте slapd, зібраний із її підтримкою, може бути доступний не у всіх дистрибутивах:


Якщо натиснути "Ні", то у випадку видалення slapd, база залишиться:


Тиснемо "Так", щоб забекапити стару базу даних у разі запиту на генерацію нової:


Підтримка LDAPv2 нам не потрібна:


Якщо ж необхідно змінити відповіді на інші, можна запустити конфігурацію пакета повторно.

У випадку автоматизації установки та конфігурації пакета slapd (Ansible, Puppet і т.п.), інтерактивний режим очевидно не підійде, тому, наприклад, в Debian-подібних ОС можна встановити пакет із змінною середовища "DEBIAN_FRONTEND=noninteractive":

# DEBIAN_FRONTEND=noninteractive apt-get -yq install slapd

Потім виконати налаштування через debconf-set-selections:

# cat << EOF | sudo debconf-set-selections
slapd slapd/internal/adminpw password your_password
slapd slapd/internal/generated_adminpw password your_password
slapd slapd/password2 password your_password
slapd slapd/password1 password your_password
slapd slapd/domain string ipeacocks.info
slapd shared/organization string ipeacocks
slapd slapd/backend string MDB
slapd slapd/purge_database boolean false
slapd slapd/move_old_database boolean true
slapd slapd/allow_ldap_v2 boolean false
slapd slapd/no_configuration boolean false
slapd slapd/dump_database string when needed
EOF


І вже після виконати реконфігурацію slapd:

# dpkg-reconfigure -f noninteractive slapd
  Moving old database directory to /var/backups:
  - directory unknown... done.
  Creating initial configuration... done.
  Creating LDAP directory... done.


Всі можливі ключі пакета можна переглянути так (зірочки вказують на параметри, що були змінені):

# debconf-show slapd
* slapd/password2: (password omitted)
* slapd/internal/generated_adminpw: (password omitted)
* slapd/internal/adminpw: (password omitted)
* slapd/password1: (password omitted)
* slapd/move_old_database: true
  slapd/dump_database_destdir: /var/backups/slapd-VERSION
  slapd/unsafe_selfwrite_acl:
  slapd/upgrade_slapcat_failure:
* slapd/allow_ldap_v2: false
  slapd/invalid_config: true
* slapd/domain: ipeacocks.info
* slapd/dump_database: when needed
  slapd/password_mismatch:
* slapd/purge_database: false
* slapd/backend: MDB
* shared/organization: ipeacocks
* slapd/no_configuration: false


OpenLDAP сервер налаштовано і запущено на незахищеному 389 порту. Це зовсім не годиться для production-інсталяцій, тому одразу ж активуємо захищений протокол LDAPS (TLS). Для цього нам знадобиться сертифікат для ключ (в деяких випадках не буде зайвим і CA сертифікат), який наразі можна отримати безкоштовно через Let's Encrypt.

Звісно можна згенерувати самопідписний сертифікат та ключ, але це не бажано, адже певні сервіси можуть його не приймати без можливості ігнорування його правильності (наприклад, Google Apps Directory Sync).

Для початку активуємо ldaps протокол в slapd:

# vim /etc/default/slapd
...
SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///"
...

Незахищений ldap не буде зайвим лишити для локальних сервісів, далі ми його будемо використовувати для локальних адмін-панелей. Перезапустимо демон:

# service slapd restart

Тепер створимо окрему директорію ssl та розмістимо в ній попередньо отримані ключі:

# mkdir /etc/ldap/ssl/
# ls /etc/ldap/ssl/
ldap.crt  ldap.key

Сертифікат центру сертифікації розмістимо в /etc/ssl/certs/:

# file /etc/ssl/certs/cacert.crt
/etc/ssl/certs/cacert.crt: PEM certificate

Виставимо безпечні права та власників ключів:

# chmod go+r /etc/ssl/certs/cacert.crt
# chown -R root:openldap /etc/ldap/ssl
# chmod -R o-rwx /etc/ldap/ssl

Тепер опишимо їх в ldif та підключимо до slapd:

# vim tls-config.ldif
dn: cn=config
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ssl/certs/cacert.crt
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/ssl/ldap.crt
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/ssl/ldap.key

# ldapmodify -QY EXTERNAL -H ldapi:/// -f tls-config.ldif
modifying entry "cn=config"

Все має запрацювати, перевантажувати slapd не потрібно. Перевіримо чи ключі справді додались до конфігурації slapd:

# slapcat -n0 | grep -i tls
olcTLSCACertificateFile: /etc/ssl/certs/cacert.crt
olcTLSCertificateFile: /etc/ldap/ssl/ldap.crt
olcTLSCertificateKeyFile: /etc/ldap/ssl/ldap.key

Або ж підключені ключі можна побачити, переглянувши налаштування дерева cn=config:

# ldapsearch -QY EXTERNAL -H ldapi:/// -b cn=config 'cn=config' | grep TLS
olcTLSCACertificateFile: /etc/ssl/certs/cacert.crt
olcTLSCertificateFile: /etc/ldap/ssl/ldap.crt
olcTLSCertificateKeyFile: /etc/ldap/ssl/ldap.key

Не зайвим буде перевірити порти:

# netstat -tunlp | grep slapd

tcp     0   0 0.0.0.0:636          0.0.0.0:*            LISTEN   2462/slapd      
tcp     0   0 127.0.0.1:389        0.0.0.0:*            LISTEN   2462/slapd 

Чудово, все як і було заплановано. Наразі перевіримо роботу ldap:

# ldapsearch -LLL -QY EXTERNAL -H ldapi:/// -b 'dc=ipeacocks,dc=info'
dn: dc=ipeacocks,dc=info
objectClass: top
objectClass: dcObject
objectClass: organization
o: ipeacocks
dc: ipeacocks

dn: cn=admin,dc=ipeacocks,dc=info
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator


Команда наведена вище вивела вміст всього дерева записів dc=ipeacocks,dc=info. База майже порожня, описано лише базовий DN, та адміністратор cn=admin, dc=ipeacocks, dc=info.

Управляти та наповнювати базу можна використовуючи утиліти з пакету ldap-utils, котрий було установлено на початку, або ж простіший і більш наочний метод - LDAP-менеджери. Наприклад, JXplorer:


У якості параметрів для підключення варто використовувати наступні:


2. HARDENING OPENLDAP


За замовчуванням slapd дозволяє анонімні підключення для перегляду всього дерева записів окрім паролей. Мабуть це не дуже хороша практика, особливо якщо OpenLDAP буде доступний для підключень ззовні. Тож заборонимо анонімні підключення, додавши відповідний запис в дерево cn=config:

# vim anon_disable.ldif
dn: cn=config
changetype: modify
add: olcDisallows
olcDisallows: bind_anon

dn: cn=config
changetype: modify
add: olcRequires
olcRequires: authc

dn: olcDatabase={-1}frontend,cn=config
changetype: modify
add: olcRequires
olcRequires: authc


# ldapadd -Y EXTERNAL -H ldapi:/// -f anon_disable.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn=config"
modifying entry "cn=config"
modifying entry "olcDatabase={-1}frontend,cn=config"


Перевіримо чи насправді анонімний доступ було деактивовано:

# ldapsearch -QY EXTERNAL -H ldapi:/// -b cn=config 'cn=config' | grep 'olcDisallows'
olcDisallows: bind_anon


Звісно не зайвим буде перевірити це також на практиці.

Окрім цього для підключень сервісів, авторизацію яких необхідно дозволити через LDAP, ліпше за все користуватись не admin аккаунтом, а таким, у якого є лише права на читання всього дерева користувачів. Тому опишемо і створимо такого користувача:

# vim admin_ro_desc.ldif
dn: cn=admin_ro,dc=ipeacocks,dc=info
objectClass: simpleSecurityObject
objectClass: organizationalRole
userPassword: {SSHA}162PQPb5VNmSbhTDhQIHNnoeNDQACMwl


# vim admin_ro_access.ldif
dn: olcDatabase={1}mdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {3}to dn.base="dc=ipeacocks,dc=info" by dn.exact="cn=admin_ro,dc=ipeacocks,dc=info" read


# ldapadd -x -D "cn=admin,dc=ipeacocks,dc=info" -f admin_ro_desc.ldif -w your_admin_password
adding new entry "cn=admin_ro,dc=ipeacocks,dc=info"

# ldapmodify -QY EXTERNAL -H ldapi:/// -f admin_ro_access.ldif
modifying entry "olcDatabase={1}mdb,cn=config"

SSHA хеш був згенерований програмою slapcat:

# slappasswd -s your_admin_ro_password
{SSHA}162PQPb5VNmSbhTDhQIHNnoeNDQACMwl

Перевірити чи створений користувач admin_ro та з якими правами можна так:

# ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b 'cn=admin_ro,dc=ipeacocks,dc=info' -D 'cn=admin,dc=ipeacocks,dc=info'
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: cn=admin_ro,dc=ipeacocks,dc=info
objectClass: simpleSecurityObject
objectClass: organizationalRole
 
cn: admin_ro
 

# ldapsearch -LLL -QY EXTERNAL -H ldapi:/// -b cn=config 'olcDatabase={1}mdb' 'olcAccess'
dn: olcDatabase={1}mdb,cn=config
...
olcAccess: {3}to dn.base="dc=ipeacocks,dc=info" by dn.exact="cn=admin_ro,dc=ipeacocks,dc=info" read


У разі якщо є інші ідеї як убезпечити OpenLDAP - запрошую до обговорень в коментарі.


3. phpLDAPadmin LDAP BROWSER


Окремі web-admin панелі не обов'язковий елемент для роботи з OpenLDAP, але вони значно її полегшують. Спершу я розповім про установку та досвід користуванням phpLDAPadmin.

Встановимо пакет:

# apt install phpldapadmin

Відредагуємо конфігураційний файл адмін-панелі:

# vim /etc/phpldapadmin/config.php
[...]
$config->custom->appearance['timezone'] = 'Europe/Kiev';
[...]
$servers->setValue('server','name','Ipeacocks LDAP Server');
[...]
$servers->setValue('server','host','127.0.0.1');
[...]
$servers->setValue('server','base',array('dc=ipeacocks,dc=info'));
[...]
//comment this line
# $servers->setValue('login','bind_id','cn=admin,dc=example,dc=com');
//avoid some annoying warnings that are unimportant
$config->custom->appearance['hide_template_warning'] = true;

У цьому ж конфігураційному файлі можна змінити порядок відображення атрибутів для профілю користувача, вказати псевдоніми для них і т.п.

Apache був встановлений із залежностями до пакету phpldapadmin. Зупинимо його та приберемо з автостарту, адже надалі ми будемо використовувати Nginx:

# systemctl stop apache2
# systemctl disable apache2

Встановимо Nginx та PHP-FPM:

# apt install nginx nginx php-fpm

Скопіюємо сертифікат та ключ для майбутнього віртуального хосту в окрему директорію (сертифікат у моєму випадку покриває всі піддомени *.ipeacocks.info):

# mkdir /etc/nginx/ssl
# cp -p /etc/ldap/ssl/ldap.crt /etc/ldap/ssl/ldap.key /etc/nginx/ssl


Звісно, що можна використовувати сертифікати і напряму з директорії /etc/ldap/ssl/, головне, щоб Nginx міг їх прочитати.

Створимо конфігураційний файл для віртуального хосту, активуємо його та деактивуємо default віртуальний хост:

# vim /etc/nginx/sites-available/pla.conf

server {
  listen 80 default_server;
  listen [::]:80 default_server;
  server_name pla.ipeacocks.info;
  return 301 https://$host$request_uri;
}

server {
  listen 443 ssl;

  root /usr/share/phpldapadmin;
  index index.php;

  server_name pla.ipeacocks.info;
  ssl_certificate /etc/nginx/ssl/ldap.crt;
  ssl_certificate_key /etc/nginx/ssl/ldap.key;

  location ~ ^/.*\.php(/|$) {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php7.0-fpm.sock;


  }


  # logging
  error_log /var/log/nginx/pla.error.log;
  access_log /var/log/nginx/pla.access.log;


}

# ln -s /etc/nginx/sites-available/pla.conf /etc/nginx/sites-enabled/pla.conf
# rm /etc/nginx/sites-enabled/default
# systemctl restart nginx


Тож всі звернення на адресу http://pla.ipeacocks.info будуть перенаправлятись на захищене з'єднання https://pla.ipeacocks.info. Можливо, додаткова базова авторизація також не буде зайвою.

Логінимось з root DN:


Тепер створимо Organisational Unit (ou), де і будемо описувати групи користувачів. Для цього натиснемо "Create new entry here" --> "Generic: Organisational Unit", як на зображенні:


Обираємо "groups" у якості назви для "ou" та тиснемо "Create Object":


Аналогічно створимо "ou=users". Надалі тут будуть зберігати всі користувачі, але про це трохи пізніше.

У  "groups" створимо групу "ldap-users". Ця група буде групою по-замовчуванню, в котру потраплятимуть всі користувачі. Перейдемо в "ou=groups" та натиснемо як на малюнку "Create a child entry":


Цього разу оберемо інший темплейт - "Generic: Posix Group":


Обираємо ім'я групи і тиснемо "Create Object" та "Commit":


Так само створюємо групу "mail-aliases" в якій вже створюємо групи, котрі будуть email-розсилками (їх перечитувати може наприклад GADS), але поки що без користувачів:


І остання група, що ми створимо - 'ssh', в цю групу будуть входити люди, котрим буде необхідний SSH-доступ до серверів. Для цього також необхідно використати "Generic: Posix Group" шаблон.

Повернемось до вищої групи "ou=users" та наповнимо її користувачами. На рівні цієї групи обираємо "Create a child entry" -> "Generic: User Account":


За замовчуванням поле "Common Name" автоматично формується з вмісту двох полів "First name (givenName)" + "Last name(sn)". Значення "Common Name" має бути унікальним, адже з нього формується DN атрибут кожного користувача. Виходячи з цих особливостей, я у якості "Common Name" обираю коротке ім'я. Якщо ж з'являється користувач із аналогічним іменем - просто додаю першу літеру від імені по батькові чи щось на зразок цього.

Пересвідчившись у правильності даних користувача, натискаємо "Create Object" та "Commit". 

У якості функції хешування паролю раджу обирати в SSHA (SHA1** + sault), адже деякі сервіси можуть не приймати вже застарілі хеші.

Набір класів нового користувача та DN буде мати наступний вигляд:

# ldapsearch -LLL -x -H ldaps://ldap.ipeacocks.info -b 'cn=jdoe,ou=users,dc=ipeacocks,dc=info' -D "cn=admin,dc=ipeacocks,dc=info" -W

dn: cn=jdoe,ou=users,dc=ipeacocks,dc=info
cn: jdoe
givenName: John
gidNumber: 500
sn: Doe
loginShell: /bin/sh
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
userPassword:: e1NTSEF9MDhwT09sTGJCWmt0Nk01NWMvaEZ3T21ZQm03eWg3ZkI=
uidNumber: 1000
uid: jdoe
homeDirectory: /home/jdoe

Аналогічно створюємо нового користувача Vasil Pupkin. Цю процедуру можна спростити, скопіювавши вже створеного користувача за допомогою опції "Copy or move this entry", змінивши деякі параметри на нові:


За необхідності можна додати значення для користувача, створивши нові атрибути чи підключивши додаткові класи.

Вже створених користувачів можна додавати до груп, котрі ми створили раніше. Додамо користувача "jdoe" до групи "ssh". Для цього перейдемо в цю групу та натиснемо "Add new attribute", де в випадаючому списку оберемо "memberUid", напишемо ім'я користувача:



Натиснемо "Update Object" для збереження змін:


У групи користувачів можна додавати також скопом, в чому допоможе кнопка "modify group members" під полем "memberUid". Саме таким чином додамо користувачів "vpupkin" та "jdoe" до групи "kyiv", що є підгрупою групи  "mail-aliases":


Як я вже згадував, логіка груп заключається в тому, кому саме буде наданий доступ до конкретних підсистем. Звісно, що ці треті системи попередньо необхідно налаштувати на читання саме з цих груп.

Структура групи "kyiv", яка в майбутньому буде поштовою розсилкою, матиме такий вигляд :

# ldapsearch -LLL -QY EXTERNAL -H ldapi:/// -b 'cn=kyiv,cn=mail-aliases,ou=groups,dc=ipeacocks,dc=info' -D cn=admin,dc=ipeacocks,dc=info
dn: cn=kyiv,cn=mail-aliases,ou=groups,dc=ipeacocks,dc=info
gidNumber: 502
cn: kyiv
objectClass: posixGroup
objectClass: top
memberUid: vpupkin
memberUid: jdoe


2.1. phpLDAPadmin/openLDAP ldapPublicKey SCHEMA


За замовчуванням можливість додати публічний SSH RSA до опису користувача в phpLDAPadmin відсутня. Для цього необхідно додати окремий клас 'ldapPublicKey'. Опишемо ldif для цього:

# vim openssh-lpk.ldif
dn: cn=openssh-lpk,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: openssh-lpk
olcAttributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME'sshPublicKey'
  DESC 'MANDATORY: OpenSSH Public key'
  EQUALITY octetStringMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
olcObjectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME'ldapPublicKey' SUP top AUXILIARY
  DESC 'MANDATORY: OpenSSH LPK objectclass'
  MAY ( sshPublicKey $ uid )
  )


І додамо нову схему:

# ldapadd -Y EXTERNAL -H ldapi:/// -f openssh-lpk.ldif
adding new entry "cn=openssh-lpk,cn=schema,cn=config"

Після цього має з'явитись додатковий клас в openLDAP. Продемонструю як додати новий клас до вже створеного користувача 'vpupkin' в phpLDAPadmin. Спочатку додаємо новий об'єктний клас "ldapPublicKey" до опису користувача:



Після збереження змін додаємо новий атрибут 'sshPublicKey':



І вже потім в нове поле записуємо публічний ключ користувача і зберігаємо форму:


Перевіримо запис користувача утилітами ldap-utils:

$ ldapsearch -LLL -x -H ldaps://ldap.kaaiot.io -b 'cn=vpupkin,ou=users,dc=ipeacocks,dc=info' -D "cn=admin,dc=ipeacocks,dc=info" -W
Enter LDAP Password: 
dn: cn=vpupkin,ou=users,dc=ipeacocks,dc=info
cn: vpupkin
gidNumber: 500
givenName: Vasya
homeDirectory: /home/vpupkin
loginShell: /bin/sh
sn: Pupkin
uidNumber: 1001
uid: vpupkin
userPassword:: e1NTSEF9bGF3MHM4dUsvMmlYM1ExdzhJbFZRcTdQOHVQOW9GYkQ=
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
objectClass: ldapPublicKey
sshPublicKey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDB6n9K78fB+4HzwqgwLQkd94ba
 waMdxF6LHqm4eeBWcvVKdE4EJwTGNA6QgfklJevZZFx/BU7xKn0I1iU86Z8Jwmn0dSa
 ...
 OsonJqBB vpupkin@ipeacocks.info

Варто згадати, що phpLDAPadmin вміє працювати не лише з openLDAP, а і з іншими реалізаціями серверів, що працюють по LDAP-протоколу. Серед яких Apache DS389 Directory Server від Fedora Project, Active Directory від Microsoft та інші.

На цій ноті хотілось би згадати про недоліки phpLDAPadmin (PLA). Це дуже древній проект, який схоже вже не розвивається: останній реліз програми був аж в 2012 році! Також досить часто в PLA з'являються проблеми з відображенням вмісту сторінок, для чого необхідно робити додаткові оновлення сторінки браузера. Власне я не рекомендую використовувати цей web-менеджер, але наведена структура груп може бути комусь корисною. Як заміну PLA я рекомендую розглянути панель FusionDirectory, мова про яку піде в наступній статті.

** Наразі SHA1 вважається небезпечним, варто використовувати сучасніші hash-функції.


Посилання:
http://www.unixmen.com/openldap-installation-configuration-ubuntu-12-1013-0413-10-debian-67/
https://wiki.debian.org/LDAP/OpenLDAPSetup
https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-a-basic-ldap-server-on-an-ubuntu-12-04-vps
https://help.ubuntu.com/16.04/serverguide/openldap-server.html
http://mindref.blogspot.com/2010/12/debian-openldap-ssl-tls-encryption.html
http://stezz.blogspot.com/2012/05/how-to-add-new-schema-to-openldap-24.html
http://phpldapadmin.sourceforge.net/wiki/index.php/FAQ
http://techiezone.rottigni.net/2011/12/change-root-dn-password-on-openldap/
http://www.linuxtopia.org/online_books/network_administration_guides/ldap_administration/schema_Extending_Schema.html
https://blog.shichao.io/2015/04/17/setup_openldap_server_with_openssh_lpk_on_ubuntu.html
https://pro-ldap.ru/

Немає коментарів:

Дописати коментар