Last active
October 16, 2019 17:12
-
-
Save kennwhite/ac586cfa1f8673a5cbec8c8b91e29bbc to your computer and use it in GitHub Desktop.
MongoDB Client Side Field Level Encryption Quickstart Part 2 (KMS version)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Simple demonstration using MongoDB Client-Side Field Level Encryption (KMS version) | |
// Requires Community or (preferrably) Enterprise Shell and a MongoDB 4.2+ database | |
// Local, stand-alone, or Atlas MongoDB will all work. | |
// To use this, just open Mongo shell, with this file, e.g.: `mongo localhost --shell hello_world_shell_kms.js` | |
// Note, you will need the attached `kms_config.env` file, see below. | |
// See: Client-Side Field Level Encryption Quickstart Part 1: | |
// https://gist.github.com/kennwhite/e64e5b6770e89a797c3a08ecaa0cb7d0 | |
var demoDB = "demoFLE" | |
var keyVaultColl = "__keystore" // nothing special about this key vault collection name, but make it stand out | |
const ENC_DETERM = 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' | |
const ENC_RANDOM = 'AEAD_AES_256_CBC_HMAC_SHA_512-Random' | |
// populate AWS & connection string variables | |
var env = {} | |
print("\nLoading connection & key settings file...") | |
try { | |
load( 'kms_config.env' ); | |
} catch (err) { | |
print("Exiting: Unable to open file: " + envFile ); | |
quit() | |
} | |
if (env.KMSKEY == "xxxxxxxxxxxxxxxxxxxxxxxxx"){ | |
print("\nPlease generate a KMS key & IAM credentials (see `kms_config.env` file). Exiting. \n\n"); quit(); | |
} | |
var clientSideFLEOptions = { | |
"kmsProviders" : { | |
"aws" : { | |
"accessKeyId" : env.KMSKID , | |
"secretAccessKey" : env.KMSKEY | |
} | |
}, | |
schemaMap: {}, // on first invocation prior to field key generation, this should be empty | |
keyVaultNamespace: demoDB + "." + keyVaultColl | |
}; | |
encryptedSession = new Mongo(env.connStr, clientSideFLEOptions); | |
// javascript shell script equivalent of: use demoFLE | |
db = encryptedSession.getDB( demoDB ) | |
// Wipe sandbox. Approximate Atlas equivalent of: db.dropDatabase() | |
db.getCollectionNames().forEach(function(c){db.getCollection(c).drop()}); | |
var keyVault = encryptedSession.getKeyVault(); | |
print("Attempting to create field keys...") | |
keyVault.createKey("aws", env.KMSARN, ["fieldKey1"]) | |
keyVault.createKey("aws", env.KMSARN, ["fieldKey2"]) | |
keyVault | |
db.getCollection( keyVaultColl ).find().pretty() | |
print("Attempting to retrieve field keys...") | |
var key1 = db.getCollection( keyVaultColl ).find({ keyAltNames: 'fieldKey1' }).toArray()[0]._id | |
var key2 = db.getCollection( keyVaultColl ).find({ keyAltNames: 'fieldKey2' }).toArray()[0]._id | |
print("Setting server-side json schema for automatic encryption on `people` collection...") | |
db.createCollection("people") | |
db.runCommand({ | |
collMod: "people", | |
validator: { | |
$jsonSchema: { | |
"bsonType": "object", | |
"properties": { | |
"ssn": { bsonType: "binData" }, | |
"dob": { bsonType: "binData" }, | |
} | |
} | |
} | |
}) | |
print("Creating client-side json schema config for automatic encryption on `people` collection...") | |
var peopleSchema = { | |
"demoFLE.people": { | |
"bsonType": "object", | |
"properties": { | |
"ssn": { | |
"encrypt": { | |
"bsonType": "string", | |
"algorithm": ENC_DETERM, | |
"keyId": [ key1 ] | |
} | |
}, | |
"dob": { | |
"encrypt": { | |
"bsonType": "date", | |
"algorithm": ENC_RANDOM, | |
"keyId": [ key1 ] | |
} | |
}, | |
"contact": { | |
"bsonType": "object", | |
"properties": { | |
"email": { | |
"encrypt": { | |
"bsonType": "string", | |
"algorithm": ENC_DETERM, | |
"keyId": [ key2 ] | |
} | |
}, | |
"mobile": { | |
"encrypt": { | |
"bsonType": "string", | |
"algorithm": ENC_DETERM, | |
"keyId": [ key2 ] | |
} | |
} | |
}, | |
}, | |
} | |
} | |
} | |
print("Updating FLE mode session to enable server- and client-side json schema for automatic encryption...") | |
var clientSideFLEOptions = { | |
"kmsProviders": { | |
"aws": { | |
"accessKeyId": env.KMSKID, | |
"secretAccessKey": env.KMSKEY | |
} | |
}, | |
schemaMap: peopleSchema, | |
keyVaultNamespace: demoDB + "." + keyVaultColl | |
} | |
var encryptedSession = new Mongo(env.connStr, clientSideFLEOptions) | |
var db = encryptedSession.getDB( demoDB ); | |
print("Attempting to detect server-side Enterprise edition mode...") | |
var edition = db.runCommand({buildInfo:1}).modules | |
var enterprise = false | |
if ( edition !== undefined && edition.length != 0 ){ | |
var enterprise = true | |
} | |
print("MongoDB server running in enterprise mode: " + enterprise + "\n") | |
print("Attempting to insert sample document with automatic encryption...") | |
try { | |
var res = null | |
res = db.people.insert({ | |
firstName: 'Grace', | |
lastName: 'Hopper', | |
ssn: "901-01-0001", | |
dob: new Date('1989-12-13'), | |
address: { | |
street: '123 Main Street', | |
city: 'Omaha', | |
state: 'Nebraska', | |
zip: '90210' | |
}, | |
contact: { | |
mobile: '202-555-1212', | |
email: '[email protected]', | |
} | |
}) | |
} catch (err) { | |
res = err | |
} | |
print("Result: " + res) | |
print("Attempting to insert sample document with explicit encryption...") | |
try{ | |
var res = null | |
res = db.people.insert({ | |
firstName: 'Alan', | |
lastName: 'Turing', | |
ssn: db.getMongo().encrypt( key1 , "901-01-0002" , ENC_DETERM ), | |
dob: db.getMongo().encrypt( key1 , new Date('1912-06-23'), ENC_RANDOM ), | |
address: { | |
street: '123 Oak Lane', | |
city: 'Cleveland', | |
state: 'Ohio', | |
zip: '90210' | |
}, | |
contact: { | |
mobile: db.getMongo().encrypt( key2 , '202-555-1234', ENC_DETERM ), | |
email: db.getMongo().encrypt( key2 , '[email protected]', ENC_DETERM ), | |
} | |
}) | |
} catch (err) { | |
res = err | |
} | |
print("Result: " + res) | |
print("\nEnabling session bypass on automatic encrypt/decrypt... \n") | |
var clientSideFLEOptions = { | |
"kmsProviders": { | |
"aws": { | |
"accessKeyId": env.KMSKID, | |
"secretAccessKey": env.KMSKEY | |
} | |
}, | |
bypassAutoEncryption: true, | |
schemaMap: peopleSchema, | |
keyVaultNamespace: demoDB + "." + keyVaultColl | |
} | |
var encryptedSession = new Mongo(env.connStr, clientSideFLEOptions) | |
var db = encryptedSession.getDB( demoDB ); | |
print("Attempting to insert sample document with explicit encryption...") | |
try{ | |
var res = null | |
res = db.people.insert({ | |
firstName: 'Alan', | |
lastName: 'Turing', | |
ssn: db.getMongo().encrypt( key1 , "901-01-0002" , ENC_DETERM ), | |
dob: db.getMongo().encrypt( key1 , new Date('1912-06-23'), ENC_RANDOM ), | |
address: { | |
street: '123 Oak Lane', | |
city: 'Cleveland', | |
state: 'Ohio', | |
zip: '90210' | |
}, | |
contact: { | |
mobile: db.getMongo().encrypt( key2 , '202-555-1234', ENC_DETERM ), | |
email: db.getMongo().encrypt( key2 , '[email protected]', ENC_DETERM ), | |
} | |
}) | |
} catch (err) { | |
res = err | |
} | |
print("Result: " + res) | |
print("Dumping (raw) records from `people`:") | |
var records = db.people.find().pretty() | |
while (records.hasNext()) { | |
printjson(records.next()); | |
} | |
print("\nDisabling session bypass for automatic encrypt/decrypt...\n") | |
var clientSideFLEOptions = { | |
kmsProviders: { | |
aws: { | |
accessKeyId: env.KMSKID, | |
secretAccessKey: env.KMSKEY | |
} | |
}, | |
schemaMap: peopleSchema, | |
keyVaultNamespace: demoDB + "." + keyVaultColl | |
} | |
var encryptedSession = new Mongo(env.connStr, clientSideFLEOptions) | |
var db = encryptedSession.getDB( demoDB ); | |
print("Dumping (automatic decrypted) records from `people`:") | |
var records = db.people.find().pretty() | |
while (records.hasNext()) { | |
printjson(records.next()); | |
} | |
print("\nDemo complete.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Database host connection string. For Atlas, e.g.: "mongodb+srv://dbuser01:[email protected]" | |
env.connStr = "localhost" | |
// This is the KMS IAM AWS Key ID (see Quickstart Part 1 for the values below) | |
env.KMSKID = "AKIxxxxxxxx" | |
// This is the KMS IAM Secret Key | |
env.KMSKEY = "xxxxxxxxxxxxxxxxxxxxxxxxx" | |
// This is the KMS Master Key AWS ARN | |
env.KMSARN = "arn:aws:kms:us-east-1:12345678:key/123456-1234-1234-1234-123456789" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ mongo localhost refactor_atlas.js | |
MongoDB shell version v4.2.0 | |
[...] | |
Implicit session: session { "id" : UUID("db61b4f1-ac41-4a31-b11a-b964e3a469ce") } | |
MongoDB server version: 4.2.0 | |
Loading connection & key settings file... | |
Attempting to create field keys... | |
Attempting to retrieve field keys... | |
Setting server-side json schema for automatic encryption on `people` collection... | |
Creating client-side json schema config for automatic encryption on `people` collection... | |
Updating FLE mode session to enable server- and client-side json schema for automatic encryption... | |
Attempting to detect server-side Enterprise edition mode... | |
MongoDB server running in enterprise mode: true | |
Attempting to insert sample document with automatic encryption... | |
Result: WriteResult({ "nInserted" : 1 }) | |
Attempting to insert sample document with explicit encryption... | |
Result: Error: Cannot encrypt element of type binData because schema requires that type is one of: [ string ] | |
Enabling session bypass on automatic encrypt/decrypt... | |
Attempting to insert sample document with explicit encryption... | |
Result: WriteResult({ "nInserted" : 1 }) | |
Dumping (raw) records from `people` | |
{ | |
"_id" : ObjectId("5d69554415098d520aa7f4a6"), | |
"firstName" : "Grace", | |
"lastName" : "Hopper", | |
"ssn" : BinData(6,"Aa+ZP9KU2EfEty4csdYHca4Cz0Lhm4WhZxz4Vi5aiRD0bySp/7D70UYcHkHLQ9+NjA5EleMKmPO9eqeWU5vHx0Cj/MgcerxAu63dFGmVxVDXAxSDqN9uuZiom1WR69sRIhU="), | |
"dob" : BinData(6,"Aq+ZP9KU2EfEty4csdYHca4JjDrGBd9jQg4X/nuNJtNXKxgxMzhaAs6ES3mIa8KgOLOmIsuzmtcaTxiWfQ3/4BMot8OhCnNyZebsjwmO+BUvyQ=="), | |
"address" : { | |
"street" : "123 Main Street", | |
"city" : "Omaha", | |
"state" : "Nebraska", | |
"zip" : "90210" | |
}, | |
"contact" : { | |
"mobile" : BinData(6,"AT297A95l0jDkcqeJ8xSZ/UCSh38UNgi8VBkd78T1tVASQyUxlkAtoR5g8MQrSiwjp5CU9M0XcFXnZteN00+f2wiDk8tnP3aPfdRWgS5nzjfxhcPkv3PJYSUSSZK5G0W12A="), | |
"email" : BinData(6,"AT297A95l0jDkcqeJ8xSZ/UCcDFY+Z4O9TV4HE68+I7U79878NgaD4LXRmMn8DUcdi7rFsZei140/rCTL9BoH4SLLhU9Hv2nT9W09vCt4SBVvU4ql9hHm9vEq8PCn3N8h10=") | |
} | |
} | |
{ | |
"_id" : ObjectId("5d69554515098d520aa7f4a8"), | |
"firstName" : "Alan", | |
"lastName" : "Turing", | |
"ssn" : BinData(6,"Aa+ZP9KU2EfEty4csdYHca4Cs3QqsRJe2GcIalTeldS6RdLQ8gIoHA0lWak7CgoBzbxcW0KDmf3C50/zmvJx9VOuM1DYI63xJdkJ/DYz7yuTON7GFBRgduGvpALtVwtjAOw="), | |
"dob" : BinData(6,"Aq+ZP9KU2EfEty4csdYHca4JwWP/RMRIaO7HuEepbONVDv32jYTX7bSfAi8++ajC3LU5MbnFjw9bjuYw2LD9S/N2z6MULbF1PG1JTnvl4Xfqaw=="), | |
"address" : { | |
"street" : "123 Oak Lane", | |
"city" : "Cleveland", | |
"state" : "Ohio", | |
"zip" : "90210" | |
}, | |
"contact" : { | |
"mobile" : BinData(6,"AT297A95l0jDkcqeJ8xSZ/UCAavFkesDhvIbzx9taq7XzRblXMmz2BDs0ADcLvZwtjgAywsGco1WSL3sUToeye8nVpIcMifz8E/d2+WOB33f7JfUARH0VmvzXn+6mc99KXM="), | |
"email" : BinData(6,"AT297A95l0jDkcqeJ8xSZ/UCudkM45g77Xic3S6xr1pjuIHxq9iIdsclkqaMyr+Jp0WxFPk06QGPt4fN9knC7a9oHtM+WkB5OUuzolUgV/EB7iegorDBk9k5gDdbcaSPEJE=") | |
} | |
} | |
Disabling session bypass for automatic encrypt/decrypt... | |
Dumping (automatic decrypted) records in `people` | |
{ | |
"_id" : ObjectId("5d69554415098d520aa7f4a6"), | |
"firstName" : "Grace", | |
"lastName" : "Hopper", | |
"ssn" : "901-01-0001", | |
"dob" : ISODate("1989-12-13T00:00:00Z"), | |
"address" : { | |
"street" : "123 Main Street", | |
"city" : "Omaha", | |
"state" : "Nebraska", | |
"zip" : "90210" | |
}, | |
"contact" : { | |
"mobile" : "202-555-1212", | |
"email" : "[email protected]" | |
} | |
} | |
{ | |
"_id" : ObjectId("5d69554515098d520aa7f4a8"), | |
"firstName" : "Alan", | |
"lastName" : "Turing", | |
"ssn" : "901-01-0002", | |
"dob" : ISODate("1912-06-23T00:00:00Z"), | |
"address" : { | |
"street" : "123 Oak Lane", | |
"city" : "Cleveland", | |
"state" : "Ohio", | |
"zip" : "90210" | |
}, | |
"contact" : { | |
"mobile" : "202-555-1234", | |
"email" : "[email protected]" | |
} | |
} | |
Demo complete. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment