Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

Queryable Encryption con Symfony y Doctrine ODM

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.

Antes de comenzar este tutorial, completa las siguientes tareas previas:

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.

Sigue los pasos de esta sección para instalar las dependencias del proyecto, configurar tu entorno y crear la estructura de la aplicación.

1

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

2

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.

3

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.php

  • src/Document/PatientRecord.php

  • src/Document/Billing.php

  • src/Command/QueryableEncryptionCommand.php

Los pasos futuros en este tutorial le instruyen a agregar código a cada archivo.

4

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:

src/Document/Patient.php
<?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:

src/Document/PatientRecord.php
<?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:

src/Document/Billing.php
<?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 igualdad

  • patientRecord.billingCifrado, pero no consultable

5

Pega el siguiente código en el archivo src/Command/QueryableEncryptionCommand.php:

<?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;
#[AsCommand(
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.

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.

1

En tu archivo src/Command/QueryableEncryptionCommand.php, añade el siguiente código bajo el comentario // Paste application variables below:

src/Command/QueryableEncryptionCommand.php
// 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 __keyVault en la base de datos encryption.

  • 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.

2

Añade el siguiente código debajo del comentario // Paste encryption credentials below:

src/Command/QueryableEncryptionCommand.php
// 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.

3

Agrega el siguiente código directamente debajo de la configuración del proveedor de KMS del paso anterior:

src/Command/QueryableEncryptionCommand.php
$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.

4

Añade el siguiente código debajo del comentario // Paste connection and configuration below:

src/Command/QueryableEncryptionCommand.php
// 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.

5

Añade el siguiente código debajo del comentario // Paste collection setup below:

src/Command/QueryableEncryptionCommand.php
// 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.

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.

1

En tu archivo src/Command/QueryableEncryptionCommand.php, añade el siguiente código bajo el comentario // Paste insert operation below:

src/Command/QueryableEncryptionCommand.php
// 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.

2

Añade el siguiente código debajo del comentario // Paste encrypted query below:

src/Command/QueryableEncryptionCommand.php
// 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.

3

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": {
...
}
}
]
}

¡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:

Volver

TLS

En esta página