Traditionelt består den typiske applikation af følgende komponenter:
I dette simple tilfælde ville en grundlæggende opsætning være tilstrækkelig:
- applikationen bruger en simpel lokal godkendelsesmekanisme for sine brugere
- applikationen bruger en simpel forbindelsespulje
- der er en enkelt bruger defineret til databaseadgang
Men efterhånden som organisationen udvikler sig og bliver større, tilføjes flere komponenter:
- flere lejer-apps eller forekomster af appen, der får adgang til databasen
- flere tjenester og systemer, der får adgang til databasen
- central godkendelse/autorisation (AA) for alle (eller de fleste) tjenester
- adskillelse af komponenter for lettere fremtidig skalering
I ovenstående skema er alle bekymringer opdelt i individuelle komponenter, hver komponent tjener et specialiseret formål. Dog bruger forbindelsespuljen stadig en enkelt dedikeret databasebruger som i den tidligere enklere opsætning, vi så ovenfor.
Udover de nye komponenter kommer der også nye krav:
- bedre finkornet kontrol over, hvad brugere kan gøre på databaseniveau
- revision
- bedre mere nyttig systemlogning
Vi kan altid implementere alle tre med mere applikationskode eller flere lag i applikationen, men dette er bare besværligt og svært at vedligeholde.
Derudover tilbyder PostgreSQL et så rigt sæt af løsninger på de førnævnte områder (sikkerhed, Row Level Security, revision osv.), at det giver perfekt mening at flytte alle disse tjenester til databaselaget. For at tage disse tjenester direkte fra databasen, skal vi glemme en enkelt bruger i databasen og i stedet bruge rigtige individuelle brugere.
Dette fører os til en ordning som nedenstående:
I vores use case vil vi beskrive en typisk virksomhedsopsætning bestående af ovenstående skema, hvor vi bruger:
- Wildfly-appserver (eksempler vist for version 10)
- LDAP-godkendelses-/godkendelsestjeneste
- pgbouncer-forbindelsespooler
- PostgreSQL 10
Det virker som en typisk opsætning, da jboss/wildfly har understøttet LDAP-godkendelse og -autorisation i mange år, har PostgreSQL understøttet LDAP i mange år.
Men pgbouncer startede kun understøttelse af LDAP (og dette via PAM) siden version 1.8 i slutningen af 2017, hvilket betyder, at nogen indtil da ikke kunne bruge den hotteste PostgreSQL forbindelsespooler i sådan en virksomhedsopsætning (hvilket ikke lød lovende ud fra en hvilken som helst vinkel, vi valgte at se på det)!
I denne blog vil vi beskrive den nødvendige opsætning i hvert lag.
Wildfly 10-konfiguration
Datakildekonfigurationen skal se sådan ud, jeg viser de vigtigste ting:
<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>
Jeg har sat de vigtige parametre og værdier med fed skrift. Husk at definere IP-adressen (eller værtsnavnet), databasenavnet og porten i henhold til din pgbouncer-servers opsætning.
I stedet for det typiske brugernavn/adgangskode skal du også have et sikkerhedsdomæne defineret, som skal angives i datakildeafsnittet som vist ovenfor. Dens definition vil se sådan ud:
<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>
På denne måde vil wildfly uddelegere sikkerhedskonteksten til pgbouncer.
BEMÆRK: i denne blog dækker vi det grundlæggende, dvs. vi gør ingen brug eller omtaler af TLS, men du opfordres kraftigt til at bruge det i din installation.
Wildfly-brugerne skal autentificere mod din LDAP-server som følger:
<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>
Ovenstående konfigurationsfiler gælder for wildfly 10.0, du rådes under alle omstændigheder til at konsultere den officielle dokumentation for dit miljø.
PostgreSQL-konfiguration
For at bede PostgreSQL om at godkende (BEMÆRK: ikke autorisere!) mod din LDAP-server skal du foretage de relevante ændringer til postgresql.conf og pg_hba.conf. Indtastningerne af interesse er følgende:
I postgresql.conf:
listen_addresses = '*'
og i 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"
Sørg for, at de LDAP-indstillinger, der er defineret her, matcher nøjagtigt dem, du definerede i din app-serverkonfiguration. Der er to driftsformer, som PostgreSQL kan instrueres i at kontakte LDAP-serveren:
- simpel binding
- søg og bind derefter
Den simple bind-tilstand kræver kun én forbindelse til LDAP-serveren, derfor er den hurtigere, men kræver en på en eller anden måde strengere LDAP-ordbogsorganisation end den anden tilstand. Søge- og bindetilstanden giver mulighed for større fleksibilitet. For den gennemsnitlige LDAP-mappe vil den første tilstand (simpel binde) dog fungere fint. Vi skal understrege visse punkter om PostgreSQL LDAP-godkendelse:
- Dette har at gøre med kun godkendelse (kontrollerer adgangskoder).
- Rollemedlemskab udføres stadig i PostgreSQL, som sædvanligt.
- Brugerne skal oprettes i PostgreSQL (via CREATE bruger/rolle) som normalt.
Der er nogle løsninger, der hjælper med synkronisering mellem LDAP- og PostgreSQL-brugere (f.eks. ldap2pg), eller du kan simpelthen skrive din egen wrapper, der håndterer både LDAP og PostgreSQL til tilføjelse eller sletning af brugere.
Download Whitepaper Today PostgreSQL Management &Automation med ClusterControlFå flere oplysninger om, hvad du skal vide for at implementere, overvåge, administrere og skalere PostgreSQLDownload WhitepaperPgBouncer-konfiguration
Dette er den sværeste del af vores opsætning, på grund af det faktum, at native LDAP-understøttelse stadig mangler fra pgbouncer, og den eneste mulighed er at autentificere via PAM, hvilket betyder, at dette afhænger af den korrekte lokale UNIX/Linux PAM-opsætning til LDAP.
Så proceduren er opdelt i to trin.
Det første trin er at konfigurere og teste, at pgbouncer fungerer med PAM, og det andet trin er at konfigurere PAM til at arbejde med LDAP.
pgbouncer
pgbouncer skal være kompileret med PAM-understøttelse. For at gøre det skal du:
- installer libpam0g-dev
- ./configure --with-pam
- genkompiler og installer pgbouncer
Din pgbouncer.ini (eller navnet på din pgbouncer-konfigurationsfil) skal konfigureres til pam. Den skal også indeholde de korrekte parametre for din database og din applikation i overensstemmelse med parametrene beskrevet i afsnittene ovenfor. Ting du bliver nødt til at definere eller ændre:
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
Selvfølgelig skal du læse pgbouncer-dokumenterne og justere din pgbouncer efter dine behov. For at teste ovenstående opsætning skal du blot oprette en ny lokal UNIX-bruger og prøve at godkende til pgbouncer:
# adduser testuser
<answer to all question, including password>
For at pgbouncer kan arbejde med PAM, når du læser fra de lokale passwd-filer, skal den eksekverbare pgbouncer være ejet af root og med 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
Bemærk:Nødvendigheden af root-ejerskab og setuid (hvilket er sandt for alle debian/ubuntu-systemer, jeg har testet) er ingen steder dokumenteret, hverken i de officielle pgbouncer-dokumenter eller nogen steder på nettet.
Derefter logger vi på (som pgsql-superbruger) på postgresql-værten (eller psql -h your.pgsql.server) og opretter den nye bruger:
CREATE USER testuser PASSWORD 'same as the UNIX passwd you gave above';
derefter fra pgbouncer-værten:
psql -h localhost -p 6432 yourdbname -U testuser
Du skulle være i stand til at få en prompt og se tabellerne, som om du var forbundet direkte til din databaseserver. Husk at slette denne bruger fra systemet og slip også fra databasen, når du er færdig med alle dine tests.
PAM
For at PAM kan kommunikere med LDAP-serveren, kræves der en ekstra pakke:libpam-ldap . Dets postinstallationsscript vil køre en teksttilstandsdialog, som du skal besvare med de korrekte parametre for din LDAP-server. Denne pakke vil lave de nødvendige opdateringer i /etc/pam.d filer og også oprette en fil med navnet:/etc/pam_ldap.conf. Hvis noget ændrer sig i fremtiden, kan du altid gå tilbage og redigere denne fil. De vigtigste linjer i denne fil er:
base cn=users,cn=accounts,dc=yourorgname,dc=com
uri ldap://your.ldap.server/
ldap_version 3
pam_password crypt
Navnet/adressen på din LDAP-server og søgebasen skal være nøjagtig det samme som dem, der er angivet i PostgreSQL pg_hba.conf og Wildfly standalone.xml conf-filerne forklaret ovenfor. pam_login_attribute er som standard uid. Du opfordres til at tage et kig på /etc/pam.d/common-* filerne og se, hvad der ændrede sig efter installationen af libpam-ldap. Efter dokumenterne, kan du oprette en ny fil ved navn /etc/pam.d/pgbouncer og definere alle PAM-indstillinger der, men standardfilerne almindelig-* vil være tilstrækkelige. Lad os tage et kig i /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 vil blive kontrolleret først, og hvis dette mislykkes, vil LDAP blive kontrolleret, så husk på, at du bliver nødt til at slette eventuelle lokale adgangskoder for de brugere, der er defineret både til den lokale linux/unix /etc/passwd og i LDAP . Nu er det tid til at lave den sidste test. Vælg en bruger, der er defineret i din LDAP-server og også oprettet i PostgreSQL, og prøv at autentificere fra DB'en (via pgsql -h your.pgsql.server ), derefter fra pgbouncer (også via psql -h your.pgbouncer.server) , og endelig via din app. Du har lige gjort det til en realitet at have ét enkelt sikkerhedssystem til app, forbindelsespooler og PostgreSQL!