sql >> Database >  >> RDS >> PostgreSQL

Eén beveiligingssysteem voor toepassingen, pooling van verbindingen en PostgreSQL - de zaak voor LDAP

Traditioneel bestaat de typische toepassing uit de volgende componenten:

In dit eenvoudige geval zou een basisconfiguratie voldoende zijn:

  • de applicatie gebruikt een eenvoudig lokaal authenticatiemechanisme voor zijn gebruikers
  • de applicatie gebruikt een eenvoudige verbindingspool
  • er is één gebruiker gedefinieerd voor databasetoegang

Naarmate de organisatie evolueert en groter wordt, worden er echter meer componenten toegevoegd:

  • meer tenant-apps of instanties van de app die toegang hebben tot de database
  • meer services en systemen die toegang hebben tot de database
  • centrale authenticatie/autorisatie (AA) voor alle (of de meeste) services
  • scheiding van componenten voor eenvoudiger schalen in de toekomst

In het bovenstaande schema zijn alle zorgen onderverdeeld in afzonderlijke componenten, waarbij elk onderdeel een gespecialiseerd doel dient. De verbindingspool gebruikt echter nog steeds een enkele toegewijde databasegebruiker, zoals in de vorige eenvoudigere configuratie die we hierboven zagen.

Naast de nieuwe componenten komen er ook nieuwe eisen bij:

  • betere fijnmazige controle over wat gebruikers kunnen doen op databaseniveau
  • controleren
  • beter nuttiger systeemregistratie

We kunnen ze altijd alle drie implementeren met meer applicatiecode of meer lagen in de applicatie, maar dit is gewoon omslachtig en moeilijk te onderhouden.

Bovendien biedt PostgreSQL zo'n rijke reeks oplossingen op de bovengenoemde gebieden (beveiliging, beveiliging op rijniveau, auditing, enz.) dat het volkomen logisch is om al die services naar de databaselaag te verplaatsen. Om die services rechtstreeks uit de database te halen, moeten we de enkele gebruiker in de database vergeten en in plaats daarvan echte individuele gebruikers gebruiken.

Dit brengt ons bij een schema zoals hieronder:

In onze use-case zullen we een typische enterprise-setup beschrijven die bestaat uit het bovenstaande schema, waarbij we gebruik maken van:

  • Wildfly-app-server (voorbeelden getoond voor versie 10)
  • LDAP-authenticatie-/autorisatieservice
  • pgbouncer-verbindingspooler
  • PostgreSQL 10

Het lijkt een typische setup, aangezien jboss/wildfly al vele jaren LDAP-authenticatie en autorisatie ondersteunt, en PostgreSQL ondersteunt al vele jaren LDAP.

Pgbouncer startte echter pas met ondersteuning voor LDAP (en dit via PAM) sinds versie 1.8 eind 2017, wat betekent dat iemand tot dan toe de populairste PostgreSQL-verbindingspooler niet kon gebruiken in een dergelijke enterprise-setup (wat in geen enkel opzicht veelbelovend klonk om ernaar te kijken)!

In deze blog beschrijven we de benodigde instellingen in elke laag.

Wildfly 10-configuratie

De configuratie van de gegevensbron zal er als volgt uit moeten zien, ik laat de belangrijkste dingen zien:

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

Ik heb de belangrijke parameters en waarden vet gedrukt. Vergeet niet om het IP-adres (of hostnaam), de databasenaam en de poort te definiëren volgens de instellingen van uw pgbouncer-server.

In plaats van de typische gebruikersnaam/wachtwoord, moet u ook een beveiligingsdomein hebben gedefinieerd, dat moet worden opgegeven in het gedeelte over de gegevensbron, zoals hierboven weergegeven. De definitie ziet er als volgt uit:

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

Op deze manier zal wildfly de beveiligingscontext delegeren aan pgbouncer.

OPMERKING: in deze blog behandelen we de basis, d.w.z. we maken geen gebruik van TLS en noemen dit niet, maar we raden je ten zeerste aan om het in je installatie te gebruiken.

De wildfly-gebruikers moeten zich als volgt authenticeren tegen uw LDAP-server:

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

Bovenstaande configuratiebestanden zijn van toepassing op wildfly 10.0, u wordt geadviseerd in ieder geval de officiële documentatie voor uw omgeving te raadplegen.

PostgreSQL-configuratie

Om PostgreSQL te vertellen om te authenticeren (OPMERKING: niet autoriseren!) tegen uw LDAP-server, moet u de juiste wijzigingen aanbrengen in postgresql.conf en pg_hba.conf. De interessante items zijn de volgende:

In postgresql.conf:

listen_addresses = '*'

en in 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"

Zorg ervoor dat de hier gedefinieerde LDAP-instellingen exact overeenkomen met de instellingen die u hebt gedefinieerd in uw app-serverconfiguratie. Er zijn twee manieren waarop PostgreSQL kan worden geïnstrueerd om contact op te nemen met de LDAP-server:

  • eenvoudig binden
  • zoek en bind dan

De eenvoudige bindmodus vereist slechts één verbinding met de LDAP-server en is daarom sneller, maar vereist een op de een of andere manier striktere LDAP-woordenboekorganisatie dan de tweede modus. De zoek- en bindmodus zorgt voor meer flexibiliteit. Voor de gemiddelde LDAP-directory werkt de eerste modus (eenvoudige binding) echter prima. We moeten bepaalde punten over PostgreSQL LDAP-authenticatie onderstrepen:

  • Dit heeft te maken met alleen authenticatie (wachtwoorden controleren).
  • Het lidmaatschap van rollen wordt zoals gewoonlijk nog steeds gedaan in PostgreSQL.
  • De gebruikers moeten zoals gewoonlijk worden aangemaakt in PostgreSQL (via CREATE user/role).

Er zijn enkele oplossingen om te helpen bij synchronisatie tussen LDAP- en PostgreSQL-gebruikers (bijv. ldap2pg) of u kunt eenvoudig uw eigen wrapper schrijven die zowel LDAP als PostgreSQL kan verwerken voor het toevoegen of verwijderen van gebruikers.

Download de whitepaper vandaag PostgreSQL-beheer en -automatisering met ClusterControlLees wat u moet weten om PostgreSQL te implementeren, bewaken, beheren en schalenDownload de whitepaper

PgBouncer-configuratie

Dit is het moeilijkste deel van onze setup, vanwege het feit dat native LDAP-ondersteuning nog steeds ontbreekt in pgbouncer, en de enige optie is om te authenticeren via PAM, wat betekent dat dit afhangt van de juiste lokale UNIX/Linux PAM-setup voor LDAP.

De procedure is dus opgedeeld in twee stappen.

De eerste stap is om te configureren en te testen dat pgbouncer met PAM werkt, en de tweede stap is om PAM te configureren om met LDAP te werken.

pgbouncer

pgbouncer moet worden gecompileerd met PAM-ondersteuning. Om dit te doen moet je:

  • installeer libpam0g-dev
  • ./configure --with-pam
  • compileer en installeer pgbouncer

Uw pgbouncer.ini (of de naam van uw pgbouncer-configuratiebestand) moet geconfigureerd zijn voor pam. Het moet ook de juiste parameters voor uw database en uw toepassing bevatten in overeenstemming met de parameters die in de bovenstaande secties zijn beschreven. Dingen die u moet definiëren of wijzigen:

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

Natuurlijk moet u de pgbouncer-documenten lezen en uw pgbouncer afstemmen op uw behoeften. Om de bovenstaande instellingen te testen, hoeft u alleen maar een nieuwe lokale UNIX-gebruiker aan te maken en te proberen te authenticeren bij pgbouncer:

# adduser testuser
<answer to all question, including password>

Om pgbouncer met PAM te laten werken bij het lezen van de lokale passwd-bestanden, moet het uitvoerbare bestand pgbouncer eigendom zijn van root en met 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

Opmerking:De noodzaak van root-eigendom en setuid (wat geldt voor elk debian/ubuntu-systeem dat ik heb getest) is nergens gedocumenteerd, noch in de officiële pgbouncer-documenten, noch ergens op het net.

Vervolgens loggen we in (als pgsql-superuser) op de postgresql-host (of psql -h your.pgsql.server) en maken de nieuwe gebruiker aan:

CREATE USER testuser PASSWORD 'same as the UNIX passwd you gave above';

dan van de pgbouncer-host:

psql -h localhost -p 6432 yourdbname -U testuser

U zou een prompt moeten kunnen krijgen en de tabellen kunnen zien alsof u rechtstreeks verbonden bent met uw databaseserver. Vergeet niet om deze gebruiker uit het systeem te verwijderen en ook uit de database te verwijderen wanneer u klaar bent met al uw tests.

PAM

Om PAM te laten communiceren met de LDAP-server, is een extra pakket nodig:libpam-ldap . Het post-installatiescript zal een tekstmodusdialoogvenster starten dat u moet beantwoorden met de juiste parameters voor uw LDAP-server. Dit pakket brengt de nodige updates aan in /etc/pam.d bestanden en maakt ook een bestand aan met de naam:/etc/pam_ldap.conf. Mocht er in de toekomst iets veranderen, dan kunt u altijd teruggaan en dit bestand bewerken. De belangrijkste regels in dit bestand zijn:

base cn=users,cn=accounts,dc=yourorgname,dc=com
uri ldap://your.ldap.server/
ldap_version 3
pam_password crypt

De naam/het adres van uw LDAP-server en de zoekbasis moeten exact hetzelfde zijn als die gespecificeerd in de PostgreSQL pg_hba.conf en de Wildfly standalone.xml conf-bestanden die hierboven zijn uitgelegd. pam_login_attribute is standaard uid. U wordt aangemoedigd om de /etc/pam.d/common-* bestanden te bekijken en te zien wat er is veranderd na de installatie van libpam-ldap. Als u de documenten volgt, kunt u een nieuw bestand maken met de naam /etc/pam.d/pgbouncer en alle PAM-opties daar definiëren, maar de standaard common-*-bestanden zijn voldoende. Laten we eens kijken in /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 zal eerst worden gecontroleerd, en als dit niet lukt, zal LDAP worden gecontroleerd, dus houd er rekening mee dat u alle lokale wachtwoorden moet wissen voor die gebruikers die zijn gedefinieerd voor zowel de lokale linux/unix /etc/passwd als in LDAP . Nu is het tijd om de laatste test te doen. Kies een gebruiker die is gedefinieerd in uw LDAP-server en ook is gemaakt in PostgreSQL, en probeer te authenticeren vanuit de DB (via pgsql -h your.pgsql.server ), en vervolgens vanuit pgbouncer (ook via psql -h your.pgbouncer.server) , en tot slot via uw app. Je hebt zojuist één enkel beveiligingssysteem voor app, verbindingspooler en PostgreSQL gerealiseerd!


  1. Opgeslagen T-SQL-procedure die meerdere id-waarden accepteert

  2. Vraag en aanbod afstemmen - Oplossingen, deel 2

  3. Geavanceerde SQL:CROSS APPLY en OUTER APPLY

  4. Simulatie van CONNECT BY PRIOR van Oracle in SQL Server