Ein weiterer wichtiger Punkt ist die Eingabekontrolle. Dieser untergliedert sich in mehrere Teilaufgaben. Zum einen sollten wir festhalten, woher die Daten kommen und wer diese eingegeben hat. Bei der Eingabe ist darauf zu achten, nicht zu viele Daten zu fordern (Privacy By Default)!
Zum anderen sollten aber auch Änderungen und Löschungen protokolliert werden.
Erweitern wir also unser Beispiel vom letzten Beitrag.
Felder in einer Tabelle können mit Regeln (Constraints) validiert werden. Diese Constraints geben Minimal-/Maximal- und Default-Werte vor und bestimmen, ob das Feld NULL beinhalten darf oder nicht (undefinierter Zustand erlaubt). Hier kommen wir bei DBF-basierten Tabellen an die Grenze: NULL gibt es bei DBF nicht und daher kann auch kein entsprechender Constraint gesetzt werden. Als heißt es nun, die Datenbank so umzustellen, dass ADT als Default verwendet wird. Dies geschieht durch einen Rechtsklick auf die Datenbank im Connection Repository | Connection Properties. Ein Umstellen der Eigenschaft TableType auf ADT und ein erneutes Verbinden reicht dazu. Für die Applikationen müsste entsprechendes in den Verbindungseigenschaften bzw. dem Connection String erfolgen.
Eine vorhandene DBF in eine ADT umzuwandeln kann mithilfe folgender SQL-Befehle durchgeführt werden:

-- Umbenennen der Tabelle
EXECUTE PROCEDURE sp_RenameDDObject('Kunde', 'Kunde_DBF', 1, 0);
-- ADT-Kopie der Tabelle erstellen 
SELECT * INTO Kunde FROM Kunde_DBF;
-- Neu erstellte Tabelle in die Datenbank aufnehmen
EXECUTE PROCEDURE sp_AddTableToDatabase('Kunde', 'Kunde.adt', 3, 1, '', '');
-- Bisherige Tabelle (DBF) löschen
DROP TABLE Kunde_DBF;

Allerdings verlieren wir dadurch auch die Berechtigungen auf die Tabelle, wir müssen sie also neu setzen.

GRANT SELECT, INSERT, UPDATE, DELETE ON Kunde TO Vertrieb;

Die „Pflichtfelder“ sollten gemäß dem Grundsatz Privacy by Default auf ein Minimum begrenzt werden. Dies legt man über ein Verändern der Feldeigenschaft fest, was beim ADS auch im laufenden Betrieb möglich ist.

ALTER ONLINE TABLE Kunde ALTER COLUMN ID ID Integer CONSTRAINT NOT NULL;
ALTER ONLINE TABLE Kunde ALTER COLUMN KNR KNR Char(10) CONSTRAINT NOT NULL;
ALTER ONLINE TABLE Kunde ALTER COLUMN NAME NAME Char(30) CONSTRAINT NOT NULL;
ALTER ONLINE TABLE Kunde ALTER COLUMN VORNAME VORNAME Char(30) CONSTRAINT NOT NULL;

Die Herkunft eines Datensatzes bei personenbezogenen Daten sollte als Pflichtfeld in der Tabelle hinterlegt sein. Der Anwender ist dafür verantwortlich, dieses mit validen Daten zu befüllen. Im gleichen Zug können wir die ID von einem Eingabe- auf einen automatisch vergebenen Datentyp ändern sowie das neue Feld mit einem validen Wert versehen.

ALTER TABLE Kunde 
  ADD COLUMN HERKUNFT Memo CONSTRAINT NOT NULL
  ALTER COLUMN ID ID AutoInc CONSTRAINT NOT NULL;
UPDATE Kunde SET HERKUNFT = 'Altdaten Import am 24.07.2018';

Im nächsten Schritt erstellen wir ein Log der Datensätze. Auf dieses Log sollten nur administrative Benutzer Zugriff haben!

CREATE TABLE Log_Kunde(ID AutoInc, Kunde_ID LongInt, Zeit TimeStamp, Benutzer CIChar(30), OP CIChar(1), Bemerkung MEMO);

Befüllt wird die Tabelle über Trigger. Zuerst für das Anlegen eines Datensatzes:

CREATE TRIGGER trig_ins ON Kunde AFTER INSERT
BEGIN
  DECLARE @Bem String;
  @Bem =        'KNR = '+COALESCE(TRIM(__new.Knr),'')+'; ';
  @Bem = @Bem+  'Name = '+COALESCE(TRIM(__new.Name),'')+'; ';
  @Bem = @Bem+  'VorName = '+COALESCE(TRIM(__new.VorName),'')+'; ';
  @Bem = @Bem+  'Strasse = '+COALESCE(TRIM(__new.Strasse),'')+'; ';
  @Bem = @Bem+  'PLZ = '+COALESCE(TRIM(__new.PLZ),'')+'; ';
  @Bem = @Bem+  'Ort = '+COALESCE(TRIM(__new.Ort),'')+'; ';
  @Bem = @Bem+  'Telefon = '+COALESCE(TRIM(__new.Telefon),'')+'; ';
  @Bem = @Bem+  'Geburtstag = '+COALESCE(TRIM(CAST(__new.Geburtstag AS SQL_Char)),'')+'; ';
  @Bem = @Bem+  'Religion = '+COALESCE(TRIM(__new.Religion),'')+'; ';
  INSERT INTO Log_Kunde(Kunde_ID, Zeit, Benutzer, OP, Bemerkung)
    VALUES (__new.id, now(), user(), 'i', @Bem);
END;

Beim Ändern eines Datensatzes überprüfen wir, ob sich Daten geändert haben und schreiben nur dann in die Log-Tabelle, falls dies der Fall ist. In diesem Fall werden die neuen Daten gespeichert.

CREATE TRIGGER trig_upd ON Kunde AFTER UPDATE
BEGIN
  DECLARE @Bem String;
  @Bem='';
  IF __new.Knr<>__old.Knr THEN
    @Bem = @Bem+'KNR = '+COALESCE(TRIM(__new.Knr),'')+'; ';
  END;
  IF __new.Name<>__old.Name THEN
    @Bem = @Bem+  'Name = '+COALESCE(TRIM(__new.Name),'')+'; ';
  END;
  IF __new.VorName<>__old.VorName THEN
    @Bem = @Bem+  'VorName = '+COALESCE(TRIM(__new.VorName),'')+'; ';
  END;
  IF __new.Strasse<>__old.Strasse THEN
    @Bem = @Bem+  'Strasse = '+COALESCE(TRIM(__new.Strasse),'')+'; ';
  END;
  IF __new.PLZ<>__old.PLZ THEN
    @Bem = @Bem+  'PLZ = '+COALESCE(TRIM(__new.PLZ),'')+'; ';
  END;
  IF __new.Ort<>__old.Ort THEN
    @Bem = @Bem+  'Ort = '+COALESCE(TRIM(__new.Ort),'')+'; ';
  END;
  IF __new.Telefon<>__old.Telefon THEN
    @Bem = @Bem+  'Telefon = '+COALESCE(TRIM(__new.Telefon),'')+'; ';
  END;
  IF __new.Geburtstag<>__old.Geburtstag THEN
    @Bem = @Bem+  'Geburtstag = '+COALESCE(TRIM(CAST(__new.Geburtstag AS SQL_Char)),'')+'; ';
  END;
  IF __new.Religion<>__old.Religion THEN
    @Bem = @Bem+  'Religion = '+COALESCE(TRIM(__new.Religion),'')+'; ';
  END;
  IF LENGTH(@Bem)>0 THEN
    INSERT INTO Log_Kunde(Kunde_ID, Zeit, Benutzer, OP, Bemerkung)
      VALUES (__new.id, now(), user(), 'u', @Bem);
  END;
END;

Als letzte Operation wird noch das Löschen überwacht. Hier wird neben der Datensatznummer noch die Kundennummer mit vermerkt (nur für alle Fälle).

CREATE TRIGGER trig_del ON Kunde AFTER DELETE
BEGIN
  DECLARE @Bem String;
  @Bem='KNR = '+COALESCE(TRIM(__old.Knr),'')+'; ';
  INSERT INTO Log_Kunde(Kunde_ID, Zeit, Benutzer, OP, Bemerkung)
    VALUES (__old.id, now(), user(), 'd', @Bem);
END;

Zum Schluß bleibt noch das Testen mit einem eingeschränkten Benutzer. Melden Sie sich dazu von der Datenbank ab und verbinden neu mit Benutzer1. Sie sollten in der Lage sein, gewisse Datenoperationen auszuführen, aber die Log-Datei nicht einsehen können. Ein erneutes Anmelden als ADSSYS bringt die Log-Tabelle wieder zum Vorschein und die zuvor als Benutzer1 ausgeführten Operationen sollten verzeichnet sein.
Hinweis: Falls ein neu erstellter Trigger beim ADS nicht greift, kann es daran liegen, dass die Tabelle beim Anlegen des Triggers bereits ohne Trigger geöffnet war. In diesem Fall sollte die Tabelle überall geschlossen werden.

REFERENZ: DSGVO-Reihe

DSGVO: Eingabekontrolle
Markiert in:         

2 Kommentare zu „DSGVO: Eingabekontrolle

  • 25. Juli 2018 um 8:53 Uhr
    Permalink

    Wer darf denn eigentlich diese Log-Tabelle einsehen? Nur der Datenschutzbeauftragte?

    Antworten
    • 25. Juli 2018 um 9:01 Uhr
      Permalink

      Das ist schwer zu beantworten. Der Zugang zur Log solte stark eingegenzt sein, da hier auch nach dem Löschen noch personenbezogene Daten stehen. Dem Admin kann man den Zugang nicht verwehren. Die Tabelle dient zum Nachweis, also sollte der DSB auch Zugang dazu bekommen, wenn auch über den Umweg Admin.

      Antworten

Schreibe einen Kommentar zu Joachim Höhne Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert