diff --git a/dapla-manual/statistikkere/pseudonymisering.qmd b/dapla-manual/statistikkere/pseudonymisering.qmd index 90a24216..4a6a1516 100644 --- a/dapla-manual/statistikkere/pseudonymisering.qmd +++ b/dapla-manual/statistikkere/pseudonymisering.qmd @@ -1,17 +1,16 @@ # Pseudonymisering -På Dapla er det flere tjenester som til sammen gir team muligheten til å pseudonymisere, de-pseudonymisere eller re-pseudonymisere data^[Pseudonymisering defineres her som å erstatte spesifikke data med kunstige data (pseudonymer), mens de-pseudonymisering gjør det samme bare motsatt vei. Re-pseudonymisering defineres som å bytte ut et pseudonym med et annet, uten at brukeren nødvendigvis får tilgang til den opprinnelige verdien. ]. Disse tjenestene er satt opp på en slik måte at statistikkteam kan være selvbetjent i bruken av funksjonaliteten, samtidig som de sikrer at *direkte identifiserende opplysninger* håndteres i henhold til lovverk og SSBs egne bestemmelser. +På Dapla er det flere tjenester som til sammen gir team muligheten til å pseudonymisere, de-pseudonymisere eller re-pseudonymisere data^[Pseudonymisering defineres her som å erstatte spesifikke data med kunstige data (pseudonymer), mens de-pseudonymisering gjør det samme bare motsatt vei. Re-pseudonymisering defineres som å bytte ut et pseudonym med et annet, uten at brukeren nødvendigvis får tilgang til den opprinnelige verdien. ]. Disse tjenestene er satt opp på en slik måte at statistikkteam kan være selvbetjent i bruken av funksjonaliteten, samtidig som de sikrer at *direkte identifiserende opplysninger* håndteres i henhold til lovverk og SSBs tolkninger av disse. I dette kapitlet forteller vi hvordan man går frem for å pseudonymisere data i et statistikkteam på Dapla. Før man leser videre er det viktig at leseren har en klar forståelse av hvordan [Dapla-team og tilgangsstyring](./hva-er-dapla-team.html) fungerer på Dapla, samt er kjent med tjenesten [Kildomaten](./kildomaten.html). Kildomaten er tjenesten som automatiserer overgangen fra [kildedata](./datatilstander.html#kildedata) til [inndata](./datatilstander.html#inndata), som blant annet inkluderer pseudonymisering. ## Forberedelser -For å pseudonymisere på Dapla må man være en del av Dapla-team og [Kildomaten](./kildomaten.html) må være skrudd på for teamet. Hvis du er usikker på om Kildomaten er skrudd på kan du [sjekke dette selv i teamets IaC-repo](../faq.html#hvordan-sjekker-jeg-om-kildomaten-er-tilgjengelig-for-mitt-team). - +For å pseudonymisere på Dapla må man være en del av Dapla-team og [Kildomaten](./kildomaten.html) må være tilgjengeliggjort for teamet. Hvis du er usikker på om ditt team har tilgang til Kildomaten, så kan du [sjekke dette selv i teamets IaC-repo](../faq.html#hvordan-sjekker-jeg-om-kildomaten-er-tilgjengelig-for-mitt-team). For hjelp til å aktivere Kildomaten kan man kontakte Kundeservice. ## Hva skal pseudonymiseres? -Hvert team er ansvarlig for å selv vurdere hvordan sine [kildedata](./datatilstander.html.#kildedata) skal behandles. All kildedata i SSB er klassifisert som sensitivt, og hvis man har kildedata som skal pseudonymiseres, så skal det skje i overgangen fra kildedata til [inndata](./datatilstander.html#inndata). Er man usikker på om man skal pseudonymisere eller ikke, eller hvilke regler som gjelder for teamets kildedata, så kan man diskutere med [personvernombudet](https://ssbno.sharepoint.com/sites/Sikkerhetogpersonvern/SitePages/Personvernombud-i-SSB.aspx), eventuelt ta kontakt med juristene i SSB. +Hvert team er selv ansvarlig for at deres sensitiv data håndteres i henhold til lover og regler. I kontekst av pseudonymisering vil dette bety at teamet må finne ut av hvilken informasjon som skal pseudomymiseres i overgangen fra [kildedata](./datatilstander.html.#kildedata) til [inndata](./datatilstander.html#inndata). All kildedata i SSB er klassifisert som sensitivt, og hvis man har kildedata som skal pseudonymiseres, så skal det skje i overgangen fra kildedata til [inndata](./datatilstander.html#inndata). Er man usikker på om man skal pseudonymisere eller ikke, eller hvilke lover og regler som gjelder for teamets kildedata, så kan man diskutere med [personvernombudet](https://ssbno.sharepoint.com/sites/Sikkerhetogpersonvern/SitePages/Personvernombud-i-SSB.aspx) og/eller ta kontakt med juristene i SSB. ::: {.callout-warning} ## Ikke glem dataminimering! @@ -20,7 +19,7 @@ Et av de viktigste tiltakene for å verne om personvern i data er å fjerne info ### Personidentifiserende informasjon (PII) -Definisjon. Det følger av både personopplysningsloven og statistikkloven at personidentifiserende informasjon (PII) som samles inn for statistikkformål skal pseudonymiseres. I SSB så er det gjennomført personvernkonsekvensutredning^[Personvernkonsekvensutredningen (PVK) er det norske ordet for den engelske betegnelsen *Data Protection Impact Assessment (DPIA)*. Datatilsynet definerer en DPIA som en *systematisk prosess, som identifiserer og evaluerer potensielle personvernkonsekvenser fra alle interessenters synsvinkel i et prosjekt, initiativ, foreslått system eller prosess.* [Les mer om DPIA i SSB](https://statistics-norway.atlassian.net/wiki/spaces/ARK/pages/2889154616/Personvernkonsekvensvurdering+DPIA)] (PVK) for to områder som benytter seg av PII: +Personidentifiserende informasjon (PII) er alle opplysninger som kan knyttes til en enkeltperson. Det følger av både personopplysningsloven og statistikkloven at personidentifiserende informasjon som samles inn for statistikkformål skal pseudonymiseres. I SSB så er det gjennomført personvernkonsekvensutredninger^[Personvernkonsekvensutredningen (PVK) er det norske ordet for den engelske betegnelsen *Data Protection Impact Assessment (DPIA)*. Datatilsynet definerer en DPIA som en *systematisk prosess, som identifiserer og evaluerer potensielle personvernkonsekvenser fra alle interessenters synsvinkel i et prosjekt, initiativ, foreslått system eller prosess.* [Les mer om DPIA i SSB](https://statistics-norway.atlassian.net/wiki/spaces/ARK/pages/2889154616/Personvernkonsekvensvurdering+DPIA)] (PVK) for to områder som benytter seg av PII: 1. Personstatistikk 2. Næringsstatistikk @@ -32,23 +31,21 @@ Under går vi gjennom hvordan PII skal behandels i de to tilfellene, og hvilke k :::: {.columns} ::: {.column width="65%"} - I SSB er det også gjennomført en [Personvernkonsekvensutredningen (PVK) for personstatistikk](https://statistics-norway.atlassian.net/wiki/spaces/ARK/pages/2888237093/Personvernkonsekvensvurdering+PVK+-+Personstatistikk+p+SSBs+skyplattform) som presiserer at dette gjelder for all personstatistikk. - -Hvert team som håndterer personopplysninger må derfor vurdere sine kildedata og identifisere mulige PII. All data som innholder PII, og som ikke kan dataminimeres bort, skal pseudonymiseres. @tbl-pii-examples viser en ikke-uttømmende liste over PII som har vært identifisert i SSB tidligere. Merk at dette ikke er en fullstendig liste over PII, men hvis et team har denne informasjonen i sine data så skal de pseudonymiseres i overgangen fra kildedata til inndata. - -For mange er fødselsnummer en viktig variabel i kraft at den fungerer som en koblingsnøkkel for ulike typer persondata. Men som vist i @tbl-pii-examples så er mye annen informasjon som regnes som PII. For eksempel er også adresse og bankkontonummer å regne som PII. + I SSB er det gjennomført en [PVK for personstatistikk](https://statistics-norway.atlassian.net/wiki/spaces/ARK/pages/2888237093/Personvernkonsekvensvurdering+PVK+-+Personstatistikk+p+SSBs+skyplattform) som presiserer at all PII innen personstatistikk skal pseudonymiseres. Hvert team som håndterer personopplysninger må derfor vurdere sine kildedata og identifisere alt av PII. All data som innholder PII, og som ikke kan dataminimeres bort, skal pseudonymiseres. + + @tbl-pii-examples viser en ikke-uttømmende liste over PII som har vært identifisert i SSB tidligere. Merk at dette ikke er en fullstendig liste over PII, men hvis et team har denne informasjonen i sine data så skal de pseudonymiseres i overgangen fra kildedata til inndata. +For mange er fødselsnummer en viktig variabel i kraft at den fungerer som en koblingsnøkkel for ulike typer persondata. Men som vist i @tbl-pii-examples så er det mye annen informasjon som også er å regne som PII. For eksempel er også adresse og bankkontonummer å regne som PII. #### Enkeltpersonforetak I @tbl-pii-examples ser vi at organisasjonsnummeret til et [enkeltpersonforetak (ENK)](https://snl.no/enkeltpersonforetak) er å regne som PII. Grunnen til det er at en ENK eies av en fysisk person og all informasjon knyttet til ENK er å regne som personopplysninger. [PVK for personstatistikk](https://statistics-norway.atlassian.net/wiki/spaces/ARK/pages/2888237093/Personvernkonsekvensvurdering+PVK+-+Personstatistikk+p+SSBs+skyplattform) begrenser sine vurderinger til å ikke inkludere informasjon om ENK. -Siden personstatistikk skal pseudonymisere PII så følger det at også PII knyttet til ENK også bør pseudonymiseres. Grunnen til det er at det finnes mye åpen informasjon om ENK, og derfor kan man lett knytte pseudonym til en person basert lett tilgjengelig informasjon. Kan man knytte et pseudonym til en person så kan pseudonymet anses å være avslørt. Selv om det samme ikke gjelder for andre organisasjonsformer (AS, ansvarlig selskap, etc.) så vil det være naturlig at disse også pseudonymiseres, blant annet for å sikre ENK'er lett kan skilles ut. +Siden personstatistikk skal pseudonymisere PII så følger det at også PII knyttet til ENK også bør pseudonymiseres. Grunnen til det er at det finnes mye åpen informasjon om ENK, og derfor kan man lett knytte pseudonym til en person basert lett tilgjengelig informasjon. Kan man knytte et pseudonym til en person så kan pseudonymet anses å være avslørt. Selv om det samme ikke gjelder for andre organisasjonsformer (AS, ansvarlig selskap, etc.) så vil det være naturlig at disse også pseudonymiseres, blant annet for å sikre ENK'er ikke lett kan skilles ut. #### Næringsstatistikk -I SSB er det gjennomført en egen [PVK for næringsstatistikk](https://statistics-norway.atlassian.net/wiki/spaces/ARK/pages/3114663957/Personvernkonsekvensvurdering+for+SSBs+n+ringsstatistikk). Grunnen er at det også her behandles personopplysninger, men at behandlingen av disse krever en annen tilnærming enn for personstatistikk. Et viktig bakteppe for denne vurderingen at organisasjonsidentifiserende informasjon (OII) tidligere blitt vurdert som nødvendig å kunne se klarttekst. [Les mer OII her](./pseudonymisering.qmd#organisasjonsidentifiserende-informasjon-(oii)). - +I SSB er det gjennomført en egen [PVK for næringsstatistikk](https://statistics-norway.atlassian.net/wiki/spaces/ARK/pages/3114663957/Personvernkonsekvensvurdering+for+SSBs+n+ringsstatistikk). Grunnen til det er at det også her behandles personopplysninger, men at behovene i næringstatistikken er vurdert som såpass annerledes sammenlignet med personstatistikk, at de gjennomførte en egen PVK. Et viktig bakteppe for denne vurderingen var at organisasjonsidentifiserende informasjon (OII) tidligere hadde blitt vurdert som nødvendig å se klarttekst. [Mer om OII i neste avsnitt](./pseudonymisering.qmd#organisasjonsidentifiserende-informasjon-(oii)). ::: @@ -84,14 +81,16 @@ I SSB er det gjennomført en egen [PVK for næringsstatistikk](https://statistic :::: -I PVK for næringsstatistikk skiller man mellom behov knyttet til populasjonsforvaltning og statistikkproduksjon. Det blir vurdert som nødvendig at ansatte som jobber med populasjonsforvaltning alltid har tilgang til all informasjon i klartekst, dvs. at ingen informasjon skal pseudonymiseres. Når det gjelder personopplysninger i statistikkproduksjons så er bildet noe mer sammensatt. Følgende PII blir identifisert som tilstede i produksjon av næringsstatistikk: +Siden informasjon om ENK, en viktig del av næringstatistikken, er regnet som personopplysninger, var dette et viktig område som måtte avklares i PVK for næringsstatistikk. I tillegg kobles det andre personopplysninger, blant annet fra team som er definert under PVK for personstatistikk, som ytterligere kompliserer behandlingen av personopplysninger i statistikkproduksjon. -- Enkeltpersonforetak -- Fysiske personer som innehar roller i foretak eller bedrifter -- Fysiske personer som er kontaktpersoner for virksomheter i rapporteringer til SSB -- Personopplysninger fra administrative registre og skjemaundersøkelser om fysiske personer som har roller i foretak eller virksomheter +Konklusjonen i PVK for næringsstatistikk er et klart skille mellom personopplysninger knyttet til populasjonsforvaltning og statistikkproduksjon. Det blir vurdert som nødvendig at ansatte som jobber med populasjonsforvaltning alltid har tilgang til all informasjon i klartekst, dvs. at ingen personopplysninger skal pseudonymiseres. Når det gjelder personopplysninger i statistikkproduksjons så er bildet noe mer sammensatt. Følgende PII blir identifisert som tilstede i produksjon av næringsstatistikk: -De tre første punktene over blir vurdert som ikke nødvendig å pseudonymisere. Det siste punktet, som ofte innebærer å koble på informasjon fra personstatistikk, skal som hovedregel pseudonymiseres. I disse tilfellene skal man da som hovedregel pseudonymisere både PII og OII. Men det åpnes for at unntak kan gjøres i følgende scenarioer: +- Enkeltpersonforetak (ENK). +- Fysiske personer som innehar roller i foretak eller bedrifter. +- Fysiske personer som er kontaktpersoner for virksomheter i rapporteringer til SSB. +- Personopplysninger fra administrative registre og skjemaundersøkelser om fysiske personer som har roller i foretak eller virksomheter. + +De tre første punktene over blir vurdert som ikke nødvendig å pseudonymisere. Det siste punktet, som ofte innebærer å koble på informasjon fra team som er definert under PVK for personstatistikk, skal som hovedregel pseudonymiseres. I disse tilfellene skal man da som hovedregel pseudonymisere både PII og OII. Men det åpnes for at unntak kan gjøres i følgende scenarioer: - Dersom opplysninger om foretak/virksomhet (OII) må behandles upseudonymisert, så må både PII og OII behandles upseudonymisert^[Grunnen til dette er at hvis hvis PII er pseudonymisert og OII ikke, så vil det være lett å avsløre pseudonymet.]. - Hvis det er opplysninger om foretak/virksomhet som gjør det enkelt å identifisere enheten ut fra f.eks. geografisk tilhørighet, næringskode eller dominans innen næringen som utøves, bør både PII og OII behandles upseudonymisert. @@ -100,78 +99,251 @@ I sum betyr dette at PII i næringstatistikk kun skal pseudonymiseres der det ko ### Organisasjonsidentifiserende informasjon (OII) -I 2022 ble satt ned en gruppe som skulle evaluere hvordan SSB skulle behandle organisasjonsidentifiserende informasjon (OII) etter den nye statistikkloven fra 2019. [Gruppa leverte en rapport](https://statistics-norway.atlassian.net/wiki/spaces/ARK/pages/3268182105/Rapport+fra+arbeidsgruppe+-+behandling+av+org.nr.+etter+ny+statistikklov) med konklusjonen om at pseudonymisering av OII er uforenlig med formålet med behandlingen. Med andre ord skal OII ikke pseudonymiseres. +Organisasjonsidentifiserende informasjon (OII) er alle opplysninger som kan knyttes til en konkret virksomhet, foretak, selskap eller annen organisasjonsenhet. I SSB har det vært en lang tradisjon for at OII må kunne ses i klartekst, og at kravene er mindre strenge enn for personopplysninger. Men i statistikkloven av 2019 ble kravene til informasjonssikkerhet skjerpet, og § 9 (2) inneholder en mer generell bestemmelse om at *direkte identifiserende opplysninger skal behandles og lagres adskilt fra øvrige opplysninger*. Statisikklovutvalget presiserer også følgende om intensjonen med bak bestemmelsen: + +> Byrået behandler imidlertid også opplysninger som faller utenfor personopplysningsloven, inkludert markedssensitiv informasjon om foretak. Det bør derfor tas inn en generell bestemmelse om informasjonssikkerhet i statistikkloven, som omfatter alle opplysninger. Det kan være grunn til å behandle ulike opplysninger ulikt, og derfor bør bestemmelsen være av nokså generell karakter. + +I 2022 ble satt ned en gruppe som skulle evaluere hvordan SSB skulle behandle organisasjonsidentifiserende informasjon (OII) etter den nye statistikkloven fra 2019. [Gruppa leverte en rapport](https://statistics-norway.atlassian.net/wiki/spaces/ARK/pages/3268182105/Rapport+fra+arbeidsgruppe+-+behandling+av+org.nr.+etter+ny+statistikklov) med konklusjonen om at pseudonymisering av OII er *uforenlig med formålet med behandlingen*. + +Konklusjonen er at **OII ikke skal pseudonymiseres**. + +### Konsekvenser for organisering + +På Dapla jobber man i team som organisasjonen selv utformer. Team som definerer seg under PVK for næringsstatistikk må derfor ta hensyn til hvilke data ulike medarbeidere får tilgang til når de oppretter et team. F.eks. kan ikke de samme ansatte være med i team arbeider med PII i klartekst, samtidig som de er med i team der PII behandles i pseudonymisert form. I disse tilfellene må [managers](./hva-er-dapla-team.html#managers) (som er ansvarlig for teamet) sikre at tilgang til data ikke avslører pseudonymer eller bryter regelverket. + +### Konsekvenser for deling av data + +Siden team som definerer seg under PVK for personstatistikk pseudonymiserer både PII og OII, skaper dette hindringer for deling av data med team som definerer seg under PVK for næringstatistikk. F.eks. hvis førstnevnte deler et datasett med pseudonymer med sistnevnte, vil det være stor risiko for at pseudonymet blir avslørt. I tillegg vil det være praktisk vanskelig å koble data på tvers når koblingsnøkkelen er representert forskjellig. På nåværende tidspunkt finnes det ingen tjenester på Dapla som lar et team koble data der koblingsnøkkel er behandlet forskjellig. + +## Funksjonalitet + +Pseudonymisering skjer med python-biblioteket [dapla-toolbelt-pseudo](https://github.com/statisticsnorway/dapla-toolbelt-pseudo), og skal skje i overgangen fra [kildedata](./datatilstander.qmd#kildedata) til [inndata](./datatilstander.qmd#inndata). Brukeren kan sende inn skriptet som skal kjøres på dataene, men selve kjøringen skjer automatisk i [Kildomaten](./kildomaten.qmd). + +::: {.callout-note} +# Ikke mulig å pseudonymisere "manuelt" +Det er ikke mulig å pseudonymisere "manuelt" fra en Jupyter Notebook eller lignende med ekte data i prod-miljøet. Grunnen til det er at det ville gitt brukeren/data-admins mulighet til å printe ut både data i klartekst og pseudonymisert form, og på den måten avsløre pseudonymet. Av den grunn er det bare systembrukeren i Kildomaten som kan prosessere skarpe data. Hvis man ønsker å teste koden sin manuelt før man produksjonssetter det i Kildomaten, så kan man benytte testdata i teamets test-miljø. +::: -## Eksempel figur +### Et enkelt eksempel +I dette avsnittet viser vi et en eksempel på en typisk arbeidsflyt for et team skal pseudonymisere data. La oss anta at det finnes et team som heter **dapla-example**, som ønsker å dataminimere og pseudonymisere sine kildedata i overgangen til inndata. Kort fortalt må teamet gjøre følgende: +1. Sørg for at Kildomaten er aktivert i prod-miljøet. +2. Skriv et script som skal kjøres på alle nye filer som kommer inn på en gitt filsti i kildebøtta. +3. Automatiser scriptet som en kilde i Kildomaten. -```{mermaid} -%%| label: fig-papis -%%| fig-cap: "Pseudonymisering med Papis-nøkkel på Dapla." +Punkt 1 og 3 er nøye forklart i kapitlet oom [Kildomaten](./kildomaten.html). Derfor fokuserer vi på skriving av selve sciptet under, deriblant bruken av **dapla-toolbelt-pseudo. -stateDiagram -state Kildomaten { - direction LR - fnr --> snr - snr --> pseudonym +#### Skrive script - state dapla_toolbelt { - fnr - } +Anta at team dapla-example fortløpende får inn nye kildedatafiler^[For å holde eksempelet enkelt så kan vi anta at filene kommer i parquet-formatet] i sin kildebøtte som vist i @tbl-example-kildedata. - state sidService { - snr - } +| fødselsnummer | fornavn | etternavn | adresse | inntekt | +| ------------- | ------- | --------- | --------- | ------- | +| 11111122222 | Donald | Duck | Andeby 15 | 500000 | +: Kildedata for team dapla-example {#tbl-example-kildedata} - state pseudoService { - pseudonym - } - } +Teamet er definert under [PVK for personstatistikk](./pseudonymisering.html#personstatistikk) og ønsker dataminimere bort kolonnene `fornavn`, `etternavn` og `adresse`, mens de ønsker å pseudonymisere `fødselsnummer` og beholde `inntekt` som den er. Teamet skriver derfor følgende script: +```{.python filename="process_source_data.py"} +import dapla as dp +from dapla_pseudo import Pseudonymize + +# Filsti til en kildedatafil +source_file = "gs://ssb-dapla-example-data-kilde-prod/donald/andeby_inntekt_p2024_v1.parquet" + +# Leser inn parquet-filen til en Pandas dataframe +df = dp.read_pandas(source_file) + +# Dataminimerer ved å beholde to kolonner +df2 = df[['fødselsnummer', 'inntekt']] + +# Pseudonymiserer fødselsnummer +df3 = ( + Pseudonymize.from_pandas(df2) + .on_fields("fødselsnummer") + .with_stable_id() + .run() + .to_pandas() +) + +# Skriv inndata til produktbøtte ved å bytte ut et ord i bøttenavnet +inndata_file = source_file.replace("kilde", "produkt") +dp.write_pandas(inndata_file) ``` +I `process_source_data.py`-eksempelet over så leses det inn en konkret fil fra kildebøtta, deretter dataminimeres det ved å kun beholde de to kolonne av interesse. Så pseudonymiseres `fødselsnummer`, og til slutt skrives en parquet-fil til produktbøtta. -## Tilgangsstyring +`Pseudonymize()`-metoden følger et såkalt *builder-pattern* der vi kan spesifisere hva som skal gjøres i hvilken rekkefølge. I `from_pandas()` sier vi at dataene som skal brukes er en Pandas dataframe, i `on_fields()` spesifiseres hvilke kolonner som skal pseudonymiseres, og `with_stable_id` spesifiserer at vi ønsker å oversette fnr til stabil ID og bruke samme krypteringsalgoritme som i Papis-prosjektet^[Papis-prosjektet pseudonymiserte alle PII på bakken med et spesifikt formatbevarende krypteringsalgoritme. Dette kunne gjøres direkte på fødselsnummer eller på stabil ID, også kjent som snr-nummer. For å gjøre det lett å migrere data til Dapla så støtter også pseudonymisering på Dapla denne tilnærmingen.]. Til slutt ber vi om at alt blir kjørt med `run()` og output skal være en Pandas dataframe med `to_pandas()`. -Når et team har fått tilgang til *Dapla Pseudo Service*, så må de fortsatt forholde seg til tilgangsstyring på 2 nivåer: +Resultatet blir en dataframe som vist i @tbl-pseudo-inndata. -1. **Miljøet** -I prod-miljøet til teamet kan man bare pseudonymisere data via automatiske prosesseringer i Kildomaten. Dvs. at man IKKE kan sitte i Jupyter og interaktivt pseudonymisere sensitiv informasjon. Ønsker man å gjøre dette fra Jupyter må man gjøre det med testdata i teamets test-miljø. -2. **Teamet** -Siden personopplysninger kun skal forekomme i [kildedata](./datatilstander.html#kildedata), og det kun er de med tilgangsrollen [data-admins](./hva-er-dapla-team.html#data-admins) som kan godkjenne den automatiske prosesseringen som skjer fra kildedata til inndata. -3. **data-admins** -data-admins er de eneste på teamet som kan gi seg selv tilgang til å manuelt inspisere kildedata. Disse tilgangene er kortvarige og aktiveres med en begrunnelse i [JIT-applikasjonen](./jit.qmd). +| fødselsnummer | inntekt | +| ------------- | ------- | +| 1a45x88 | 500000 | +: Dataminimert og pseudonymisert inndata fra @tbl-example-kildedata {#tbl-pseudo-inndata} -På grunn av den strenge tilgangen til kildedata og pseudonymisering så er det anbefalt at man utvikler skriptet som pseudonymiserer i test-miljøet til teamet. Under forklarer vi hvordan dette gjøres. Les mer her. +Siden `with_stable_id()` bytter ut fødselsnummer med stabil ID før den pseudonymiseres med en formatbevarende algoritme, og stabil ID alltid er syv karakterer lang, så får vi tilbake et pseudonym som er syv karakterer lang. Legg også merke til at pseudonymiseringen aldri endrer navn på kolonner eller datatyper. -## Filformater +For å teste denne koden på noe data fra et verktøy som Jupyterlab, så må vi gjøre det i test-miljøet til teamet. Til det trenger vi noe testdata. I tilfellet med stabil ID, så må man da generere testdata med fødselsnummer som finnes i test-versjonen av stabilID-katalogen (mer informasjon rundt dette kommer snart). -Kommer snart. +Før vi kan sende inn dette scriptet for automatisk prosessering i Kildomaten, så må vi tilpasse koden litt. Helt konkret må vi gjøre følgende: -## Papis-pseudonym +1. Pakke koden inn i en `main()`-funksjon +2. Kvitte oss med hardkoding av stier i koden. -Kommer snart. +I eksempelet over kan gjøre følgende for å tilpasse koden til Kildomaten: +```{.python filename="process_source_data.py"} +def main(source_file): + import dapla as dp + from dapla_pseudo import Pseudonymize -Hvilken type informasjon som skal pseudonymiseres kan også påvirke hvordan vi pseudonymiserer. Siden fødselsnummer er mye brukt som koblingsnøkkel på tvers av team, så er man mer avhengig av at alle bruker samme pseudonym. Kravet til krypteringsalgoritmen trenger heller ikke være like strengt for et fødselsnummer bestående av 11 siffer. Til sammenligning vil informasjon som navn, som f.eks. kan inkludere mellomrom og særnorske bokstaver, kreve en algoritme som håndterer slike tilfeller. Vi diskuterer ulike algoritmer senere i kapitlet. + # Leser inn parquet-filen til en Pandas dataframe + df = dp.read_pandas(source_file) + # Dataminimerer ved å beholde to kolonner + df2 = df[['fødselsnummer', 'inntekt']] + # Pseudonymiserer fødselsnummer + df3 = ( + Pseudonymize.from_pandas(df2) + .on_fields("fødselsnummer") + .with_stable_id() + .run() + .to_pandas() + ) + # Skriv inndata til produktbøtte ved å bytte ut et ord i bøttenavnet + inndata_file = source_file.replace("kilde", "produkt") + dp.write_pandas(inndata_file) +``` -## Anbefalt arbeidsflyt +Siden Kildomaten trigges hver gang en ny fil dukker opp, så får `main()`-funksjonen filstien injisert hver gang en fil prosesseres. Du trenger derfor ikke å definere denne selv, og derfor er denne delen av koden slettet. Og med de tilpassingene kan koden produksjonssettes i IaC-repoet til dapla-example, slik som [vist her](./kildomaten.html#rull-ut-tjenesten). -Når man skal sette opp et Python-skript som automatisere overgangen fra kildedata til inndata, inkludert pseudonymisering, så er det anbefalt å utvikle koden i test-miljøet til teamet. Der kan hele teamet ha tilgang til både data, pseudonymisering og Kildomaten. Skriptet som genereres her kan enkelt overføres til prodmiljøet senere. +### Installering -### Testdata +[dapla-toolbelt-pseudo](https://pypi.org/project/dapla-toolbelt-pseudo/) er ferdig installert i Kildomaten. Men ønsker du å bruke det i test-miljøet til teamet så kan du installere det i et `ssb-project` fra [PyPI](https://pypi.org/) med denne kommandoen: -Kommer snart. +```{.bash filename="Terminal"} +poetry add dapla-toolbelt-pseudo +``` +### Pseudonymisering +Pseudonymisering tilbys via `Pseudonymize`-metoden i **dapla-toolbelt-pseudo**. Den følger et *builder-pattern* der man spesifiserer hva og i hvilken rekkefølge operasjonene skal gjøres. Anta at det finnes i en dataframe i minnet som heter `df` hvor kolonnen `fnr` skal pseudonymiseres. Da vil koden se slik ut: +```{.python} +from dapla_pseudo import Pseudonymize + +result_df = ( + Pseudonymize.from_polars(df) + .on_fields("fnr") + .with_default_encryption() + .run() + .to_polars() +) +``` +I koden over så angir `from_polars(df)` at kolonnen vi ønsker å pseudonymisere ligger i en [Polars](https://docs.pola.rs/) dataframe i minnet og heter `df`. Deretter spesifiserer vi at kolonnen `fnr` er den som skal behandles med funksjonen `on_fields("fnr")`. Videre angir `with_default_encryption()` at `fnr` skal pseudonymiseres med dapla-toolbelt-speudo sin standard-algoritme^[Standardalgoritmen i *dapla-toolbelt-pseudo* er den deterministiske krypteringsalgoritmen *Deterministic Authenticated Encryption with Associated Data*, eller DAEAD-algoritmen.]. Til slutt ber vi om at det ovennevnte blir kjørt med funksjonen `run()`, og at dataene skal returneres som en Polars dataframe med funksjonen `to_polars()`. + +Se flere [eksempler i dokumentasjonen](https://statisticsnorway.github.io/dapla-toolbelt-pseudo/index.html#pseudonymize). + +### De-pseudonymisering + +Pseudonymisering tilbys via `Depseudonymize`-metoden i **dapla-toolbelt-pseudo**. Den følger et *builder-pattern* der man spesifiserer hva og i hvilken rekkefølge operasjonene skal gjøres. Anta at det finnes i en Polars dataframe i minnet som heter `df` hvor kolonnen `fnr` skal de-pseudonymiseres. Da vil koden se slik ut: + +```{.python} +result_df = ( + Depseudonymize.from_polars(df) + .on_fields("fnr") + .with_default_encryption() + .run() + .to_polars() +) +``` +Oppbygningen av koden med `Depseudonymize()` er helt lik som for `Pseudonomize()`. Les beskrivelsen der for å se hva de ulike funksjonskallene gjør. +`Depseudonymize()` fungerer ikke for data som er pseudponymisert med `with_stable_id()` enda. Kommer snart. +Se flere [eksempler i dokumentasjonen](https://github.com/statisticsnorway/dapla-toolbelt-pseudo#depseudonymize). +### Re-pseudonymisering + +Ikke tilgjengelig enda. + +### Stabil ID + +I statistikkproduksjon og forskning er det viktig å kunne følge de samme personene over tid. Derfor har fødselsnummer ofte blitt oversatt til en mer stabilt identifikator, ofte kalt SNR eller stabil ID^[SNR-katalogen eies og tilbys av Team Register på Dapla.]. Funksjonene `with_stable_id()` og `validator()` bruker stabilID-katalogen til å henholdsvis bytte ut fødselsnummer med stabil ID, og for å validere om fødselsnummer er gyldige(se under). + +Du kan selv spesifisere hvilken versjon av SNR-katalogen du ønsker å bruke. Det gjør du ved å oppgi en gyldighetsdato og så finner dapla-toolbelt-pseudo hvilken versjon av katalogen som ligger nærmest i tid. + +### Validere fødselsnummer + +`Validator`-metoden kan benyttes til å sjekke om fødselsnummer finnes i SNR-katalogen (se over). Her kan man også spesifisere hvilken versjon av SNR-katalogen man ønsker å bruke. Standard, hvis ingenting velges, er at siste tilgjengelige versjon velges. Under er et eksempel på hvordan man validerer fødselsnummer for en gitt gyldighetsdato: + +```{.python} +from dapla_pseudo import Validator +from dapla_pseudo.utils import convert_to_date + +result = ( + Validator.from_polars(df) + .on_field("fnr") + .validate_map_to_stable_id( + sid_snapshot_date=convert_to_date("2023-08-29") + ) +) +# Vis hvilken versjon av SNR-katalogen som er benyttet +result.metadata +# Vis fødselsnummer som ikke fikk treff i SNR-katalogen som en Polars dataframe +result.to_polars() +``` + +### Dataformater + +**dapla-toolbelt-pseudo** støtter følgende dataformater: + +- csv (filformat) +- json (filformat) +- Polars dataframe (minnet) +- Pandas dataframe (minnet) + +Over har vi vist hvordan vi leser data fra minnet, men det støttes også å lese direkte fra filformatene csv og json. Under er et eksempel med en csv-fil: + +```{.python} +from dapla_pseudo import Pseudonymize +from dapla import AuthClient + + +file_path="data/personer.csv" + +options = { + "dtypes": {"fnr": pl.Utf8, "fornavn": pl.Utf8, "etternavn": pl.Utf8, "kjonn": pl.Categorical, "fodselsdato": pl.Utf8} +} + +result_df = ( + Pseudonymize.from_file(file_path) + .on_fields("fnr") + .with_default_encryption() + .run() + .to_polars(**options) +) +``` + +Se flere [eksempler i dokumentasjonen](https://github.com/statisticsnorway/dapla-toolbelt-pseudo#read-from-file-systems). + + +### Algoritmer + +**dapla-toolbelt-pseudo** støtter mange forskjellige krypteringsalgoritmer. Les mer i [dokumentasjonen](https://github.com/statisticsnorway/dapla-toolbelt-pseudo#pseudonymize-using-custom-keyskeysets). + +### Metadata + +Kommer snart. + +## Ytelse + +Kommer snart. +