Client Side Field Level Encryption, having trouble connecting to secureClient

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) {}
}
1 Like

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

2 Likes

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

1 Like

And here’s the full repo for Node that’s referenced in the Quick Start (I’ve highlighted the crypt_shared part, but take a look at the whole ./node/local/reader folder in the repo) here: docs-in-use-encryption-examples/insert_encrypted_document.js at main · mongodb-university/docs-in-use-encryption-examples · GitHub