• saas
  • multi-tenancy
  • postgres
  • row-level security
  • rls
  • trigger function
  • multi-tenant architecture
  • single-tenant architecture

Usean vuokralaisen toteutus PostgreSQL:llä: Opi yksinkertaisen tosielämän esimerkin kautta

Opi, miten toteuttaa usean vuokralaisen arkkitehtuuri PostgreSQL:n rivikohtaisen tietoturvan (RLS) ja tietokantaroolien avulla tosielämän esimerkin kautta varmistaaksesi tietojen suojatun eristämisen vuokralaisten välillä.

Yijun
Yijun
Developer

Joissakin aiemmissa artikkeleissamme syvennyimme usean vuokralaisen käsitteeseen ja sen sovelluksiin tuotteissa ja tosielämän liiketoimintatilanteissa.

Tässä artikkelissa tutkitaan, miten toteuttaa usean vuokralaisen arkkitehtuuri sovelluksellesi PostgreSQL:n avulla teknisestä näkökulmasta.

Mitä on yhden vuokralaisen arkkitehtuuri?

Yhden vuokralaisen arkkitehtuuri viittaa ohjelmistoarkkitehtuuriin, jossa jokaisella asiakkaalla on oma dedikoitu sovelluksen ja tietokannan instanssi.

Tässä arkkitehtuurissa jokaisen vuokralaisen tiedot ja resurssit ovat täysin eristettyjä muista vuokralaisista.

Yhden vuokralaisen arkkitehtuuri

Mitä on usean vuokralaisen arkkitehtuuri?

Usean vuokralaisen arkkitehtuuri on ohjelmistoarkkitehtuuri, jossa useat asiakkaat (vuokralaiset) jakavat saman sovelluksen instanssin ja infrastruktuurin säilyttäen samalla tietojen eristyksen. Tässä arkkitehtuurissa yksi ohjelmiston instanssi palvelee useita vuokralaisia, ja kunkin vuokralaisen tiedot pidetään erillään toisista erilaisilla eristemekanismeilla.

Usean vuokralaisen arkkitehtuuri

Yhden vuokralaisen vs usean vuokralaisen arkkitehtuuri

Yhden vuokralaisen arkkitehtuuri ja usean vuokralaisen arkkitehtuuri eroavat näkökulmista kuten tietojen eristys, resurssien hyödyntäminen, skaalaus, hallinta ja ylläpito sekä turvallisuus.

Yhden vuokralaisen arkkitehtuurissa jokaisella asiakkaalla on riippumaton tietotila, mikä johtaa pienempään resurssien hyödyntämiseen, mutta suhteellisen yksinkertaiseen räätälöintiin. Tyypillisesti yhden vuokralaisen ohjelmisto on räätälöity tiettyjen asiakkaiden tarpeisiin, kuten varastointijärjestelmät tietylle kangastoimittajalle tai henkilökohtainen blogiweb-sovellus. Niiden yleinen piirre on, että jokainen asiakas käyttää erillistä sovelluspalvelun instanssia, mikä helpottaa räätälöintiä vastaamaan erityisiä vaatimuksia.

Usean vuokralaisen arkkitehtuurissa useat vuokralaiset jakavat samat taustaresurssit, mikä johtaa suurempaan resurssien hyödyntämiseen. On kuitenkin tärkeää varmistaa tietojen eristys ja turvallisuus.

Usean vuokralaisen arkkitehtuuri on usein suosikkiohjelmistoarkkitehtuuri, kun palveluntarjoajat tarjoavat vakioituja palveluja eri asiakkaille. Näillä palveluilla on tyypillisesti alhainen räätälöintitaso, ja kaikki asiakkaat jakavat saman sovelluksen instanssin. Kun sovellus vaatii päivityksen, yhden sovelluksen instanssin päivittäminen vastaa sovelluksen päivittämistä kaikille asiakkaille. Esimerkiksi CRM (Asiakkuudenhallinta) on vakiotettu vaatimus. Näissä järjestelmissä käytetään tyypillisesti usean vuokralaisen arkkitehtuuria tarjotakseen saman palvelun kaikille vuokralaisille.

Vuokratietojen eristämisstrategiat usean vuokralaisen arkkitehtuurissa

Usean vuokralaisen arkkitehtuurissa kaikki vuokralaiset jakavat samat taustaresurssit, mikä tekee resurssien eristämisestä vuokralaisten välillä ratkaisevan tärkeää. Tämä eristys ei välttämättä tarvitse olla fyysistä; se vaatii vain varmistamaan, että resurssit eivät ole näkyvissä vuokralaisten välillä.

Arkkitehtuurin suunnittelussa voidaan saavuttaa erilaisia tasoja resurssieristystä vuokralaisten välillä:

Eristetty jaettu

Yleisesti ottaen, mitä enemmän resursseja jaetaan vuokralaisten kesken, sitä alhaisemmat järjestelmän iterointikustannukset ja ylläpito ovat. Vastaavasti, mitä vähemmän resursseja jaetaan, sitä korkeammat kustannukset ovat.

Aloita usean vuokralaisen toteutus tosielämän esimerkillä

Tässä artikkelissa käytämme CRM-järjestelmää esimerkkinä esitelläksemme yksinkertaisen, mutta käytännöllisen usean vuokralaisen arkkitehtuurin.

Tunnistamme, että kaikki vuokralaiset käyttävät samoja vakioituja palveluja, joten päätimme, että kaikilla vuokralaisilla on samat perustavanlaatuiset resurssit ja toteutamme tietojen eristämisen eri vuokralaisten välillä tietokantatasolla PostgreSQL:n avulla käyttäen rivikohtaista tietoturvaa.

Lisäksi luomme erillisen tiedonsiirtoyhteyden jokaiselle vuokralaiselle paremman vuokralaisoikeuksien hallinnan mahdollistamiseksi.

Seuraavaksi esittelemme kuinka toteuttaa tämä usean vuokralaisen arkkitehtuuri.

Kuinka toteuttaa usean vuokralaisen arkkitehtuuri PostgreSQL:llä

Lisää vuokralaisen tunniste kaikille resursseille

CRM-järjestelmässä meillä on paljon resursseja ja ne tallennetaan eri tauluihin. Esimerkiksi asiakastiedot tallennetaan customers-tauluun.

Ennen usean vuokralaisen toteuttamista nämä resurssit eivät ole yhteydessä mihinkään vuokralaiseen:

Eritelläksemme eri resurssien omistavat vuokralaiset, esittelemme tenants-taulun vuokralaisen tietojen tallentamiseksi (missä db_user ja db_user_password tallentavat tietokantayhteyden tiedot kullekin vuokralaiselle, yksityiskohdat alla). Lisäksi lisäämme tenant_id-kentän jokaiseen resurssiin tunnistamaan, mihin vuokralaiseen se kuuluu:

Nyt jokainen resurssi on liitetty tenant_id:n, mikä mahdollistaa meitä lisäämään where-ehdon kaikkiin kyselyihin rajoittamaan resurssien pääsyn kullekin vuokralaiselle:

Aluksi tämä vaikuttaa yksinkertaiselta ja toteutuskelpoiselta. Kuitenkin sillä on seuraavat ongelmat:

  • Lähes jokaisessa kyselyssä on tämä where-ehto, mikä sekoittaa koodia ja tekee siitä vaikeampaa ylläpitää, erityisesti kirjoitettaessa monimutkaisia liittymälausuntoja.
  • Koodipohjan uudet tulokkaat saattavat helposti unohtaa lisätä tämän where-ehdon.
  • Tietoja eri vuokralaisten välillä ei ole todella eristetty, koska jokaisella vuokralaisella on edelleen oikeudet päästä toisten vuokralaisten tietoihin.

Siksi emme omaksu tätä lähestymistapaa. Käytämme sen sijaan PostgreSQL:n Row Level Security-ominaisuutta näiden ongelmien ratkaisemiseksi. Ennen kuin jatkamme, luomme kuitenkin kullekin vuokralaiselle dedikoidun tietokantatilin, joka pääsee tähän jaettuun tietokantaan.

Aseta tietokantaroolit vuokralaisille

On hyvä käytäntö liittää tietokantarooleja jokaiselle käyttäjälle, joka voi muodostaa yhteyden tietokantaan. Tämä mahdollistaa paremman hallinnan kunkin käyttäjän pääsyyn tietokantaan, helpottaen eri käyttäjien toimintojen eristämistä ja parantaen järjestelmän vakautta ja turvallisuutta.

Koska kaikilla vuokralaisilla on samat tietokantaoperaatio-oikeudet, voimme luoda perustason roolin hallitsemaan näitä oikeuksia:

Sitten, erottaaksemme kunkin vuokralaisen roolin, perustasosta peritty rooli liitetään kullekin vuokralaiselle luodessa:

Seuraavaksi kunkin vuokralaisen tietokantayhteyden tiedot tallennetaan tenants-tauluun:

iddb_userdb_user_password
x2euiccrm_tenant_x2euicpa55w0rd

Tämä mekanismi antaa kullekin vuokralaiselle oman tietokantaroolin ja nämä roolit jakavat crm_tenant-roolille myönnetyt oikeudet.

Voimme sitten määritellä vuokralaisten käyttöoikeuksien laajuuden käyttämällä crm_tenant-roolia:

  • Vuokralaisilla tulisi olla CRUD-pääsy kaikkiin CRM-järjestelmän resurssitauluihin.
  • Taulut, joilla ei ole yhteyttä CRM-järjestelmän resursseihin, tulisi olla näkymättömiä vuokralaisille (olettaen, että vain systems-taulu).
  • Vuokralaiset eivät saisi pystyä muokkaamaan tenants-taulua, ja vain id ja db_user kenttien tulisi olla näkyvillä tiedustellessaan oman vuokralaisen tunnusta tietokantaoperaatioissa.

Kun roolit vuokralaisille on asetettu, kun vuokralainen pyytää pääsyä palveluun, voimme olla vuorovaikutuksessa tietokannan kanssa käyttäen roolia, joka edustaa sitä vuokralaista:

Suojaa vuokralaisen tiedot PostgreSQL:n Row Level Security:llä

Tällä hetkellä olemme perustaneet vastaavia tietokantarooleja vuokralaisille, mutta tämä ei rajoita tietojen käyttöä vuokralaisten välillä. Seuraavaksi hyödynnämme PostgreSQL:n Row Level Security -ominaisuutta rajoittamaan kunkin vuokralaisen pääsyä vain heidän omiin tietoihinsa.

PostgreSQL:ssä tauluilla voi olla rivikohtaisia tietoturvapolitiikkoja, jotka kontrolloivat, mitä rivejä voidaan käyttää kyselyiden tai datan muokkauskomentojen avulla. Tämä ominaisuus tunnetaan myös nimellä RLS (Row-Level Security).

Oletusarvoisesti tauluilla ei ole rivikohtaisia tietoturvapolitiikkoja. Hyödyntääksesi RLS:ää, sinun täytyy ottaa se käyttöön taululle ja luoda tietoturvapolitiikkoja, jotka suoritetaan aina, kun tauluun päästään käsiksi.

Käyttäen customers-taulua CRM-järjestelmässä esimerkkinä, otamme RLS:n käyttöön ja luomme tietoturvapolitiikan rajoittamaan, että kukin vuokralainen pääsee käsiksi vain omiin asiakastietoihinsa:

Tietoturvapolitiikan luomista koskevassa lausunnossa:

  • for all (valinnainen) osoittaa, että tätä käyttöpolitiikkaa käytetään select, insert, update ja delete -operaatioihin taulussa. Voit määritellä käyttöpolitiikan tietyille toiminnoille käyttämällä for ja komennon avainsanaa.
  • to crm_tenant osoittaa, että tämä politiikka koskee käyttäjiä, joilla on tietokantaroooli crm_tenant, eli kaikki vuokralaiset.
  • as restrictive määrittelee politiikan valvontatilan, mikä osoittaa, että pääsy tulisi rajoittaa tiukasti. Oletusarvoisesti taululla voi olla useita politiikkoja, useat permissive-politiikat yhdistetään TAI-suhteella. Tässä skenaariossa määrittelemme tämän politiikan restrictive, koska haluamme, että tämä politiikan tarkistus on pakollinen käyttäjille, jotka kuuluvat CRM-järjestelmän vuokralaisiin.
  • using lauseke määrittelee todellisen käyttöehdon, rajoittaen nykyistä kysyvää tietokannan käyttäjää näkemästä vain tietoja, jotka kuuluvat heidän omaan vuokralaiseen. Tämä rajoitus koskee rivejä, jotka valitaan komennolla (select, update tai delete).
  • with check lauseke määrittelee rajoituksen, joka vaaditaan, kun datarivejä muokataan (insert tai update), taaten, että vuokralaiset voivat lisätä tai päivittää tietoja vain itselleen.

RLS:n käyttö vuokralaisten pääsyn rajoittamiseen resurssitauluihimme tarjoaa useita etuja:

  • Tämä politiikka käytännössä lisää where tenant_id = (select id from tenants where db_user = current_user) kaikkiin kyselyoperaatioihin (select, update tai delete). Esimerkiksi, kun suoritat select * from customers, se vastaa select * from customers where tenant_id = (select id from tenants where db_user = current_user). Tämä poistaa tarpeen lisätä where-ehtoja sovelluskoodissa, yksinkertaistaen sitä ja vähentäen virheiden todennäköisyyttä.
  • Se hallitsee tietojen käyttöoikeuksia eri vuokralaisten välillä keskitetysti tietokantatasolla, mikä vähentää haavoittuvuuksien tai epäjohdonmukaisuuksien riskiä sovelluksessa, parantaen näin järjestelmän turvallisuutta.

Kuitenkin, on joitain asioita huomioida:

  • RLS-politiikkoja suoritetaan jokaista tietoriviä kohden. Jos RLS-politiikan kyselyehdot ovat liian monimutkaisia, se saattaa merkittävästi vaikuttaa järjestelmän suorituskykyyn. Onneksi vuokratietojen tarkastuskyselymme on riittävän yksinkertainen eikä vaikuta suorituskykyyn. Jos aiot toteuttaa muita toimintoja RLS:n avulla myöhemmin, voit seurata Supabasen rivikohtaisen tietoturvan suorituskykysuosituksia optimoidaksesi RLS-suorituskyvyn.
  • RLS-politiikat eivät automaattisesti täytä tenant_id:tä insert-toimintojen aikana. Ne vain rajoittavat vuokralaisia insertoimaan vain omaa dataansa. Tämä tarkoittaa, että dataa insertaessa meidän on silti annettava vuokralaisen tunnus, mikä ei ole johdonmukainen kyselyprosessin kanssa ja voi aiheuttaa sekaannusta kehityksen aikana, lisäten virheiden todennäköisyyttä (tämä käsitellään seuraavissa vaiheissa).

customers-taulun lisäksi meidän täytyy soveltaa samoja toimintoja kaikkiin CRM-järjestelmän resurssitauluihin (tämä prosessi voi olla hieman työläs, mutta voimme kirjoittaa ohjelman sen konfiguroimiseksi taulujen alustusvaiheen aikana), d näin eristäen eri vuokralaisten tiedot.

Luo trigger-toiminto datan lisäämistä varten

Kuten aiemmin mainittiin, RLS (Row-Level Security) mahdollistaa kyselyiden suorittamisen ilman, että tarvitsee huolehtia tenant_id:n olemassaolosta, koska tietokanta käsittelee sen automaattisesti. Kuitenkin, insert-toimintojen kohdalla, meidän täytyy silti manuaalisesti ilmoittaa vastaava tenant_id.

Jotta saavutettaisiin samanlainen mukavuus RLS:lle datan lisäämisessä, meidän täytyy saattaa tietokanta käsittelemään tenant_id:tä automaattisesti datan lisäyksen aikana.

Tällä on selvä etu: sovelluskehitystasolla meidän ei enää tarvitse miettiä, mihin vuokralaiseen data kuuluu, vähentäen virheiden todennäköisyyttä ja pieniäen henkistä kuormaa kehitettäessä monivuokralaisohjelmistoja.

Onneksi PostgreSQL tarjoaa tehokkaita trigger-toimintoja.

Triggerit ovat erityistoimintoja, jotka liittyvät tauluihin ja jotka suorittavat automaattisesti tiettyjä toimia (kuten insert, update tai delete), kun niitä tehdään tauluun. Nämä toimenpiteet voidaan laukaista rivi- (jokaiselle riville) tai lausuntasolla (koko lausunnolle). Triggereiden avulla voimme suorittaa mukautettua logiikkaa ennen tai jälkeen tiettyjen tietokantaoperaatioiden suorittamista, mikä mahdollistaa näytavoitteemme saavuttamisen helposti.

Ensiksi luodaan trigger-toiminto set_tenant_id, joka suoritetaan ennen jokaista datan lisäystä:

Seuraavaksi liitetään tämä trigger-toiminto customers-tauluun lisäystoimintoja varten (samalla tavalla kuin RLS:n käyttöönotto taulussa, tämä trigger-toiminto täytyy liittää kaikkiin asiaankuuluviin tauluihin):

Tämä trigger varmistaa, että lisätty data sisältää oikean tenant_id:n. Jos uudella datalla on jo tenant_id, trigger-toiminto ei tee mitään. Muussa tapauksessa se täyttää automaattisesti tenant_id-kentän käyttäjänsenä presenticken tusa n vuokralaisen tiedoista.

Tällä tavoin saavuttamme automaattisen tenant_id:n hallinnan tietokantatasolla vuokralaisten datan lisäyksen aikana.

Yhteenveto

Tässä artikkelissa syvennymme usean vuokralaisen arkkitehtuurin käytännön käyttöön, käyttäen CRM-järjestelmää esimerkkinä osoittamaan käytännöllistä ratkaisua hyödyntäen PostgreSQL-tietokantaa.

Keskustelemme tietokantarooleista, pääsynhallinnasta ja PostgreSQL:n rivikohtaisen tietoturva-ominaisuuden käytöstä tietojen eristämiseksi vuokralaisten välillä. Lisäksi hyödynnämme trigger-toimintoja vähentääksemme kehittäjien kognitiivista kuormaa eri vuokralaisten hallitsemisessa.

Tässä oli kaikki tältä artikkelilta. Jos haluat parantaa monivuokralaisohjelmaasi käyttäjäkäytön hallinnan avulla, voit viitata Helppo opas Logto-organisaatioiden aloittamiseen - monivuokralaisen sovelluksen rakentamiseen saadaksesi lisää näkemyksiä.