7 / 7
Dec 2024

trying to implement client side field level encryption with free mongodb atlas cluster, completed the part of generating data key id.
Then while trying to do insert encrypted doc facing problem, the code is working till connecting to reg client and after that having trouble to connect to secureClient

question 1 : do we need to install mongocryptd for atlas as well
question 2: am doing something wrong with extraOptions what should be value to the field
mongocryptdSpawnPath in extraOptions for atlas cluster

if am doing wrong anything please correct me

Thank you

code:

const mongodb = require("mongodb"); const { ClientEncryption } = require("mongodb-client-encryption"); const { MongoClient, Binary } = mongodb; const { join } = require('path'); require('dotenv').config(); // const { getCredentials } = require("./your_credentials"); // credentials = getCredentials(); var db = "medicalRecords"; var coll = "patients"; var namespace = `${db}.${coll}`; // start-kmsproviders const {readFileSync} = require("fs"); const provider = "local"; const path = join(__dirname,"./master-key.txt") const localMasterKey = readFileSync(path); console.log(localMasterKey) const kmsProviders = { local: { key: localMasterKey, }, }; // end-kmsproviders const connectionString = process.env.URI; // start-key-vault const keyVaultNamespace = "encryption.__keyVault"; // end-key-vault // start-schema const schema = { bsonType: "object", encryptMetadata: { // keyId: { // $binary:{ // base64: "PadTrVggQL+MaHprhtzdcA==", // subType: "04", // } // }, keyId: [ new Binary(Buffer.from("PadTrVggQL+MaHprhtzdcA==", "base64"),4)], }, properties: { insurance: { bsonType: "object", properties: { policyNumber: { encrypt: { bsonType: "int", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random", }, }, }, }, medicalRecords: { encrypt: { bsonType: "array", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random", }, }, bloodType: { encrypt: { bsonType: "string", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random", }, }, ssn: { encrypt: { bsonType: "int", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random", }, }, }, }; var patientSchema = {}; patientSchema[namespace] = schema; // end-schema // start-extra-options const extraOptions = { // mongocryptdSpawnPath: '.' mongocryptdBypassSpawn: true, }; // end-extra-options // start-client - const secureClient = new MongoClient(connectionString, { useNewUrlParser: true, useUnifiedTopology: true, autoEncryption: { keyVaultNamespace, kmsProviders, schemaMap: patientSchema, extraOptions: extraOptions, }, }); // end-client const regularClient = new MongoClient(connectionString, { useNewUrlParser: true, useUnifiedTopology: true, }); async function main() { console.log("inside main"); try { //await regularClient.connect(); console.log('reg client') try { await secureClient.connect(); console.log('sec client') // start-insert try { const writeResult = await secureClient .db(db) .collection(coll) .insertOne({ name: "Jon Doe", ssn: 241014209, bloodType: "AB+", "key-id": "demo-data-key", medicalRecords: [{ weight: 180, bloodPressure: "120/80" }], insurance: { policyNumber: 123142, provider: "MaestCare", }, }); } catch (writeError) { console.error("writeError occurred:", writeError); } // end-insert // start-find console.log("Finding a document with regular (non-encrypted) client."); console.log( await regularClient.db(db).collection(coll).findOne({ name: /Jon/ }) ); console.log( "Finding a document with encrypted client, searching on an encrypted field" ); console.log( await secureClient.db(db).collection(coll).findOne({ name: /Jon/ }) ); // end-find } catch(err) { console.log("secure",err); } finally { await secureClient.close(); } } finally { await regularClient.close(); } } main();

Error:

MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27020 at Timeout._onTimeout (D:\Node js\MongoDB_encryption\node_modules\mongodb\lib\sdam\topology.js:277:38) at listOnTimeout (internal/timers.js:557:17) at processTimers (internal/timers.js:500:7) { reason: TopologyDescription { type: 'Unknown', servers: Map(1) { 'localhost:27020' => [ServerDescription] }, stale: false, compatible: true, heartbeatFrequencyMS: 10000, localThresholdMS: 15, setName: null, maxElectionId: null, maxSetVersion: null, commonWireVersion: 0, logicalSessionTimeoutMinutes: null }, code: undefined, [Symbol(errorLabels)]: Set(0) {} }

Hello. The “connect ECONNREFUSED 127.0.0.1:27020” indicates the Node code was attempting to perform automatic encryption, but could not locate either the mongocryptd or shared_crypt libraries (you only need one, and both packages are available from the Enterprise Downloads page (MongoDB Enterprise Server Download | MongoDB); note you only need the cryptd or crypt_shared package, not the entire server. Both libraries are fully licensed for all Atlas users (including the free tiers) and Enterprise, but one or the other need to be specifically installed, they won’t get pulled down automatically with your language dependencies like libmongocrypt will.

Hope that helps!

-Kenn

8 days later

Hi Kennth_White,

I have downloaded the crypt-shared package for the above example. Can you please guide me on what particular file in that package I need to specify in my code?

Hi Rajat.

For crypt_shared, you need to either put the mongo_crypt_v1.so (mongo_crypt_v1.dylib on Mac) on the default path, or specify it explicitly on the extraOptions cryptSharedLibPath, e.g.:

ExtraOptions: { cryptSharedLibPath: "/home/appUser/node/mongo_crypt_v1.so" }

Alternatively, if you choose to use the mongocryptd package, then you can just run that on bootup/container start, or launch into a detached background process, e.g.:
$ ( ./mongocryptd 2>&1 >> /var/log/mongocryptd.log &)

See https://www.mongodb.com/docs/manual/core/csfle/reference/mongocryptd/ and
https://www.mongodb.com/docs/manual/core/queryable-encryption/reference/shared-library/#configuration.

There’s a full code example with switchable language snippets for setting crypt_shared here: https://www.mongodb.com/docs/manual/core/queryable-encryption/quick-start/#create-your-encrypted-collection

Cheers.
Kenn

2 years later

Hi, thanks for guide on this, after setting up locally, how we can setup in docker for cloud deployments on render

here is my current docker file, followed through most installation guides, yet still having issues installing mongo_client_encryption FROM node:15-alpine3.11 WORKDIR /usr/src/app RUN apk update && apk add --no-cache nmap && \ echo @edge https://dl-cdn.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories && \ echo @edge https://dl-cdn.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories && \ apk update && \ apk add --no-cache \ python3 \ py3-pip \ py3-packaging \ py3-setuptools \ make \ g++ \ gcc \ git \ cmake \ openssl-dev \ linux-headers \ chromium \ harfbuzz \ "freetype>2.8" \ ttf-freefont \ nss \ bash \ wget \ curl \ libgcc \ libstdc++ \ ca-certificates \ libcurl # Build and install libmongocrypt RUN git clone https://github.com/mongodb/libmongocrypt.git && \ cd libmongocrypt && \ cmake -DENABLE_SHARED_BSON=ON \ -DCMAKE_INSTALL_PREFIX=/usr/local \ -DBUILD_VERSION=1.7.3 . && \ make && \ make install && \ cd .. && \ rm -rf libmongocrypt # Set environment variables ENV PYTHON=/usr/bin/python3 ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ENV LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH RUN curl -L -o mongo_crypt_shared.tgz \ https://github.com/Talesconnect/mongo_tools/raw/main/mongo_crypt_shared_v1-linux-x86_64-enterprise-ubuntu2004-8.0.4.tgz && \ tar -xvf mongo_crypt_shared.tgz && \ mkdir -p /usr/local/lib && \ mv lib/mongo_crypt_v1.so /usr/local/lib/mongo_crypt_v1.so && \ rm mongo_crypt_shared.tgz # Set the library path ENV CSFLE_CRYPT_SHARED_LIB_PATH=/usr/local/lib/mongo_crypt_v1.so ENV MONGODB_CRYPT_SHARED_LIB_PATH=/usr/local/lib/mongo_crypt_v1.so ENV MONGOCRYPT_LIB_DIR=/usr/local/lib ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true # Copy package.json and yarn.lock to install dependencies COPY package*.json ./ RUN yarn global add rimraf && \ yarn install # Copy application code COPY . . RUN yarn build CMD ["node", "--optimize_for_size", "--max_old_space_size=460", "--gc_interval=100", "dist/main.js"]