Pseudonymisieren
Die Pseudonymisierung modellieren
Info
Alle in diesem Tutorial beschriebenen Modellierungen kannst du dir mit Kommentaren im
Testordner der Profile Templates (TestPseudonymizeProfile.php) anschauen.
Einen Überblick verschaffen
Um die Pseudonymisierung modellieren zu können, musst du genau wissen, in welchen Datenbankspalten sich die Daten befinden welche du pseudonymisieren möchtest.
Pseudify liefert dir für diese Aufgabe Werkzeuge, welche im Kapitel "Analysieren" dokumentiert sind.
Wir analysieren die Datenbank mit folgendem Profil (siehe Kapitel "Analysieren"):
<?php
namespace Waldhacker\Pseudify\Profiles;
use Waldhacker\Pseudify\Core\Processor\Encoder\Base64Encoder;
use Waldhacker\Pseudify\Core\Processor\Encoder\ChainedEncoder;
use Waldhacker\Pseudify\Core\Processor\Encoder\GzEncodeEncoder;
use Waldhacker\Pseudify\Core\Processor\Encoder\HexEncoder;
use Waldhacker\Pseudify\Core\Processor\Processing\Analyze\TargetDataDecoderContext;
use Waldhacker\Pseudify\Core\Processor\Processing\Analyze\TargetDataDecoderPreset;
use Waldhacker\Pseudify\Core\Processor\Processing\DataProcessing;
use Waldhacker\Pseudify\Core\Profile\Analyze\ProfileInterface;
use Waldhacker\Pseudify\Core\Profile\Model\Analyze\TableDefinition;
use Waldhacker\Pseudify\Core\Profile\Model\Analyze\TargetColumn;
use Waldhacker\Pseudify\Core\Profile\Model\Analyze\TargetTable;
class TestAnalyzeProfile implements ProfileInterface
{
public function getIdentifier(): string
{
return 'test-profile';
}
public function getTableDefinition(): TableDefinition
{
$tableDefinition = new TableDefinition(identifier: $this->getIdentifier());
$tableDefinition->setTargetDataFrameCuttingLength(length: 0);
$tableDefinition
->addSourceTable(table: 'wh_user', columns: [
'username',
'password',
'first_name',
'last_name',
'email',
'city',
])
->addSourceString(string: 'regex:(?:[0-9]{1,3}\.){3}[0-9]{1,3}')
->excludeTargetColumnTypes(columnTypes: TableDefinition::COMMON_EXCLUED_TARGET_COLUMN_TYPES)
->addTargetTable(table: TargetTable::create(identifier: 'wh_log',
columns: [
TargetColumn::create(identifier: 'log_data', dataType: TargetColumn::DATA_TYPE_HEX)
->addDataProcessing(dataProcessing: new DataProcessing(identifier: 'decode conditional log data',
processor: function (TargetDataDecoderContext $context): void {
$row = $context->getDatebaseRow();
if ('foo' !== $row['log_type']) {
return;
}
$data = $context->getDecodedData();
$encoder = new Base64Encoder();
$logData = $encoder->decode(data: $data);
$context->setDecodedData(decodedData: $logData);
}
)),
TargetColumn::create(identifier: 'log_message')->addDataProcessing(dataProcessing: TargetDataDecoderPreset::normalizedJsonString()),
]
))
->addTargetTable(table: TargetTable::create(identifier: 'wh_meta_data',
columns: [
TargetColumn::create(identifier: 'meta_data')->setEncoder(encoder: new ChainedEncoder(encoders: [
new HexEncoder(),
new GzEncodeEncoder(defaultContext: [
GzEncodeEncoder::ENCODE_LEVEL => 5,
GzEncodeEncoder::ENCODE_ENCODING => ZLIB_ENCODING_GZIP,
]),
])),
]
))
;
return $tableDefinition;
}
}
Bereits bekannt ist uns, dass sich in der Tabelle wh_user
in den Spalten username
, password
, first_name
, last_name
, email
, city
Daten befinden, welche pseudonymisiert werden sollen.
Diese Daten liegen in skalarer Form vor. Sie müssen also nicht dekodiert werden.
Die Analyse liefert uns nun die Fundstellen in der Datenbank und zeigt uns die betreffenden Datenstrukturen an:
$ pseudify pseudify:analyze test-profile -vv
wh_user.username (hpagac) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:3;s:8:"username";s:6:"hpagac";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$QXNXbTRMZWxmenBRUzdwZQ$i6hntUDLa3ZFqmCG4FM0iPrpMp6d4D8XfrNBtyDmV9U";s:18:"password_hash_type";s:7:"argon2i";s:18:"password_plaintext";s:8:"[dvGd#gI";s:10:"first_name";s:6:"Donato";s:9:"last_name";s:7:"Keeling";s:5:"email";s:26:"mcclure.ofelia@example.com";s:4:"city";s:16:"North Elenamouth";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"239.27.57.12";}})
wh_user.password ($argon2i$v=19$m=8,t=1,p=1$QXNXbTRMZWxmenBRUzdwZQ$i6hntUDLa3ZFqmCG4FM0iPrpMp6d4D8XfrNBtyDmV9U) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:3;s:8:"username";s:6:"hpagac";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$QXNXbTRMZWxmenBRUzdwZQ$i6hntUDLa3ZFqmCG4FM0iPrpMp6d4D8XfrNBtyDmV9U";s:18:"password_hash_type";s:7:"argon2i";s:18:"password_plaintext";s:8:"[dvGd#gI";s:10:"first_name";s:6:"Donato";s:9:"last_name";s:7:"Keeling";s:5:"email";s:26:"mcclure.ofelia@example.com";s:4:"city";s:16:"North Elenamouth";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"239.27.57.12";}})
wh_user.first_name (Donato) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:3;s:8:"username";s:6:"hpagac";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$QXNXbTRMZWxmenBRUzdwZQ$i6hntUDLa3ZFqmCG4FM0iPrpMp6d4D8XfrNBtyDmV9U";s:18:"password_hash_type";s:7:"argon2i";s:18:"password_plaintext";s:8:"[dvGd#gI";s:10:"first_name";s:6:"Donato";s:9:"last_name";s:7:"Keeling";s:5:"email";s:26:"mcclure.ofelia@example.com";s:4:"city";s:16:"North Elenamouth";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"239.27.57.12";}})
wh_user.last_name (Keeling) -> wh_log.log_data ({"userName":"ronaldo15","email":"mcclure.ofelia@example.com","lastName":"Keeling","ip":"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8"})
wh_user.last_name (Keeling) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:3;s:8:"username";s:6:"hpagac";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$QXNXbTRMZWxmenBRUzdwZQ$i6hntUDLa3ZFqmCG4FM0iPrpMp6d4D8XfrNBtyDmV9U";s:18:"password_hash_type";s:7:"argon2i";s:18:"password_plaintext";s:8:"[dvGd#gI";s:10:"first_name";s:6:"Donato";s:9:"last_name";s:7:"Keeling";s:5:"email";s:26:"mcclure.ofelia@example.com";s:4:"city";s:16:"North Elenamouth";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"239.27.57.12";}})
wh_user.email (mcclure.ofelia@example.com) -> wh_log.log_data ({"userName":"ronaldo15","email":"mcclure.ofelia@example.com","lastName":"Keeling","ip":"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8"})
wh_user.email (mcclure.ofelia@example.com) -> wh_log.log_message ({"message":"foo text \"ronaldo15\", another \"mcclure.ofelia@example.com\""})
wh_user.email (mcclure.ofelia@example.com) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:3;s:8:"username";s:6:"hpagac";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$QXNXbTRMZWxmenBRUzdwZQ$i6hntUDLa3ZFqmCG4FM0iPrpMp6d4D8XfrNBtyDmV9U";s:18:"password_hash_type";s:7:"argon2i";s:18:"password_plaintext";s:8:"[dvGd#gI";s:10:"first_name";s:6:"Donato";s:9:"last_name";s:7:"Keeling";s:5:"email";s:26:"mcclure.ofelia@example.com";s:4:"city";s:16:"North Elenamouth";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"239.27.57.12";}})
wh_user.city (North Elenamouth) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:3;s:8:"username";s:6:"hpagac";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$QXNXbTRMZWxmenBRUzdwZQ$i6hntUDLa3ZFqmCG4FM0iPrpMp6d4D8XfrNBtyDmV9U";s:18:"password_hash_type";s:7:"argon2i";s:18:"password_plaintext";s:8:"[dvGd#gI";s:10:"first_name";s:6:"Donato";s:9:"last_name";s:7:"Keeling";s:5:"email";s:26:"mcclure.ofelia@example.com";s:4:"city";s:16:"North Elenamouth";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"239.27.57.12";}})
wh_user.username (georgiana59) -> wh_log.log_data (a:2:{i:0;s:14:"243.202.241.67";s:4:"user";O:8:"stdClass":5:{s:8:"userName";s:11:"georgiana59";s:8:"lastName";s:5:"Block";s:5:"email";s:19:"nolan11@example.net";s:2:"id";i:2;s:4:"user";R:3;}})
wh_user.username (georgiana59) -> wh_log.log_message ({"message":"bar text \"Block\", another \"georgiana59\""})
wh_user.username (georgiana59) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:4;s:8:"username";s:11:"georgiana59";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$SUJJeWZGSGEwS2h2TEw5Ug$kCQm4/5DqnjXc/3SiXwimtTBvbDO9H0Ru1f5hkQvE/Q";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:10:"uGZIc|aX4d";s:10:"first_name";s:7:"Maybell";s:9:"last_name";s:8:"Anderson";s:5:"email";s:29:"cassin.bernadette@example.net";s:4:"city";s:17:"South Wilfordland";}s:4:"key2";a:2:{s:2:"id";i:4;s:12:"session_data";s:65:"a:1:{s:7:"last_ip";s:37:"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8";}";}s:4:"key3";a:1:{s:4:"key4";s:11:"20.1.58.149";}})
wh_user.password ($argon2i$v=19$m=8,t=1,p=1$SUJJeWZGSGEwS2h2TEw5Ug$kCQm4/5DqnjXc/3SiXwimtTBvbDO9H0Ru1f5hkQvE/Q) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:4;s:8:"username";s:11:"georgiana59";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$SUJJeWZGSGEwS2h2TEw5Ug$kCQm4/5DqnjXc/3SiXwimtTBvbDO9H0Ru1f5hkQvE/Q";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:10:"uGZIc|aX4d";s:10:"first_name";s:7:"Maybell";s:9:"last_name";s:8:"Anderson";s:5:"email";s:29:"cassin.bernadette@example.net";s:4:"city";s:17:"South Wilfordland";}s:4:"key2";a:2:{s:2:"id";i:4;s:12:"session_data";s:65:"a:1:{s:7:"last_ip";s:37:"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8";}";}s:4:"key3";a:1:{s:4:"key4";s:11:"20.1.58.149";}})
wh_user.first_name (Maybell) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:4;s:8:"username";s:11:"georgiana59";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$SUJJeWZGSGEwS2h2TEw5Ug$kCQm4/5DqnjXc/3SiXwimtTBvbDO9H0Ru1f5hkQvE/Q";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:10:"uGZIc|aX4d";s:10:"first_name";s:7:"Maybell";s:9:"last_name";s:8:"Anderson";s:5:"email";s:29:"cassin.bernadette@example.net";s:4:"city";s:17:"South Wilfordland";}s:4:"key2";a:2:{s:2:"id";i:4;s:12:"session_data";s:65:"a:1:{s:7:"last_ip";s:37:"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8";}";}s:4:"key3";a:1:{s:4:"key4";s:11:"20.1.58.149";}})
wh_user.last_name (Anderson) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:4;s:8:"username";s:11:"georgiana59";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$SUJJeWZGSGEwS2h2TEw5Ug$kCQm4/5DqnjXc/3SiXwimtTBvbDO9H0Ru1f5hkQvE/Q";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:10:"uGZIc|aX4d";s:10:"first_name";s:7:"Maybell";s:9:"last_name";s:8:"Anderson";s:5:"email";s:29:"cassin.bernadette@example.net";s:4:"city";s:17:"South Wilfordland";}s:4:"key2";a:2:{s:2:"id";i:4;s:12:"session_data";s:65:"a:1:{s:7:"last_ip";s:37:"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8";}";}s:4:"key3";a:1:{s:4:"key4";s:11:"20.1.58.149";}})
wh_user.email (cassin.bernadette@example.net) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:4;s:8:"username";s:11:"georgiana59";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$SUJJeWZGSGEwS2h2TEw5Ug$kCQm4/5DqnjXc/3SiXwimtTBvbDO9H0Ru1f5hkQvE/Q";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:10:"uGZIc|aX4d";s:10:"first_name";s:7:"Maybell";s:9:"last_name";s:8:"Anderson";s:5:"email";s:29:"cassin.bernadette@example.net";s:4:"city";s:17:"South Wilfordland";}s:4:"key2";a:2:{s:2:"id";i:4;s:12:"session_data";s:65:"a:1:{s:7:"last_ip";s:37:"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8";}";}s:4:"key3";a:1:{s:4:"key4";s:11:"20.1.58.149";}})
wh_user.city (South Wilfordland) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:4;s:8:"username";s:11:"georgiana59";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$SUJJeWZGSGEwS2h2TEw5Ug$kCQm4/5DqnjXc/3SiXwimtTBvbDO9H0Ru1f5hkQvE/Q";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:10:"uGZIc|aX4d";s:10:"first_name";s:7:"Maybell";s:9:"last_name";s:8:"Anderson";s:5:"email";s:29:"cassin.bernadette@example.net";s:4:"city";s:17:"South Wilfordland";}s:4:"key2";a:2:{s:2:"id";i:4;s:12:"session_data";s:65:"a:1:{s:7:"last_ip";s:37:"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8";}";}s:4:"key3";a:1:{s:4:"key4";s:11:"20.1.58.149";}})
wh_user.username (howell.damien) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"139.81.0.139";}})
wh_user.username (howell.damien) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:15:"187.135.239.239";}})
wh_user.username (howell.damien) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:5;s:12:"session_data";s:42:"a:1:{s:7:"last_ip";s:14:"197.110.248.18";}";}s:4:"key3";a:1:{s:4:"key4";s:14:"83.243.216.115";}})
wh_user.password ($argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"139.81.0.139";}})
wh_user.password ($argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:15:"187.135.239.239";}})
wh_user.password ($argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:5;s:12:"session_data";s:42:"a:1:{s:7:"last_ip";s:14:"197.110.248.18";}";}s:4:"key3";a:1:{s:4:"key4";s:14:"83.243.216.115";}})
wh_user.first_name (Mckayla) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"139.81.0.139";}})
wh_user.first_name (Mckayla) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:15:"187.135.239.239";}})
wh_user.first_name (Mckayla) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:5;s:12:"session_data";s:42:"a:1:{s:7:"last_ip";s:14:"197.110.248.18";}";}s:4:"key3";a:1:{s:4:"key4";s:14:"83.243.216.115";}})
wh_user.last_name (Stoltenberg) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"139.81.0.139";}})
wh_user.last_name (Stoltenberg) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:15:"187.135.239.239";}})
wh_user.last_name (Stoltenberg) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:5;s:12:"session_data";s:42:"a:1:{s:7:"last_ip";s:14:"197.110.248.18";}";}s:4:"key3";a:1:{s:4:"key4";s:14:"83.243.216.115";}})
wh_user.email (conn.abigale@example.net) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"139.81.0.139";}})
wh_user.email (conn.abigale@example.net) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:15:"187.135.239.239";}})
wh_user.email (conn.abigale@example.net) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:5;s:12:"session_data";s:42:"a:1:{s:7:"last_ip";s:14:"197.110.248.18";}";}s:4:"key3";a:1:{s:4:"key4";s:14:"83.243.216.115";}})
wh_user.city (Dorothyfort) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"139.81.0.139";}})
wh_user.city (Dorothyfort) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:15:"187.135.239.239";}})
wh_user.city (Dorothyfort) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:5;s:12:"session_data";s:42:"a:1:{s:7:"last_ip";s:14:"197.110.248.18";}";}s:4:"key3";a:1:{s:4:"key4";s:14:"83.243.216.115";}})
__custom__.__custom__ (1321:57fc:460b:d4d0:d83f:c200:4b:f1c8) -> wh_log.log_data ({"userName":"ronaldo15","email":"mcclure.ofelia@example.com","lastName":"Keeling","ip":"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8"})
__custom__.__custom__ (1321:57fc:460b:d4d0:d83f:c200:4b:f1c8) -> wh_log.ip (1321:57fc:460b:d4d0:d83f:c200:4b:f1c8)
__custom__.__custom__ (155.215.67.191) -> wh_log.log_data ({"userName":"stark.judd","email":"srowe@example.net","lastName":"Boyer","ip":"155.215.67.191"})
__custom__.__custom__ (155.215.67.191) -> wh_log.ip (155.215.67.191)
__custom__.__custom__ (4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98) -> wh_log.log_data (a:2:{i:0;s:38:"4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98";s:4:"user";O:8:"stdClass":5:{s:8:"userName";s:12:"freida.mante";s:8:"lastName";s:5:"Tromp";s:5:"email";s:23:"lafayette64@example.net";s:2:"id";i:10;s:4:"user";R:3;}})
__custom__.__custom__ (4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98) -> wh_log.ip (4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98)
__custom__.__custom__ (243.202.241.67) -> wh_log.log_data (a:2:{i:0;s:14:"243.202.241.67";s:4:"user";O:8:"stdClass":5:{s:8:"userName";s:11:"georgiana59";s:8:"lastName";s:5:"Block";s:5:"email";s:19:"nolan11@example.net";s:2:"id";i:2;s:4:"user";R:3;}})
__custom__.__custom__ (243.202.241.67) -> wh_log.ip (243.202.241.67)
__custom__.__custom__ (132.188.241.155) -> wh_log.log_data (a:2:{i:0;s:15:"132.188.241.155";s:4:"user";O:8:"stdClass":5:{s:8:"userName";s:7:"cyril06";s:8:"lastName";s:8:"Homenick";s:5:"email";s:21:"clinton44@example.net";s:2:"id";i:91;s:4:"user";R:3;}})
__custom__.__custom__ (132.188.241.155) -> wh_log.ip (132.188.241.155)
__custom__.__custom__ (244.166.32.78) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"139.81.0.139";}})
__custom__.__custom__ (139.81.0.139) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"139.81.0.139";}})
__custom__.__custom__ (244.166.32.78) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:15:"187.135.239.239";}})
__custom__.__custom__ (187.135.239.239) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:15:"187.135.239.239";}})
__custom__.__custom__ (20.1.58.149) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:4;s:8:"username";s:11:"georgiana59";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$SUJJeWZGSGEwS2h2TEw5Ug$kCQm4/5DqnjXc/3SiXwimtTBvbDO9H0Ru1f5hkQvE/Q";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:10:"uGZIc|aX4d";s:10:"first_name";s:7:"Maybell";s:9:"last_name";s:8:"Anderson";s:5:"email";s:29:"cassin.bernadette@example.net";s:4:"city";s:17:"South Wilfordland";}s:4:"key2";a:2:{s:2:"id";i:4;s:12:"session_data";s:65:"a:1:{s:7:"last_ip";s:37:"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8";}";}s:4:"key3";a:1:{s:4:"key4";s:11:"20.1.58.149";}})
__custom__.__custom__ (1321:57fc:460b:d4d0:d83f:c200:4b:f1c8) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:4;s:8:"username";s:11:"georgiana59";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$SUJJeWZGSGEwS2h2TEw5Ug$kCQm4/5DqnjXc/3SiXwimtTBvbDO9H0Ru1f5hkQvE/Q";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:10:"uGZIc|aX4d";s:10:"first_name";s:7:"Maybell";s:9:"last_name";s:8:"Anderson";s:5:"email";s:29:"cassin.bernadette@example.net";s:4:"city";s:17:"South Wilfordland";}s:4:"key2";a:2:{s:2:"id";i:4;s:12:"session_data";s:65:"a:1:{s:7:"last_ip";s:37:"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8";}";}s:4:"key3";a:1:{s:4:"key4";s:11:"20.1.58.149";}})
__custom__.__custom__ (197.110.248.18) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:5;s:12:"session_data";s:42:"a:1:{s:7:"last_ip";s:14:"197.110.248.18";}";}s:4:"key3";a:1:{s:4:"key4";s:14:"83.243.216.115";}})
__custom__.__custom__ (83.243.216.115) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:5;s:8:"username";s:13:"howell.damien";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs";s:18:"password_hash_type";s:8:"argon2id";s:18:"password_plaintext";s:13:"nF5;06?nsS/nE";s:10:"first_name";s:7:"Mckayla";s:9:"last_name";s:11:"Stoltenberg";s:5:"email";s:24:"conn.abigale@example.net";s:4:"city";s:11:"Dorothyfort";}s:4:"key2";a:2:{s:2:"id";i:5;s:12:"session_data";s:42:"a:1:{s:7:"last_ip";s:14:"197.110.248.18";}";}s:4:"key3";a:1:{s:4:"key4";s:14:"83.243.216.115";}})
__custom__.__custom__ (244.166.32.78) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:3;s:8:"username";s:6:"hpagac";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$QXNXbTRMZWxmenBRUzdwZQ$i6hntUDLa3ZFqmCG4FM0iPrpMp6d4D8XfrNBtyDmV9U";s:18:"password_hash_type";s:7:"argon2i";s:18:"password_plaintext";s:8:"[dvGd#gI";s:10:"first_name";s:6:"Donato";s:9:"last_name";s:7:"Keeling";s:5:"email";s:26:"mcclure.ofelia@example.com";s:4:"city";s:16:"North Elenamouth";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"239.27.57.12";}})
__custom__.__custom__ (239.27.57.12) -> wh_meta_data.meta_data (a:3:{s:4:"key1";a:9:{s:2:"id";i:3;s:8:"username";s:6:"hpagac";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$QXNXbTRMZWxmenBRUzdwZQ$i6hntUDLa3ZFqmCG4FM0iPrpMp6d4D8XfrNBtyDmV9U";s:18:"password_hash_type";s:7:"argon2i";s:18:"password_plaintext";s:8:"[dvGd#gI";s:10:"first_name";s:6:"Donato";s:9:"last_name";s:7:"Keeling";s:5:"email";s:26:"mcclure.ofelia@example.com";s:4:"city";s:16:"North Elenamouth";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"239.27.57.12";}})
__custom__.__custom__ (4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98) -> wh_user_session.session_data (a:1:{s:7:"last_ip";s:38:"4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98";})
__custom__.__custom__ (4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98) -> wh_user_session.session_data_json ({"data":{"last_ip":"4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98"}})
__custom__.__custom__ (107.66.23.195) -> wh_user_session.session_data (a:1:{s:7:"last_ip";s:13:"107.66.23.195";})
__custom__.__custom__ (107.66.23.195) -> wh_user_session.session_data_json ({"data":{"last_ip":"107.66.23.195"}})
__custom__.__custom__ (244.166.32.78) -> wh_user_session.session_data (a:1:{s:7:"last_ip";s:13:"244.166.32.78";})
__custom__.__custom__ (244.166.32.78) -> wh_user_session.session_data_json ({"data":{"last_ip":"244.166.32.78"}})
__custom__.__custom__ (1321:57fc:460b:d4d0:d83f:c200:4b:f1c8) -> wh_user_session.session_data (a:1:{s:7:"last_ip";s:37:"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8";})
__custom__.__custom__ (1321:57fc:460b:d4d0:d83f:c200:4b:f1c8) -> wh_user_session.session_data_json ({"data":{"last_ip":"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8"}})
__custom__.__custom__ (197.110.248.18) -> wh_user_session.session_data (a:1:{s:7:"last_ip";s:14:"197.110.248.18";})
__custom__.__custom__ (197.110.248.18) -> wh_user_session.session_data_json ({"data":{"last_ip":"197.110.248.18"}})
1209/1209 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100% < 1 sec/< 1 sec 4.0 MiB
summary
=======
----------------------- ---------------------------------------------------------------------------------------------- -----------------------------------
source data seems to be in
----------------------- ---------------------------------------------------------------------------------------------- -----------------------------------
__custom__.__custom__ 132.188.241.155 wh_log.ip
__custom__.__custom__ 1321:57fc:460b:d4d0:d83f:c200:4b:f1c8 wh_log.ip
__custom__.__custom__ 155.215.67.191 wh_log.ip
__custom__.__custom__ 243.202.241.67 wh_log.ip
__custom__.__custom__ 4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98 wh_log.ip
__custom__.__custom__ 132.188.241.155 wh_log.log_data
__custom__.__custom__ 1321:57fc:460b:d4d0:d83f:c200:4b:f1c8 wh_log.log_data
__custom__.__custom__ 155.215.67.191 wh_log.log_data
__custom__.__custom__ 243.202.241.67 wh_log.log_data
__custom__.__custom__ 4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98 wh_log.log_data
__custom__.__custom__ 1321:57fc:460b:d4d0:d83f:c200:4b:f1c8 wh_meta_data.meta_data
__custom__.__custom__ 139.81.0.139 wh_meta_data.meta_data
__custom__.__custom__ 187.135.239.239 wh_meta_data.meta_data
__custom__.__custom__ 197.110.248.18 wh_meta_data.meta_data
__custom__.__custom__ 20.1.58.149 wh_meta_data.meta_data
__custom__.__custom__ 239.27.57.12 wh_meta_data.meta_data
__custom__.__custom__ 244.166.32.78 wh_meta_data.meta_data
__custom__.__custom__ 83.243.216.115 wh_meta_data.meta_data
__custom__.__custom__ 107.66.23.195 wh_user_session.session_data
__custom__.__custom__ 1321:57fc:460b:d4d0:d83f:c200:4b:f1c8 wh_user_session.session_data
__custom__.__custom__ 197.110.248.18 wh_user_session.session_data
__custom__.__custom__ 244.166.32.78 wh_user_session.session_data
__custom__.__custom__ 4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98 wh_user_session.session_data
__custom__.__custom__ 107.66.23.195 wh_user_session.session_data_json
__custom__.__custom__ 1321:57fc:460b:d4d0:d83f:c200:4b:f1c8 wh_user_session.session_data_json
__custom__.__custom__ 197.110.248.18 wh_user_session.session_data_json
__custom__.__custom__ 244.166.32.78 wh_user_session.session_data_json
__custom__.__custom__ 4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98 wh_user_session.session_data_json
wh_user.city Dorothyfort wh_meta_data.meta_data
wh_user.city North Elenamouth wh_meta_data.meta_data
wh_user.city South Wilfordland wh_meta_data.meta_data
wh_user.email mcclure.ofelia@example.com wh_log.log_data
wh_user.email mcclure.ofelia@example.com wh_log.log_message
wh_user.email cassin.bernadette@example.net wh_meta_data.meta_data
wh_user.email conn.abigale@example.net wh_meta_data.meta_data
wh_user.email mcclure.ofelia@example.com wh_meta_data.meta_data
wh_user.first_name Donato wh_meta_data.meta_data
wh_user.first_name Maybell wh_meta_data.meta_data
wh_user.first_name Mckayla wh_meta_data.meta_data
wh_user.last_name Keeling wh_log.log_data
wh_user.last_name Anderson wh_meta_data.meta_data
wh_user.last_name Keeling wh_meta_data.meta_data
wh_user.last_name Stoltenberg wh_meta_data.meta_data
wh_user.password $argon2i$v=19$m=8,t=1,p=1$QXNXbTRMZWxmenBRUzdwZQ$i6hntUDLa3ZFqmCG4FM0iPrpMp6d4D8XfrNBtyDmV9U wh_meta_data.meta_data
wh_user.password $argon2i$v=19$m=8,t=1,p=1$SUJJeWZGSGEwS2h2TEw5Ug$kCQm4/5DqnjXc/3SiXwimtTBvbDO9H0Ru1f5hkQvE/Q wh_meta_data.meta_data
wh_user.password $argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs wh_meta_data.meta_data
wh_user.username georgiana59 wh_log.log_data
wh_user.username georgiana59 wh_log.log_message
wh_user.username georgiana59 wh_meta_data.meta_data
wh_user.username howell.damien wh_meta_data.meta_data
wh_user.username hpagac wh_meta_data.meta_data
----------------------- ---------------------------------------------------------------------------------------------- -----------------------------------
Wir können anhand der Analyseergebnisse folgende Datenstrukturen und Inhalte erkennen:
Tabelle: wh_user.username
Datenkodierung: Skalar
Datentyp: Skalar
Beinhaltet: Benutzername
Beispiel: georgiana59
Tabelle: wh_user.password
Datenkodierung: Skalar
Datentyp: Skalar
Beinhaltet: Passwort-Hash
Beispiel: $argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs
Tabelle: wh_user.first_name
Datenkodierung: Skalar
Datentyp: Skalar
Beinhaltet: Vorname
Beispiel: Mckayla
Tabelle: wh_user.last_name
Datenkodierung: Skalar
Datentyp: Skalar
Beinhaltet: Nachname
Beispiel: Keeling
Tabelle: wh_user.email
Datenkodierung: Skalar
Datentyp: Skalar
Beinhaltet: E-Mail
Beispiel: mcclure.ofelia@example.com
Tabelle: wh_user.city
Datenkodierung: Skalar
Datentyp: Skalar
Beinhaltet: Stadt
Beispiel: North Elenamouth
Tabelle: wh_meta_data.meta_data
Datenkodierung: Hex > GzEncode
Datentyp: serialisierte PHP-Daten
Beinhaltet: Benutzername, Vorname, Nachname, E-Mail, Stadt, Passwort, IPv4, IPv6
Beispiel: a:3:{s:4:"key1";a:9:{s:2:"id";i:3;s:8:"username";s:6:"hpagac";s:8:"password";s:92:"$argon2i$v=19$m=8,t=1,p=1$QXNXbTRMZWxmenBRUzdwZQ$i6hntUDLa3ZFqmCG4FM0iPrpMp6d4D8XfrNBtyDmV9U";s:18:"password_hash_type";s:7:"argon2i";s:18:"password_plaintext";s:8:"[dvGd#gI";s:10:"first_name";s:6:"Donato";s:9:"last_name";s:7:"Keeling";s:5:"email";s:26:"mcclure.ofelia@example.com";s:4:"city";s:16:"North Elenamouth";}s:4:"key2";a:2:{s:2:"id";i:3;s:12:"session_data";s:41:"a:1:{s:7:"last_ip";s:13:"244.166.32.78";}";}s:4:"key3";a:1:{s:4:"key4";s:12:"239.27.57.12";}}
Tabelle: wh_log.log_data (logType == foo)
Datenkodierung: Hex
Datentyp: JSON
Beinhaltet: Benutzername, Vorname, Nachname, E-Mail, IPv4, IPv6
Beispiel: {"userName":"ronaldo15","email":"mcclure.ofelia@example.com","lastName":"Keeling","ip":"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8"}
Tabelle: wh_log.log_data (logType == bar)
Datenkodierung: Hex > Base64
Datentyp: serialisierte PHP-Daten
Beinhaltet: Benutzername, Vorname, Nachname, E-Mail, IPv4, IPv6
Beispiel: a:2:{i:0;s:14:"243.202.241.67";s:4:"user";O:8:"stdClass":5:{s:8:"userName";s:11:"georgiana59";s:8:"lastName";s:5:"Block";s:5:"email";s:19:"nolan11@example.net";s:2:"id";i:2;s:4:"user";R:3;}}
Tabelle: wh_log.log_message (logType == foo)
Datenkodierung: Skalar
Datentyp: JSON
Beinhaltet: Benutzername, E-Mail
Beispiel: {"message":"foo text \"ronaldo15\", another \"mcclure.ofelia@example.com\""}
Tabelle: wh_log.log_message (logType == bar)
Datenkodierung: Skalar
Datentyp: JSON
Beinhaltet: Benutzername, Nachname
Beispiel: {"message":"bar text \"Block\", another \"georgiana59\""}
Tabelle: wh_log.ip
Datenkodierung: Skalar
Datentyp: Skalar
Beinhaltet: IPv4, IPv6
Beispiel: 155.215.67.191
Tabelle: wh_user_session.session_data
Datenkodierung: Skalar
Datentyp: serialisierte PHP-Daten
Beinhaltet: IPv4, IPv6
Beispiel: a:1:{s:7:"last_ip";s:38:"4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98";}
Tabelle: wh_user_session.session_data_json
Datenkodierung: Skalar
Datentyp: JSON
Beinhaltet: IPv4, IPv6
Beispiel: {"data":{"last_ip":"107.66.23.195"}}
Ein "Pseudonymizer Profile" modellieren
Ein "Profile" anlegen
Lege im Ordner src/Profiles eine PHP Datei mit einem beliebigen Namen an.
Im Beispiel wird die Datei TestPseudonymizeProfile.php
genannt.
Die Datei bekommt folgenden Inhalt:
<?php
declare(strict_types=1);
namespace Waldhacker\Pseudify\Profiles;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\TableDefinition;
use Waldhacker\Pseudify\Core\Profile\Pseudonymize\ProfileInterface;
class TestPseudonymizeProfile implements ProfileInterface
{
public function getIdentifier(): string
{
return 'test-profile';
}
public function getTableDefinition(): TableDefinition
{
$tableDefinition = new TableDefinition(identifier: $this->getIdentifier());
return $tableDefinition;
}
}
Die Methode getIdentifier()
muss eine eindeutige Bezeichnung deines Profils wiedergeben und sollte nur aus Buchstaben, Zahlen oder den Zeichen -
und _
bestehen und darf keine Leerzeichen enthalten.
Nach der Erzeugung des Profils muss der Cache geleert werden.
$ docker run -it -v $(pwd):/data \
ghcr.io/waldhacker/pseudify cache:clear
Der Befehl pseudify pseudify:debug:pseudonymize test-profile
gibt dir nun bereits (leere) Informationen über dein Profil aus.
$ pseudify pseudify:debug:pseudonymize test-profile
Pseudonymization profile "test-profile"
=======================================
Pseudonymize data in this tables
--------------------------------
------- -------- --------------- -------------------
Table column data decoders data manipulators
------- -------- --------------- -------------------
Daten einer Datenbankspalten pseudonymisieren
Wir beginnen damit, die skalaren Datenbankdaten zu modellieren.
Dazu erweiterst du die Methode getTableDefinition()
im Profil.
<?php
declare(strict_types=1);
namespace Waldhacker\Pseudify\Profiles;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\Column;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\TableDefinition;
use Waldhacker\Pseudify\Core\Profile\Pseudonymize\ProfileInterface;
class TestPseudonymizeProfile implements ProfileInterface
{
public function getIdentifier(): string
{
return 'test-profile';
}
public function getTableDefinition(): TableDefinition
{
$tableDefinition = new TableDefinition(identifier: $this->getIdentifier());
$tableDefinition
->addTable(table: 'wh_user', columns: [
Column::create(identifier: 'username'),
Column::create(identifier: 'password'),
Column::create(identifier: 'first_name'),
Column::create(identifier: 'last_name'),
Column::create(identifier: 'email'),
Column::create(identifier: 'city'),
])
->addTable(table: 'wh_log', columns: [
Column::create(identifier: 'ip'),
])
;
return $tableDefinition;
}
}
Mit der Methode addTable()
sagst du pseudify, dass Du eine Datenbanktabelle modellieren willst.
Im Parameter columns
können eine oder mehrere Datenbankspalten modelliert werden (Column::create()
).
Der Befehl pseudify pseudify:debug:pseudonymize test-profile
gibt dir nun unter Pseudonymize data in this tables
die eben modellierten Datenbankspalten aus.
Unter data decoders
steht Scalar
, was bedeutet, dass die Daten während der Pseudonymisierung nicht dekodiert werden.
$ pseudify pseudify:debug:pseudonymize test-profile
Pseudonymization profile "test-profile"
=======================================
Pseudonymize data in this tables
--------------------------------
--------- --------------------- --------------- -------------------
Table column data decoders data manipulators
--------- --------------------- --------------- -------------------
wh_user username (string) Scalar
wh_user password (string) Scalar
wh_user first_name (string) Scalar
wh_user last_name (string) Scalar
wh_user email (string) Scalar
wh_user city (string) Scalar
wh_log ip (string) Scalar
--------- --------------------- --------------- -------------------
Encodierte Datenbankspalten
Wie bereits im Kapitel "Enkodierte Daten durchsuchen" gelernt, kann es vorkommen, dass Daten in Datenbankspalten in enkodierter Form vorliegen.
Das bedeutet, der kodierte Klartext muss vor der Pseudonymisierung dekodiert werden und nach der Pseudonymisierung wieder enkodiert werden.
In unserem Beispiel enthält die Datenbankspalte log_message
der Tabelle wh_log
und die Datenbankspalte session_data_json
der Tabelle wh_user_session
enkodierte Daten im JSON-Format.
Die Datenbankspalte session_data
der Tabelle wh_user_session
enthält enkodierte Daten in Form von serialisierten PHP-Daten.
Wie diese Daten enkodiert sind, musst du anhand des Quellcodes oder der Dokumentation der Applikation, welche die Datenbank verwendet, herausfinden.
Damit pseudify die Daten pseudonymisieren kann, müssen die Daten erst dekodiert werden.
Hierzu muss der Definition einer Datenbankspalte (Column::create()
) der Datentyp (Parameter dataType
) übergeben werden.
<?php
declare(strict_types=1);
namespace Waldhacker\Pseudify\Profiles;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\Column;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\TableDefinition;
use Waldhacker\Pseudify\Core\Profile\Pseudonymize\ProfileInterface;
class TestPseudonymizeProfile implements ProfileInterface
{
public function getIdentifier(): string
{
return 'test-profile';
}
public function getTableDefinition(): TableDefinition
{
$tableDefinition = new TableDefinition(identifier: $this->getIdentifier());
$tableDefinition
// ...
->addTable(table: 'wh_log', columns: [
// ...
Column::create(identifier: 'log_message', dataType: Column::DATA_TYPE_JSON),
])
->addTable(table: 'wh_user_session', columns: [
Column::create(identifier: 'session_data', dataType: Column::DATA_TYPE_SERIALIZED),
Column::create(identifier: 'session_data_json', dataType: Column::DATA_TYPE_JSON),
])
;
return $tableDefinition;
}
}
Der Methode Column::create()
kann mit dem Parameter dataType
ein Name eines Built-in Dekodierers übergeben werden.
Dies ist gleichbedeutend mit der ausgeschriebenen Variante ->setEncoder(encoder: new JsonEncoder())
bzw. ->setEncoder(encoder: new SerializedEncoder())
:
<?php
declare(strict_types=1);
namespace Waldhacker\Pseudify\Profiles;
use Waldhacker\Pseudify\Core\Processor\Encoder\JsonEncoder;
use Waldhacker\Pseudify\Core\Processor\Encoder\SerializedEncoder;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\Column;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\TableDefinition;
use Waldhacker\Pseudify\Core\Profile\Pseudonymize\ProfileInterface;
class TestPseudonymizeProfile implements ProfileInterface
{
public function getIdentifier(): string
{
return 'test-profile';
}
public function getTableDefinition(): TableDefinition
{
$tableDefinition = new TableDefinition(identifier: $this->getIdentifier());
$tableDefinition
// ...
->addTable(table: 'wh_log', columns: [
// ...
Column::create(identifier: 'log_message')->setEncoder(encoder: new JsonEncoder()),
])
->addTable(table: 'wh_user_session', columns: [
Column::create(identifier: 'session_data')->setEncoder(encoder: new SerializedEncoder()),
Column::create(identifier: 'session_data_json')->setEncoder(encoder: new JsonEncoder()),
])
;
return $tableDefinition;
}
}
Der Befehl pseudify pseudify:debug:pseudonymize test-profile
gibt dir nun unter Pseudonymize data in this tables
die eben modellierten Datenbankspalten aus.
Unter data decoders
werden nun die gerade definierten Dekodierer aufgelistet (Json
/ Serialized
).
pseudify pseudify:debug:pseudonymize test-profile
Pseudonymization profile "test-profile"
=======================================
Pseudonymize data in this tables
--------------------------------
----------------- -------------------------- --------------- -------------------
Table column data decoders data manipulators
----------------- -------------------------- --------------- -------------------
wh_user username (string) Scalar
wh_user password (string) Scalar
wh_user first_name (string) Scalar
wh_user last_name (string) Scalar
wh_user email (string) Scalar
wh_user city (string) Scalar
wh_log ip (string) Scalar
wh_log log_message (text) Json
wh_user_session session_data (blob) Serialized
wh_user_session session_data_json (text) Json
----------------- -------------------------- --------------- -------------------
Mehrfach enkodierte Datenbankspalten
Wie bereits im Kapitel "Mehrfach enkodierte Daten durchsuchen" gelernt, kann es vorkommen, dass Daten in Datenbankspalten in mehrfach enkodierter Form abgespeichert sind.
In unserem Beispiel enthält die Datenbankspalte meta_data
der Tabelle wh_meta_data
mehrfach enkodierte Daten.
Damit pseudify die Daten pseudonymisieren kann, müssen die Daten erst von hexadezimaler Darstellungsform in ein Binärformat umgewandelt werden und dann müssen die Binärdaten noch im ZLIB-Format dekomprimiert werden.
Um mehrfache Dekodierung durchzuführen, kann der ChainedEncoder
verwendet werden.
Mit dem ChainedEncoder können mehrere Dekodierer konfiguriert werden, welche dann der Reihe nach die Daten dekodieren.
<?php
declare(strict_types=1);
namespace Waldhacker\Pseudify\Profiles;
use Waldhacker\Pseudify\Core\Processor\Encoder\ChainedEncoder;
use Waldhacker\Pseudify\Core\Processor\Encoder\GzEncodeEncoder;
use Waldhacker\Pseudify\Core\Processor\Encoder\HexEncoder;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\Column;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\TableDefinition;
use Waldhacker\Pseudify\Core\Profile\Pseudonymize\ProfileInterface;
class TestPseudonymizeProfile implements ProfileInterface
{
public function getIdentifier(): string
{
return 'test-profile';
}
public function getTableDefinition(): TableDefinition
{
$tableDefinition = new TableDefinition(identifier: $this->getIdentifier());
$tableDefinition
// ...
->addTable(table: 'wh_meta_data', columns: [
Column::create(identifier: 'meta_data')->setEncoder(encoder: new ChainedEncoder(encoders: [
new HexEncoder(),
new GzEncodeEncoder(defaultContext: [
GzEncodeEncoder::ENCODE_LEVEL => 5,
GzEncodeEncoder::ENCODE_ENCODING => ZLIB_ENCODING_GZIP,
]),
])),
])
;
return $tableDefinition;
}
}
Bei der Pseudonymisierung der Datenbankspalte meta_data
der Tabelle wh_meta_data
wird pseudify die Daten der Datenbankspalte dann zuerst mittels der Methode decode()
des HexEncoder
und dann mittels der Methode decode()
des GzEncodeEncoder verarbeiten, damit das Resultat anschließend pseudonymisiert werden kann.
Danach wird pseudify die pseudonymisierten Daten mittels der Methode encode()
des GzEncodeEncoder
und dann mittels der Methode encode()
des HexEncoder verarbeiten und zurück in die Datenbank schreiben.
pseudify pseudify:debug:pseudonymize test-profile
Pseudonymization profile "test-profile"
=======================================
Pseudonymize data in this tables
--------------------------------
----------------- -------------------------- --------------- -------------------
Table column data decoders data manipulators
----------------- -------------------------- --------------- -------------------
wh_user username (string) Scalar
wh_user password (string) Scalar
wh_user first_name (string) Scalar
wh_user last_name (string) Scalar
wh_user email (string) Scalar
wh_user city (string) Scalar
wh_log ip (string) Scalar
wh_log log_message (text) Json
wh_user_session session_data (blob) Serialized
wh_user_session session_data_json (text) Json
wh_meta_data meta_data (blob) Hex<>GzEncode
----------------- -------------------------- --------------- -------------------
Du siehst unter Pseudonymize data in this tables
nun, dass unter data decoders
der Datenbankspalte wh_meta_data
die Namen Hex<>GzEncode
aufgelistet werden.
Dies signalisiert dir, dass die Daten zuerst mittels des HexEncoder dekodiert werden und dann mittels des GzEncodeEncoder.
Unterschiedlich enkodierte Datenbankspalten
Wie bereits im Kapitel "Unterschiedlich enkodierte Daten durchsuchen" gelernt, kann es vorkommen, dass Daten in Datenbankspalten in unterschiedlich enkodierter Form abgespeichert sind.
Anhand von Bedingungen speichern Applikationen die Daten in anderen Formen ab.
In unserem Beispiel sind die Daten der Datenbankspalte log_data
der Tabelle wh_log
serialisierte PHP-Data, welche im Base64-Format enkodiert worden sind und dann in hexadezimaler Form abgespeichert wurden, wenn die Datenbankspalte log_type
den Wert bar
enthält.
Die Daten der Datenbankspalte log_data
sind im JSON-Format, welche in hexadezimaler Form abgespeichert wurden, wenn die Datenbankspalte log_type
den Wert foo
enthält.
In beiden Fällen (log_type
== foo
und log_type
== bar
) können die Daten zuerst von hexadezimaler Darstellungsform zum Binärformat umgewandelt werden.
Die weiteren Dekodierungen müssen manuell modelliert werden:
<?php
declare(strict_types=1);
namespace Waldhacker\Pseudify\Profiles;
use Waldhacker\Pseudify\Core\Processor\Encoder\Base64Encoder;
use Waldhacker\Pseudify\Core\Processor\Encoder\ChainedEncoder;
use Waldhacker\Pseudify\Core\Processor\Encoder\GzEncodeEncoder;
use Waldhacker\Pseudify\Core\Processor\Encoder\HexEncoder;
use Waldhacker\Pseudify\Core\Processor\Encoder\JsonEncoder;
use Waldhacker\Pseudify\Core\Processor\Processing\DataProcessing;
use Waldhacker\Pseudify\Core\Processor\Processing\Pseudonymize\DataManipulatorContext;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\Column;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\TableDefinition;
use Waldhacker\Pseudify\Core\Profile\Pseudonymize\ProfileInterface;
class TestPseudonymizeProfile implements ProfileInterface
{
public function getIdentifier(): string
{
return 'test-profile';
}
public function getTableDefinition(): TableDefinition
{
$tableDefinition = new TableDefinition(identifier: $this->getIdentifier());
$tableDefinition
// ...
->addTable(table: 'wh_log', columns: [
// ...
Column::create(identifier: 'log_data', dataType: Column::DATA_TYPE_HEX)
->addDataProcessing(dataProcessing: new DataProcessing(identifier: 'process logs',
processor: function (DataManipulatorContext $context): void {
$row = $context->getDatebaseRow();
if ('foo' === $row['log_type']) {
$encoder = new ChainedEncoder(encoders: [new Base64Encoder(), new JsonEncoder()]);
} else if ('bar' === $row['log_type']) {
$encoder = new SerializedEncoder();
} else {
return;
}
$logData = $encoder->decode(data: $context->getDecodedData());
// pseudonymize the data
// ...
}
)),
])
// ...
;
return $tableDefinition;
}
}
Mit der Methode addDataProcessing()
können zusätzlich zur Dekodierung der Daten weitere manuelle Datentransformationen programmiert werden.
Die DataProcessings
werden nach der Dekodierung der Daten ausgeführt.
Es können beliebig viele DataProcessings
definiert werden, welche nacheinander abgearbeitet werden.
Ein DataProcessing
besteht aus einer eindeutigen Identifizierung pro Datenbankspalte (Parameter identifier
) und
einer anonymen Funktion (Parameter processor
).
Die anonyme Funktion wird mit einem Parameter context
vom Typ DataManipulatorContext
aufgerufen.
Durch den DataManipulatorContext
können diverse Informationen über den zu verarbeitenden Datensatz erhalten werden:
$context->getRawData()
: Die Originaldaten der Datenbankspalte$context->getDecodedData()
: Die Daten der Datenbankspalte nach der Dekodierung$context->getDatebaseRow()
: Enthält die Originaldaten aller Datenbankspalten der Datenbankzeile die verarbeitet wird$context->getProcessedData()
: Enthält die verarbeiteten Daten welche mittels$context->setProcessedData()
gesetzt wurden, anderenfalls die Daten der Datenbankspalte nach der Dekodierung
In unserem Beispiel ermitteln wir anhand des Wertes der Datenbankspalte log_type
, wie die Daten noch weiter dekodiert werden müssen.
Ist der Wert von log_type
gleich foo
, so werden die Daten mittels des Base64Encoder() und dann mittels des JsonEncoder() dekodiert.
Ist der Wert von log_type
gleich bar
, so werden die Daten mittels des SerializedEncoder() dekodiert.
Die Daten sind nun dekodiert und können im Anschluss pseudonymisiert werden.
pseudify pseudify:debug:pseudonymize test-profile
Pseudonymization profile "test-profile"
=======================================
Pseudonymize data in this tables
--------------------------------
----------------- -------------------------- --------------- -------------------
Table column data decoders data manipulators
----------------- -------------------------- --------------- -------------------
wh_user username (string) Scalar
wh_user password (string) Scalar
wh_user first_name (string) Scalar
wh_user last_name (string) Scalar
wh_user email (string) Scalar
wh_user city (string) Scalar
wh_log ip (string) Scalar
wh_log log_message (text) Json
wh_log log_data (blob) Hex process logs
wh_user_session session_data (blob) Serialized
wh_user_session session_data_json (text) Json
wh_meta_data meta_data (blob) Hex<>GzEncode
----------------- -------------------------- --------------- -------------------
Skalare Daten Faken (pseudonymisieren)
Die Pseudonymisierung wird auf Spaltenebene mittels der Methode addDataProcessing()
implementiert.
Im Kapitel Unterschiedlich enkodierte Datenbankspalten
wurden bereits die DataProcessings
beschrieben.
In einem DataProcessing
findet nicht nur eine ggf. benötigte erweiterte Dekodierung / Enkodierung der Daten statt, sonder vor allem die Pseudonymisierung selbst.
Jede definierte Datenbankspalte (Column::create()
) benötigt mindestens ein DataProcessing
damit pseudify weiß, wie es die Daten in der Datenbankspalte pseudonymisieren muss.
Wir beginnen wieder mit den leicht zu pseudonymisierenden skalaren Datenstrukturen.
Dazu erweiterst du die definierten Datenbankspalten (Column::create()
) im Profil.
<?php
declare(strict_types=1);
namespace Waldhacker\Pseudify\Profiles;
use Faker\Provider\Person;
use Waldhacker\Pseudify\Core\Processor\Processing\DataProcessing;
use Waldhacker\Pseudify\Core\Processor\Processing\Pseudonymize\DataManipulatorPreset;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\Column;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\TableDefinition;
use Waldhacker\Pseudify\Core\Profile\Pseudonymize\ProfileInterface;
class TestPseudonymizeProfile implements ProfileInterface
{
public function getIdentifier(): string
{
return 'test-profile';
}
public function getTableDefinition(): TableDefinition
{
$tableDefinition = new TableDefinition(identifier: $this->getIdentifier());
$tableDefinition
->addTable(table: 'wh_user', columns: [
Column::create(identifier: 'username')
->addDataProcessing(dataProcessing: DataManipulatorPreset::scalarData(
fakerFormatter: 'userName'
)),
Column::create(identifier: 'password')
->addDataProcessing(dataProcessing: DataManipulatorPreset::scalarData(
fakerFormatter: 'argon2iPassword'
)),
Column::create(identifier: 'first_name')
->addDataProcessing(dataProcessing: DataManipulatorPreset::scalarData(
fakerFormatter: 'firstName',
fakerArguments: [Person::GENDER_FEMALE]
)),
Column::create(identifier: 'last_name')
->addDataProcessing(dataProcessing: DataManipulatorPreset::scalarData(
fakerFormatter: 'lastName'
)),
Column::create(identifier: 'email')
->addDataProcessing(dataProcessing: DataManipulatorPreset::scalarData(
fakerFormatter: 'safeEmail'
)),
Column::create(identifier: 'city')
->addDataProcessing(dataProcessing: DataManipulatorPreset::scalarData(
fakerFormatter: 'city'
)),
])
// ...
;
return $tableDefinition;
}
}
Der Methode addDataProcessing()
wird das vorgefertigte DataProcessing
DataManipulatorPreset::scalarData()
übergeben.
Info
DataManipulatorPreset::scalarData()
implementiert bereits alles, was nötig ist, um einfache Datenstrukturen in der Datenbank zu pseudonymisieren.
Dem Argument fakerFormatter
übergibst du einen von der FakerPHP/Faker Komponente bereitgestellten oder selbst implementierten Formatierer z.B. email
.
Unterstützt ein Formatierer Argumente wie z.B. beim firstName
Formatierer, so können diese mit dem Argument fakerArguments
übergeben werden.
Eine Analyse des Profils sieht nun so aus:
$ pseudify pseudify:debug:pseudonymize test-profile
Pseudonymization profile "test-profile"
=======================================
Pseudonymize data in this tables
--------------------------------
----------------- -------------------------- --------------- -----------------------------
Table column data decoders data manipulators
----------------- -------------------------- --------------- -----------------------------
wh_user username (string) Scalar autogenerated-63db8d8426b5f
wh_user password (string) Scalar autogenerated-63db8d8426b64
wh_user first_name (string) Scalar autogenerated-63db8d84270ab
wh_user last_name (string) Scalar autogenerated-63db8d84270b0
wh_user email (string) Scalar autogenerated-63db8d84270b1
wh_user city (string) Scalar autogenerated-63db8d84270b2
wh_log ip (string) Scalar
wh_log log_message (text) Json
wh_log log_data (blob) Hex foo logs
wh_user_session session_data (blob) Serialized
wh_user_session session_data_json (text) Json
wh_meta_data meta_data (blob) Hex<>GzEncode
----------------- -------------------------- --------------- -----------------------------
Unter data manipulators
kannst du nun sehen, dass für einige Spalten DataProcessings
modelliert wurden.
Die Werte (z.B. autogenerated-63db8d8426b5f
) werden von pseudify automatisch generiert.
Möchtest du zur besseren Übersicht menschenlesbare Bezeichnungen aufgelistet bekommen, so kannst du der Methode DataManipulatorPreset::scalarData()
das Argument processingIdentifier
übergeben.
<?php
declare(strict_types=1);
namespace Waldhacker\Pseudify\Profiles;
use Faker\Provider\Person;
use Waldhacker\Pseudify\Core\Processor\Processing\DataProcessing;
use Waldhacker\Pseudify\Core\Processor\Processing\Pseudonymize\DataManipulatorPreset;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\Column;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\TableDefinition;
use Waldhacker\Pseudify\Core\Profile\Pseudonymize\ProfileInterface;
class TestPseudonymizeProfile implements ProfileInterface
{
public function getIdentifier(): string
{
return 'test-profile';
}
public function getTableDefinition(): TableDefinition
{
$tableDefinition = new TableDefinition(identifier: $this->getIdentifier());
$tableDefinition
->addTable(table: 'wh_user', columns: [
Column::create(identifier: 'username')
->addDataProcessing(dataProcessing: DataManipulatorPreset::scalarData(
fakerFormatter: 'userName',
processingIdentifier: 'fake user names'
)),
Column::create(identifier: 'password')
->addDataProcessing(dataProcessing: DataManipulatorPreset::scalarData(
fakerFormatter: 'argon2iPassword',
processingIdentifier: 'fake argon2i passwords'
)),
Column::create(identifier: 'first_name')
->addDataProcessing(dataProcessing: DataManipulatorPreset::scalarData(
fakerFormatter: 'firstName',
fakerArguments: [Person::GENDER_FEMALE],
processingIdentifier: 'fake female first names'
)),
Column::create(identifier: 'last_name')
->addDataProcessing(dataProcessing: DataManipulatorPreset::scalarData(
fakerFormatter: 'lastName',
processingIdentifier: 'fake last names'
)),
Column::create(identifier: 'email')
->addDataProcessing(dataProcessing: DataManipulatorPreset::scalarData(
fakerFormatter: 'safeEmail',
processingIdentifier: 'fake safe email addresses'
)),
Column::create(identifier: 'city')
->addDataProcessing(dataProcessing: DataManipulatorPreset::scalarData(
fakerFormatter: 'city',
processingIdentifier: 'fake citiy names'
)),
])
// ...
;
return $tableDefinition;
}
}
$ pseudify pseudify:debug:pseudonymize test-profile
Pseudonymization profile "test-profile"
=======================================
Pseudonymize data in this tables
--------------------------------
----------------- -------------------------- --------------- ---------------------------
Table column data decoders data manipulators
----------------- -------------------------- --------------- ---------------------------
wh_user username (string) Scalar fake user names
wh_user password (string) Scalar fake argon2i passwords
wh_user first_name (string) Scalar fake female first names
wh_user last_name (string) Scalar fake last names
wh_user email (string) Scalar fake safe email addresses
wh_user city (string) Scalar fake citiy names
wh_log ip (string) Scalar
wh_log log_message (text) Json
wh_log log_data (blob) Hex foo logs
wh_user_session session_data (blob) Serialized
wh_user_session session_data_json (text) Json
wh_meta_data meta_data (blob) Hex<>GzEncode
----------------- -------------------------- --------------- ---------------------------
Nicht-Skalare Daten Faken (pseudonymisieren)
In komplexen Datenstrukturen möchte man in der Regel nur ganz bestimmte Eigenschaften pseudonymisieren.
Als Beispiel eignen sich die Daten der Datenbankspalte session_data_json
in der Tabelle wh_meta_data
.
Darin befinden sich JSON-Strings wie z.B. {"data":{"last_ip":"107.66.23.195"}}
.
Wir möchten nun gezielt den Wert der Eigenschaft last_ip
mit Fakedaten ersetzten.
Dafür definieren wir ein DataProcessing
(addDataProcessing()
) an der Datenbankspalte (Column::create()
).
Im Kapitel "Unterschiedlich enkodierte Datenbankspalten" wurden bereits der DataManipulatorContext
erwähnt, welcher an die anonyme Funktion eines DataProcessing
übergeben wird.
Durch den DataManipulatorContext
können diverse Informationen über den zu verarbeitenden Datensatz erhalten werden:
$context->getRawData()
: Die Originaldaten der Datenbankspalte$context->getDecodedData()
: Die Daten der Datenbankspalte nach der Dekodierung$context->getDatebaseRow()
: Enthält die Originaldaten aller Datenbankspalten der Datenbankzeile die verarbeitet wird$context->getProcessedData()
: Enthält die verarbeiteten Daten welche mittels$context->setProcessedData()
gesetzt wurden, anderenfalls die Daten der Datenbankspalte nach der Dekodierung
Mittels des DataManipulatorContext
können die Daten ebenfalls pseudonymisiert und zurück an pseudify übergeben werden:
Mit der Methode fake()
kann die FakerPHP/Faker Komponente initialisiert werden, um Pseudonyme zu erzeugen.
Mit der Methode setProcessedData()
kann die pseudonymisierte Datenstruktur zurück an pseudify übergeben werden.
<?php
declare(strict_types=1);
namespace Waldhacker\Pseudify\Profiles;
use Waldhacker\Pseudify\Core\Processor\Processing\DataProcessing;
use Waldhacker\Pseudify\Core\Processor\Processing\Pseudonymize\DataManipulatorContext;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\Column;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\TableDefinition;
use Waldhacker\Pseudify\Core\Profile\Pseudonymize\ProfileInterface;
class TestPseudonymizeProfile implements ProfileInterface
{
public function getIdentifier(): string
{
return 'test-profile';
}
public function getTableDefinition(): TableDefinition
{
$tableDefinition = new TableDefinition(identifier: $this->getIdentifier());
$tableDefinition
// ...
->addTable(table: 'wh_user_session', columns: [
// ...
Column::create(identifier: 'session_data_json', dataType: Column::DATA_TYPE_JSON)
->addDataProcessing(dataProcessing: new DataProcessing(identifier: 'fake IPv4',
processor: function (DataManipulatorContext $context): void {
$data = $context->getDecodedData();
$ip = $data['data']['last_ip'];
$fakeIp = $context->fake(source: $ip)->ipv4();
$data['data']['last_ip'] = $fakeIp;
$context->setProcessedData(processedData: $data);
}
)),
])
// ...
;
return $tableDefinition;
}
}
Mit $data = $context->getDecodedData();
bekommen wir den dekodierten JSON-String in Form eines assoziativen Arrays geliefert.
Mit $ip = $data['data']['last_ip'];
holen wir uns gezielt den Wert aus der Datenstruktur (die IP-Adresse), welchen wir pseudonymisieren wollen.
Der Aufruf $context->fake(source: $ip);
initialisiert den Faker.
Dem Argument source
wird der zu pseudonymisierende Eingangswert übergeben, im Beispiel ist das die IP-Adresse.
Es folgt der Aufruf eines von der FakerPHP/Faker Komponente bereitgestellten oder selbst implementierten Formatierers, z.B. ->ipv4()
.
Info
Unterstützt ein Formatierer Argumente, wie z.B. beim firstName
Formatierer, so können die Argumente dem Aufruf übergeben werden (z.B. ->firstName(gender: \Faker\Provider\Person::GENDER_FEMALE)
).
Die pseudonymisierten Daten ($fakeIp
) müssen dann in die Datenstruktur zurückgeschrieben werden ($data['data']['last_ip'] = $fakeIp;
).
Mit $context->setProcessedData(processedData: $data);
wird die nun pseudonymisierte Datenstruktur an pseudify übergeben.
Pseudify wird die Datenstruktur dann wieder enkodieren und zurück in die Datenbank schreiben.
Unterschiedliche Datenformate in einer Datenbankspalte Faken (pseudonymisieren)
Wie bereits im Kapitel "Unterschiedlich enkodierte Datenbankspalten" und "Unterschiedlich enkodierte Daten durchsuchen" gelernt, kann es vorkommen, dass Daten in Datenbankspalten in unterschiedlich enkodierter Form abgespeichert sind.
Es kann auch vorkommen, dass Daten in Datenbankspalten in unterschiedlichen Datenformaten abgespeichert sind.
Anhand von Bedingungen muss detektiert werden, in welchem Datenformat die Daten vorliegen, um sie dann entsprechend pseudonymisieren zu können.
In unserem Beispiel sind die Plaintext-Daten der Datenbankspalte log_data
der Tabelle wh_log
serialisierte PHP-Data, wenn die Datenbankspalte log_type
den Wert bar
enthält.
Die Plaintext-Daten der Datenbankspalte log_data
sind im JSON-Format, wenn die Datenbankspalte log_type
den Wert foo
enthält.
Wenn die Datenbankspalte log_data
der Tabelle wh_log
den Wert foo
enthält, dann sieht die Datenstruktur folgendermaßen aus:
{"message":"foo text \"ronaldo15\", another \"mcclure.ofelia@example.com\""}
^ ^
Benutzername E-Mail Adresse
Wenn die Datenbankspalte log_data
der Tabelle wh_log
den Wert bar
enthält, dann sieht die Datenstruktur so aus:
{"message":"bar text \"Block\", another \"georgiana59\""}
^ ^
Nachname Benutzername
Anhand der Daten aus dem DataManipulatorContext
können wir nun differenzieren, um welche Datenstruktur es sich gerade handelt ('foo' === $row['log_type']
), um diese dann entsprechend zu pseudonymisieren.
<?php
declare(strict_types=1);
namespace Waldhacker\Pseudify\Profiles;
use Waldhacker\Pseudify\Core\Processor\Processing\DataProcessing;
use Waldhacker\Pseudify\Core\Processor\Processing\Pseudonymize\DataManipulatorContext;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\Column;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\TableDefinition;
use Waldhacker\Pseudify\Core\Profile\Pseudonymize\ProfileInterface;
class TestPseudonymizeProfile implements ProfileInterface
{
public function getIdentifier(): string
{
return 'test-profile';
}
public function getTableDefinition(): TableDefinition
{
$tableDefinition = new TableDefinition(identifier: $this->getIdentifier());
$tableDefinition
// ...
->addTable(table: 'wh_log', columns: [
// ...
Column::create(identifier: 'log_message', dataType: Column::DATA_TYPE_JSON)
->addDataProcessing(dataProcessing: new DataProcessing(identifier: 'process log messages',
processor: function (DataManipulatorContext $context): void {
$logMessage = $context->getProcessedData();
preg_match('/^.*(".*").*(".*")$/', $logMessage['message'], $matches);
array_shift($matches);
$row = $context->getDatebaseRow();
if ('foo' === $row['log_type']) {
$userName = trim($matches[0], '"');
$mail = trim($matches[1], '"');
$logMessage['message'] = strtr($logMessage['message'], [
$matches[0] => sprintf('"%s"', $context->fake(source: $userName)->userName()),
$matches[1] => sprintf('"%s"', $context->fake(source: $mail)->safeEmail()),
]);
} else {
$lastName = trim($matches[0], '"');
$userName = trim($matches[1], '"');
$logMessage['message'] = strtr($logMessage['message'], [
$matches[0] => sprintf('"%s"', $context->fake(source: $lastName)->lastName()),
$matches[1] => sprintf('"%s"', $context->fake(source: $userName)->userName()),
]);
}
$context->setProcessedData(processedData: $logMessage);
}
)),
// ...
])
// ...
;
return $tableDefinition;
}
}
Mit $context->setProcessedData(processedData: $logMessage);
wird die pseudonymisierte Datenstruktur an pseudify übergeben.
Pseudify wird die Datenstruktur nun wieder enkodieren und zurück in die Datenbank schreiben.
Erweiterte Anwendung
Unterschiedliche Pseudonyme für gleiche Eingangsdaten verwenden
Um Datenintegrität zu wahren ist pseudify so gestaltet, dass es währen eines Pseudonymisierungslaufs für gleiche Eingangsdaten immer das gleiche Pseudonym liefert.
Das bedeutet, dass während der Ausführung einer Pseudonymisierung mittels pseudify pseudify:pseudonymize test-profile
bei allen Aufrufen von $context->fake(source: 'Stan')->userName()
jedes Mal z.B. das Pseudonym Klaus
erzeugt wird und nicht jedes Mal ein anderes.
Eine erneute Pseudonymisierung der Originaldatenbank mittels pseudify pseudify:pseudonymize test-profile
wird bei allen Aufrufen von $context->fake(source: 'Stan')->userName()
jedes Mal z.B. das Pseudonym Roger
erzeugen und nicht Klaus
wie im ersten Pseudonymisierungslauf.
Somit sind 2 Dinge sichergestellt:
- Innerhalb eines Pseudonymisierungslaufs werden gleiche Originaldaten immer mit demselben Pseudonymen ersetzt
(Der Wert "Stan" aus Tabelle 1 und Tabelle 2 wird in Tabelle 1 und Tabelle 2 mit "Klaus" ersetzt) - Zwischen verschiedenen Pseudonymisierungsläufen erzeugen gleiche Originaldaten unterschiedliche Pseudonyme
(Bei der ersten Pseudonymisierung wird der Wert "Stan" aus Tabelle 1 und Tabelle 2 in beiden Tabellen mit "Klaus" ersetzt,
bei der zweiten Pseudonymisierung wird der Wert "Stan" aus Tabelle 1 und Tabelle 2 in beiden Tabellen mit dem Wert "Roger" ersetzt usw.)
Möchte man aus irgendwelchen Gründen dieses Verhalten ändern, so kann der Methode $context->fake()
der Parameter scope
mitgegeben werden.
Mit diesem Parameter kannst du pseudify anweisen für gleiche Eingangsdaten unterschiedliche Pseudonyme pro scope
zu bilden.
Beispiel:
$context->fake(source: 'Stan')->userName()
liefert Greg
$context->fake(source: 'Stan', scope: 'something_else')->userName()
liefert Terry
$context->fake(source: 'Stan')->userName()
liefert Greg
$context->fake(source: 'Stan', scope: 'something_else')->userName()
liefert Terry
$context->fake(source: 'Terry')->userName()
liefert Brian
$context->fake(source: 'Terry', scope: 'something_else')->userName()
liefert Lewis
Info
Aufrufe von $context->fake()
erzeugen gleiche Pseudonyme auf Basis der folgenden Variablen:
- gleiche Quelldaten
- gleicher Formatierer
- gleiche Formatierer-Argumente
- gleicher
scope
- gleiches
APP_SECRET
Dies gilt innerhalb eines Pseudonymisierungslaufs. Ein erneuter Pseudonymisierungslauf wird mit den gleichen Variablen andere Pseudonyme bilden.
Die onBeforeUpdateData()
Lebenszyklus-Methode
Kurz bevor pseudify die pseudonymisierten Daten in die Datenbank zurückschreibt, wird die Lebenszyklus-Methode aufgerufen
.
Diese kann an einer Datenbankspalte (Column::create()
) definiert werden.
<?php
declare(strict_types=1);
namespace Waldhacker\Pseudify\Profiles;
use Doctrine\DBAL\Query\QueryBuilder;
use Doctrine\DBAL\Schema\Column as DoctrineColumn;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\Column;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\TableDefinition;
use Waldhacker\Pseudify\Core\Profile\Model\Pseudonymize\Table;
use Waldhacker\Pseudify\Core\Profile\Pseudonymize\ProfileInterface;
class TestPseudonymizeProfile implements ProfileInterface
{
public function getIdentifier(): string
{
return 'test-profile';
}
public function getTableDefinition(): TableDefinition
{
$tableDefinition = new TableDefinition(identifier: $this->getIdentifier());
$tableDefinition
// ...
->addTable(table: 'wh_log', columns: [
Column::create(identifier: 'log_message')
// ...
->onBeforeUpdateData(onBeforeUpdateData: function (QueryBuilder $queryBuilder, Table $table, Column $column, DoctrineColumn $columnInfo, mixed $originalData, mixed $processedData, array $databaseRow): void {
// ...
}),
// ...
])
// ...
;
return $tableDefinition;
}
}
In diesem callback hast du Zugriff auf alle wichtigen Objekte und Daten, um in irgendwelchen verrückten Szenarien noch Datenmanipulationen vornehmen zu können:
$originalData
: Die Originaldaten in der Datenbank, welche gleich ersetzt werden$processedData
: Die pseudonymisierten Daten, welche gleich geschrieben werden$databaseRow
: Der gesamte Originaldatensatz$queryBuilder
: DieQuery Builder
Instanz, die verwendet wird, um die Daten zu schreiben$table
: Die pseudifyTable
Instanz, die von dir modelliert wurde$column
: Die pseudifyColumn
Instanz, die von dir modelliert wurde$columnInfo
: Die doctrineColumn
Instanz mit nützlichen technischen Informationen über die Datenbankspalte
Möchtest du vor dem Update der Daten noch etwas manipulieren, so ist dies mittels der $queryBuilder
Instanz möglich. Eine Änderung der anderen Objekte und Daten wird keinerlei Auswirkung haben.
Ein "Pseudonymizer Profile" anwenden
Ein "Pseudonymizer Profile" kann mit dem Kommando pseudify:pseudonymize <profil-name>
ausgeführt werden.
Nach der Pseudonymisierung wird das Wort done
ausgegeben.
$ pseudify pseudify:pseudonymize test-profile
done
dry run
Du kannst dein Profil testen, ohne die Daten in der Datenbank zu überschreiben. Mit dem Parameter --dry-run
werden dir alle SQL Anweisungen aufgelistet, die pseudify ausführen würde.
pseudify pseudify:pseudonymize test-profile --dry-run
UPDATE `wh_user` SET `username` = :dcValue1:'tavares.satterfield' WHERE `username` = :dcValue2:'karl13'
UPDATE `wh_user` SET `password` = :dcValue1:'$argon2i$v=19$m=8,t=1,p=1$WUlUVS9HOW1PN1dXd1pyeg$GTKopoFTAlCufz2QS/c/DzcaLKm/6xMo80ZNiph48Q4' WHERE `password` = :dcValue2:'$argon2i$v=19$m=8,t=1,p=1$amo3Z28zNTlwZG84TG1YZg$1Ka95oewxn3xs/jLrTN0R9lhIxtNnQynBFRdE/70cAQ'
UPDATE `wh_user` SET `first_name` = :dcValue1:'Annalise' WHERE `first_name` = :dcValue2:'Jordyn'
UPDATE `wh_user` SET `last_name` = :dcValue1:'Strosin' WHERE `last_name` = :dcValue2:'Shields'
UPDATE `wh_user` SET `email` = :dcValue1:'ugutkowski@example.com' WHERE `email` = :dcValue2:'madaline30@example.net'
UPDATE `wh_user` SET `city` = :dcValue1:'Schoenborough' WHERE `city` = :dcValue2:'Lake Tanner'
UPDATE `wh_user` SET `username` = :dcValue1:'hollie.walter' WHERE `username` = :dcValue2:'reilly.chase'
UPDATE `wh_user` SET `password` = :dcValue1:'$argon2i$v=19$m=8,t=1,p=1$S1ZHRS54Z1FsNzBMSE11Mg$40Wr1wY7Az1e/cLZA04Jd25dGUYa5Xwcx1hyVsJv6QI' WHERE `password` = :dcValue2:'$2y$04$O0XKmRw3wl9mni55dSEJXuj3vygjCgdyUviihec.PTiTAu2SS/C6u'
UPDATE `wh_user` SET `first_name` = :dcValue1:'Daphnee' WHERE `first_name` = :dcValue2:'Keenan'
UPDATE `wh_user` SET `last_name` = :dcValue1:'Dietrich' WHERE `last_name` = :dcValue2:'King'
UPDATE `wh_user` SET `email` = :dcValue1:'felicia63@example.org' WHERE `email` = :dcValue2:'johns.percy@example.com'
UPDATE `wh_user` SET `city` = :dcValue1:'Juddport' WHERE `city` = :dcValue2:'Edwardotown'
UPDATE `wh_user` SET `username` = :dcValue1:'miller.ullrich' WHERE `username` = :dcValue2:'hpagac'
UPDATE `wh_user` SET `password` = :dcValue1:'$argon2i$v=19$m=8,t=1,p=1$NHlRS2E2Y0E5Z2JlWEJTLg$Rn20zQq0a+RDa0+x3YfWmaQ27duZdQyHEF7RcnODPFk' WHERE `password` = :dcValue2:'$argon2i$v=19$m=8,t=1,p=1$QXNXbTRMZWxmenBRUzdwZQ$i6hntUDLa3ZFqmCG4FM0iPrpMp6d4D8XfrNBtyDmV9U'
UPDATE `wh_user` SET `first_name` = :dcValue1:'Susanna' WHERE `first_name` = :dcValue2:'Donato'
UPDATE `wh_user` SET `last_name` = :dcValue1:'O\'Kon' WHERE `last_name` = :dcValue2:'Keeling'
UPDATE `wh_user` SET `email` = :dcValue1:'hjaskolski@example.com' WHERE `email` = :dcValue2:'mcclure.ofelia@example.com'
UPDATE `wh_user` SET `city` = :dcValue1:'Teresachester' WHERE `city` = :dcValue2:'North Elenamouth'
UPDATE `wh_user` SET `username` = :dcValue1:'caleigh.mayert' WHERE `username` = :dcValue2:'georgiana59'
UPDATE `wh_user` SET `password` = :dcValue1:'$argon2i$v=19$m=8,t=1,p=1$TEVqLm5JQncyWVZubWExbg$juQQzt5GPMHodHYEii5LhFK1l7kQQB4twaTLi5WId+k' WHERE `password` = :dcValue2:'$argon2i$v=19$m=8,t=1,p=1$SUJJeWZGSGEwS2h2TEw5Ug$kCQm4/5DqnjXc/3SiXwimtTBvbDO9H0Ru1f5hkQvE/Q'
UPDATE `wh_user` SET `first_name` = :dcValue1:'Kaya' WHERE `first_name` = :dcValue2:'Maybell'
UPDATE `wh_user` SET `last_name` = :dcValue1:'Ullrich' WHERE `last_name` = :dcValue2:'Anderson'
UPDATE `wh_user` SET `email` = :dcValue1:'meggie.stracke@example.com' WHERE `email` = :dcValue2:'cassin.bernadette@example.net'
UPDATE `wh_user` SET `city` = :dcValue1:'Leschmouth' WHERE `city` = :dcValue2:'South Wilfordland'
UPDATE `wh_user` SET `username` = :dcValue1:'smith.tianna' WHERE `username` = :dcValue2:'howell.damien'
UPDATE `wh_user` SET `password` = :dcValue1:'$argon2i$v=19$m=8,t=1,p=1$UG5xNENBektsOTk3bmpyTw$BAj6FBUDYe2t6QnW14qC+5S22gsI0iVLWawob1YiXKo' WHERE `password` = :dcValue2:'$argon2i$v=19$m=8,t=1,p=1$ZldmOWd2TDJRb3FTNVpGNA$ORIwp6yekRx02mqM4WCTVhllgXpUpuFJZ1MmbYwAMXs'
UPDATE `wh_user` SET `first_name` = :dcValue1:'Kelly' WHERE `first_name` = :dcValue2:'Mckayla'
UPDATE `wh_user` SET `last_name` = :dcValue1:'Block' WHERE `last_name` = :dcValue2:'Stoltenberg'
UPDATE `wh_user` SET `email` = :dcValue1:'shanny.gulgowski@example.org' WHERE `email` = :dcValue2:'conn.abigale@example.net'
UPDATE `wh_user` SET `city` = :dcValue1:'Port Wilberfurt' WHERE `city` = :dcValue2:'Dorothyfort'
UPDATE `wh_log` SET `ip` = :dcValue1:'973a:942c:b9c7:d128:f8d4:c4cf:3d16:d168' WHERE `ip` = :dcValue2:'1321:57fc:460b:d4d0:d83f:c200:4b:f1c8'
UPDATE `wh_log` SET `log_message` = :dcValue1:'{"message":"foo text \\"jamison59\\", another \\"hjaskolski@example.com\\""}' WHERE `log_message` = :dcValue2:'{"message":"foo text \\"ronaldo15\\", another \\"mcclure.ofelia@example.com\\""}'
UPDATE `wh_log` SET `ip` = :dcValue1:'187.165.144.16' WHERE `ip` = :dcValue2:'155.215.67.191'
UPDATE `wh_log` SET `log_message` = :dcValue1:'{"message":"foo text \\"jerald.harber\\", another \\"sporer.tierra@example.org\\""}' WHERE `log_message` = :dcValue2:'{"message":"foo text \\"stark.judd\\", another \\"srowe@example.net\\""}'
UPDATE `wh_log` SET `ip` = :dcValue1:'6f5a:517a:963e:86fd:d691:c2a9:fe4f:4ea7' WHERE `ip` = :dcValue2:'4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98'
UPDATE `wh_log` SET `log_message` = :dcValue1:'{"message":"bar text \\"Volkman\\", another \\"bayer.casandra\\""}' WHERE `log_message` = :dcValue2:'{"message":"bar text \\"Tromp\\", another \\"freida.mante\\""}'
UPDATE `wh_log` SET `ip` = :dcValue1:'237.29.53.144' WHERE `ip` = :dcValue2:'243.202.241.67'
UPDATE `wh_log` SET `log_message` = :dcValue1:'{"message":"bar text \\"Ruecker\\", another \\"caleigh.mayert\\""}' WHERE `log_message` = :dcValue2:'{"message":"bar text \\"Block\\", another \\"georgiana59\\""}'
UPDATE `wh_log` SET `ip` = :dcValue1:'253.3.54.48' WHERE `ip` = :dcValue2:'132.188.241.155'
UPDATE `wh_log` SET `log_message` = :dcValue1:'{"message":"bar text \\"Braun\\", another \\"johann.thompson\\""}' WHERE `log_message` = :dcValue2:'{"message":"bar text \\"Homenick\\", another \\"cyril06\\""}'
UPDATE `wh_user_session` SET `session_data` = :dcValue1:'a:1:{s:7:"last_ip";s:39:"6f5a:517a:963e:86fd:d691:c2a9:fe4f:4ea7";}' WHERE `session_data` = :dcValue2:'a:1:{s:7:"last_ip";s:38:"4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98";}'
UPDATE `wh_user_session` SET `session_data_json` = :dcValue1:'{"data":{"last_ip":"6f5a:517a:963e:86fd:d691:c2a9:fe4f:4ea7"}}' WHERE `session_data_json` = :dcValue2:'{"data":{"last_ip":"4fb:1447:defb:9d47:a2e0:a36a:10d3:fd98"}}'
UPDATE `wh_user_session` SET `session_data` = :dcValue1:'a:1:{s:7:"last_ip";s:13:"223.86.155.35";}' WHERE `session_data` = :dcValue2:'a:1:{s:7:"last_ip";s:13:"107.66.23.195";}'
UPDATE `wh_user_session` SET `session_data_json` = :dcValue1:'{"data":{"last_ip":"223.86.155.35"}}' WHERE `session_data_json` = :dcValue2:'{"data":{"last_ip":"107.66.23.195"}}'
UPDATE `wh_user_session` SET `session_data` = :dcValue1:'a:1:{s:7:"last_ip";s:13:"49.170.101.59";}' WHERE `session_data` = :dcValue2:'a:1:{s:7:"last_ip";s:13:"244.166.32.78";}'
UPDATE `wh_user_session` SET `session_data_json` = :dcValue1:'{"data":{"last_ip":"49.170.101.59"}}' WHERE `session_data_json` = :dcValue2:'{"data":{"last_ip":"244.166.32.78"}}'
UPDATE `wh_user_session` SET `session_data` = :dcValue1:'a:1:{s:7:"last_ip";s:39:"973a:942c:b9c7:d128:f8d4:c4cf:3d16:d168";}' WHERE `session_data` = :dcValue2:'a:1:{s:7:"last_ip";s:37:"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8";}'
UPDATE `wh_user_session` SET `session_data_json` = :dcValue1:'{"data":{"last_ip":"973a:942c:b9c7:d128:f8d4:c4cf:3d16:d168"}}' WHERE `session_data_json` = :dcValue2:'{"data":{"last_ip":"1321:57fc:460b:d4d0:d83f:c200:4b:f1c8"}}'
UPDATE `wh_user_session` SET `session_data` = :dcValue1:'a:1:{s:7:"last_ip";s:13:"78.176.79.162";}' WHERE `session_data` = :dcValue2:'a:1:{s:7:"last_ip";s:14:"197.110.248.18";}'
UPDATE `wh_user_session` SET `session_data_json` = :dcValue1:'{"data":{"last_ip":"78.176.79.162"}}' WHERE `session_data_json` = :dcValue2:'{"data":{"last_ip":"197.110.248.18"}}'
UPDATE `wh_meta_data` SET `meta_data` = :dcValue1:'1f8b08000000000000036551b14ec33010fd15e48181c1c44e429bcb0002d105211531b0118ec64dac3a7664bb6a23e8bf6387462d62bbe7f7eededd33420a5f0e32201b3130522214117320b226a584bc743007b275c26aec04099005d275d2b7d44bd41ac9afa447e776c6d6a324e045fa5e3e5c7af2a15f96c9d3d5fa9b4ecca4ac5a746de5875e1c47a06d8ce6b2fe27ec154aedc5de8f4c0a442ff232b9b9d5eef55a3f8e8f0990b5b4ce57d39a3320cf58a31a7444051085676c0ee45e99d5e6588b0ea58a350fb6ae0d670db4d9aac6ecdc46de893d76bd12d4d8266a42582be987d136f42e8df5176f527d0abbdedab0e261ca93c73cf99f3cd32940e19c34baaad18f01662c9c0f2c6a67c755653f5d9b1594cd12ca1246f322cc3fb348a3053b7d6136f6847a9e077d46194f2867f3d071f8013d717beaeb010000' WHERE `meta_data` = :dcValue2:'1f8b080000000000000365525d4f023110fc2fcd3d9a4a7bc7570951236234011340455fc8c215aea1d7d66b112e86ff6e7b7211e3db4e77ba33d32db0987d599630b4e525413d60dd80294322453dc19a3dcb3a0ced2c2f14e41c7948628632bde752e21472c115fae118b076af8b34c0ae1f1041b1d18a8ae8b34fba51deef5cb83eb9307d12bdcb347f7a4de96cf03859c6c3d9f8c5dc8f6fa2a7c9c3deb44abe9d1c1a34ff1825afb7b3974ccacddc3c9bddf0f19d8cf2e5dbfe6634b7958f33cd4506365bb8d2f093999376fa8f682408e5f8c1d551d4b0d96bb4ae949d5eaabbeab0c1d05a14d62deac46d8646ab2d9412aa6c0c4938eb12c2d0d469e9b85af262138e9a0cf11c840c35f56fbbd24a61588a0d487ecd0f901bc9b1e29587d016aeac270d74a15d56ae75e1bbc77a33346c86fed94c1c2e7864b9b542ab450aaeb297f821c048e0b64f4e85a9c3d224c1a4d5c231c5ed8e9f7f26110709f2fb1912741220711777086e605f78fef11bb387fddf33020000'
UPDATE `wh_meta_data` SET `meta_data` = :dcValue1:'1f8b08000000000000036551cb4ec33010fc15e403070e26cea3259b0308442f08a9880337c2d2b88955c78e6c576d04fd776cd3a845dc763cb33bbb63840cbe2ce440367c64a44228034e81888654028acac20d90ade54661cf8987cc93b617aea34ea052487e25035abbd3a689128f17d97bf570e9c8877a59264f57eb6f3a3193b2eed076b51b077e1c81a6d52a15cd3fe1205128c7f72e321910b528aa6476abecebb57a8c8f0990b530d6d5d39a7320cfd8a01c5540251089676c01e45eead5e658f31e850c75ea6d6de7cf1a69bb95added98db8e37bec07c9a9366dd0f8b056c28dd1d6f72eb571176f427e72b3de1abfe261ca330d79a67ff2cca600b9b542abba411703cc993f1f58d0ce8fab8a61ba362f299b2794258c16a59f7f6691050b76fac23cf6e4b127cd67949519652c341d7e0050c4f2c6eb010000' WHERE `meta_data` = :dcValue2:'1f8b080000000000000365525b4fc23014fe2fcd1ecda4ddc6a5842851319a800920282fe4cc55d6d0b5752dc262f8efb693458c0f4d7a6edfa5a74023fa65684cd1965518f581f67c4c28e219ea739af40ded52b433ac945030e4421c5194ab3d1322cca0e04ca29f1e0dc6ec5599f9b0e7000228374a121e7c0e702f2806dd0b3bc0177a808395c88aa76546e6b78fd3341acd270b7d3f19064fd387bd6e576c3b3db448f1318e9737f3452ec4e6453febdde87185c745faba1f8e5f4cade38c739d83c9d7b6d2ec24e6c49dfd6bd402b8b4ec601b2b7294f45bed2b696697f2ae4eb6287ae7a5b1ebc67187a2f1db162a01b5378a049c5531a6686695b04ca6acdcf85442112b800b7f27ee6ddf949421a47c03825db303145ab050b25a832f735b3548b7aa5436afde55e9aac76633c46f86fcd94ce4075c6498315cc97506b696173b10a0d8f7764e4ab96ecc92380e71bb1d4624ec741dfe1945e429f0ef6788eb19e704773b218e9290443d7fdcc8f11b4093841d36020000'
UPDATE `wh_meta_data` SET `meta_data` = :dcValue1:'1f8b08000000000000036591416fc3200c85ff0b937a8c0aa149ea5e769b2a6dc749532f99076e820a4914a8d6a8eb7f1f748dd669379efdc17bd808399c3d4860079a38db20ac9316c08c661b0372e3a10276f43476e88845c923acd09269dacce14463603fd080de7ff6a3be422b60bbf7b35b368b7e11e881b6876bf90eab5bf46d1da6816ef7716cfa4e18fd0f1c2c9a2ed0e96ac49731ced36eabbef04deab9b237a30ff51cb104f6829aecd425b50666f16ff7d5dad1a836a918941c1a9bcea200e6a8690c653e8ca80ef448277483a54cf52e11e9ef264cb3ed3379d5bafe18e25397798c228d51fc1b238fca93f7a6ef6a8d01d31b45cc82c0135bde529a2135f2187a5de6711d5228f858ab12341715ec2b2d4149b5875cf322d68a2a3adf99e7c99cffee54cedb10ab3c137299f1b2c8b888d8e5f20dabf0038ffd010000' WHERE `meta_data` = :dcValue2:'1f8b08000000000000036592dd6ea33010855f65657159116ca0818922f52fca6ea5d52a4bab46bd89066c821b302c769246ddbcfbda6ca246eae5f11cfb3be31984103e34444036e240c90421759a01919c4c2444130d0990ad16bdc246102b2905b2166dbf96a8304ec97f47875aefdb9e3b99daeb1ef6eb5631e9eda634f59a697265a6f4aa9b522f7b7e7c142faff36c3edb67ac624fb37dfcbcf636f78b261ac50f7fd4dbb21885995cee65639eee76f9c3aff47bf07b4bcbb8da2c76b3d1624871c15c55a8ab953974e214e6c4e65f8c5d8d5219f16e864a601b9bbffe28fee232e2e79352f6daaccecd8e81fcc4432eea7a680c488d1755fbf4ade2a2d7ad723206221a948395596f61b152f9b9fb3b2e8c1137e21d9bae16be124302fbed853487016d4959bb35d5b7175997366b8dca663a9e67c3dc6cd897d950abb4b09856ad381a744f5ddb1c08d479c7a7c0b27385d04a1a320af1b82c20ba0e72e0110f80276109050b02887228699158ee053a7468fab926d1790b58e0533f4e7c1ad92d381eff01fdaee8ae4c020000'
UPDATE `wh_meta_data` SET `meta_data` = :dcValue1:'1f8b08000000000000036551cb4ec33010fc15e403070ea6cea349370710885e105211076e84a57113ab8e1dd98eda08faefd82111957adbf1cceeec8e1162f8b69000d9f3819102611570044454a4109016167220bde54661cb8987cc93b615aea14ea05248fe241d5a7bd0a61a251eafe38fe2f1da914ff5ba593cdfec7ee8cccccab241db946ee8f834024dad5524aa0b61275128c78f6e6462206a9d168be59db26fb7ea697c5c00d909635d39af990179c10ae5a0025a019178c6a6401ea4deeea79ab72864a8236f6b1b7fd640eb5ed6fa60f7e29e1fb1ed24a7dad441e3c3da0a378cb6be77a38dbb7a17f28b9b5d6ffc8aa739cf28e4195de43906c8ad155a9515ba31c084f9f381056d36ad2abaf9da2ca72c5bd26c45d9d2cf3c9d59c4c182fd7f6132ff104b539ae7344e7d8fd79f7e01b01c72f9e9010000' WHERE `meta_data` = :dcValue2:'1f8b08000000000000036552616bc23010fd2fa11fa5336dd51a299bcc3926e8409d3abfc8d5461b4c93ac89d332fcef4b3bcb043f047277efde7b970b109ffc68121074a005463d20dd32f6086209ea31d2ea69121274d4341790516443ec1394ca13e5dc4d206354a03f8c02ad4f324fcab06b091cc8f75278ccf98e70d7c9a2b06122dc501176d63cc9de9789371f8ca6b13f9c4f16ea75d277dea76f27d52ee8617a6e7ad9d738583ecf1729e7fb95fa50c7e1688dc759fc79ea8f57baf271a3b94941a71b53287a3573d54eee808a0313869e4d3d8a18b67acdf6a3d0b307f152259b04ed58aecda69eb843d0787b808243351b411c6eaa18133433921b2a629aefcb548b209a01e3e5ddb36fbb9542b810b33d70fa44cf90294e5d412b0f659999a2661ac85c9ab4d8c9dc562ff566bc7233dedd66b08d34d59a49b149c054f6029b03824b6ce7ea94a98add52e16ec7c5b8e97a41e8e2d00adc68f8a506feff0d41dd14fa166f0f6edbde96edb8fc020ca4e19b36020000'
UPDATE `wh_meta_data` SET `meta_data` = :dcValue1:'1f8b080000000000000365514d4fc3300cfd2f06895bb4a42ba5ee85cb8410425cb8200e95d5863534fd509cc12ab4ff4ed2ad6268a7f8c9cfcf7e2f8409fe30ae115a3d492808f3881582a9a13098148c77083bd6aea74e438032903b63ad766267ad33550347d248ccdf83ab23bc4578ebdaebcd669e386b960d7153fa699cb5320472dba157e682375a32bdd77b7f527fafbf1eeaabede34c5c217c18c7be5c8e4a119e0dfb29d63982a5ffbd979ba7a13fd5ba236363ad82cbe693b81d2cb7e65eefa91bad16d5d0c56e705999a3a04c105eb5d34c55a3d96b07c561c94cc5ccd445663220d6cc66e8cb9a3ccd8a32b84519b9d9e944332efaeb5cc86c25e44a8a340ffa672b92b842fe7dd37a9991a9506922940a6f16060ebfc7a9a250ce010000' WHERE `meta_data` = :dcValue2:'1f8b080000000000000365915f4fc23014c5bf8aa97b240bedc6c64a480c22c428448828c10772dd0a6b5cd7ba967f1abebbedc448c25b4feeb9f7776e2fd0807e6b1a52f4c10e187580264e138a78863a9c061d4ddb146d34ab4a100c591951942b58438a7e6b0ab4dec92a7332b18d1e546b5912ee6dbb38f144b7dd305ddc505dec4de6e3f9fbf374b478dd0b56f6a6b3af6cb798783cca4b33eb3f42b0187c8adb61381835f953a5462acac27e7bbeaac63d73e88b9764e618f88cb9cc41e74b735075b298a213fbc2a70ae0a5617b730afd966d87d9f5fabe3636295af14a9be5d98a7d598291f54e14157056b49407c60a5eae9d6a51c404f0c2bd89ed13695a6c2ae6cb95b5c00ddb835005f353299cc3fe73cacda1a65af3585626bfba2b989d2d3726479de3df2d88bb05b9b805b64a33adb92c971918a88762bb37c5ce1b9fb2725523028a4818fa388afc80f871dbce3f43040e81ffcf1fa2138004894f62bf15fbd8c6381e7f00628e8a6d25020000'
Note
Die Originaldaten und die pseudonymisierten Daten werden nicht 1:1 ausgegeben.
Valides SQL der ersten Zeile müsste UPDATE wh_user SET username = 'tavares.satterfield' WHERE username = 'karl13'
lauten.
--dry-run
listet jedoch zusätzlich vor den Daten den Namen des intern verwendeten Platzhalters (z.B. :dcValue1:
, :dcValue2:
...) auf, was das Debugging vereinfachen kann.