Data og sporbarhed
Revisionslog: se hvem der ændrede hvad i appen
Når flere bruger appen, er den aktuelle databaseværdi ikke altid nok. En sag står måske som godkendt, en pris er ændret, eller en kunde er slettet – men hvem gjorde det, hvornår og gennem hvilken funktion? Et revisionsspor gemmer de vigtige forretningshændelser, så support, ledelse og sikkerhedsansvarlige kan undersøge dem uden at gætte ud fra løse beskeder eller almindelige fejllogs.
Driftslog og revisionslog løser forskellige spørgsmål
Driftslogs hjælper med fejl, svartider og tekniske hændelser. Et revisionsspor forklarer en forretningsændring i en rækkefølge, der kan føres tilbage til en aktør. OWASP anbefaler at holde audit- og transaktionsspor adskilt fra almindelig sikkerhedslogning, når formål og data er forskellige.
| Spor | Typisk spørgsmål | Eksempel |
|---|---|---|
| Driftslog | Hvorfor fejlede requesten? | Timeout mod fakturaservice |
| Sikkerhedslog | Blev en adgang afvist eller misbrugt? | Gentagne forsøg på at ændre en anden kundes sag |
| Revisionslog | Hvem ændrede den konkrete forretningspost? | Status ændret fra kladde til godkendt af bruger 7f2 |
| Versionshistorik | Kan hele indholdet sammenlignes eller genskabes? | Tidligere version af en kontraktskabelon |
Et revisionsspor er ikke automatisk en komplet backup, dokumentversionering eller et juridisk bevis. Dets troværdighed afhænger af identitet, datakvalitet, adgang og beskyttelse mod efterfølgende ændringer.
Vælg hændelser efter konsekvens – ikke efter hvert klik
Begynd med de handlinger, hvor en senere forklaring har reel værdi. Log ikke hvert museklik eller hvert automatisk felt. Beskriv i stedet de forretningshændelser, der påvirker penge, adgang, persondata, ejerskab eller en vigtig status.
- Oprettelse, ændring og sletning: Kunder, sager, ordrer, priser, dokumentmetadata og andre centrale poster.
- Godkendelser og status: Hvem godkendte, afviste, genåbnede eller afsluttede et forløb.
- Adgang og roller: Tildeling af administratorrettigheder, skift af tenant eller adgang til særligt følsomme funktioner.
- Eksport og massehandlinger: Udtræk af data, masseændringer, imports og sletning af mange poster.
- Systemhandlinger: Job, webhook eller integration, der ændrer data uden et menneskeligt klik.
- Relevant læsning: Adgang til fortrolige eller følsomme personoplysninger, når risikovurderingen viser et behov.
Gem aktør, handling, objekt, resultat og tid
Appen har den bedste kontekst om brugeren, rollen og den berørte post. Hver hændelse bør derfor kunne svare på hvem, hvad, hvor og hvornår – plus om handlingen lykkedes. Brug stabile interne id'er, så et ændret navn eller en ændret mailadresse ikke bryder sammenhængen.
{
"eventId": "evt_01...",
"occurredAt": "server-generated timestamp",
"actor": { "type": "user", "id": "usr_7f2" },
"tenantId": "org_42",
"action": "case.status.changed",
"object": { "type": "case", "id": "case_918" },
"result": "success",
"changes": {
"status": { "from": "draft", "to": "approved" }
},
"requestId": "req_b31",
"source": "web"
}- Aktør: Skeln mellem bruger, administrator, servicekonto og automatisk job. Gem også hvem en administrator handlede på vegne af, hvis appen har supportadgang.
- Objekt og tenant: Angiv posttype, stabilt id og virksomhed eller kunde, så søgning og adgang kan afgrænses korrekt.
- Handling og resultat: Brug aftalte eventnavne og registrér succes, afvisning eller fejl uden at lade en mislykket handling ligne en udført ændring.
- Tid: Brug et servergenereret tidspunkt. Klientens ur og payload må ikke bestemme det autoritative tidspunkt.
- Sammenhæng: Et request-id eller job-id kan forbinde revisionshændelsen med tekniske logs uden at kopiere hele requesten.
Registrér ændringen på den betroede side
Browseren må gerne vise en aktivitetshistorik, men den må ikke være den eneste, der skriver den. En bruger kan springe brugerfladen over, ændre requesten eller lukke fanen. Opret revisionshændelsen i backend, databasefunktion, trigger eller anden kontrolleret grænse, hvor identitet, rettighed og resultat allerede er verificeret.
SQL og transaktioner
Skriv forretningsændring og revisionspost i samme transaktion, når de skal lykkes eller fejle samlet. En databasetrigger kan dække ændringer fra flere adgangsveje, men den skal stadig modtage en troværdig aktørkontekst.
Dokumentdatabase og events
Brug platformens transaktion eller en server-side eventmekanisme efter den konkrete stack. Hvis revisionssporet oprettes asynkront, skal tabte events, dubletter, retries og alarmer være en bevidst del af designet.
Aftal også, hvad der sker, hvis revisionslageret er nede. En risikofyldt godkendelse eller rettighedsændring kan kræve, at hele handlingen afvises. En mindre kritisk ændring kan eventuelt køes og forsøges igen. Valget skal være dokumenteret, testet og synligt i overvågningen – ikke opstå tilfældigt under et nedbrud.
Gør sporet append-only og begræns adgangen
En bruger, der kan ændre en forretningspost, bør ikke samtidig kunne omskrive dens historik. Lad den normale appidentitet tilføje hændelser uden almindelig adgang til at opdatere eller slette dem. Begræns læsning efter rolle, tenant og formål, og registrér administrativ adgang til selve revisionssporet.
- Brug en separat tabel, collection eller logtjeneste med egne adgangsregler.
- Overvej en beskyttet kopi uden for appens normale datalager, hvis en kompromitteret administrator ellers kan ændre både data og historik.
- Brug backup, eksport eller platformens uforanderlige lagring efter den konkrete risiko og stack.
- Overvåg usædvanlige læsninger, masseeksport, ændrede logindstillinger og ophør af forventede hændelser.
- Beskriv beskyttelsen som manipulationsmodstand eller mulighed for at opdage manipulation – ikke som en garanti, medmindre løsningen faktisk kan bevise det.
Gem forskellen uden at kopiere hele posten
Før- og efterværdier kan være nyttige, men en ukritisk kopi af hele objektet gør revisionsloggen til endnu en database med persondata, dokumentindhold og secrets. Vælg en tilladt liste over de felter, som forklarer hændelsen, og maskér eller udelad resten.
- Gem normalt ikke: Adgangskoder, tokens, sessions, API-nøgler, connection strings, hele dokumenter eller komplette request bodies.
- Minimér identitet: Brug internt bruger-id og visningsnavn via kontrolleret opslag, hvis navnet ikke behøver ligge i hver hændelse.
- Fastlæg opbevaring: Vælg periode efter formål, risikovurdering og relevante krav. “For evigt” er ikke en neutral standard.
- Planlæg sletning: Beslut hvordan udløb, sikkerhedshændelser, backupkopier og eventuelle juridiske bevaringsbehov håndteres.
- Oplys brugerne: Hvis medarbejderes brug af personoplysninger overvåges, skal formål, praksis og relevante regler være afklaret.
Datatilsynet fremhæver, at behov, opbevaring og kontrol skal bero på den konkrete risiko, og at logs skal beskyttes med hensyn til fortrolighed, integritet og tilgængelighed. Guiden her er en teknisk arbejdsramme, ikke juridisk rådgivning.
Gør historikken brugbar uden at åbne hele loggen
En aktivitetsvisning ved den konkrete sag kan være mere nyttig end adgang til en global logdatabase. Vis kun de hændelser og felter, brugerens rolle må se, og giv support mulighed for at filtrere på tid, aktør, handling, objekt og request-id.
- Vis et forståeligt handlingsnavn, tidspunkt, aktør og den relevante ændring.
- Skeln tydeligt mellem brugerhandling, supporthandling, import, webhook og planlagt job.
- Lad rettelser oprette en ny modgående hændelse; omskriv ikke den oprindelige historie.
- Giv ikke en kunde adgang til andre kunders hændelser, interne sikkerhedsdetaljer eller følsomme førværdier.
- Dokumentér hvordan support læser sporet, og lad en anden person rekonstruere et kendt scenarie som blindtest.
Typiske fejl
- Aktivitetshistorikken skrives kun i frontend: Direkte API-kald og automatiske jobs efterlader intet troværdigt spor.
- Kun brugerens navn gemmes: Navnet ændres eller deles, og hændelsen kan ikke bindes til en stabil identitet.
- Systemet bruger fælleskonto: Alle handlinger ser ud til at komme fra samme person, så individuel sporbarhed forsvinder.
- Hele posten kopieres hver gang: Loggen vokser til en ubeskyttet parallel database med unødige persondata.
- Audit-tabellen kan redigeres fra adminpanelet: Den samme adgang kan ændre både hændelsen og dens forklaring.
- Kun vellykkede ændringer registreres: Afviste adgangsforsøg og fejlede massehandlinger kan ikke undersøges.
- Alle platformlogs kaldes revisionsspor: De mangler objekt, forretningshandling eller aktørkontekst og kan ikke forklare sagen.
- Ingen kontrollerer, at logningen stadig virker: En ny API-rute, import eller integration omgår hændelseskataloget.
Test at en anden kan rekonstruere hændelsen
Opret kendte ændringer i et isoleret miljø, og kontrollér både forretningsdata og revisionsspor. Test alle adgangsveje til samme handling – brugerflade, API, import, webhook, administratorværktøj og planlagt job, hvis de findes.
- Opret, ændr, godkend, slet og gendan en post med forskellige roller og tenants.
- Forsøg en forbudt handling, og kontrollér at resultatet vises korrekt uden at skabe en falsk dataændring.
- Kør samme webhook eller job igen, og kontrollér om sporet viser retry og dublet uden at fordoble forretningshandlingen.
- Simulér fejl i revisionslageret, og bevis den aftalte adfærd for kritiske og mindre kritiske handlinger.
- Forsøg at opdatere og slette en revisionspost med appens normale identitet.
- Kontrollér at tokens, secrets, følsomt indhold og andre kunders data ikke vises i event, eksport eller brugerflade.
- Giv hændelserne til en person, der ikke udførte dem, og se om personen kan forklare rækkefølgen korrekt.
Tjekliste før flere får adgang til appen
- ☐ Kritiske forretningshændelser er valgt efter risiko og samlet i et hændelseskatalog.
- ☐ Hver hændelse har stabilt id, servertid, aktørtype og -id, tenant, handling, objekt, resultat og sammenhæng.
- ☐ Bruger, administrator, servicekonto, webhook og job kan skelnes fra hinanden.
- ☐ Revisionshændelsen oprettes på den betroede side og dækker alle adgangsveje til ændringen.
- ☐ Kritiske dataændringer og revisionsposter lykkes samlet eller følger en dokumenteret fejlpolitik.
- ☐ Den normale appidentitet kan tilføje, men ikke frit ændre eller slette historikken.
- ☐ Læseadgang er afgrænset efter rolle, tenant og konkret arbejdsbehov.
- ☐ Før- og efterværdier bruger en tilladt liste uden secrets eller unødige persondata.
- ☐ Opbevaring, sletning, backup, eksport og adgang til loggen har en ansvarlig og et formål.
- ☐ Alarmer opdager manglende events, ændrede logindstillinger og mistænkelig adgang eller eksport.
- ☐ Tests beviser sporbarhed, isolation, manipulationsmodstand og forståelig rekonstruktion.
Relaterede guides
Officielle kilder
Den konkrete implementering afhænger af appens database, backend og krav. Principperne er kontrolleret mod aktuelle officielle sikkerheds- og databeskyttelseskilder. Følg også den valgte platforms dokumentation, og test løsningen i den faktiske stack.