Skip to content

Commit d8c9d6c

Browse files
authored
Merge pull request #15139 from mongodb-js/NODE-6505/ci-setup
ci(NODE-6505): CI Setup for Encryption Support
2 parents 62e9447 + 42a7b5e commit d8c9d6c

File tree

7 files changed

+222
-1
lines changed

7 files changed

+222
-1
lines changed

.eslintrc.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ module.exports = {
1414
'**/docs/js/native.js',
1515
'!.*',
1616
'node_modules',
17-
'.git'
17+
'.git',
18+
'data'
1819
],
1920
overrides: [
2021
{
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Encryption Tests
2+
3+
on:
4+
push:
5+
branches: ['master']
6+
pull_request:
7+
branches: [ 'master' ]
8+
workflow_dispatch: {}
9+
10+
permissions:
11+
contents: write
12+
pull-requests: write
13+
id-token: write
14+
15+
jobs:
16+
run-tests:
17+
permissions:
18+
# required for all workflows
19+
security-events: write
20+
id-token: write
21+
contents: write
22+
runs-on: ubuntu-latest
23+
name: Encryption tests
24+
env:
25+
FORCE_COLOR: true
26+
steps:
27+
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
28+
- name: Setup node
29+
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
30+
with:
31+
node-version: 22
32+
- name: Install Dependencies
33+
run: npm install
34+
- name: Install mongodb-client-encryption
35+
run: npm install mongodb-client-encryption
36+
- name: Setup Tests
37+
run: npm run setup-test-encryption
38+
- name: Run Tests
39+
run: npm run test-encryption

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,6 @@ examples/ecommerce-netlify-functions/.netlify/state.json
6767

6868
notes.md
6969
list.out
70+
71+
data
72+
*.pid

CONTRIBUTING.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ If you have a question about Mongoose (not a bug report) please post it to eithe
4646
* execute `npm run test-tsd` to run the typescript tests
4747
* execute `npm run ts-benchmark` to run the typescript benchmark "performance test" for a single time.
4848
* execute `npm run ts-benchmark-watch` to run the typescript benchmark "performance test" while watching changes on types folder. Note: Make sure to commit all changes before executing this command.
49+
* in order to run tests that require an cluster with encryption locally, run `npm run setup-test-encryption` followed by `npm run test-encryption`. Alternatively, you can start an encrypted cluster using the `scripts/configure-cluster-with-encryption.sh` file.
50+
* These scripts can take a few minutes to run.
51+
* To change an encryption configuration, it is recommended to follow these steps:
52+
* Edit the variables in `scripts/configure-cluster-with-encryption.sh` with your desired configuration.
53+
* Restart your shell.
54+
* Delete the `data/` directory if it exists.
55+
* Finally, run the configuration script.
4956

5057
## Documentation
5158

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@
104104
"test-deno": "deno run --allow-env --allow-read --allow-net --allow-run --allow-sys --allow-write ./test/deno.js",
105105
"test-rs": "START_REPLICA_SET=1 mocha --timeout 30000 --exit ./test/*.test.js",
106106
"test-tsd": "node ./test/types/check-types-filename && tsd",
107+
"setup-test-encryption": "bash scripts/configure-cluster-with-encryption.sh",
108+
"test-encryption": "mocha --exit ./test/encryption/*.test.js",
107109
"tdd": "mocha ./test/*.test.js --inspect --watch --recursive --watch-files ./**/*.{js,ts}",
108110
"test-coverage": "nyc --reporter=html --reporter=text npm test",
109111
"ts-benchmark": "cd ./benchmarks/typescript/simple && npm install && npm run benchmark | node ../../../scripts/tsc-diagnostics-check"
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# note: in order to use FLE with mongodb, we must
2+
# have mongocryptd or the shared library downloaded
3+
# have an enterprise server >= 4.2
4+
5+
# this script downloads all tools required to use FLE with mongodb, then starts a cluster of the provided configuration (sharded on 8.0 server)
6+
7+
export CWD=$(pwd);
8+
9+
# install extra dependency
10+
npm install mongodb-client-encryption
11+
12+
# set up mongodb cluster and encryption configuration if the data/ folder does not exist
13+
if [ ! -d "data" ]; then
14+
15+
mkdir data
16+
cd data
17+
18+
# note:
19+
# we're using drivers-evergreen-tools which is a repo used by MongoDB drivers to start clusters for testing.
20+
# if you'd like to make changes to the cluster settings, edit the exported variables below.
21+
# for configuration options for the exported variables, see here: https://github.com/mongodb-labs/drivers-evergreen-tools/blob/master/.evergreen/run-orchestration.sh
22+
# after this script is run, the data/ folder will notably contain the following:
23+
# 'mo-expansion.yml' file which contains for your cluster URI and crypt shared library path
24+
# 'drivers-evergreen-tools/mongodb/bin' which contain executables for other mongodb libraries such as mongocryptd, mongosh, and mongod
25+
if [ ! -d "drivers-evergreen-tools/" ]; then
26+
git clone --depth=1 "https://github.com/mongodb-labs/drivers-evergreen-tools.git"
27+
fi
28+
29+
# configure cluster settings
30+
export DRIVERS_TOOLS=$CWD/data/drivers-evergreen-tools
31+
export MONGODB_VERSION=8.0
32+
export AUTH=true
33+
export MONGODB_BINARIES=$DRIVERS_TOOLS/mongodb/bin
34+
export MONGO_ORCHESTRATION_HOME=$DRIVERS_TOOLS/mo
35+
export PROJECT_ORCHESTRATION_HOME=$DRIVERS_TOOLS/.evergreen/orchestration
36+
export TOPOLOGY=sharded_cluster
37+
export SSL=nossl
38+
39+
cd $DRIVERS_TOOLS
40+
rm -rf mongosh mongodb mo
41+
mkdir mo
42+
cd -
43+
44+
rm expansions.sh 2> /dev/null
45+
46+
echo 'Configuring Cluster...'
47+
48+
# start cluster
49+
(bash $DRIVERS_TOOLS/.evergreen/run-orchestration.sh) 1> /dev/null 2> /dev/null
50+
51+
echo 'Cluster Configuration Finished!'
52+
53+
cd ..
54+
fi

test/encryption/encryption.test.js

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
'use strict';
2+
3+
const assert = require('assert');
4+
const mongodb = require('mongodb');
5+
const fs = require('fs');
6+
const isBsonType = require('../../lib/helpers/isBsonType');
7+
8+
const LOCAL_KEY = Buffer.from('Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk', 'base64');
9+
10+
describe('ci', () => {
11+
12+
const cachedUri = process.env.MONGOOSE_TEST_URI;
13+
const cachedLib = process.env.CRYPT_SHARED_LIB_PATH;
14+
15+
before(function() {
16+
const cwd = process.cwd();
17+
const file = fs.readFileSync(cwd + '/data/mo-expansion.yml', { encoding: 'utf-8' }).trim().split('\n');
18+
const regex = /^(?<key>.*): "(?<value>.*)"$/;
19+
const variables = file.map((line) => regex.exec(line.trim()).groups).reduce((acc, { key, value }) => ({ ...acc, [key]: value }), {});
20+
process.env.CRYPT_SHARED_LIB_PATH = variables.CRYPT_SHARED_LIB_PATH;
21+
process.env.MONGOOSE_TEST_URI = variables.MONGODB_URI;
22+
});
23+
24+
after(function() {
25+
process.env.CRYPT_SHARED_LIB_PATH = cachedLib;
26+
process.env.MONGOOSE_TEST_URI = cachedUri;
27+
});
28+
29+
describe('environmental variables', () => {
30+
it('MONGOOSE_TEST_URI is set', async function() {
31+
const uri = process.env.MONGOOSE_TEST_URI;
32+
assert.ok(uri);
33+
});
34+
35+
it('CRYPT_SHARED_LIB_PATH is set', async function() {
36+
const shared_library_path = process.env.CRYPT_SHARED_LIB_PATH;
37+
assert.ok(shared_library_path);
38+
});
39+
});
40+
41+
describe('basic integration', () => {
42+
let keyVaultClient;
43+
let dataKey;
44+
let encryptedClient;
45+
let unencryptedClient;
46+
47+
beforeEach(async function() {
48+
keyVaultClient = new mongodb.MongoClient(process.env.MONGOOSE_TEST_URI);
49+
await keyVaultClient.connect();
50+
await keyVaultClient.db('keyvault').collection('datakeys');
51+
const clientEncryption = new mongodb.ClientEncryption(keyVaultClient, {
52+
keyVaultNamespace: 'keyvault.datakeys',
53+
kmsProviders: { local: { key: LOCAL_KEY } }
54+
});
55+
dataKey = await clientEncryption.createDataKey('local');
56+
57+
encryptedClient = new mongodb.MongoClient(
58+
process.env.MONGOOSE_TEST_URI,
59+
{
60+
autoEncryption: {
61+
keyVaultNamespace: 'keyvault.datakeys',
62+
kmsProviders: { local: { key: LOCAL_KEY } },
63+
schemaMap: {
64+
'db.coll': {
65+
bsonType: 'object',
66+
encryptMetadata: {
67+
keyId: [dataKey]
68+
},
69+
properties: {
70+
a: {
71+
encrypt: {
72+
bsonType: 'int',
73+
algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Random',
74+
keyId: [dataKey]
75+
}
76+
}
77+
}
78+
}
79+
},
80+
extraOptions: {
81+
cryptdSharedLibRequired: true,
82+
cryptSharedLibPath: process.env.CRYPT_SHARED_LIB_PATH
83+
}
84+
}
85+
}
86+
);
87+
88+
unencryptedClient = new mongodb.MongoClient(process.env.MONGOOSE_TEST_URI);
89+
});
90+
91+
afterEach(async function() {
92+
await keyVaultClient.close();
93+
await encryptedClient.close();
94+
await unencryptedClient.close();
95+
});
96+
97+
it('ci set-up should support basic mongodb auto-encryption integration', async() => {
98+
await encryptedClient.connect();
99+
const { insertedId } = await encryptedClient.db('db').collection('coll').insertOne({ a: 1 });
100+
101+
// client not configured with autoEncryption, returns a encrypted binary type, meaning that encryption succeeded
102+
const encryptedResult = await unencryptedClient.db('db').collection('coll').findOne({ _id: insertedId });
103+
104+
assert.ok(encryptedResult);
105+
assert.ok(encryptedResult.a);
106+
assert.ok(isBsonType(encryptedResult.a, 'Binary'));
107+
assert.ok(encryptedResult.a.sub_type === 6);
108+
109+
// when the encryptedClient runs a find, the original unencrypted value is returned
110+
const unencryptedResult = await encryptedClient.db('db').collection('coll').findOne({ _id: insertedId });
111+
assert.ok(unencryptedResult);
112+
assert.ok(unencryptedResult.a === 1);
113+
});
114+
});
115+
});

0 commit comments

Comments
 (0)