sql >> Databasteknik >  >> RDS >> PostgreSQL

Ett säkerhetssystem för applikationer, anslutningspooling och PostgreSQL - fallet för LDAP

Traditionellt består den typiska applikationen av följande komponenter:

I det här enkla fallet skulle det räcka med en grundläggande installation:

  • applikationen använder en enkel lokal autentiseringsmekanism för sina användare
  • applikationen använder en enkel anslutningspool
  • det finns en enskild användare definierad för databasåtkomst

Men när organisationen utvecklas och blir större läggs fler komponenter till:

  • fler klientappar eller instanser av appen som får åtkomst till databasen
  • fler tjänster och system som får åtkomst till databasen
  • central autentisering/auktorisering (AA) för alla (eller de flesta) tjänster
  • separering av komponenter för enklare framtida skalning

I ovanstående schema är alla problem uppdelade i individuella komponenter, varje komponent tjänar ett specialiserat syfte. Dock använder anslutningspoolen fortfarande en enda dedikerad databasanvändare som i den tidigare enklare installationen vi såg ovan.

Förutom de nya komponenterna kommer även nya krav:

  • bättre finkornig kontroll över vad användare kan göra på databasnivå
  • revision
  • bättre mer användbar systemloggning

Vi kan alltid implementera alla tre med mer applikationskod eller fler lager i applikationen, men detta är bara krångligt och svårt att underhålla.

Dessutom erbjuder PostgreSQL en så rik uppsättning lösningar på de ovannämnda områdena (säkerhet, radnivåsäkerhet, revision, etc) att det är perfekt att flytta alla dessa tjänster till databaslagret. För att ta dessa tjänster direkt från databasen måste vi glömma bort en enda användare i databasen och använda riktiga enskilda användare istället.

Detta tar oss till ett schema som nedan:

I vårt användningsfall kommer vi att beskriva en typisk företagskonfiguration som består av ovanstående schema där vi använder:

  • Wildfly-appserver (exempel visas för version 10)
  • LDAP-autentiserings-/auktoriseringstjänst
  • pgbouncer-anslutningspoolare
  • PostgreSQL 10

Det verkar vara en typisk installation, eftersom jboss/wildfly har stödt LDAP-autentisering och auktorisering i många år, har PostgreSQL stödt LDAP i många år.

Men pgbouncer startade endast stöd för LDAP (och detta via PAM) sedan version 1.8 i slutet av 2017, vilket innebär att någon tills dess inte kunde använda den hetaste PostgreSQL-anslutningspoolern i en sådan företagsuppsättning (vilket inte lät lovande från någon vinkel vi valt att titta på det)!

I den här bloggen kommer vi att beskriva inställningarna som behövs i varje lager.

Konfiguration av Wildfly 10

Datakällans konfiguration måste se ut så här, jag visar de viktigaste sakerna:

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

Jag har skrivit de viktiga parametrarna och värdena i fetstil. Kom ihåg att definiera IP-adressen (eller värdnamnet), databasnamnet och porten enligt din pgbouncer-servers inställningar.

Dessutom, istället för det typiska användarnamnet/lösenordet, måste du ha en säkerhetsdomän definierad, som måste anges i datakällan enligt ovan. Dess definition kommer att se ut så här:

<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å detta sätt kommer wildfly att delegera säkerhetskontexten till pgbouncer.

OBS: i den här bloggen tar vi upp grunderna, d.v.s. vi använder eller nämner inte TLS, men du uppmuntras starkt att använda det i din installation.

Wildfly-användarna måste autentisera mot din LDAP-server enligt följande:

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

Ovanstående konfigurationsfiler gäller för wildfly 10.0, du rekommenderas i alla fall att konsultera den officiella dokumentationen för din miljö.

PostgreSQL-konfiguration

För att tala om för PostgreSQL att autentisera (OBS: inte auktorisera!) mot din LDAP-server måste du göra lämpliga ändringar av postgresql.conf och pg_hba.conf. Posterna av intresse är följande:

I postgresql.conf:

listen_addresses = '*'

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

Se till att LDAP-inställningarna som definieras här matchar exakt de du definierade i din appserverkonfiguration. Det finns två driftsätt som PostgreSQL kan instrueras att kontakta LDAP-servern:

  • enkel bindning
  • sök och bind sedan

Det enkla bindningsläget kräver bara en anslutning till LDAP-servern, därför är det snabbare men kräver en på något sätt strängare LDAP-ordboksorganisation än det andra läget. Sök- och bindningsläget möjliggör större flexibilitet. Men för den genomsnittliga LDAP-katalogen kommer det första läget (enkel bindning) att fungera bra. Vi måste understryka vissa punkter om PostgreSQL LDAP-autentisering:

  • Detta har att göra med enbart autentisering (kontrollera lösenord).
  • Rollmedlemskap görs fortfarande i PostgreSQL, som vanligt.
  • Användarna måste skapas i PostgreSQL (via CREATE användare/roll) som vanligt.

Det finns några lösningar som hjälper till med synkronisering mellan LDAP- och PostgreSQL-användare (t.ex. ldap2pg) eller så kan du helt enkelt skriva din egen wrapper som hanterar både LDAP och PostgreSQL för att lägga till eller ta bort användare.

Ladda ner Whitepaper Today PostgreSQL Management &Automation med ClusterControlLäs om vad du behöver veta för att distribuera, övervaka, hantera och skala PostgreSQLDladda Whitepaper

PgBouncer-konfiguration

Detta är den svåraste delen av vår installation, på grund av det faktum att inbyggt LDAP-stöd fortfarande saknas från pgbouncer, och det enda alternativet är att autentisera via PAM, vilket innebär att detta beror på den korrekta lokala UNIX/Linux PAM-inställningen för LDAP.

Så proceduren är uppdelad i två steg.

Det första steget är att konfigurera och testa att pgbouncer fungerar med PAM, och det andra steget är att konfigurera PAM för att fungera med LDAP.

pgbouncer

pgbouncer måste kompileras med PAM-stöd. För att göra det måste du:

  • installera libpam0g-dev
  • ./configure --with-pam
  • kompilera om och installera pgbouncer

Din pgbouncer.ini (eller namnet på din pgbouncer-konfigurationsfil) måste konfigureras för pam. Den måste också innehålla de korrekta parametrarna för din databas och din applikation i enlighet med parametrarna som beskrivs i avsnitten ovan. Saker du måste definiera eller ändra:

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

Naturligtvis måste du läsa pgbouncer-dokumenten och ställa in din pgbouncer efter dina behov. För att testa ovanstående inställning behöver du bara skapa en ny lokal UNIX-användare och försöka autentisera till pgbouncer:

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

För att pgbouncer ska fungera med PAM när man läser från de lokala passwd-filerna måste den körbara filen pgbouncer ägas av root och 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

Obs:Nödvändigheten av root-ägande och setuid (vilket är sant för alla debian/ubuntu-system jag har testat) finns ingenstans dokumenterad, varken i de officiella pgbouncer-dokumenten eller någonstans på nätet.

Sedan loggar vi in ​​(som pgsql-superanvändare) på postgresql-värden (eller psql -h your.pgsql.server) och skapar den nya användaren:

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

sedan från pgbouncer-värden:

psql -h localhost -p 6432 yourdbname -U testuser

Du bör kunna få en prompt och se tabellerna som om du var ansluten direkt till din databasserver. Kom ihåg att ta bort denna användare från systemet och även släppa från databasen när du är klar med alla dina tester.

PAM

För att PAM ska kunna samverka med LDAP-servern behövs ett extra paket:libpam-ldap . Dess efterinstallationsskript kommer att köra en textlägesdialog som du måste svara med rätt parametrar för din LDAP-server. Det här paketet kommer att göra de nödvändiga uppdateringarna i /etc/pam.d-filerna och även skapa en fil med namnet:/etc/pam_ldap.conf. Om något ändras i framtiden kan du alltid gå tillbaka och redigera den här filen. De viktigaste raderna i denna fil är:

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

Namnet/adressen till din LDAP-server och sökbasen måste vara exakt samma som de som anges i PostgreSQL pg_hba.conf och Wildfly standalone.xml conf-filerna som förklaras ovan. pam_login_attribute är standard på uid. Du uppmuntras att ta en titt på /etc/pam.d/common-*-filerna och se vad som ändrades efter installationen av libpam-ldap. Efter dokumenten kan du skapa en ny fil med namnet /etc/pam.d/pgbouncer och definiera alla PAM-alternativ där, men standardfilerna common-* räcker. Låt oss ta en titt 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 kommer att kontrolleras först, och om detta misslyckas kommer LDAP att kontrolleras, så kom ihåg att du måste radera alla lokala lösenord för de användare som är definierade både till den lokala linux/unix /etc/passwd och i LDAP . Nu är det dags att göra det sista testet. Välj en användare som är definierad i din LDAP-server och även skapad i PostgreSQL, och försök autentisera från DB (via pgsql -h your.pgsql.server ), sedan från pgbouncer (även via psql -h your.pgbouncer.server) , och slutligen via din app. Du gjorde precis att ha ett enda säkerhetssystem för app, anslutningspooler och PostgreSQL till verklighet!


  1. Säkerhetskopiera en enda tabell med dess data från en databas i sql server 2008

  2. 4 sätt att hitta rader som innehåller versaler i Oracle

  3. SQL Server 2016:Importera data

  4. Populära Docker-bilder för MySQL och MariaDB Server