Visão geral
Neste guia, você pode aprender como criar um aplicação que usa Mongoose para implementar o recurso Queryable Encryption do MongoDB.
A Queryable Encryption permite criptografar e descriptografar automaticamente os campos do documento . Você pode usar a Queryable Encryption para criptografar dados confidenciais em seu aplicação, armazenar campos de dados como dados criptografados aleatórios no servidor e consultar os campos criptografados. Este tutorial mostra como configurar a Queryable Encryption usando o Mongoose, que fornece uma biblioteca ODM (Object Document Mapper) para interação de dados.
Pré-requisitos
Antes de iniciar este tutorial, conclua as seguintes tarefas de pré-requisito:
Crie uma conta MongoDB Atlas e configure um cluster. Certifique-se de que seu cluster seja executado no MongoDB Server versão 7.0 ou posterior. Para saber mais, consulte o guia Introduçãoao MongoDB .
Baixe a biblioteca compartilhada de criptografia automática. Para visualizar as instruções, consulte o guia Instalar e configurar um componente de análise de query. Estas instruções mostram como navegar até o Centro de Download do MongoDB e preencher o formulário necessário para baixar a biblioteca.
Instale Node.js 1620v..1 ou posterior.
Tutorial
Este tutorial mostra como criar um aplicação Queryable Encryption que usa Mongoose. O aplicação criptografa e descriptografa registros médicas de pacientes e consulta dados médicas criptografados.
Dica
Aplicativo completo
Para visualizar o aplicação de amostra completo para este tutorial, consulte a pasta mongoose-qe-app no GitHub.
Configurar seu projeto
Siga as etapas desta seção para instalar as dependências do projeto , configurar seu ambiente e criar a estrutura do aplicação .
Configure seu ambiente.
Execute os seguintes comandos no seu terminal para inicializar seu projeto e instalar as dependências necessárias:
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
Estes comandos criam um diretório de projeto do mongoose-qe-app e instalam as seguintes dependências:
Mongoose, o ODM do Node.js
Controlador Node.js
mongodb-client-encryption, o pacotede criptografia
Especifique suas variáveis de ambiente.
Na raiz do seu projeto , crie um arquivo .env e cole o seguinte 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>"
Substitua o espaço reservado <connection URI> pelo URI de conexão que se conecta ao seu cluster e substitua o <Automatic Encryption Shared Library path> pelo caminho completo para sua Biblioteca compartilhada de criptografia automática. Certifique-se de que o caminho aponte para lib/mongo_crypt_v1.dylib dentro do pacote baixado.
Se você usar um dos Key Management System (KMS) listados no modelo .env, substitua os valores de espaço reservado correspondentes. Caso contrário, você pode deixar esses valores não atribuídos e armazenar sua Chave Mestre do Cliente localmente. Esse aplicação cria o arquivo da Chave Mestra do Cliente local para você.
Aviso
Armazenamento local da chave mestra do cliente
Se você armazenar sua Chave Mestre do Cliente localmente, não use este aplicação em produção. Sem um KMS remoto, você corre o risco de acesso não autorizado à chave de criptografia ou de perda da chave necessária para descriptografar seus dados.
Dica
Sistemas de gerenciamento de chaves
Para saber mais sobre o KMS, veja o verbete Key Management na Wikipedia.
Crie seus arquivos de aplicação .
Navegue até o diretório mongoose-qe-app e crie um arquivo denominado queryable-encryption-tutorial.js, que armazenará sua lógica de aplicação . Cole o seguinte código neste arquivo:
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);
Em seguida, crie um arquivo chamado queryable-encryption-helpers.js e cole o seguinte 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 arquivo contém uma função assistente do dropExistingDatabase() para seu aplicação. As etapas futuras deste tutorial instruem você a adicionar funções de assistente adicionais.
Atribua suas variáveis de aplicação .
Especifique o banco de dados inicial e as variáveis de criptografia colando o seguinte código na função runExample() do seu arquivo 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';
Substitua o espaço reservado '<KMS provider>' pelo seu provedor de chaves: 'aws', 'azure', 'gcp' ou 'kmip'. Para armazenar sua Chave Mestre do Cliente localmente, defina este valor para 'local'.
O código preenche previamente as seguintes variáveis:
keyVaultDatabaseName - O banco de dados no MongoDB que armazena suas chaves de criptografia de dados (DEKs). Este tutorial utiliza o
encryptionbanco de dados .keyVaultCollectionName - A coleção no MongoDB que armazena seus DEKs. O código define essa variável
__keyVaultcomo, prefixada com um sublinhado para diferenciá-la de uma collection de usuários.keyVaultNamespace - O namespace no MongoDB que armazena seus DEKs. Essa variável consiste nas
keyVaultDatabaseNamekeyVaultCollectionNamevariáveis e, separadas por um período.encryptionDatabaseName - O banco de dados no MongoDB que armazena seus dados criptografados. Este tutorial utiliza o
medicalRecordsbanco de dados .encryptionCollectionName - A coleção no MongoDB que armazena seus dados criptografados. Este tutorial utiliza a
patientscollection.
Configurar credenciais de criptografia
Após configurar a estrutura do projeto , siga as etapas nesta seção para configurar as credenciais do provedor de KMS e as opções de criptografia.
Recupere suas credenciais do provedor de KMS.
Adicione a função getKMSProviderCredentials() ao seu arquivo queryable-encryption-helpers.js. Essa função recupera as credenciais do provedor do sistema de gerenciamento de chaves ou cria um arquivo de chave mestra do cliente local se você não usar um provedor KMS.
Cole o seguinte código após a função 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 função do getKMSProviderCredentials() suporta vários fornecedores de KMS, incluindo AWS, Azure, GCP, KMIP e armazenamento de chave local.
Recupere suas credenciais de chave mestra do cliente.
Adicione a função getCustomerMasterKeyCredentials() ao seu arquivo queryable-encryption-helpers.js. Esta função recupera as credenciais da chave mestra do cliente com base em seu provedor de KMS.
Cole o seguinte código após a função 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.` ); } }
Essa função configura as credenciais da chave mestra do cliente correspondentes para o provedor de KMS escolhido.
Recupere suas opções de criptografia automática .
Adicione a função getAutoEncryptionOptions() ao seu arquivo queryable-encryption-helpers.js. Esta função configura as opções de criptografia automática para seu aplicação.
Cole o seguinte código após a função 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; } }
Atribua suas variáveis de credenciais.
Agora que você definiu as funções de assistente , pode usá-las para acessar suas credenciais a partir do arquivo principal do aplicação .
Navegue até seu arquivo queryable-encryption-tutorial.js e cole o seguinte código após o comentário do 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 );
Esse código chama suas funções assistente para recuperar as credenciais do provedor KMS, as credenciais da Chave Mestra do Cliente e as opções de criptografia automática usadas para configurar a Queryable Encryption.
Criptografar e conectar ao MongoDB
Após configurar as configurações de criptografia, siga as etapas desta seção para configurar sua conexão MongoDB , criar chaves de dados e definir seu esquema criptografado.
Configure sua conexão e cliente MongoDB .
Para configurar sua conexão MongoDB e cliente, navegue até seu arquivo queryable-encryption-tutorial.js e cole o seguinte código após o comentário 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 cria uma conexão Mongoose para operações criptografadas, um cliente MongoDB para gerenciamento de chaves e uma instância ClientEncryption para criar chaves de dados. Ele também descarta todos os bancos de dados existentes para garantir uma configuração limpa para o tutorial.
Crie suas chaves de dados.
Para criar as chaves de dados necessárias, cole o seguinte código após o comentário do 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 cria três chaves de criptografia de dados usadas para criptografar campos diferentes em seus documentos de pacientes. Cada campo criptografado requer sua própria chave de dados.
Defina seu esquema de criptografia.
Para criar a definição do esquema criptografado, cole o seguinte código após o comentário do 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 a estrutura para documentos na collection patients e especifica os seguintes campos criptografados:
patientRecord.ssn: criptografado e configurado para queries de igualdadepatientRecord.billing.type: criptografado, mas não consultávelpatientRecord.billing.number: criptografado, mas não consultável
Registre o esquema de criptografia em um modelo.
Crie um novo modelo denominado Patient para representar a collection patients e registrar seu esquema de criptografia no modelo. Para criar o modelo, cole o seguinte código após o comentário de código // Paste the model below:
const Patient = connection.model('Patient', patientSchema);
Esse código cria um modelo Mongoose que lida com a criptografia automática de campos quando você executa operações de banco de dados .
Estabeleça sua conexão com o banco de dados .
Após registrar seu modelo, você pode estabelecer a conexão do banco de dados colando o seguinte código após o comentário de código // Paste connection code below:
await connection.openUri(uri, { autoEncryption: autoEncryptionOptions, dbName: encryptedDatabaseName });
Isto estabelece a conexão com seu banco de dados do medicalRecords , no qual a criptografia automática está habilitada.
Realizar operações criptografadas
Depois de configurar o aplicação e a conexão do banco de dados , siga as etapas nesta seção para inserir e consultar documentos criptografados.
Insira dados criptografados.
Para inserir um documento com campos criptografados, navegue até seu arquivo queryable-encryption-tutorial.js e cole o seguinte código após o comentário do 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); }
A Queryable Encryption criptografa automaticamente os campos patientRecord.ssn e patientRecord.billing antes de armazenar o documento no MongoDB.
Consultar dados criptografados.
Para executar query de um campo criptografado, cole o seguinte código após o comentário do 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 executa uma query de igualdade no campo patientRecord.ssn criptografado.
Execute seu aplicação.
Finalmente, você pode executar as operações criptografadas definidas nas etapas anteriores executando o seguinte comando no seu diretório mongoose-qe-app:
npm start
Se for bem-sucedida, a saída do comando será semelhante ao exemplo a seguir:
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 passos
Parabéns por concluir o tutorial Queryable Encryption do Mongoose! Agora você tem um aplicação Mongoose de amostra que usa o Queryable Encryption para criptografar e descriptografar automaticamente os campos de documento . Seu aplicação criptografa dados confidenciais no lado do servidor e consulta os dados no lado do cliente .
Para saber mais sobre Queryable Encryption e Mongoose, acesse os seguintes recursos:
Veja mais tutoriais de Queryable Encryption do driver no manual do MongoDB Server .
Saiba como criar um aplicação que usa Mongoose sem Queryable Encryption no tutorial Introdução ao Mongoose.
Saiba mais sobre o Mongoose na documentação do Mongoose.