Har du en Postgres-database, uten at du har konfigurert Row Level Security? I denne artikkelen får du vite når, hvorfor og hvordan du legger til RLS for et ekstra lag med sikkerhet på databasenivå.
Hva er Row-Level Security (RLS)?
Row-Level Security (RLS) i PostgreSQL er en funksjon som lar deg definere regler for hvem som kan se eller endre spesifikke rader i en tabell. Dette gjør det mulig å begrense brukerens tilgang til data direkte på databasenivå, uten behov for å implementere tilpasset logikk i applikasjonen.
RLS fungerer ved å koble en brukers identitet til en unik identifikator, ofte referert til som en UID. Når en bruker logger inn, genererer autentiseringssystemet en UID som følger med hver forespørsel til databasen. Denne UID-en fungerer som en “nøkkel” som databasen bruker for å avgjøre hvilke data brukeren har tilgang til. For eksempel kan en RLS-regel sørge for at en bruker kun ser rader i en tabell der UID-en matcher deres egen.
Hvordan fungerer dette i praksis?
Når en bruker sender en forespørsel til databasen, sjekker RLS-reglene om brukerens UID stemmer overens med de dataene som forespørselen prøver å hente. Selv om applikasjonen bruker en offentlig nøkkel, for eksempel en såkalt anon-key (anonym nøkkel), sikrer RLS at ingen bruker kan hente data som ikke tilhører dem. Dette skyldes at selve tilgangen valideres av RLS-reglene i databasen, basert på UID-en som er sendt inn.
Hvorfor er dette sikkert?
Ved å beskytte hele databasen med RLS-regler kan du teoretisk sett dele en anon-key offentlig uten risiko for datalekkasjer. Selv om noen får tilgang til nøkkelen, kan de ikke hente andres data uten den riktige UID-en. Dette gjør det mulig å lagre anon-key på brukernes enheter uten bekymring for sikkerhetsbrudd.
Eksempel på bruk
Tenk deg at du bygger en app. Med RLS og en anon-key kan appen sende forespørsler til databasen uten ekstra sikkerhetslogikk i applikasjonen. Brukeren vil kun få tilgang til sine egne data, fordi RLS-reglene sørger for at forespørselen filtreres basert på UID-en deres.
Ved å kombinere RLS med UID-styrt autentisering, kan du skape en sikker og effektiv datatilgangsmodell som minimerer kompleksiteten i applikasjonen din.
Hvordan setter jeg opp RLS?
Du kan sette opp RLS i Postgres uten å legge til noen ekstra utvidelser. Først må du skru det på i databasen din:
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
Deretter kan du begynne å opprette regler. For eksempel kan denne regelen være praktisk hvis man har en database med banktransaksjoner:
CREATE POLICY "Allow access to own transactions only"
ON public.transactions -- Tabellen som policien skal gjelde for
FOR ALL -- Gjelder alle operasjoner (SELECT, INSERT, UPDATE og DELETE)
TO authenticated -- Begrenser policien til å kun gjelde brukere som er knyttet til authenticated (ikke superbrukere for eksempel)
USING (auth.uid() = user_id) -- Hvilke rader brukeren får lese eller slette
WITH CHECK (auth.uid() = user_id); -- Hvilke rader brukeren kan opprette eller endre
Lag tilsvarende regler for alle tabellene dine, og vips, så har du oppgradert sikkerheten din rett på databasenivå 🤩🔒. Hvis du bruker RLS riktig, så kan du også slippe å inkludere en filter for gjeldende bruker for alle spørringene dine. Du får altså både et sikrere system med mindre feil, og penere kode!
Er RLS all sikkerheten man trenger?
Nei, man bør ikke stole blindt på RLS alene. RLS er effektivt og sikkert, men ett lag med sikkerhet er skjelden en god idé. Det er fort gjort å gjøre konfigurasjonsfeil, spesielt når man bygger ekstra kompleksitet i databaselaget. En superbruker på avveie kan også bety ubegrenset tilgang til en angriper, hvis ikke man har lagt til noen ekstra lag med sikkerhet.
Det er også verdt å nevne at RLS kan by på dårligere ytelse i databasen din, spesielt hvis man benytter uindekserte kolonner i reglene man lager.
Til slutt: En julemetafor
Jeg tenkte å bruke ChatGPT til å lage et stilig forsidebilde til denne artikkelen, men jeg fikk istedenfor en fin julemetafor som forklarer RLS på en enkel måte:
Dette var kort og godt om RLS;
God jul til Per, Kari, Lise og selvfølgelig deg som leser dette!