개요
이 가이드 에서는 Mongoose 사용하여 MongoDB의 Queryable Encryption 기능 구현 애플리케이션 을 만드는 방법을 학습 수 있습니다.
Queryable Encryption 사용하면 문서 필드를 자동으로 암호화하고 해독할 수 있습니다. Queryable Encryption 사용하여 애플리케이션 의 민감한 데이터를 암호화하고, 데이터 필드를 서버 에 무작위로 암호화됨 데이터로 저장 , 암호화됨 필드를 쿼리 수 있습니다. 이 튜토리얼에서는 데이터 상호 작용을 위한 ODM(객체 문서 매퍼) 라이브러리를 제공하는 Mongoose 사용하여 Queryable Encryption 설정하다 방법을 보여줍니다.
전제 조건
이 튜토리얼을 시작하기 전에 다음 전제 조건 작업을 완료하세요.
MongoDB Atlas 계정을 만들고 클러스터 구성합니다. 클러스터 가 MongoDB Server 버전 이상에서 실행되는지 7.0 확인합니다. 자세한 학습 은 MongoDB 시작하기 가이드 참조하세요.
자동 암호화 공유 라이브러리를 다운로드합니다. 지침을 보려면 쿼리 분석 구성 요소 설치 및 구성 가이드 참조하세요. 이 지침은 MongoDB 다운로드 센터로 이동하여 라이브러리를 다운로드 데 필요한 양식을 작성하는 방법을 보여줍니다.
Node.js v..16 201 이상을 설치합니다.
튜토리얼
이 튜토리얼에서는 Mongoose 사용하는 Queryable Encryption 애플리케이션 만드는 방법을 보여줍니다. 이 애플리케이션 환자의 의료 기록을 암호화 및 복호화하고 암호화됨 의료 데이터를 쿼리합니다.
프로젝트 설정
이 섹션의 단계에 따라 프로젝트 종속성을 설치하고, 환경을 구성하고, 애플리케이션 구조를 만듭니다.
환경을 설정합니다.
터미널에서 다음 명령을 실행하여 프로젝트 초기화하고 필요한 종속성을 설치합니다.
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
이 명령은 mongoose-qe-app 프로젝트 디렉토리 만들고 다음 종속성을 설치합니다.
Mongoose, Node.js ODM
Node.js 운전자
환경 변수를 로드하는 모듈인Dotenv
환경 변수를 지정합니다.
프로젝트 루트에서 .env 파일 만들고 다음 코드를 붙여넣습니다.
# 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>"
<connection URI> 자리 표시자를 클러스터 에 연결하는 연결 URI로 바꾸고 <Automatic Encryption Shared Library path> 을 자동 암호화 공유 라이브러리의 전체 경로로 바꿉니다. 경로가 다운로드한 패키지 내부의 lib/mongo_crypt_v1.dylib 를 가리키는지 확인합니다.
.env 템플릿에 나열된 키 관리 시스템(KMS ) 중 하나를 사용하는 경우 해당 자리 표시자 값을 바꿉니다. 그렇지 않으면 이러한 값을 할당하지 않은 상태로 두고 고객 마스터 키 로컬에 저장 수 있습니다. 이 애플리케이션 로컬 고객 마스터 키 파일 생성합니다.
경고
로컬 CMK 스토리지
고객 마스터 키 로컬에 저장 경우 프로덕션 환경에서는 이 애플리케이션 사용하지 마세요. 원격 KMS 없으면 암호화 키 에 무단으로 액세스 하거나 데이터를 해독하는 데 필요한 키를 잃을 위험이 있습니다.
애플리케이션 파일을 생성합니다.
mongoose-qe-app 디렉토리 로 이동하여 애플리케이션 로직을 저장 queryable-encryption-tutorial.js 파일 만듭니다. 이 파일 에 다음 코드를 붙여넣습니다.
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);
그런 다음 queryable-encryption-helpers.js 이라는 파일 만들고 다음 코드를 붙여넣습니다.
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
이 파일 애플리케이션 에 대한 dropExistingDatabase() 헬퍼 함수가 포함되어 있습니다. 이 튜토리얼의 이후 단계에서는 헬퍼 함수를 추가하는 방법을 설명합니다.
애플리케이션 변수를 할당합니다.
queryable-encryption-tutorial.js 파일 의 runExample() 함수에 다음 코드를 붙여넣어 초기 데이터베이스 및 암호화 변수를 지정합니다.
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';
'<KMS provider>' 자리 표시자를 키 제공자 ( 'aws', 'azure', 'gcp' 또는 'kmip')로 바꿉니다. 고객 마스터 키 로컬에 저장 하려면 이 값을 'local'로 설정하다 .
이 코드는 다음 변수를 미리 채웁니다.
keyVaultDatabaseName - 데이터 암호화 키(DEK)를 저장하는 MongoDB 의 데이터베이스 입니다. 이 튜토리얼에서는
encryption데이터베이스 사용합니다.keyVaultCollectionName - DEK를 저장하는 MongoDB 의 컬렉션 입니다. 이 코드에서는 이 변수를 로
__keyVault설정하고, 사용자 컬렉션 과 구분하기 위해 밑줄이 앞에 붙습니다.keyVaultNamespace - DEK를 저장하는 MongoDB 의 네임스페이스 . 이 변수는
keyVaultDatabaseNamekeyVaultCollectionName마침표로 구분된 및 변수로 구성됩니다.encryptionDatabaseName - 암호화됨 데이터를 저장하는 MongoDB 의 데이터베이스 입니다. 이 튜토리얼에서는
medicalRecords데이터베이스 사용합니다.encryptionCollectionName - 암호화됨 데이터를 저장하는 MongoDB 의 컬렉션 입니다. 이 튜토리얼에서는
patients컬렉션 사용합니다.
암호화 자격 증명 구성
프로젝트 구조를 설정한 후 이 섹션의 단계에 따라 KMS 제공자 자격 증명 및 암호화 옵션을 구성합니다.
KMS 제공자 자격 증명 조회합니다.
queryable-encryption-helpers.js 파일 에 getKMSProviderCredentials() 함수를 추가합니다. 이 함수는 키 관리 시스템 제공자 의 자격 증명 조회하거나, KMS 제공자 사용하지 않는 경우 로컬 고객 마스터 키 파일 생성합니다.
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.` ); } }
이 getKMSProviderCredentials() 함수는 AWS, Azure, GCP, KMIP 및 로컬 키 저장 포함한 여러 KMS 제공자를 지원합니다.
고객 마스터 키 자격 증명 조회합니다.
queryable-encryption-helpers.js 파일 에 getCustomerMasterKeyCredentials() 함수를 추가합니다. 이 함수는 KMS 제공자 기반으로 고객 마스터 키 자격 증명 검색합니다.
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.` ); } }
이 함수는 선택한 KMS 제공자 에 해당하는 고객 마스터 키 자격 증명 구성합니다.
자동 암호화 옵션을 조회합니다.
queryable-encryption-helpers.js 파일 에 getAutoEncryptionOptions() 함수를 추가합니다. 이 함수는 애플리케이션 에 대한 자동 암호화 옵션을 구성합니다.
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; } }
자격 증명 변수를 할당합니다.
이제 헬퍼 함수를 정의했으므로 이를 사용하여 메인 애플리케이션 파일 에서 자격 증명 에 액세스 할 수 있습니다.
queryable-encryption-tutorial.js 파일 로 이동하여 // Paste credential and options variables below 코드 주석 뒤에 다음 코드를 붙여넣습니다.
const kmsProviderCredentials = qeHelper.getKMSProviderCredentials(kmsProviderName); const customerMasterKeyCredentials = qeHelper.getCustomerMasterKeyCredentials(kmsProviderName); const autoEncryptionOptions = await qeHelper.getAutoEncryptionOptions( kmsProviderName, keyVaultNamespace, kmsProviderCredentials );
이 코드는 헬퍼 함수를 호출하여 Queryable Encryption 구성하는 데 사용되는 KMS 제공자 자격 증명, 고객 마스터 키 자격 증명 및 자동 암호화 옵션을 조회 .
MongoDB 암호화 및 연결
암호화 설정을 구성한 후 이 섹션의 단계에 따라 MongoDB 연결을 설정하다 하고, 데이터 키를 만들고, 암호화됨 스키마 정의합니다.
MongoDB 연결 및 클라이언트 구성합니다.
MongoDB 연결 및 클라이언트 설정하다 하려면 queryable-encryption-tutorial.js 파일 로 이동하여 // 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);
이 코드는 암호화됨 작업을 위한 Mongoose 연결, 키 관리 위한 MongoDB 클라이언트 , 데이터 키 생성을 위한 ClientEncryption 인스턴스 생성합니다. 또한 튜토리얼을 깔끔하게 설정 수 있도록 기존 데이터베이스를 모두 삭제합니다.
데이터 키를 생성합니다.
필요한 데이터 키를 만들려면 // 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, });
이 코드는 환자 문서의 서로 다른 필드를 암호화하는 데 사용되는 3개의 데이터 암호화 키를 생성합니다. 암호화됨 각 필드 자체 데이터 키가 필요합니다.
암호화 스키마 정의합니다.
암호화됨 스키마 정의를 만들려면 // 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 });
이 스키마 patients 컬렉션 에 있는 문서의 구조를 정의하고 다음과 같은 암호화됨 필드를 지정합니다.
patientRecord.ssn: 동일성 쿼리를 위해 암호화 및 구성patientRecord.billing.type: 암호화되었지만 쿼리할 수 없음patientRecord.billing.number: 암호화되었지만 쿼리할 수 없음
암호화된 작업 수행
애플리케이션 과 데이터베이스 연결을 구성한 후 이 섹션의 단계에 따라 암호화됨 문서를 삽입하고 쿼리 .
암호화됨 데이터를 삽입합니다.
암호화됨 필드가 있는 문서 삽입하려면 queryable-encryption-tutorial.js 파일 로 이동하여 // 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); }
Queryable Encryption 문서 MongoDB 에 저장하기 전에 patientRecord.ssn 및 patientRecord.billing 필드를 자동으로 암호화합니다.
애플리케이션 실행합니다.
마지막으로 mongoose-qe-app 디렉토리 에서 다음 명령을 실행 하여 이전 단계에서 정의된 암호화됨 작업을 실행 수 있습니다.
npm start
성공적인 하면 명령 출력이 다음 예시 와 유사합니다.
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.
다음 단계
Mongoose Queryable Encryption 튜토리얼을 완료한 것을 축하합니다! 이제 Queryable Encryption 사용하여 문서 필드를 자동으로 암호화하고 해독하는 샘플 Mongoose 애플리케이션 생겼습니다. 애플리케이션 은 서버 사이드에서 민감한 데이터를 암호화하고 클라이언트 사이드에서 데이터를 쿼리합니다.
Queryable Encryption 및 Mongoose 에 대해 자세히 학습 다음 리소스를 참조하세요.
MongoDB Server매뉴얼에서 더 많은 운전자 Queryable Encryption 튜토리얼을 확인하세요.
Mongoose 시작하기 튜토리얼에서 Queryable Encryption 없이 Mongoose 사용하는 애플리케이션 만드는 방법을 알아보세요.
Mongoose 에 대한 자세히 보기 Mongoose 설명서를 참조하세요.