News
DBA-Tipp: „Data Masking“ light für alle Editionen - Anonymisierung von Daten beim DataPump-Export

Die Information ist ein schnelllebiges Gut. Jeden Tag werden wir mit hunderten Informationen zugemüllt. Deshalb sind wir bestrebt uns auf das Wesentliche zu konzentrieren und nur substantiell nachhaltige Informationen bereitzustellen.

Icon Unternehmen

Logische Datenbanksicherungen mittels Oracle DataPump werden gern verwendet, um produktive Daten für interne Testzwecke oder Fehleranalysen durch externe Dienstleister oder Anwendungshersteller zu extrahieren. Viel zu oft kommt dabei leider der Datenschutz zu kurz, wenn schutzwürdige Daten Bestandteil der DataPump-Exporte sind und dann ohne Zustimmung der Betroffenen und damit für nicht autorisierte Zwecke verwendet werden.

Diesem Problem begegnet Oracle sehr detailliert mit der „Data Masking and Subsetting“-Option. Neben den dafür zu entrichtenden Lizenzgebühren ist ein weiterer wesentlicher Nachteil, dass diese (wie alle anderen Options auch) nur für die Enterprise Edition der Datenbank verfügbar ist.

Das Data Masking kann aber mit etwas Programmieraufwand auch in allen anderen Datenbankeditionen, zumindest in Bezug auf Datenaustausch mittels DataPump, nachgebildet werden – unter Zuhilfenahme der remap_data-Klausel.

Implementierung

Das  remap_data-API ist sehr simpel gehalten. Für jede Spalte, deren Inhalt beim Export verändert werden soll, muss es eine korrespondierende Funktion geben, die die entsprechenden Änderungsregeln implementiert. Folgende Bedingungen müssen dabei erfüllt sein:

  • Alle remap-Funktionen müssen Bestandteil von Packages sein. Standalone functions sind nicht zulässig.
  • Die Funktion hat genau ein Argument und (natürlich) genau einen Rückgabewert. Beide müssen typkompatibel zum Typ der zu verändernden Tabellenspalte sein.
  • Funktionen dürfen keine commits/rollbacks außerhalb autonomer Transaktionen durchführen.
  • Je Tabelle können maximal 10 Spalten mit Ersetzungsfunktionen verändert werden.

Beispiel

Anhand des folgenden Beispiels soll die Umsetzung eines „Data Masking“ beim DataPump-Export gezeigt werden.

Wir exportieren das aus den Datenbank-Samples bekannte HR-Schema. Im Zuge des Exports sollen dabei sensible Mitarbeiterdaten in der EMPLOYEES-Tabelle wie folgt anonymisiert werden, um einem Missbrauch in den Zielsystemen vorzubeugen:

  • In der Telefonnummer wird die Durchwahl verborgen, indem sie durch „***“ ersetzt wird.
  • Das Einstellungsdatum (NOT NULL) wird durch einen festen Wert ersetzt.
  • Das Gehalt wird durch geNULLt.

Die drei genannten Regeln setzen wir in einem Package um, dass wir der Einfachheit halber ebenfalls im HR-Schema ablegen. Grundsätzlich kann es natürlich auch in einem anderen, im Produktivfall vielleicht nur für diesen Zweck angelegten Schema, untergebracht werden. Wichtig ist lediglich, dass der später exportierende Benutzer execute-Privileg auf dem Package bzw. den Packages besitzt.

Die Packagedefinition enthält drei Funktionsdefinitionen, eine für jede der drei oben benannten Ersetzungsregeln. Der Übersichtlichkeit halber gleichen die Funktionsnamen den Spaltennamen. Tatsächlich wäre die Benennung aber natürlich frei.

CREATE OR REPLACE PACKAGE ANONYMIZE
AS
  FUNCTION phone_number(
      phone_number employees.phone_number%type)
    RETURN employees.phone_number%type;

  FUNCTION hire_date(
      hire_date employees.hire_date%type)
    RETURN employees.hire_date%type;

  FUNCTION salary(
      salary employees.salary%type)
    RETURN employees.salary%type;
END ANONYMIZE;

Im Package Body wird die entsprechende Business-Logik für die Ersetzungsregeln implementiert:

CREATE OR REPLACE PACKAGE BODY ANONYMIZE
AS
  FUNCTION phone_number(
      phone_number employees.phone_number%type)
    RETURN employees.phone_number%type
  IS
  BEGIN
    -- ersetze die Durchwahl durch "***"
    RETURN SUBSTR(phone_number,1,instr(phone_number,'.',-1))||'***';
  END phone_number;
 
  FUNCTION hire_date(
      hire_date employees.hire_date%type)
    RETURN employees.hire_date%type
  IS
  BEGIN
    -- ersetze das Einstellungsdatum durch einen festen Wert
    RETURN to_date('0001-01-01','YYYY-MM-DD');
  END hire_date;
 
  FUNCTION salary(
      salary employees.salary%type)
    RETURN employees.salary%type
  IS
  BEGIN
    -- ersetze das Gehalt durch NULL
    RETURN NULL;
  END salary;
END ANONYMIZE;

Nun können wir im Zuge des Exportes die gewünschten Ersetzungen on-the-fly vornehmen lassen. Für jede zu verändernde Spalte geben wir dabei die korrespondierende Funktion im Package hr.anonymize an:

expdp \
    schemas=hr \
    dumpfile=hr_anon.dmp \
    reuse_dumpfiles=yes \     remap_data=hr.employees.phone_number:hr.anonymize.phone_number \     remap_data=hr.employees.hire_date:hr.anonymize.hire_date \     remap_data=hr.employees.salary:hr.anonymize.salary

Nun kann das Dumpfile beliebig importiert werden. Schutzwürdige Daten sind aus diesem logischen Backup für die EMPLOYEES-Tabelle nicht wiederherstellbar. Importieren wir also das Backup in ein anderes Schema und schauen uns das Ergebnis an:

impdp \
    dumpfile=hr_anon.dmp \
    remap_schema=hr:hr_anon

Die sensiblen Daten, die im HR-Schema an den Mitarbeitern hinterlegt sind...

Sensible Daten im HR-Schema

… sind nach dem Import im Zielschema nicht mehr sichtbar. Sie wurden entsprechend der oben definierten Regeln ersetzt.

Anonymisierte Daten im HR-Schema

Fazit
Wenngleich sich das remap_data des DataPump nicht wirklich mit der „Data Masking and Subsetting“ der Enterprise Edition messen kann, so ist es doch zumindest eine interessante Möglichkeit, vielleicht auch in der Standard Edition etwas mehr für den Datenschutz im Unternehmen zu tun.

Auf Basis der remap_data-API können sowohl einfache Regeln (wie hier im DBA-Tipp) als auch nahezu beliebig komplexe Regelwerke umgesetzt werden, da es über das Package-Konzept auf PL/SQL aufbaut.

Der Vollständigkeit halber soll zum Schluss noch erwähnt sein, dass remap_data auch für den Import zur Verfügung steht. Für den hier beschrieben Anwendungszweck ist das aber natürlich kein geeigneter Weg.