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
/ /

Tutorial: Queryable Encryption con Mongoose

En esta guía, puedes aprender cómo crear una aplicación que utilice Mongoose para implementar la funcionalidad Queryable Encryption de MongoDB.

Queryable Encryption le permite cifrar y descifrar automáticamente los campos de documentos. Queryable Encryption se puede usar para cifrar datos confidenciales en la aplicación, almacenar campos de datos como datos cifrados aleatorios en el servidor y consultar los campos cifrados. Este tutorial muestra cómo configurar Queryable Encryption usando Mongoose, que proporciona una librería Object Document Mapper (ODM) para la interacción con datos.

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 se ejecute en MongoDB Server versión 7.0 o posterior. Para obtener más información, consulte la MongoDB Get Started guía.

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

  • Instalar Node.js v16.20.1 o después.

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

Aplicación completa

Para ver la aplicación de muestra completa de este tutorial, vea la carpeta mongoose-qe-app en GitHub.

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

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 generan un mongoose-qe-app directorio del proyecto e instalar las siguientes dependencias:

2

En la raíz del proyecto, crea un archivo .env y pega 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 el URI de conexión que conecta a su clúster y reemplace el <Automatic Encryption Shared Library path> con la ruta completa a su librería Compartida de Cifrado Automático. Asegúrate de que la ruta apunte a lib/mongo_crypt_v1.dylib dentro de tu paquete descargado.

Si utiliza uno de los Sistemas de Gestión de Claves (KMS) que aparecen en la plantilla .env, reemplace los valores de marcador de posición correspondientes. De lo contrario, puede dejar estos valores sin asignar y almacenar la llave maestra de cliente localmente. Esta aplicación crea el archivo local de la clave maestra del cliente para ti.

Advertencia

Almacenamiento local de llave maestra de cliente

Si almacenas tu clave maestra de cliente localmente, no uses esta aplicación en producción. Sin un KMS remoto, corres el riesgo de que haya un acceso no autorizado a la llave de cifrado o la pérdida de la clave necesaria para descifrar tus 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

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.

4

Especifica la base de datos inicial y las variables de cifrado pegando el siguiente código en la función runExample() de tu 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 de posición '<KMS provider>' por su proveedor de llaves: 'aws', 'azure', 'gcp' o 'kmip'. Para almacenar localmente su clave maestra de cliente, configure este valor en 'local'.

El código rellena previamente las siguientes variables:

  • keyVaultDatabaseName - La base de datos en MongoDB que almacena tus claves de cifrado de datos (DEK). Este tutorial usa la base de datos encryption.

  • keyVaultCollectionName - La colección en MongoDB que almacena tus DEK. El código establece esta variable en __keyVault, con un guion bajo al principio para distinguirla de una colección de usuarios.

  • keyVaultNamespace: El espacio de nombres en MongoDB que almacena sus DEK. Esta variable consta de keyVaultDatabaseName las keyVaultCollectionName variables y, separadas por un punto.

  • encryptedDatabaseName - La base de datos en MongoDB que almacena sus datos cifrados. Este tutorial utiliza la base de datos medicalRecords.

  • encryptedCollectionName: La colección en MongoDB que almacena sus datos cifrados. Este tutorial utiliza la patients colección.

Después de configurar la estructura de tu proyecto, sigue los pasos en esta sección para configurar las credenciales del proveedor de KMS y las opciones de cifrado.

1

Agrega la función getKMSProviderCredentials() a tu archivo queryable-encryption-helpers.js. Esta función recupera las credenciales de tu proveedor de Key Management System o crea un archivo de llave maestra de cliente local si no utilizas un proveedor de 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 de getKMSProviderCredentials() es compatible con varios proveedores de KMS, incluidos AWS, Azure, GCP, KMIP y almacenamiento local de claves.

2

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.

3

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;
}
}
4

Ahora que has definido funciones asistentes, puedes usarlas para acceder a tus credenciales desde el archivo principal de la aplicación.

Navegue a su archivo queryable-encryption-tutorial.js y pegue el siguiente código después del comentario de 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 tus funciones asistentes para recuperar las credenciales del proveedor KMS, las credenciales de la llave maestra de cliente y las opciones de cifrado automático usadas para configurar Queryable Encryption.

Después de configurar los ajustes de cifrado, sigue los pasos de esta sección para establecer tu conexión a MongoDB, crear claves de datos y definir tu esquema cifrado.

1

Para configurar tu conexión y cliente de MongoDB, navega a tu archivo queryable-encryption-tutorial.js y pega el siguiente código después del comentario de 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 de Mongoose para operaciones cifradas, un cliente de MongoDB para la gestión de claves y una ClientEncryption instancia para crear claves de datos. También descarta cualquier base de datos existente para garantizar una configuración limpia para el tutorial.

2

Para crear las claves de datos necesarias, pega el siguiente código después del comentario de 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.

3

Para crear la definición de esquema cifrado, pega el siguiente código después del comentario en el 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 igualdad

  • patientRecord.billing.type:Encriptado, pero no consultable

  • patientRecord.billing.number:Encriptado, pero no consultable

4

Crea un nuevo modelo llamado Patient para representar la colección patients y registra tu esquema de cifrado en el modelo. Para crear el modelo, pega 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.

5

Después de registrar tu modelo, puedes 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 con tu base de datos medicalRecords, en la que el cifrado automático está habilitado.

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.

1

Para insertar un documento que tiene campos cifrados, navega hasta tu archivo queryable-encryption-tutorial.js y pega el siguiente código después del comentario de 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.

2

Para query un campo cifrado, pega el siguiente código después del comentario de 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.

3

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, la salida 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.

¡Felicidades por completar el tutorial de Mongoose Queryable Encryption! Ahora tienes una aplicación Mongoose de muestra que utiliza la Queryable Encryption para encriptar y desencriptar automáticamente los campos de documentos. Tu aplicación encripta datos sensibles en el lado del servidor y realiza consultas de los datos en el lado del cliente.

Para obtener más información sobre Queryable Encryption y Mongoose, accede a los siguientes recursos:

  • Consulta más tutoriales sobre el driver de Queryable Encryption en el manual de MongoDB Server.

  • Aprenda a crear una aplicación que utiliza Mongoose sin cifrado consultable en el Tutorial de introducción de Mongoose.

  • Obtén más información sobre Mongoose en la documentación de Mongoose.

Volver

Mongoose Primeros pasos

En esta página