Être conforme au GDPR dans tous vos projets est un défi quotidien - en particulier si vous gérez des données utilisateur sensibles sur vos projets. Upsun adopte une approcheGDPR everywhere avec des niveaux élevés de sécurité et de conformité intégrés en standard - mais il existe des moyens de sécuriser davantage vos données sur notre PaaS lorsqu'il s'agit d'environnements de prévisualisation.
Chaque fois que vous créez une nouvelle branche Git sur un projet sur Upsun, l'environnement correspondant hérite des données (actifs et base de données) de son parent. Cela signifie que des données potentiellement sensibles de votre site web de production peuvent être exposées à l'environnement de prévisualisation.
Alors, comment s'y retrouver et s'assurer que votre application reste conforme ? Deux mots : assainissement des données. Il s'agit de l'effacement délibéré et permanent de données sensibles d'un dispositif de stockage, ce qui rend les données irrécupérables. Dans cet article, je partagerai les méthodes d'assainissement des données que vous pouvez mettre en œuvre pour les environnements de prévisualisation afin de garantir que vos données restent en sécurité à chaque étape du développement.
Nous avons quelques prérequis pour nous assurer que vous pouvez suivre les solutions et les étapes détaillées dans cet article - veuillez vous assurer que vous avez installé les éléments suivants :
Pour les besoins de cet article, nous allons nous concentrer sur l'assainissement des données de l'environnement de prévisualisation sur Symfony, cependant, les méthodes détaillées s'appliquent à tous les frameworks.
Tout au long de l'article, nous allons passer en revue les différentes méthodes disponibles pour assainir les données de l'environnement Symfony sur Upsun - 5 méthodes pour être exact - que vous pouvez évaluer et choisir la meilleure pour vous. Cependant, assurez-vous que vous avez terminé l'étape de création d'une commande avant de procéder à une méthode.
Si vous connaissez déjà la méthode que vous préférez utiliser, cliquez sur le titre correspondant ci-dessous et nous vous y emmènerons directement :
Pour exécuter l'une des cinq méthodes d'assainissement des données listées ci-dessus, nous avons besoin d'un appelable pour assainir nos environnements. Il y a deux façons possibles de le faire :
Puisque nous utilisons une application Symfony Demo, nous utiliserons la seconde option. Faites ce qui suit, à partir de la branche principale
de Git :
symfony composer require --dev fakerphp/faker git add composer.json composer.lock && git commit -m "composer require --dev fakerphp bundle"
Ensuite, ouvrez votre code dans votre IDE préféré et créez une nouvelle commande Symfony, dans un fichier SRC/command/SanitizeDataCommand.php, avec ce qui suit :
<?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 : 'Assainissement des données utilisateur (nom d'utilisateur et 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('Cette commande permet d'assainir les données des utilisateurs (nom d'utilisateur et email).') ; } 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() ; // suspend l'auto-commit try { /** @var User $user */ foreach ($users as $user) { $this->io->progressAdvance() ; // initialise le faker $faker = Faker\Factory ::create() ; $this->io->text('faking user '.$user->getUsername()) ; // fausse info utilisateur $user->setUsername(uniqid($faker->userName())) ; $user->setEmail($faker->email()) ; // veuillez adapter à vos besoins }
$this->entityManager->flush() ; $this->entityManager->getConnection()->commit() ; $this->io->progressFinish() ; } catch (\Exception $e) { $this->entityManager->getConnection()->rollBack() ; throw $e ; } return Command::SUCCESS ; } }
Cette commande app:sanitize-data
utilise le UserRepository et falsifie le nom d'utilisateur et l'email de l'entité par défaut User Symfony. Veuillez l'adapter à vos besoins. Ensuite, ajoutez votre code à la branche principale
:
git add src/Command/SanitizeDataCommand.php && git commit -m "sanitize data command"
déploiement de symfony
Maintenant que votre code source contient une commande Symfony pour assainir vos données, nous allons l'utiliser manuellement dans un nouvel environnement de prévisualisation. En commençant par créer une nouvelle branche staging et en attendant que le processus se termine, comme suit :
symfony branch staging --type=staging
Ensuite, exécutez votre commande Symfony nouvellement créée sur votre environnement Upsun staging, comme indiqué ci-dessous :
symfony ssh php bin/console -e dev app:sanitize-data
Et voilà, les données de votre environnement de prévisualisation sont assainies !
Dans cette section, nous allons créer un environnement de prévisualisation, assainir ses données, et ensuite faire en sorte que tous les nouveaux environnements héritent de cet environnement de prévisualisation.
Comme mentionné au début de cet article, chaque fois que vous créez une nouvelle branche Git sur Upsun, l'environnement créé héritera des données de l'environnement parent. Cependant, il est possible de modifier l'héritage des données par défaut et de le configurer plus tard pour synchroniser les données d'un nouveau parent - l'environnement de prévisualisation que nous allons créer.
Le CLI Symfony offre la possibilité de créer une branche sans parent, en utilisant l'option --no-clone-parent
, puis en définissant le parent à staging (a.k.a preview), ce qui garantit que les nouvelles branches héritent des données de l'environnement de prévisualisation. Suivez les instructions de l'étape 1 pour plus de détails sur la façon d'assainir manuellement les données de l'environnement de prévisualisation afin de garantir que toutes les branches futures héritent de données assainies et conformes au GDPR.
symfony checkout main symfony branch dev --no-clone-parent symfony env:info -e dev parent staging symfony sync -e dev data
Et voilà, votre nouvel environnement dedéveloppement
est maintenant créé avec les données nettoyées de votre environnement de prévisualisation.
Plutôt que de s'appuyer sur l'héritage, il peut être souhaitable d'assainir certaines données à chaque déploiement. Dans ce cas, nous pouvons déplacer notre appel de script dans la section " hooks"
de la configuration.
Le type de crochet que vous choisissez est libre- crochets de déploiement ou crochetspost_déploiement - mais voici quelques points à garder à l'esprit :
Pour exécuter une commande Symfony pendant le hook post_deploy
, ajoutez ce qui suit dans votre .upsun/config.yaml
:
applications : app : hooks : build : ... deploy : ... post_deploy : | if [ "$PLATFORM_ENVIRONMENT_TYPE" != production ] ; then # L'assainissement de la base de données devrait avoir lieu ici (puisque c'est de la non-production) php bin/console -e dev app:sanitize-data fi
Poussez ensuite votre code sur la branche principale:
git checkout main && git add .upsun/config.yaml && git commit -m "add sanitize data command to post_deploy hook"
symfony deploy
Il y a une autre option qui vous permet de créer un déclencheur personnalisé qui est exécuté en réponse à certaines activités qui ont lieu sur le projet. Par exemple, lors de la synchronisation d'un environnement avec son parent, nous pourrions synchroniser les données non anonymisées du parent (par exemple, si la synchronisation se fait à partir de l'environnement de production).
Les deux composants qui permettront de réaliser cette opération sont les suivants :
Nous allons donc ajouter une intégration (script d'activité) qui répond à certains événements pour exécuter une opération d'exécution afin d'assainir les données à la volée, voir l'ajout d'une intégration d' un script d'activité ci-dessous.
Pour configurer une opération d'exécution, nous devons ajouter une nouvelle clé YAML de premier niveau dans notre fichier.upsun/config.yaml
avec ce qui suit :
applications : app :
operations : sanitize : role : admin commands : start : | if [ "$PLATFORM_ENVIRONMENT_TYPE" != production ] ; then # L'assainissement de la base de données devrait avoir lieu ici (puisqu'il s'agit d'une non-production) php bin/console -e dev app:sanitize-data fi
Poussez ensuite votre fichier vers la branche principale
et déployez-le.
git checkout main git add .upsun/config.yaml && git commit -m "add runtime operation to sanitize data" symfony deploy
Et si vous voulez tester cette opération d'exécution manuellement, vous pouvez utiliser ce qui suit :
symfony operation:run sanitize --app=app
Upsun supporte les scripts personnalisés qui peuvent être déclenchés en réponse à n'importe quelle activité. Ce script est exécuté en dehors du contexte de l'environnement et nous devons donc recréer ce contexte pour que le script d'activité soit exécuté avec les droits nécessaires. Pour ce faire, créez un nouveau fichier src/runtime/sanitize.js
avec ce qui suit :
// src/runtime/sanitize.js let app_container = "app" ; let runtime_operation_name = "sanitize" ; if (!variables.api_token) { console.log("Variable API Token is not defined !") ; console.log("Veuillez définir une variable d'environnement avec votre jeton API à l'aide de la commande : ") ; console.log("upsun project:curl /integrations/<INTEGRATION_ID>/variables -X POST -d '{\"name\" : \N- "api_token\N", \N- "value\N" : \"<API_TOKEN>", "is_sensitive" : true, "is_json" : false}' ") ; } else { console.log("OAuth2 API Token defined") ; 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 ; } // exécuter l'opération runtime runtime_operation_name sur l'environnement actuel/ciblé 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") ; } }
Ce script d'activité utilise un jeton API, en tant que variable d'environnement, pour se connecter à l'environnement actuel et exécuter l'opération d'exécution définie précédemment à l'aide de l'API Upsun. Nous devons définir cette variable d'environnement pour l'intégration de notre script d'activité, et ajouter plus tard une variable d'environnement API Token.
Ensuite, poussez votre fichier sur la branche principale
et déployez-le, comme suit :
symfony checkout main git add src/runtime/sanitize.js git commit -m "add activity script" symfony deploy
Trois événements Upsun doivent déclencher cette opération d'exécution :
environment.branch
), environment.synchronize
), environment.activate
) .
Pour mettre en place ces déclencheurs, utilisez cette commande dans votre terminal pour ajouter une intégration de script d'activité.
symfony integration:add --type script --file ./src/runtime/sanitize.js --events environment.branch,environment.synchronize,environment.activate --states complete --environments \*
Ajouter une variable d'environnement API Token
Tout d'abord, obtenez l'ID de l'intégration précédente en utilisant la commande suivante :
symfony integration:list
Ensuite, créez un nouveau Token API depuis la Console, gardez la valeur en main, et remplacez-la dans cette commande du terminal :
symfony project:curl /integrations/<INTEGRATION_ID>/variables -X POST -d '{"name" : "api_token", "value" : "<API_TOKEN>", "is_sensitive" : true, "is_json" : false}'
Vous pouvez vérifier que la variable a été créée avec cette commande :
symfony project:curl /integrations/<INTEGRATION_ID>/variables
Pour tester si tout a fonctionné, dans la Console ou avec le CLI, déclenchez la création d'une nouvelle branche à partir de main
, déclenchez une synchronisation, désactivez et réactivez votre environnement de prévisualisation, et vous devriez alors voir deux activités :
Si vous rencontrez un problème et que vous souhaitez déboguer l'intégration du script d'activité, vous devez utiliser la commande suivante :
symfony integration:activity:log <INTEGRATION_ID>
Lorsque vous ajoutez l'intégration de votre script d'activité, le script correspondant est ajouté en mémoire du côté d'Upsun. Cela signifie qu'à chaque fois que vous mettez à jour votre script, vous devez mettre à jour la version en cache du fichier, en utilisant la commande suivante : symfony integration:update <INTEGRATION_ID> :
symfony integration:update <INTEGRATION_ID> --file ./src/runtime/sanitize.js
Il est possible d'utiliser un script shell pour automatiser l'assainissement des données de tous vos environnements, à l'exception de la production, pour tous vos projets au sein d'une organisation - apprenez-enplus sur les organisations ici. Pour utiliser ce script shell, veuillez vous assurer que toutes vos sources d'environnement de tous vos projets au sein de votre organisation contiennent la commande Symfony pour assainir les données, avant de suivre les étapes suivantes.
La première étape consiste à créer un fichier nommé fleet_sanitizer.sh avec le code suivant :
if [ -n "$ZSH_VERSION" ] ; then emulate -L ksh ; fi ###################################################### # script de démonstration de l'assainissement de la flotte, en utilisant l'interface de programmation.
# # Active le flux de travail suivant sur un projet donné et assainit les environnements de prévisualisation (environnement staging, new-feature et auto-updates) : # . # └── main # ├── staging # | └── new-feature # └── auto-updates # # Utilisation # 1. sourcez ce script : `. fleet_sanitizer.sh` ou `source fleet_sanitizer.sh` en fonction de votre machine locale # 2. define ORGANIZATION var : ORGANIZATION=<organizationIdentifier> # 3. exécuter `sanitize_organization_data $ORGANIZATION` ###################################################### # Fonctions utilitaires # list_org_projects : Affiche la liste des projets sur lesquels l'opération sera appliquée avant de commencer. # $1 : Organisation, telle qu'elle apparaît dans console.upsun.com. list_org_projects() { symfony project:list -o $1 --columns="ID, Title" } # get_org_projects : Récupère un tableau d'identifiants de projets pour une organisation donnée. # Note : Rend la variable PROJECTS disponible pour les scripts suivants. # $1 : Organisation, telle qu'elle apparaît dans console.upsun.com. get_org_projects() { PROJECTS_LIST=$(symfony project:list -o $1 --pipe) PROJECTS=($PROJECTS_LIST) } # get_project_envs : Récupère un tableau d'IDs d'envs pour un projet. # Note : Rend la variable ENVS disponible pour les scripts suivants. # $1 : ProjectId, tel qu'il apparaît dans console.upsun.com. get_project_envs() { ENV_LIST=$(symfony environment:list -p $1 --pipe) ENVS=($ENV_LIST) } # list_project_envs : Imprimer la liste des envs sur lesquels l'opération sera appliquée avant de démarrer. # $1 : ProjectId, tel qu'il apparaît dans console.upsun.com. list_project_envs() { symfony environment:list -p $1 } # add_env_var : Ajouter une variable d'environnement au niveau de l'environnement. # $1 : Nom de la variable. # $2 : Valeur de la variable. # $3 : ID du projet cible. # $4 : ID de l'environnement cible. 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 existe déjà. Sauter." fi } # Fonctions principales. sanitize_organization_data() { list_org_projects $1 get_org_projects $1 for PROJECT in "${PROJECTS[@]}" ; do printf "\n#### Projet $PROJET."# obtenir la liste des environnements 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 "\nL'environnement $ENVIRONMENT existe et n'est pas encore assaini. Sanitizing 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 existe et n'a pas besoin d'être sanitizé. skipping." fi elif [ "$ENVIRONMENT" == main ] ; then printf "\nEnvironnement $ENVIRONMENT est en production, skipping." else printf "\nEnvironnement $ENVIRONMENT n'est pas actif $ENV_CHECK, skipping." fi done done }
Ensuite, en fonction de la machine sur laquelle vous voulez exécuter ce script, veuillez adapter le code à vos besoins, mais il devrait ressembler à quelque chose comme ceci :
. fleet_sanitizer.sh # ou source fleet_sanitizer.sh ORGANIZATION=<organizationIdentifier> sanitize_organization_data $ORGANIZATION
Et juste comme ça, vos données sont assainies et vous êtes sur la bonne voie pour être en conformité avec le GDPR !
Si vous avez d'autres questions sur nos capacités en matière de sécurité et de conformité ou si vous rencontrez des problèmes avec les méthodes et/ou les étapes ci-dessus, contactez notre équipe d'assistance qui se fera un plaisir de vous aider.
Restez au courant des dernières nouvelles sur nos médias sociaux et nos canaux communautaires. Retrouvez-nous sur Dev.to, Reddit et Discord.