FLE MongoError: BSON field 'insert.jsonSchema' is an unknown field

Hi Everyone!
After seeing the Field level encryption on a session of Mongo DB live we decided to try implementing it.
I successfully generated the key vault collection using a AWS KMS key. Next I followed the docs and added a JSON schema to the collection which also worked and I can see the schema in compass. Now what I cant seem to get working is the actual insert. Everything I have tried gives the following error on insert
"MongoError: BSON field ‘insert.jsonSchema’ is an unknown field. "
What exactly does this error mean with FLE?

I am actually working with dev support now, and they are looking into it.

Hi @kyle_mcarthur, and welcome to the forum!

The error message sounds related to a misconfiguration on the application side.
You may find the following resources useful:

Feel free to post back here if you have a solution. It may beneficial for other users who may encounter similar configuration issue in the future.

Regards,
Wan.

Did you find a solution? I am having the same problem.

Hi Emilio,
Yes, my problem was that the mongocryptd process was not running. You will have to download the enterprise edition of mongo and start the process.

Thanks Kyle.

I am actually using a 4.2 MongoDB Atlas Cluster. However I’m still having that error message.

What do you have on your autoEncryption.extraOptions object?

I currently have:

const extraOptions = {
        mongocryptdURI: connectionString,
        mongocryptdBypassSpawn: true,
    };

So that is the part that is confusing, you CANT use your atlas cluster as the encryption process. You have to start the process yourself and use it on the same server your backend is running or expose the process yourself on a separate server and connect with the extra options but you can’t use your atlas instance. I chose the first option and I let the mongo node driver start the process on my server (the driver will try and start it if it’s in your PATH if you remove the bypassSpawn option you have set)

Oh ok I understand.

I might end up using cloud run base on your solution. Would it be possible for you to share the code regarding including the encryption binary in the docker file? And also the exponential backoff loop you wrote?

It would really help me a lot, but if you can’t, that’s fine.

I really appreciate all your help man.

So when I talked to dev support about that (i was trying to use my atlas connection string as well at first) they said its because its “client” encryption but they would take my feedback to the team about using an atlas string. I too am using a serverless architecture but I am using Cloud Run and since that is a docker container I am able to include the encryption binary in the docker container and the node driver starts it automatically.

The biggest issue I had on cloud run was the driver code attempts to wait for the process to be started and that didnt always work on cloud run. I basically wrote an exponential backoff loop with a try catch trying to connect to the mongo cluster and now it works flawlessly as it eliminates the race condition with the node driver and the encryption process starting.

I use AWS lambda on a different project and with that you would have to do what you said and start the process on a lightsail or ec2 instance. If you havent looked at cloud run I would suggest taking a look as it works great for something like this. If you dont want to use google cloud, aws has fargate that should work similar but its a bit more involved in the setup than cloud run.

2 Likes

Hi @Emilio_Lopez and @kyle_mcarthur,

The general notion of MongoDB Client-Side Field Level Encryption is that the server never sees the unencrypted values. In this case the driver would automatically encrypt the values via a client-side process (i.e. mongocryptd) before sending data to Atlas.

Please note that MongoDB also has Encryption At Rest capability. Atlas encrypts all cluster storage and snapshot volumes, ensuring the security of all cluster data at rest.

If you’re looking for an example Dockerfile that includes just mongocryptd please see
github.com/sindbach/field-level-encryption-docker .

I’d also recommend to review FLE: Encryption Components for more information around Client-Side Field Level Encryption.

Regards,
Wan.

1 Like

A backoff loop will look something like this:

let pollForMongo = true;
let maxPolls = 0;
let backoff = 0;
while (pollForMongo && maxPolls < 10) {
    console.log('polling.....', maxPolls);
    try {
        // eslint-disable-next-line no-await-in-loop
        await mongoose.connect(uri, {
            useUnifiedTopology: true,
            useNewUrlParser: true,
            useCreateIndex: true,
            autoEncryption: {
                keyVaultNamespace,
                kmsProviders,
                schemaMap,
            },
        });
        pollForMongo = false;
    } catch (e) {
        console.log('time until next poll...', 1000 + backoff);
        // eslint-disable-next-line no-await-in-loop
        await sleep(1000 + backoff);
        maxPolls += 1;
        backoff += 1000;
    }
}

An example docker file is something like:

#Use the official lightweight Node.js 13 image.
#https://hub.docker.com/_/node
FROM node:13.5-slim

#Create and change to the app directory.
WORKDIR ./

#Copy application dependency manifests to the container image.
#A wildcard is used to ensure both package.json AND package-lock.json are copied.
#Copying this separately prevents re-running npm install on every code change.
COPY package*.json ./

#Install production dependencies.
RUN npm install --only=production

#Copy local code to the container image.
COPY . ./
RUN apt-get update && apt-get install -y --no-install-recommends apt-utils
RUN apt install /encryption/mongocryptd.deb

#Run the web service on container startup.
CMD [ "npm", "start" ]

And then in my repo I placed mongocryptd.deb in a folder called encryption.

Thanks man!

By the way, are you having any performance issues with mongocryptd? My writes are taking twice the amount of time even if the document I am saving doesn’t have any encrypted fields. Also when I make 20+ writes concurrently it just stops working.

I have fortunately not had any performance problems with the encryption process. Let me know if you find out the cause.

Nevermind I figured it out

I will.

Did you have this error when running it on docker?

Error: /app/node_modules/mongodb-client-encryption/build/Release/mongocrypt.node: invalid ELF header.

hi are you downloaded ‘mongocryptd.deb’ with these config?

I am not able to install mongocryptd.deb due to dependences.
E: Release ‘mongocryptd.deb’ for ‘python-pymongo’ was not found
E: Release ‘mongocryptd.deb’ for ‘libmongodb-java’ was not found
E: Release ‘mongocryptd.deb’ for ‘jmeter-mongodb’ was not found
E: Release ‘mongocryptd.deb’ for ‘python3-pymongo’ was not found
E: Release ‘mongocryptd.deb’ for ‘libcatmandu-store-mongodb-perl’ was not found
E: Release ‘mongocryptd.deb’ for ‘libmongodb-perl’ was not found
E: Release ‘mongocryptd.deb’ for ‘libmongo-client-dev’ was not found
E: Release ‘mongocryptd.deb’ for ‘libmongo-client0’ was not found
E: Release ‘mongocryptd.deb’ for ‘libmongo-client-doc’ was not found
E: Release ‘mongocryptd.deb’ for ‘libmongo-client0-dbg’ was not found
E: Release ‘mongocryptd.deb’ for ‘libmongoc-1.0-0’ was not found
E: Release ‘mongocryptd.deb’ for ‘libmongoc-dev’ was not found
E: Release ‘mongocryptd.deb’ for ‘libmongoc-doc’ was not found
E: Release ‘mongocryptd.deb’ for ‘libmongoclient-dev’ was not found
E: Release ‘mongocryptd.deb’ for ‘libmongoclient0’ was not found
E: Release ‘mongocryptd.deb’ for ‘php-mongodb’ was not found
E: Release ‘mongocryptd.deb’ for ‘php-doctrine-mongodb-odm’ was not found
E: Release ‘mongocryptd.deb’ for ‘php-horde-mongo’ was not found
E: Release ‘mongocryptd.deb’ for ‘php7.0-mongodb’ was not found
E: Release ‘mongocryptd.deb’ for ‘php-mongo’ was not found
E: Release ‘mongocryptd.deb’ for ‘libpocomongodb46’ was not found
E: Release ‘mongocryptd.deb’ for ‘prometheus-mongodb-exporter’ was not found
E: Release ‘mongocryptd.deb’ for ‘puppet-module-puppetlabs-mongodb’ was not found
E: Release ‘mongocryptd.deb’ for ‘python-pymongo-ext’ was not found
E: Release ‘mongocryptd.deb’ for ‘python-pymongo-doc’ was not found
E: Release ‘mongocryptd.deb’ for ‘python2.7-pymongo’ was not found
E: Release ‘mongocryptd.deb’ for ‘python2.7-pymongo-ext’ was not found
E: Release ‘mongocryptd.deb’ for ‘python3-pymongo-ext’ was not found
E: Release ‘mongocryptd.deb’ for ‘python-mongoengine’ was not found
E: Release ‘mongocryptd.deb’ for ‘python2.7-mongoengine’ was not found
E: Release ‘mongocryptd.deb’ for ‘python-mongoengine-doc’ was not found
E: Release ‘mongocryptd.deb’ for ‘python3-mongoengine’ was not found
E: Release ‘mongocryptd.deb’ for ‘rsyslog-mongodb’ was not found
E: Release ‘mongocryptd.deb’ for ‘ruby-em-mongo’ was not found
E: Release ‘mongocryptd.deb’ for ‘ruby-mongo’ was not found
E: Release ‘mongocryptd.deb’ for ‘syslog-ng-mod-mongodb’ was not found
E: Release ‘mongocryptd.deb’ for ‘uwsgi-mongodb-plugins’ was not found
E: Release ‘mongocryptd.deb’ for ‘w1retap-mongo’ was not found

Hi @Ben_Luk, and welcome to the forum!

You can install mongocryptd from apt-get on Ubuntu. For example in a Dockerfile:

RUN wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | apt-key add -
RUN echo "deb [ arch=amd64,arm64,s390x ] http://repo.mongodb.com/apt/ubuntu focal/mongodb-enterprise/4.4 multiverse" | tee /etc/apt/sources.list.d/mongodb-enterprise.list
RUN apt-get update && apt-get install -y mongodb-enterprise-cryptd=4.4.1

See also github.com/sindbach/field-level-encryption-docker/node for a working example.

Regards,
Wan

1 Like

Hello Team,

I am facing the same issue, can some one have solution for this?

@wan whats the point of having “mongocryptdURI” extra option then?

Hi @Obaid_Maroof , and welcome to the forums,

The mongocryptd configuration parameters are used to specify values that differ from the defaults. In this case, the default for mongocryptdURI is "mongodb://localhost:27020". If you would like to specify a different URI i.e. port number then you could utilise the parameter to do so.

If you have further questions, please feel free to open a new topic.

Regards,
Wan.