Традиционно типичното приложение се състои от следните компоненти:
В този прост случай, основна настройка би била достатъчна:
- приложението използва прост механизъм за локално удостоверяване за своите потребители
- приложението използва прост пул за връзки
- има един потребител, дефиниран за достъп до база данни
Въпреки това, тъй като организацията се развива и става все по-голяма, се добавят още компоненти:
- още наематели или екземпляри на приложението, които имат достъп до базата данни
- повече услуги и системи с достъп до базата данни
- централно удостоверяване/упълномощаване (AA) за всички (или повечето) услуги
- разделяне на компонентите за по-лесно бъдещо мащабиране
В горната схема всички проблеми са разделени на отделни компоненти, като всеки компонент служи за специализирана цел. Въпреки това, пулът за връзки все още използва един отделен потребител на база данни, както в предишната по-проста настройка, която видяхме по-горе.
Освен новите компоненти, пристигат и нови изисквания:
- по-добър фин контрол на това, което потребителите могат да правят на ниво база данни
- одит
- по-добро по-полезно системно регистриране
Винаги можем да внедрим и трите с повече код на приложението или повече слоеве в приложението, но това е просто тромаво и трудно за поддръжка.
В допълнение, PostgreSQL предлага толкова богат набор от решения в гореспоменатите области (сигурност, сигурност на ниво ред, одит и т.н.), че е напълно логично всички тези услуги да се преместят в слоя на базата данни. За да вземем тези услуги директно от базата данни, трябва да забравим за единичния потребител в базата данни и вместо това да използваме реални отделни потребители.
Това ни отвежда до схема като по-долу:
В нашия случай на използване ще опишем типична корпоративна настройка, състояща се от горната схема, където използваме:
- Сървър на приложения Wildfly (примери са показани за версия 10)
- Услуга за удостоверяване/оторизиране на LDAP
- pgbouncer пул за свързване
- PostgreSQL 10
Изглежда като типична настройка, тъй като jboss/wildfly поддържа LDAP удостоверяване и оторизация от много години, PostgreSQL поддържа LDAP от много години.
Въпреки това pgbouncer стартира поддръжка само за LDAP (и това чрез PAM) от версия 1.8 в края на 2017 г., което означава, че някой дотогава не може да използва най-горещия PostgreSQL пул за връзки в такава корпоративна настройка (която не звучи обещаващо от нито един ъгъл, който изберем да го погледна)!
В този блог ще опишем необходимата настройка за всеки слой.
Конфигурация на Wildfly 10
Конфигурацията на източника на данни ще трябва да изглежда така, показвам най-важните неща:
<xa-datasource jndi-name="java:/pgsql" pool-name="pgsqlDS" enabled="true" mcp="org.jboss.jca.core.connectionmanager.pool.mcp.LeakDumperManagedConnectionPool">
<xa-datasource-property name="DatabaseName">
yourdbname
</xa-datasource-property>
<xa-datasource-property name="PortNumber">
6432
</xa-datasource-property>
<xa-datasource-property name="ServerName">
your.pgbouncer.server
</xa-datasource-property>
<xa-datasource-property name="PrepareThreshold">
0
</xa-datasource-property>
<xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
<driver>postgresql-9.4.1212.jar</driver>
<new-connection-sql>
SET application_name to 'myapp';
</new-connection-sql>
<xa-pool>
<max-pool-size>400</max-pool-size>
<allow-multiple-users>true</allow-multiple-users>
</xa-pool>
<security>
<security-domain>postgresqluser</security-domain>
</security>
</xa-datasource>
Поставих с удебелен шрифт важните параметри и стойности. Не забравяйте да дефинирате IP адреса (или името на хост), името на базата данни и порта според настройката на вашия pgbouncer сървър.
Освен това, вместо типичното потребителско име/парола, ще трябва да имате дефиниран домейн за защита, който трябва да бъде посочен в раздела за източник на данни, както е показано по-горе. Неговото определение ще изглежда така:
<security-domain name="postgresqluser">
<authentication>
<login-module code="org.picketbox.datasource.security.CallerIdentityLoginModule" flag="required">
<module-option name="managedConnectionFactoryName" value="name=pgsql,jboss.jca:service=XATxCM"/>
</login-module>
</authentication>
</security-domain>
По този начин wildfly ще делегира контекста за сигурност на pgbouncer.
ЗАБЕЛЕЖКА: в този блог разглеждаме основите, т.е. не използваме и не споменаваме TLS, но силно се препоръчва да го използвате във вашата инсталация.
Потребителите на wildfly трябва да се удостоверят срещу вашия LDAP сървър, както следва:
<login-module code="<your login module class>" flag="sufficient">
<module-option name="java.naming.provider.url" value="ldap://your.ldap.server/"/>
<module-option name="java.naming.security.authentication" value="simple"/>
<module-option name="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory"/>
<module-option name="principalDNPrefix" value="uid="/>
<module-option name="uidAttributeID" value="memberOf"/>
<module-option name="roleNameAttributeID" value="cn"/>
<module-option name="roleAttributeID" value="memberOf"/>
<module-option name="principalDNSuffix"
value=",cn=users,cn=accounts,dc=yourorgname,dc=com"/>
<module-option name="userSrchBase" value="dc=yourorgname,dc=com"/>
<module-option name="rolesCtxDN"
value="cn=groups,cn=accounts,dc=yourorgname,dc=com"/>
<module-option name="matchOnUserDN" value="true"/>
<module-option name="unauthendicatedIdentity" value="foousr"/>
<module-option name="com.sun.jndi.ldap.connect.timeout" value="5000"/>
</login-module>
Горните конфигурационни файлове се отнасят за wildfly 10.0, препоръчваме ви във всеки случай да се консултирате с официалната документация за вашата среда.
Конфигурация на PostgreSQL
За да кажете на PostgreSQL да се удостовери (ЗАБЕЛЕЖКА: не разрешавайте!) срещу вашия LDAP сървър трябва да направите съответните промени в postgresql.conf и pg_hba.conf. Интересните записи са следните:
В postgresql.conf:
listen_addresses = '*'
и в pg_hba.conf:
#TYPE DATABASE USER CIDR-ADDRESS METHOD
host all all ip.ofYourPgbouncer.server/32 ldap ldapserver=your.ldap.server ldapprefix="uid=" ldapsuffix=",cn=users,cn=accounts,dc=yourorgname,dc=com"
Уверете се, че LDAP настройките, дефинирани тук, съвпадат точно с тези, които сте дефинирали в конфигурацията на вашия сървър за приложения. Има два режима на работа, на които PostgreSQL може да бъде инструктиран да се свърже с LDAP сървъра:
- просто свързване
- търсене и след това обвързване
Простият режим на свързване изисква само една връзка към LDAP сървъра, следователно е по-бърз, но изисква някак си по-строга организация на LDAP речник от втория режим. Режимът на търсене и свързване позволява по-голяма гъвкавост. Въпреки това, за средната LDAP директория, първият режим (обикновено свързване) ще работи добре. Трябва да подчертаем някои точки за PostgreSQL LDAP удостоверяване:
- Това е свързано с само удостоверяване (проверка на пароли).
- Членството в роли все още се извършва в PostgreSQL, както обикновено.
- Потребителите трябва да бъдат създадени в PostgreSQL (чрез CREATE потребител/роля), както обикновено.
Има някои решения, които да помогнат при синхронизирането между потребителите на LDAP и PostgreSQL (напр. ldap2pg) или просто можете да напишете своя собствена обвивка, която ще обработва както LDAP, така и PostgreSQL за добавяне или изтриване на потребители.
Изтеглете Бялата книга днес Управление и автоматизация на PostgreSQL с ClusterControl Научете какво трябва да знаете, за да внедрите, наблюдавате, управлявате и мащабирате PostgreSQLD Изтеглете Бялата книгаКонфигурация на PgBouncer
Това е най-трудната част от нашата настройка, поради факта, че поддръжката на родния LDAP все още липсва от pgbouncer и единствената опция е да се удостоверите чрез PAM, което означава, че това зависи от правилната локална настройка на UNIX/Linux PAM за LDAP.
Така че процедурата е разделена на две стъпки.
Първата стъпка е да конфигурирате и тествате дали pgbouncer работи с PAM, а втората стъпка е да конфигурирате PAM да работи с LDAP.
pgbouncer
pgbouncer трябва да бъде компилиран с поддръжка на PAM. За да го направите, ще трябва:
- инсталирайте libpam0g-dev
- ./configure --with-pam
- прекомпилирайте и инсталирайте pgbouncer
Вашият pgbouncer.ini (или името на вашия конфигурационен файл на pgbouncer) трябва да бъде конфигуриран за pam. Освен това той трябва да съдържа правилните параметри за вашата база данни и вашето приложение в съответствие с параметрите, описани в разделите по-горе. Неща, които ще трябва да дефинирате или промените:
yourdbname = host=your.pgsql.server dbname=yourdbname pool_size=5
listen_addr = *
auth_type = pam
# set pool_mode for max performance
pool_mode = transaction
# required for JDBC
ignore_startup_parameters = extra_float_digits
Разбира се, ще трябва да прочетете документите на pgbouncer и да настроите своя pgbouncer според вашите нужди. За да тествате горната настройка, всичко, което трябва да направите, е да създадете нов локален потребител на UNIX и да опитате да се удостоверите в pgbouncer:
# adduser testuser
<answer to all question, including password>
За да може pgbouncer да работи с PAM при четене от локалните passwd файлове, изпълнимият файл pgbouncer трябва да е собственост на root и със setuid:
# chown root:staff ~pgbouncer/pgbouncer-1.9.0/pgbouncer
# chmod +s ~pgbouncer/pgbouncer-1.9.0/pgbouncer
# ls -l ~pgbouncer/pgbouncer-1.9.0/pgbouncer
-rwsrwsr-x 1 root staff 1672184 Dec 21 16:28 /home/pgbouncer/pgbouncer-1.9.0/pgbouncer
Забележка:Необходимостта от root собственост и setuid (което е вярно за всяка система debian/ubuntu, която съм тествал) никъде не е документирана, нито в официалните документи на pgbouncer, нито навсякъде в мрежата.
След това влизаме (като pgsql суперпотребител) в хоста на postgresql (или psql -h your.pgsql.server) и създаваме новия потребител:
CREATE USER testuser PASSWORD 'same as the UNIX passwd you gave above';
след това от хоста на pgbouncer:
psql -h localhost -p 6432 yourdbname -U testuser
Трябва да можете да получите подкана и да видите таблиците, сякаш сте свързани директно към вашия сървър на база данни. Не забравяйте да изтриете този потребител от системата и също така да го откажете от базата данни, когато приключите с всичките си тестове.
PAM
За да може PAM да взаимодейства с LDAP сървъра, е необходим допълнителен пакет:libpam-ldap . Неговият скрипт след инсталиране ще стартира диалогов прозорец за текстов режим, на който ще трябва да отговорите с правилните параметри за вашия LDAP сървър. Този пакет ще направи необходимите актуализации във файловете /etc/pam.d и също така ще създаде файл с име:/etc/pam_ldap.conf. В случай, че нещо се промени в бъдеще, винаги можете да се върнете и да редактирате този файл. Най-важните редове в този файл са:
base cn=users,cn=accounts,dc=yourorgname,dc=com
uri ldap://your.ldap.server/
ldap_version 3
pam_password crypt
Името/адресът на вашия LDAP сървър и базата за търсене трябва да са точно същите като тези, посочени в PostgreSQL pg_hba.conf и обяснените по-горе конфис файлове на Wildfly standalone.xml. pam_login_attribute по подразбиране е uid. Препоръчваме ви да разгледате файловете /etc/pam.d/common-* и да видите какво се промени след инсталирането на libpam-ldap. Следвайки документите, можете да създадете нов файл с име /etc/pam.d/pgbouncer и да дефинирате всички PAM опции там, но стандартните common-* файлове ще са достатъчни. Нека да разгледаме /etc/pam.d/common-auth:
auth [success=2 default=ignore] pam_unix.so nullok_secure
auth [success=1 default=ignore] pam_ldap.so use_first_pass
auth requisite pam_deny.so
auth required pam_permit.so
Unix passwd ще бъде проверен първо и ако това не успее, тогава ще бъде проверен LDAP, така че имайте предвид, че ще трябва да изтриете всички локални пароли за тези потребители, които са дефинирани както в локалния linux/unix /etc/passwd, така и в LDAP . Сега е време да направим последния тест. Изберете потребител, който е дефиниран във вашия LDAP сървър и също създаден в PostgreSQL, и опитайте да се удостоверите от DB (чрез pgsql -h your.pgsql.server), след това от pgbouncer (също чрез psql -h your.pgbouncer.server) , и накрая чрез вашето приложение. Току-що превърнахте в реалност наличието на една единствена система за сигурност за приложение, пул за свързване и PostgreSQL!