Die Einhaltung der GDPR in all Ihren Projekten ist eine tägliche Herausforderung - vor allem, wenn Sie sensible Nutzerdaten in Ihren Projekten verwalten. Upsun verfolgt einen "GDPR everywhere" -Ansatz mit einem hohen Maß an eingebauter Sicherheit und Konformität als Standard - aber es gibt Möglichkeiten, Ihre Daten auf unserer PaaS weiter zu sichern , wenn es um Vorschauumgebungen geht.
Jedes Mal, wenn Sie einen neuen Git-Zweig für ein Projekt auf Upsun erstellen, erbt die entsprechende Umgebung die Daten (Assets und Datenbank) von ihrer Muttergesellschaft. Das bedeutet, dass potenziell sensible Daten von Ihrer Produktionswebsite in der Vorschauumgebung sichtbar werden könnten.
Wie können Sie also damit umgehen und sicherstellen, dass Ihre Anwendung konform bleibt? Zwei Worte: Datenbereinigung. Die absichtliche und dauerhafte Löschung sensibler Daten von einem Speichergerät, so dass die Daten nicht wiederhergestellt werden können. In diesem Artikel stelle ich Ihnen die Methoden der Datenbereinigung vor, die Sie in Vorschauumgebungen implementieren können , um sicherzustellen, dass Ihre Daten in jeder Phase der Entwicklung sicher sind.
Es gibt einige Voraussetzungen, die sicherstellen, dass Sie die in diesem Artikel beschriebenen Lösungen und Schritte befolgen können - bitte stellen Sie sicher, dass Sie Folgendes installiert haben:
In diesem Artikel konzentrieren wir uns auf die Bereinigung von Umgebungsdaten in der Vorschau von Symfony, die beschriebenen Methoden gelten jedoch für alle Frameworks.
Im Laufe des Artikels gehen wir durch die verschiedenen Methoden, die zur Bereinigung von Symfony-Vorschau-Umgebungsdaten auf Upsun zur Verfügung stehen - 5 Methoden, um genau zu sein -, die Sie abwägen und die beste für Sie auswählen können. Stellen Sie jedoch sicher, dass Sie den Schritt "create a command" abschließen , bevor Sie mit einer Methode fortfahren.
Wenn Sie bereits wissen, welche Methode Sie bevorzugen, klicken Sie einfach auf den entsprechenden Titel unten und wir bringen Sie direkt dorthin:
Um eine der fünf oben aufgeführten Methoden zur Datenbereinigung auszuführen, benötigen wir eine Callable, um unsere Umgebungen zu bereinigen. Es gibt zwei Möglichkeiten, dies zu tun:
Da wir eine Symfony-Demo-Anwendung verwenden, werden wir die zweite Option nutzen. Führen Sie die folgenden Schritte aus dem Haupt-Git-Zweig
aus:
symfony composer require --dev fakerphp/faker git add composer.json composer.lock && git commit -m "composer require --dev fakerphp bundle"
Öffnen Sie dann Ihren Code in Ihrer bevorzugten IDE und erstellen Sie einen neuen Symfony-Befehl in einer Datei SRC/command/SanitizeDataCommand.php mit folgendem Inhalt:
<?php /* src/Command/SanitizeDataCommand.php */ namespace App\Command; use App\Entity\User; use App\Repository\UserRepository; use Doctrine\ORM\EntityManagerInterface; use Faker; use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; #[AsCommand( name: 'app:sanitize-data', description: 'Sanitize user data (username and email).', aliases: ['app:sanitize'] )] class SanitizeDataCommand extends Command { private SymfonyStyle $io; public function __construct(private UserRepository $userRepository, private EntityManagerInterface $entityManager) { parent::__construct(); } protected function configure() { $this ->setDescription('Mit diesem Befehl können Sie die Benutzerdaten (Benutzername und E-Mail) bereinigen.'); } protected function initialize(InputInterface $input, OutputInterface $output): void { $this->io = new SymfonyStyle($input, $output); } protected function execute(InputInterface $input, OutputInterface $output): int { $users = $this->userRepository->findAll(); $this->io->progressStart(count($users)); $this->entityManager->getConnection()->beginTransaction(); // Auto-Commit aussetzen try { /** @var User $user */ foreach ($users as $user) { $this->io->progressAdvance(); // Faker initialisieren $faker = Faker\Factory::create(); $this->io->text('faking user '.$user->getUsername()); // Benutzerdaten fälschen $user->setUsername(uniqid($faker->userName())); $user->setEmail($faker->email()); // bitte an Ihre Bedürfnisse anpassen }
$this->entityManager->flush(); $this->entityManager->getConnection()->commit(); $this->io->progressFinish(); } catch (\Exception $e) { $this->entityManager->getConnection()->rollBack(); throw $e; } return Command::SUCCESS; } }
Dieser Befehl app:sanitize-data
verwendet das UserRepository und fälscht den Benutzernamen und die E-Mail aus der Symfony-Standardentität User. Bitte passen Sie ihn an Ihre Bedürfnisse an. Dann pushen Sie Ihren Code in den Hauptzweig
:
git add src/Command/SanitizeDataCommand.php && git commit -m "sanitize data command"
symfony einsetzen
Da Ihr Quellcode nun einen Symfony-Befehl zur Datenbereinigungenthält , werden wir ihn manuell in einer neuen Vorschauumgebung verwenden. Beginnen Sie mit der Erstellung eines neuen Staging-Zweiges und warten Sie, bis der Prozess abgeschlossen ist, wie folgt:
symfony branch staging --type=staging
Führen Sie dann den neu erstellten Symfony-Befehl in Ihrer Upsun-Staging-Umgebung aus, wie unten dargestellt:
symfony ssh php bin/console -e dev app:sanitize-data
Et voilà, die Daten Ihrer Vorschauumgebung sind bereinigt!
In diesem Abschnitt werden wir eine Vorschauumgebung erstellen, ihre Daten bereinigen und dann alle neuen Umgebungen von dieser Vorschauumgebung erben lassen.
Wie bereits am Anfang dieses Artikels erwähnt, erbt die erstellte Umgebung jedes Mal, wenn Sie einen neuen Git-Zweig auf Upsun erstellen, die Daten der übergeordneten Umgebung. Es ist jedoch möglich, die standardmäßige Datenvererbung zu ändern und sie später so einzustellen, dass sie Daten von einer neuen Elternumgebung synchronisiert - der Vorschauumgebung, die wir erstellen werden.
Die Symfony CLI bietet die Möglichkeit, einen Zweig ohne Elternteil zu erstellen, indem die Option --no-clone-parent
verwendet wird , und dann den Elternteil auf staging (auch bekannt als preview) zu setzen, was sicherstellt, dass neue Zweige die Daten der Preview-Umgebung erben. Folgen Sie den Anweisungen in Schritt 1, um zu erfahren, wie Sie die Daten der Preview-Umgebung manuell bereinigen, um sicherzustellen, dass alle zukünftigen Zweige bereinigte, GDPR-konforme Daten erben.
symfony checkout main symfony branch dev --no-clone-parent symfony env:info -e dev parent staging symfony sync -e dev data
Und das war's. Ihre neue Entwicklungsumgebung wird nun mit den bereinigten Daten aus Ihrer Vorschauumgebung erstellt.
Anstatt sich auf die Vererbung zu verlassen, kann es wünschenswert sein, bestimmte Daten bei jeder Bereitstellung zu bereinigen. In diesem Fall können wir unseren Skriptaufruf in den Abschnitt hooks
der Konfiguration verschieben .
Für welche Art von Hook Sie sich entscheiden- Deploy- oder Post-Deploy-Hooks -, bleibt Ihnen überlassen, aber es gibt einige Dinge zu beachten:
Um einen Symfony-Befehl während des post_deploy
Hooks auszuführen , fügen Sie das Folgende in Ihre .upsun/config.yaml
ein :
applications: app: hooks: build: ... deploy: ... post_deploy: | if [ "$PLATFORM_ENVIRONMENT_TYPE" != production ]; then # Die Bereinigung der Datenbank sollte hier stattfinden (da sie nicht produktiv ist) php bin/console -e dev app:sanitize-data fi
Pushen Sie dann Ihren Code in den Hauptzweig:
git checkout main && git add .upsun/config.yaml && git commit -m "add sanitize data command to post_deploy hook"
symfony deploy
Es gibt eine weitere Option, mit der Sie einen benutzerdefinierten Trigger erstellen können, der als Reaktion auf bestimmte Aktivitäten im Projekt ausgeführt wird. Bei der Synchronisierung einer Umgebung mit der übergeordneten Umgebung könnten wir nämlich nicht anonymisierte Daten aus der übergeordneten Umgebung zurücksynchronisieren (z. B. bei der Synchronisierung aus der Produktionsumgebung).
Die beiden Komponenten, die dies ermöglichen, sind:
Wir fügen also eine Integration (Aktivitätsskript) hinzu, die auf bestimmte Ereignisse reagiert, um eine Laufzeitoperation zur Datenbereinigung im laufenden Betrieb auszuführen, siehe Integration eines Aktivitätsskriptshinzufügen unten.
Um eine Runtime-Operation zu konfigurieren, müssen wir einen neuen Top-Level YAML-Schlüssel in unserer .upsun/config.
yaml-Datei mit folgendem Inhalthinzufügen :
applications: app:
operations: sanitize: role: admin commands: start: | if [ "$PLATFORM_ENVIRONMENT_TYPE" != production ]; then # Die Bereinigung der Datenbank sollte hier stattfinden (da sie nicht produktiv ist) php bin/console -e dev app:sanitize-data fi
Pushen Sie dann Ihre Datei in den Hauptzweig
und stellen Sie sie bereit.
git checkout main git add .upsun/config.yaml && git commit -m "add runtime operation to sanitize data" symfony deploy
Wenn Sie diese Runtime-Operation manuell testen möchten, können Sie Folgendes verwenden:
symfony operation:run sanitize --app=app
Upsun unterstützt benutzerdefinierte Skripte, die als Reaktion auf eine beliebige Aktivität ausgelöst werden können. Dieses Skript wird außerhalb des Umgebungskontextes ausgeführt. Daher müssen wir diesen Kontext neu erstellen, damit das Aktivitätsskript mit den erforderlichen Rechten ausgeführt werden kann. Erstellen Sie dazu eine neue Datei src/runtime/sanitize.js
mit folgendem Inhalt:
// src/runtime/sanitize.js let app_container = "app"; let runtime_operation_name = "sanitize"; if (!variables.api_token) { console.log("Variable API Token ist nicht definiert!"); console.log("Bitte definieren Sie eine Umgebungsvariable mit Ihrem API-Token mit dem Befehl: "); console.log("upsun project:curl /integrations/<INTEGRATION_ID>/variables -X POST -d '{\"name\": \"api_token\", \"value\": \"<API_TOKEN>\", \"is_sensitive\": true, \"is_json\": false}' "); } else { console.log("OAuth2 API Token definiert"); let resp = fetch('https://auth.api.platform.sh/oauth2/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: "client_id=platform-api-user&grant_type=api_token&api_token=" + variables.api_token }); if (!resp.ok) { console.log("Failed to get an OAuth2 token, status code was " + resp.status); } else { console.log("OAuth2 API TOKEN ok"); } let access_token = resp.json().access_token; // get current branch from activity object let branch; switch (activity.type) { case 'environment.synchronize': branch = activity.parameters.into; break; case 'environment.branch': case 'environment.activate': branch = activity.parameters.environment; break; } // Laufzeitoperation runtime_operation_name auf aktuelle/gezielte Umgebung ausführen resp = fetch("https://api.upsun.com/api/projects/" + activity.project + "/environments/" + branch + "/deployments/current/operations", { headers: { "Authorization": "Bearer " + access_token }, method: "POST", body: JSON.stringify({"service": app_container, "operation": runtime_operation_name}), }); if (!resp.ok) { console.log("Failed to invoke the runtime operation, status code was " + resp.status); } else { console.log(runtime_operation_name + " launched"); } }
Dieses Aktivitätsskript verwendet ein API-Token als Umgebungsvariable, um sich mit der aktuellen Umgebung zu verbinden und die zuvor definierte Laufzeitoperation mithilfe der Upsun-API auszuführen . Wir müssen diese Umgebungsvariable für die Integration unseres Aktivitätsskripts definieren und später eine API Token Umgebungsvariable hinzufügen.
Dann schieben Sie Ihre Datei in den Hauptzweig
und verteilen Sie sie wie folgt:
symfony checkout main git add src/runtime/sanitize.js git commit -m "add activity script" symfony deploy
Drei Upsun-Ereignisse sollten diese Laufzeitoperation auslösen:
environment.branch
), environment.synchronize
), environment.activate
). Um diese Auslöser zu implementieren, verwenden Sie diesen Befehl in Ihrem Terminal, um eine Aktivitätsskript-Integration hinzuzufügen.
symfony integration:add --type script --file ./src/runtime/sanitize.js --events environment.branch,environment.synchronize,environment.activate --states complete --environments \*
Hinzufügen einer API-Token-Umgebungsvariable
Ermitteln Sie zunächst die vorherige Integrations-ID mit dem folgenden Befehl:
symfony integration:list
Erstellen Sie dann ein neues API-Token in der Konsole, behalten Sie den Wert in der Hand und ersetzen Sie ihn in diesem Terminalbefehl:
symfony project:curl /integrations/<INTEGRATION_ID>/variables -X POST -d '{"name": "api_token", "value": "<API_TOKEN>", "is_sensitive": true, "is_json": false}'
Sie können mit diesem Befehl überprüfen, ob die Variable erstellt wurde:
symfony project:curl /integrations/<INTEGRATION_ID>/variables
Um zu testen, ob alles funktioniert hat, lösen Sie in der Konsole oder mit der CLI die Erstellung eines neuen Zweigs von main
aus, lösen Sie eine Synchronisierung aus, deaktivieren und reaktivieren Sie Ihre Vorschauumgebung, und dann sollten Sie zwei Aktivitäten sehen:
Wenn Sie auf ein Problem stoßen und die Integration des Aktivitätsskripts debuggen möchten, müssen Sie den folgenden Befehl verwenden:
symfony integration:activity:log <INTEGRATION_ID>
Wenn Sie die Integration Ihres Aktivitätsskripts hinzufügen, wird das entsprechende Skript auf der Upsun-Seite im Speicher hinzugefügt. Das bedeutet, dass Sie jedes Mal, wenn Sie Ihr Skript aktualisieren, die zwischengespeicherte Version der Datei aktualisieren müssen, indem Sie den folgenden Befehl verwenden:
symfony integration:update <INTEGRATION_ID> --file ./src/runtime/sanitize.js
Es ist möglich, ein Shell-Skript zu verwenden, um die Datenbereinigung aller Umgebungen außer der Produktionsumgebung für alle Projekte innerhalb einer Organisation zu automatisieren - erfahren Siehier mehr über Organisationen. Um dieses Shell-Skript zu verwenden, stellen Sie bitte sicher, dass alle Umgebungsquellen aller Ihrer Projekte innerhalb Ihrer Organisation den Symfony-Befehl zur Datenbereinigung enthalten , bevor Sie die folgenden Schritte durchführen.
Der erste Schritt besteht darin, eine Datei namens fleet_sanitizer.sh mit dem folgenden Code zu erstellen:
if [ -n "$ZSH_VERSION" ]; then emulate -L ksh; fi ###################################################### # fleet sanitization demo script, using the CLI.
# # Aktiviert den folgenden Arbeitsablauf für ein bestimmtes Projekt und reinigt Vorschauumgebungen (Staging-, New-Feature- und Auto-Updates-Umgebung): # . # └── main # ├── staging # | └── new-feature # └── auto-updates # # Verwendung # 1. source this script: `. fleet_sanitizer.sh` oder `source fleet_sanitizer.sh`, abhängig von Ihrem lokalen Rechner # 2. define ORGANIZATION var: ORGANIZATION=<organizationIdentifier> # 3. run `sanitize_organization_data $ORGANIZATION` ###################################################### # Utility functions. # list_org_projects: Gibt eine Liste der Projekte aus, auf die die Operation vor dem Start angewendet wird. # $1: Organisation, wie sie in console.upsun.com erscheint. list_org_projects() { symfony project:list -o $1 --columns="ID, Title" } # get_org_projects: Liefert ein Array von Projekt-IDs für eine bestimmte Organisation. # Hinweis: Macht die Array-Variable PROJECTS für nachfolgende Skripte verfügbar. # $1: Organisation, wie sie in console.upsun.com erscheint. get_org_projects() { PROJECTS_LIST=$(symfony project:list -o $1 --pipe) PROJECTS=($PROJECTS_LIST) } # get_project_envs: Ruft ein Array von Umgebungs-IDs für ein Projekt ab. # Hinweis: Macht die Array-Variable ENVS für nachfolgende Skripte verfügbar. # $1: Projekt-ID, wie sie in console.upsun.com erscheint. get_project_envs() { ENV_LIST=$(symfony environment:list -p $1 --pipe) ENVS=($ENV_LIST) } # list_project_envs: Liste der Umgebungen ausgeben, auf die die Operation vor dem Start angewendet wird. # $1: ProjectId, wie sie in console.upsun.com erscheint. list_project_envs() { symfony environment:list -p $1 } # add_env_var: Umgebungsvariable auf Umgebungsebene hinzufügen. # $1: Variablenname. # $2: Variablenwert. # $3: Zielprojekt-ID. # $4: Zielumgebungs-ID. add_env_var() { VAR_STATUS=$(symfony project:curl -p $3 /environments/$4/variables/env:$1 | jq '.status') if [ "$VAR_STATUS" != "null" ]; then symfony variable:create --name $1 --value "$2" --prefix env: --project $3 --environment $4 --level environment --json false --sensitive false --visible-build true --visible-runtime true --enabled true --inheritable true -q else printf "\nVariable $1 existiert bereits. Skipping." fi } # Hauptfunktionen. sanitize_organization_data() { list_org_projects $1 get_org_projects $1 for PROJECT in "${PROJECTS[@]}"; do printf "\n### Project $PROJECT." # get environments list list_project_envs $PROJECT get_project_envs $PROJECT for ENVIRONMENT in "${ENVS[@]}"; do unset -f ENV_CHECK ENV_CHECK=$(symfony project:curl -p $PROJECT /environments/$ENVIRONMENT | jq -r '.status') unset -f ENV_TYPE ENV_TYPE=$(symfony project:curl -p $PROJECT /environments/$ENVIRONMENT | jq -r '.type') if [ "$ENV_CHECK" = active -a "$ENV_TYPE" != production ]; then unset -f DATA_SANITIZED DATA_SANITIZED=$(symfony variable:get -p $PROJECT -e $ENVIRONMENT env:DATA_SANITIZED --property=value) if [ "$DATA_SANITIZED" != true ]; then printf "\nUmgebung $ENVIRONMENT existiert und ist noch nicht sanitized. Sanitize data." printf "\n" # do sanitization here symfony ssh -p $PROJECT -e $ENVIRONMENT -- php bin/console app:sanitize-data printf "\nSanitizing data is finished, redeploying" add_env_var DATA_SANITIZED true $PROJECT $ENVIRONMENT else printf "\nEnvironment $ENVIRONMENT exists and does not need to be sanitized. Überspringen." fi elif [ "$ENVIRONMENT" == main ]; then printf "\nEnvironment $ENVIRONMENT is production one, skipping." else printf "\nEnvironment $ENVIRONMENT is not active $ENV_CHECK, skipping." fi done done }
Je nachdem, auf welchem Rechner Sie das Skript ausführen wollen, passen Sie den Code bitte an Ihre Bedürfnisse an, aber er sollte in etwa so aussehen:
. fleet_sanitizer.sh # oder source fleet_sanitizer.sh ORGANIZATION=<organizationIdentifier> sanitize_organization_data $ORGANIZATION
Und schon sind Ihre Daten bereinigt und Sie sind auf dem besten Weg zur GDPR-Konformität!
Wenn Sie weitere Fragen zu unseren Sicherheits- und Compliance-Funktionen haben oder Probleme mit den oben genannten Methoden und/oder Schritten auftreten, wenden Sie sich an unser Support-Team, das Ihnen gerne weiterhilft.
Bleiben Sie auf unseren Social Media- und Community-Kanälen immer auf dem Laufenden. Besuchen Sie uns auf Dev.to, Reddit und Discord.