Overview
En esta guía se explica cómo crear una aplicación Symfony que utilice Doctrine MongoDB ODM para implementar la funcionalidad de Queryable Encryption de MongoDB.
Queryable Encryption te permite cifrar y descifrar automáticamente campos de documentos. Puedes usar Queryable Encryption para cifrar datos confidenciales en tu aplicación, almacenar campos de datos como datos cifrados aleatorizados en el servidor y query los campos cifrados. Este tutorial te muestra cómo configurar Queryable Encryption utilizando Doctrine MongoDB ODM, que proporciona un Object Document Mapper (ODM) para aplicaciones PHP.
Tip
Para aprender más sobre cómo integrar Symfony y Doctrine con la librería PHP de MongoDB, consulta la Tutorial de Integración de Symfony MongoDB.
Requisitos previos
Antes de comenzar este tutorial, completa las siguientes tareas previas:
Crea una cuenta de MongoDB Atlas y configura un clúster. Asegúrate de que tu clúster funcione en la versión 7.0 o posterior de MongoDB Server. Para obtener más información, consulta la guía MongoDB Primeros pasos.
Descargue la librería compartida de cifrado automático. Para ver instrucciones, consulta la guía Instalar y configurar un componente de análisis de consultas.
Descargue la extensión de PHP. Para obtener más información, consulta Instalación en la documentación de la extensión.
Instale PHP 8.1 o posterior.
Instala Composer versión 2.0 o superior.
Instala la Symfony CLI. Para aprender más, consulta la documentación de Symfony CLI.
Tutorial
Este tutorial muestra cómo crear una aplicación de Queryable Encryption que utiliza Symfony y Doctrine MongoDB ODM. La aplicación cifra y descifra los registros médicos de los pacientes y consulta datos médicos cifrados.
Configurar el proyecto
Sigue los pasos de esta sección para instalar las dependencias del proyecto, configurar tu entorno y crear la estructura de la aplicación.
Configura tu entorno.
Ejecuta los siguientes comandos en tu terminal para crear una nueva aplicación Symfony e instalar las dependencias necesarias:
symfony new qe-symfony-app cd qe-symfony-app composer require doctrine/mongodb-odm-bundle mongodb/mongodb
Estos comandos generan un qe-symfony-app directorio del proyecto e instale las siguientes dependencias:
Doctrine MongoDB ODM Bundle, la integración de Symfony para Doctrine MongoDB ODM
MongoDB PHP librería, el driver oficial de MongoDB para PHP
Especifique sus variables de entorno.
En el directorio de tu proyecto, abre el archivo .env y añade o modifica las siguientes variables:
MONGODB_URI=<connection URI> CRYPT_SHARED_LIB_PATH=<Automatic Encryption Shared Library path>
Reemplaza el marcador de posición <connection URI> con la URI de conexión que conecta con tu clúster, y reemplaza <Automatic Encryption Shared Library path> con la ruta completa hacia tu librería Compartida de Cifrado Automático. Asegúrese de que la ruta apunte a lib/mongo_crypt_v1.dylib dentro de su paquete descargado.
Cree sus archivos de aplicación.
En el directorio src/ de su proyecto, cree los siguientes subdirectorios y archivos para definir la estructura del documento y la lógica de la aplicación:
src/Document/Patient.phpsrc/Document/PatientRecord.phpsrc/Document/Billing.phpsrc/Command/QueryableEncryptionCommand.php
Los pasos futuros en este tutorial le instruyen a agregar código a cada archivo.
Define sus clases de documentos.
Este tutorial utiliza las clases Patient, PatientRecord y Billing para representar los registros médicos de los pacientes.
Pega el siguiente código en el archivo src/Document/Patient.php:
namespace App\Document; use Doctrine\ODM\MongoDB\Mapping\Attribute as ODM; #[ODM\Document(collection: 'patients')] class Patient { #[ODM\Id] public string $id; #[ODM\Field] public string $patientName; #[ODM\Field] public int $patientId; #[ODM\EmbedOne(targetDocument: PatientRecord::class)] public PatientRecord $patientRecord; }
Luego, pega el siguiente código en el archivo src/Document/PatientRecord.php:
namespace App\Document; use Doctrine\ODM\MongoDB\Mapping\Attribute as ODM; use Doctrine\ODM\MongoDB\Mapping\EncryptQuery; #[ODM\EmbeddedDocument] class PatientRecord { #[ODM\Field] #[ODM\Encrypt(queryType: EncryptQuery::Equality)] public string $ssn; #[ODM\EmbedOne(targetDocument: Billing::class)] #[ODM\Encrypt] public Billing $billing; #[ODM\Field] public int $billAmount; }
Por último, pegue el siguiente código en el archivo src/Document/Billing.php:
namespace App\Document; use Doctrine\ODM\MongoDB\Mapping\Attribute as ODM; #[ODM\EmbeddedDocument] class Billing { #[ODM\Field] public string $type; #[ODM\Field] public string $number; }
Las clases de documentos definen la estructura de los documentos en la colección patients. La clase PatientRecord incluye el atributo #[ODM\Encrypt] para especificar los siguientes campos cifrados:
patientRecord.ssn: cifrado y configurado para consultas de igualdadpatientRecord.billingCifrado, pero no consultable
Crea tu comando de consola.
Pega el siguiente código en el archivo src/Command/QueryableEncryptionCommand.php:
namespace App\Command; use App\Document\Billing; use App\Document\Patient; use App\Document\PatientRecord; use Doctrine\ODM\MongoDB\Configuration; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Mapping\Driver\AttributeDriver; use MongoDB\BSON\Binary; use MongoDB\Client; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; ( name: 'app:queryable-encryption', description: 'Demonstrates Queryable Encryption with ' . 'Doctrine MongoDB ODM', ) class QueryableEncryptionCommand extends Command { protected function execute( InputInterface $input, OutputInterface $output, ): int { // Paste application variables below // Paste encryption credentials below // Paste connection and configuration below // Paste collection setup below // Paste insert operation below // Paste encrypted query below return Command::SUCCESS; } }
Los pasos futuros de este tutorial te indican añadir código bajo cada comentario correspondiente.
Encripta y Conéctate a MongoDB
Después de configurar tus archivos de Proyecto y dependencias, sigue los pasos de esta sección para configurar tus credenciales de cifrado y conectarte a MongoDB.
Asigna tus variables de aplicación.
En tu archivo src/Command/QueryableEncryptionCommand.php, añade el siguiente código bajo el comentario // Paste application variables below:
// Paste application variables below $keyVaultNamespace = 'encryption.__keyVault'; $encryptedDatabase = 'medicalRecords'; $encryptedCollection = 'patients';
El código establece las siguientes variables:
keyVaultNamespace: el namespace en MongoDB que almacena sus claves de cifrado de datos (DEK). Este tutorial utiliza la colección
__keyVaulten la base de datosencryption.encryptedDatabase - La base de datos que almacena tus datos cifrados. Este tutorial utiliza la base de datos
medicalRecords.encryptedCollection - La colección que almacena tus datos cifrados. Este tutorial utiliza la colección
patients.
Configura tu llave maestra de cliente.
Añade el siguiente código debajo del comentario // Paste encryption credentials below:
// Paste encryption credentials below $keyFile = __DIR__ . '/../../master-key.bin'; if (!file_exists($keyFile)) { file_put_contents($keyFile, random_bytes(96)); } $masterKeyBytes = file_get_contents($keyFile); $kmsProvider = [ 'type' => 'local', 'key' => new Binary( $masterKeyBytes, Binary::TYPE_GENERIC, ), ];
Este código crea o carga un archivo de clave principal de cliente local de 96bytes. El $kmsProvider arreglo configura el proveedor local de KMS utilizado para el cifrado.
Advertencia
Almacenamiento local de llave maestra de cliente
Este tutorial almacena su Clave maestra de cliente en un archivo local. No utilices este enfoque en la producción. Sin un KMS externo, existe el riesgo de que se produzca acceso no autorizado a la llave de cifrado o de que se pierda la llave necesaria para descifrar los datos.
Tip
Sistemas de Gestión de Claves
Para obtener más información sobre KMS, consulta la entrada de Wikipedia sobre Gestión de claves.
Configura tus opciones de auto-cifrado.
Agrega el siguiente código directamente debajo de la configuración del proveedor de KMS del paso anterior:
$autoEncryptionOptions = [ 'keyVaultNamespace' => $keyVaultNamespace, ]; $cryptSharedLibPath = $_ENV['CRYPT_SHARED_LIB_PATH'] ?? ''; if ($cryptSharedLibPath) { $autoEncryptionOptions['extraOptions'] = [ 'cryptSharedLibPath' => $cryptSharedLibPath, ]; }
Este código configura el namespace del almacén de claves y configura la ruta a la librería compartida de cifrado automático.
Configura tu DocumentManager.
Añade el siguiente código debajo del comentario // Paste connection and configuration below:
// Paste connection and configuration below $cacheDir = __DIR__ . '/../../var/cache/doctrine'; $config = new Configuration(); $config->setAutoEncryption($autoEncryptionOptions); $config->setKmsProvider($kmsProvider); $config->setProxyDir($cacheDir . '/Proxies'); $config->setProxyNamespace('Proxies'); $config->setHydratorDir($cacheDir . '/Hydrators'); $config->setHydratorNamespace('Hydrators'); $config->setDefaultDB($encryptedDatabase); $config->setMetadataDriverImpl( new AttributeDriver([__DIR__ . '/../Document']) ); $client = new Client( uri: $_ENV['MONGODB_URI'], uriOptions: [], driverOptions: $config->getDriverOptions(), ); $dm = DocumentManager::create($client, $config);
Este código configura un objeto Doctrine Configuration con tus ajustes de cifrado, crea un cliente MongoDB que transmite opciones de cifrado del controlador y inicializa un DocumentManager para operaciones cifradas.
Crea tu colección cifrada.
Añade el siguiente código debajo del comentario // Paste collection setup below:
// Paste collection setup below $schemaManager = $dm->getSchemaManager(); $schemaManager->dropDocumentCollection(Patient::class); $schemaManager->createDocumentCollection(Patient::class);
Este código elimina cualquier colección existente y crea una nueva colección patients con los metadatos de cifrado requeridos para Queryable Encryption. Cada llamada a createDocumentCollection() genera nuevas claves de cifrado de datos para los campos cifrados.
Realizar operaciones cifradas
Después de configurar la aplicación y la conexión a la base de datos, sigue los pasos de esta sección para insertar y consultar documentos cifrados.
Inserta datos cifrados.
En tu archivo src/Command/QueryableEncryptionCommand.php, añade el siguiente código bajo el comentario // Paste insert operation below:
// Paste insert operation below $billing = new Billing(); $billing->type = 'Visa'; $billing->number = '4111111111111111'; $record = new PatientRecord(); $record->ssn = '987-65-4320'; $record->billing = $billing; $record->billAmount = 1500; $patient = new Patient(); $patient->patientName = 'Jon Doe'; $patient->patientId = 12345678; $patient->patientRecord = $record; $dm->persist($patient); $dm->flush(); $dm->clear(); $output->writeln( 'Successfully inserted the patient document.' );
Queryable Encryption encripta automáticamente los campos patientRecord.ssn y patientRecord.billing antes de almacenar el documento en MongoDB.
query datos cifrados.
Añade el siguiente código debajo del comentario // Paste encrypted query below:
// Paste encrypted query below $found = $dm ->getRepository(Patient::class) ->findOneBy(['patientRecord.ssn' => '987-65-4320']); if ($found instanceof Patient) { $output->writeln('Found patient:'); $output->writeln( ' Name: ' . $found->patientName ); $output->writeln( ' SSN: ' . $found->patientRecord->ssn ); $output->writeln( ' Billing type: ' . $found->patientRecord->billing->type ); $output->writeln( ' Billing number: ' . $found->patientRecord->billing->number ); $output->writeln( ' Bill amount: ' . $found->patientRecord->billAmount ); } $output->writeln('Connection closed.');
Este código realiza una consulta de igualdad en el campo cifrado patientRecord.ssn.
Ejecuta la aplicación.
Para iniciar tu aplicación, ejecuta el siguiente comando desde el directorio de tu proyecto qe-symfony-app:
php bin/console app:queryable-encryption
Si tiene éxito, la salida del comando se parecerá al siguiente ejemplo:
Successfully inserted the patient document. Found patient: Name: Jon Doe SSN: 987-65-4320 Billing type: Visa Billing number: 4111111111111111 Bill amount: 1500 Connection closed.
En la base de datos, el documento está cifrado. MongoDB almacena los campos marcados con el atributo #[ODM\Encrypt] como datos binarios BSON e incluye un campo __safeContent__ para etiquetas de metadatos. El documento almacenado se parece a lo siguiente:
{ "_id": { "$oid": "..." }, "patientName": "Jon Doe", "patientId": 12345678, "patientRecord": { "ssn": { "$binary": { ... } }, "billing": { "$binary": { ... } }, "billAmount": 1500 }, "__safeContent__": [ { "$binary": { ... } } ] }
Próximos pasos
¡Felicidades por completar el tutorial de Queryable Encryption Doctrine ODM! Ahora tienes una aplicación Symfony de muestra que utiliza Cifrado Interrogable para cifrar y descifrar automáticamente campos de documentos. Tu aplicación cifra datos confidenciales en el lado del servidor y consulta los datos en el lado del cliente.
Para obtener más información sobre Queryable Encryption y Doctrine MongoDB ODM, visita los siguientes recursos:
Consulta más tutoriales sobre el driver de Queryable Encryption en el manual de MongoDB Server.
Obtenga más información sobre Doctrine MongoDB ODM en la Doctrine MongoDB ODM documentación.
Aprende más sobre la integración de Doctrine MongoDB ODM con Symfony en el tutorial Integración de MongoDB con Symfony.