Overview
En esta guía, puede aprender cómo crear una aplicación que utiliza Mongoose para implementar la función de cifrado consultable de MongoDB.
El cifrado consultable permite cifrar y descifrar automáticamente los campos de un documento. Puede usar el cifrado consultable para cifrar datos confidenciales en su aplicación, almacenar campos de datos como datos cifrados aleatorios en el servidor y consultarlos. Este tutorial le muestra cómo configurar el cifrado consultable con Mongoose, que proporciona una biblioteca de mapeadores de objetos y documentos (ODM) para la interacción con datos.
Requisitos previos
Antes de comenzar este tutorial, complete las siguientes tareas previas:
Cree una cuenta de MongoDB Atlas y configure un clúster. Asegúrese de que su clúster se ejecute en MongoDB Server versión 7.0 o posterior. Para obtener más información, consulte Guíade introducción a MongoDB.
Descargue la biblioteca compartida de cifrado automático. Para ver las instrucciones, consulte la guía "Instalar y configurar un componente de análisis de consultas". Estas instrucciones muestran cómo acceder al Centro de descargas de MongoDB y completar el formulario para descargar la biblioteca.
Instale Node.js 1620v..1 o posterior.
Tutorial
Este tutorial muestra cómo crear una aplicación Queryable Encryption que utiliza Mongoose. La aplicación cifra y descifra registros médicos de pacientes y consulta datos médicos cifrados.
Tip
Solicitud completa
Para ver la aplicación de muestra completa para este tutorial, consulte la carpeta mongoose-qe-app en GitHub.
Configurar el proyecto
Siga los pasos de esta sección para instalar las dependencias del proyecto, configurar su entorno y crear la estructura de la aplicación.
Configura tu entorno.
Ejecute los siguientes comandos en su terminal para inicializar su proyecto e instalar las dependencias necesarias:
mkdir mongoose-qe-app cd mongoose-qe-app npm init -y npm pkg set main="queryable-encryption-tutorial.js" npm pkg set type="module" npm pkg set scripts.start="node queryable-encryption-tutorial.js" npm i mongoose mongodb dotenv mongodb-client-encryption
Estos comandos crean un mongoose-qe-app directorio del proyecto e instalar las siguientes dependencias:
Mongoose, el ODM de Node.js
Controlador Node.js
Dotenv, un módulo para cargar variables de entorno
mongodb-client-encryption, el paquete de cifrado
Especifique sus variables de entorno.
En la raíz de su proyecto, cree un archivo .env y pegue el siguiente código:
# MongoDB Connection URI and Shared Library Path MONGODB_URI="<connection URI>" SHARED_LIB_PATH="<Automatic Encryption Shared Library path>" # AWS Credentials AWS_ACCESS_KEY_ID="<Your AWS access key ID>" AWS_SECRET_ACCESS_KEY="<Your AWS secret access key>" AWS_KEY_REGION="<Your AWS key region>" AWS_KEY_ARN="<Your AWS key ARN>" # Azure Credentials AZURE_TENANT_ID="<Your Azure tenant ID>" AZURE_CLIENT_ID="<Your Azure client ID>" AZURE_CLIENT_SECRET="<Your Azure client secret>" AZURE_KEY_NAME="<Your Azure key name>" AZURE_KEY_VERSION="<Your Azure key version>" AZURE_KEY_VAULT_ENDPOINT="<Your Azure key vault endpoint>" # GCP Credentials GCP_EMAIL="<Your GCP email>" GCP_PRIVATE_KEY="<Your GCP private key>" GCP_PROJECT_ID="<Your GCP project ID>" GCP_LOCATION="<Your GCP location>" GCP_KEY_RING="<Your GCP key ring>" GCP_KEY_NAME="<Your GCP key name>" GCP_KEY_VERSION="<Your GCP key version>" # KMIP Credentials KMIP_KMS_ENDPOINT="<Endpoint for your KMIP KMS>" KMIP_TLS_CA_FILE="<Full path to your KMIP certificate authority file>" KMIP_TLS_CERT_FILE="<Full path to your client certificate file>"
Reemplace el marcador <connection URI> con la URI de conexión a su clúster y <Automatic Encryption Shared Library path> con la ruta completa a su biblioteca compartida de cifrado automático. Asegúrese de que la ruta apunte a lib/mongo_crypt_v1.dylib dentro del paquete descargado.
Si utiliza uno de los Sistemas de Gestión de Claves (KMS) enumerados en la plantilla .env, reemplace los valores de marcador de posición correspondientes. De lo contrario, puede dejar estos valores sin asignar y almacenar su Clave Maestra de Cliente localmente. Esta aplicación crea automáticamente el archivo de Clave Maestra de Cliente local.
Advertencia
Almacenamiento local de CMK
Si almacena su Clave Maestra de Cliente localmente, no utilice esta aplicación en producción. Sin un KMS remoto, corre el riesgo de acceso no autorizado a la clave de cifrado o de perder la clave necesaria para descifrar sus 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.
Crea tus archivos de aplicación.
Vaya al directorio mongoose-qe-app y cree un archivo llamado queryable-encryption-tutorial.js, que almacenará la lógica de su aplicación. Pegue el siguiente código en este archivo:
import 'dotenv/config'; import mongoose from 'mongoose'; import * as qeHelper from './queryable-encryption-helpers.js'; import { MongoClient, ClientEncryption } from 'mongodb'; async function runExample() { // Paste initial application variables below // Paste credential and options variables below // Paste connection and client configuration below // Paste data key creation code below // Paste encryption schema below // Paste the model below // Paste connection code below // Paste the insertion operation below // Paste the encrypted query below await connection.close(); console.log('Connection closed.'); } runExample().catch(console.dir);
A continuación, cree un archivo llamado queryable-encryption-helpers.js y pegue el siguiente código:
import 'dotenv/config'; import { writeFileSync, readFileSync, existsSync } from 'fs'; import { randomBytes } from 'crypto'; export async function dropExistingDatabase(client, databaseName) { const database = client.db(databaseName); await database.dropDatabase(); } // Paste helper methods below
Este archivo contiene una función asistente dropExistingDatabase() para tu aplicación. En los siguientes pasos de este tutorial, se ofrecen instrucciones para añadir funciones asistentes adicionales.
Asigne las variables de su aplicación.
Especifique la base de datos inicial y las variables de cifrado pegando el siguiente código en la función runExample() de su archivo queryable-encryption-tutorial.js:
const kmsProviderName = '<KMS provider>'; const uri = process.env.MONGODB_URI; // Your connection URI const keyVaultDatabaseName = 'encryption'; const keyVaultCollectionName = '__keyVault'; const keyVaultNamespace = `${keyVaultDatabaseName}.${keyVaultCollectionName}`; const encryptedDatabaseName = 'medicalRecords'; const encryptedCollectionName = 'patients';
Reemplace el marcador '<KMS provider>' con su proveedor de claves: 'aws', 'azure', 'gcp' o 'kmip'. Para almacenar su clave maestra de cliente localmente, configure este valor en 'local'.
El código rellena previamente las siguientes variables:
keyVaultDatabaseName: La base de datos de MongoDB que almacena sus claves de cifrado de datos (DEK). Este tutorial utiliza la
encryptionbase de datos.keyVaultCollectionName: La colección en MongoDB que almacena sus DEK. El código establece esta variable
__keyVaulten, precedida de un guion bajo para distinguirla de una colección de usuario.keyVaultNamespace: El espacio de nombres en MongoDB que almacena sus DEK. Esta variable consta de
keyVaultDatabaseNamelaskeyVaultCollectionNamevariables y, separadas por un punto.encryptedDatabaseName: La base de datos de MongoDB que almacena sus datos cifrados. Este tutorial utiliza la
medicalRecordsbase de datos.encryptedCollectionName: La colección en MongoDB que almacena sus datos cifrados. Este tutorial utiliza la
patientscolección.
Configurar credenciales de cifrado
Después de configurar la estructura de su proyecto, siga los pasos de esta sección para configurar las credenciales de su proveedor KMS y las opciones de cifrado.
Recupere las credenciales de su proveedor KMS.
Agregue la función getKMSProviderCredentials() a su archivo queryable-encryption-helpers.js. Esta función recupera las credenciales de su proveedor del Sistema de Gestión de Claves (KMS) o crea un archivo local de Clave Maestra del Cliente si no utiliza un proveedor KMS.
Pega el siguiente código después de la función dropExistingDatabase():
export function getKMSProviderCredentials(kmsProviderName) { let kmsProviders; switch (kmsProviderName) { case 'aws': kmsProviders = { aws: { accessKeyId: process.env.AWS_ACCESS_KEY_ID, // Your AWS access key ID secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, // Your AWS secret access key }, }; return kmsProviders; case 'azure': kmsProviders = { azure: { tenantId: process.env.AZURE_TENANT_ID, // Your Azure tenant ID clientId: process.env.AZURE_CLIENT_ID, // Your Azure client ID clientSecret: process.env.AZURE_CLIENT_SECRET, // Your Azure client secret }, }; return kmsProviders; case 'gcp': kmsProviders = { gcp: { email: process.env.GCP_EMAIL, // Your GCP email privateKey: process.env.GCP_PRIVATE_KEY, // Your GCP private key }, }; return kmsProviders; case 'kmip': kmsProviders = { kmip: { endpoint: process.env.KMIP_KMS_ENDPOINT, // Your KMIP KMS endpoint }, }; return kmsProviders; case 'local': (function () { if (!existsSync('./customer-master-key.txt')) { try { writeFileSync('customer-master-key.txt', randomBytes(96)); } catch (err) { throw new Error( `Unable to write Customer Master Key to file due to the following error: ${err}` ); } } })(); try { // WARNING: Do not use a local key file in a production application const localMasterKey = readFileSync('./customer-master-key.txt'); if (localMasterKey.length !== 96) { throw new Error( 'Expected the customer master key file to be 96 bytes.' ); } kmsProviders = { local: { key: localMasterKey, }, }; } catch (err) { throw new Error( `Unable to read the Customer Master Key due to the following error: ${err}` ); } return kmsProviders; default: throw new Error( `Unrecognized value for KMS provider name \'${kmsProviderName}\' encountered while retrieving KMS credentials.` ); } }
Esta función getKMSProviderCredentials() admite varios proveedores de KMS, incluidos AWS, Azure, GCP, KMIP y almacenamiento de claves locales.
Recupere sus credenciales de clave maestra de cliente.
Agrega la función getCustomerMasterKeyCredentials() a tu archivo queryable-encryption-helpers.js. Esta función recupera las credenciales de la llave maestra de cliente en función de tu proveedor de KMS.
Pega el siguiente código después de la función getKMSProviderCredentials():
export function getCustomerMasterKeyCredentials(kmsProviderName) { let customerMasterKeyCredentials; switch (kmsProviderName) { case 'aws': customerMasterKeyCredentials = { key: process.env.AWS_KEY_ARN, // Your AWS Key ARN region: process.env.AWS_KEY_REGION, // Your AWS Key Region }; return customerMasterKeyCredentials; case 'azure': customerMasterKeyCredentials = { keyVaultEndpoint: process.env.AZURE_KEY_VAULT_ENDPOINT, // Your Azure Key Vault Endpoint keyName: process.env.AZURE_KEY_NAME, // Your Azure Key Name }; return customerMasterKeyCredentials; case 'gcp': customerMasterKeyCredentials = { projectId: process.env.GCP_PROJECT_ID, // Your GCP Project ID location: process.env.GCP_LOCATION, // Your GCP Key Location keyRing: process.env.GCP_KEY_RING, // Your GCP Key Ring keyName: process.env.GCP_KEY_NAME, // Your GCP Key Name }; return customerMasterKeyCredentials; case 'kmip': case 'local': customerMasterKeyCredentials = {}; return customerMasterKeyCredentials; default: throw new Error( `Unrecognized value for KMS provider name \'${kmsProviderName}\' encountered while retrieving Customer Master Key credentials.` ); } }
Esta función configura las credenciales correspondientes de la llave maestra de cliente para el proveedor KMS seleccionado.
Recupere sus opciones de cifrado automático.
Añade la función getAutoEncryptionOptions() a tu archivo queryable-encryption-helpers.js. Esta función configura las opciones de cifrado automático para tu aplicación.
Pega el siguiente código después de la función getCustomerMasterKeyCredentials():
export async function getAutoEncryptionOptions( kmsProviderName, keyVaultNamespace, kmsProviders ) { if (kmsProviderName === 'kmip') { const tlsOptions = { kmip: { tlsCAFile: process.env.KMIP_TLS_CA_FILE, // Path to your TLS CA file tlsCertificateKeyFile: process.env.KMIP_TLS_CERT_FILE, // Path to your TLS certificate key file }, }; const extraOptions = { cryptSharedLibPath: process.env.SHARED_LIB_PATH, // Path to your Automatic Encryption Shared Library }; const autoEncryptionOptions = { keyVaultNamespace, kmsProviders, extraOptions, tlsOptions, }; return autoEncryptionOptions; } else { const extraOptions = { cryptSharedLibPath: process.env.SHARED_LIB_PATH, // Path to your Automatic Encryption Shared Library }; const autoEncryptionOptions = { keyVaultNamespace, kmsProviders, extraOptions, }; return autoEncryptionOptions; } }
Asigne variables a sus credenciales.
Ahora que ha definido las funciones auxiliares, puede usarlas para acceder a sus credenciales desde el archivo de la aplicación principal.
Navegue hasta su archivo queryable-encryption-tutorial.js y pegue el siguiente código después del comentario del código // Paste credential and options variables below:
const kmsProviderCredentials = qeHelper.getKMSProviderCredentials(kmsProviderName); const customerMasterKeyCredentials = qeHelper.getCustomerMasterKeyCredentials(kmsProviderName); const autoEncryptionOptions = await qeHelper.getAutoEncryptionOptions( kmsProviderName, keyVaultNamespace, kmsProviderCredentials );
Este código llama a sus funciones auxiliares para recuperar las credenciales del proveedor KMS, las credenciales de la clave maestra del cliente y las opciones de cifrado automático utilizadas para configurar el cifrado consultable.
Cifrar y conectarse a MongoDB
Después de configurar los ajustes de cifrado, siga los pasos de esta sección para configurar su conexión MongoDB, crear claves de datos y definir su esquema cifrado.
Configure su conexión y cliente MongoDB.
Para configurar su conexión y cliente MongoDB, navegue hasta su archivo queryable-encryption-tutorial.js y pegue el siguiente código después del comentario del código // Paste connection and client configuration below:
const connection = mongoose.createConnection(); const client = new MongoClient(uri); const clientEncryption = new ClientEncryption( client, autoEncryptionOptions ); await qeHelper.dropExistingDatabase(client, encryptedDatabaseName); await qeHelper.dropExistingDatabase(client, keyVaultDatabaseName);
Este código crea una conexión Mongoose para operaciones cifradas, un cliente MongoDB para la gestión de claves y una instancia ClientEncryption para crear claves de datos. También elimina cualquier base de datos existente para garantizar una configuración limpia para el tutorial.
Crea tus claves de datos.
Para crear las claves de datos necesarias, pegue el siguiente código después del comentario del código // Paste data key creation code below:
const keyId1 = await clientEncryption.createDataKey( kmsProviderName, { masterKey: customerMasterKeyCredentials, }); const keyId2 = await clientEncryption.createDataKey( kmsProviderName, { masterKey: customerMasterKeyCredentials, }); const keyId3 = await clientEncryption.createDataKey( kmsProviderName, { masterKey: customerMasterKeyCredentials, });
Este código crea tres claves de cifrado de datos que se utilizan para cifrar diferentes campos en los documentos de sus pacientes. Cada campo cifrado requiere su propia clave de datos.
Define tu esquema de cifrado.
Para crear la definición del esquema cifrado, pegue el siguiente código después del comentario del código // Paste encryption schema below:
const patientSchema = new mongoose.Schema({ patientName: { type: String, required: true }, patientId: { type: Number, required: true }, patientRecord: { ssn: { type: String, encrypt: { keyId: keyId1, queries: { queryType: 'equality' } } }, billing: { type: { type: String, encrypt: { keyId: keyId2, } }, number: { type: String, encrypt: { keyId: keyId3 } } }, billAmount: Number } }, { encryptionType: 'queryableEncryption', collection: encryptedCollectionName });
Este esquema define la estructura de los documentos en la colección patients y especifica los siguientes campos cifrados:
patientRecord.ssn: cifrado y configurado para consultas de igualdadpatientRecord.billing.type:Encriptado, pero no consultablepatientRecord.billing.number:Encriptado, pero no consultable
Registrar el esquema de cifrado en un modelo.
Cree un nuevo modelo llamado Patient para representar la colección patients y registre su esquema de cifrado en él. Para crear el modelo, pegue el siguiente código después del comentario de código // Paste the model below:
const Patient = connection.model('Patient', patientSchema);
Este código crea un modelo de Mongoose que gestiona el cifrado automático y descifrado de campos cuando realizas operaciones de base de datos.
Establezca su conexión a la base de datos.
Después de registrar su modelo, puede establecer la conexión a la base de datos pegando el siguiente código después del comentario de código // Paste connection code below:
await connection.openUri(uri, { autoEncryption: autoEncryptionOptions, dbName: encryptedDatabaseName });
Esto establece la conexión a su base de datos medicalRecords, en la que está habilitado el cifrado automático.
Realizar operaciones cifradas
Después de configurar su aplicación y la conexión de la base de datos, siga los pasos de esta sección para insertar y consultar documentos cifrados.
Insertar datos cifrados.
Para insertar un documento que tenga campos cifrados, navegue hasta su archivo queryable-encryption-tutorial.js y pegue el siguiente código después del comentario del código // Paste the insertion operation below:
const patientDocument = { patientName: 'Jon Doe', patientId: 12345678, patientRecord: { ssn: '987-65-4320', billing: { type: 'Visa', number: '4111111111111111', }, billAmount: 1500, }, }; const result = await Patient.create(patientDocument); if (result) { console.log('Successfully inserted the patient document.'); console.log('Document ID:', result._id); }
El cifrado consultable cifra automáticamente los campos patientRecord.ssn y patientRecord.billing antes de almacenar el documento en MongoDB.
Consultar datos cifrados.
Para consultar un campo cifrado, pegue el siguiente código después del comentario del código // Paste the encrypted query below:
const findResult = await Patient.findOne({ 'patientRecord.ssn': '987-65-4320', }); console.log('Found patient:'); console.log(findResult);
Este código realiza una consulta de igualdad en el campo cifrado patientRecord.ssn.
Ejecute su aplicación.
Finalmente, puedes ejecutar las operaciones cifradas definidas en los pasos anteriores ejecutando el siguiente comando desde tu directorio mongoose-qe-app:
npm start
Si tiene éxito, el resultado del comando se parecerá al siguiente ejemplo:
Successfully inserted the patient document. Document ID: new ObjectId('...') Found patient: { patientRecord: { billing: { type: 'Visa', number: '4111111111111111' }, ssn: '987-65-4320', billAmount: 1500 }, _id: new ObjectId('...'), patientName: 'Jon Doe', patientId: 12345678, __v: 0, __safeContent__: [ Binary.createFromBase64('EGzhQwBpf1B6W9udskSxJ8kwEEnF5P+SJPZ6ygQ9Ft8=', 0) ] } Connection closed.
Próximos pasos
¡Felicitaciones por completar el tutorial de Cifrado Consultable de Mongoose! Ahora tiene una aplicación Mongoose de ejemplo que utiliza Cifrado Consultable para cifrar y descifrar automáticamente los campos del documento. Su aplicación cifra datos confidenciales en el servidor y consulta los datos en el cliente.
Para obtener más información sobre el cifrado consultable y Mongoose, visite los siguientes recursos:
Vea más tutoriales sobre cifrado consultable de controladores en el manual del servidor MongoDB.
Aprenda a crear una aplicación que utiliza Mongoose sin cifrado consultable en el Tutorialde introducción a Mongoose.
Obtenga más información sobre Mongoose en la documentación de Mongoose.