-
-
Save karan9/7a89ba858145f266a2079f3824b83f76 to your computer and use it in GitHub Desktop.
MongoDB Client Side Field Level Encryption Quickstart Part 2 (local key 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 (local key 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 --nodb --shell hello_world_shell_local.js | |
# For a self-signed cert: mongo --tls --tlsCAFile /opt/mongodb/certs/ca.pem --shell hello_world_shell_local.js | |
Note, you will need the attached `localkey_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' | |
var env = {} | |
print("\nLoading local key configuration file...") | |
try { | |
load( 'localkey_config.js' ); | |
} catch (err) { | |
print("Exiting: Unable to open local config file." ); | |
quit() | |
} | |
if (env.keyString == "PASTE GENERATED KEY STRING HERE"){ | |
print("\nPlease generate a new local key (see `localkey_config.js` file). Exiting. \n\n"); quit(); | |
} | |
var localDevMasterKey = { key: BinData( 0, env.keyString ) } | |
var clientSideFLEOptions = { | |
kmsProviders : { local : localDevMasterKey } , | |
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("local", "", ["fieldKey1"]) | |
keyVault.createKey("local", "", ["fieldKey2"]) | |
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": { | |
"encrypt": { | |
"bsonType": "string", | |
"algorithm": ENC_DETERM, | |
"keyId": [ key1 ] | |
} | |
}, | |
"dob": { | |
"encrypt": { | |
"bsonType": "date", | |
"algorithm": ENC_RANDOM, | |
"keyId": [ key1 ] | |
} | |
}, | |
} | |
} | |
} | |
}) | |
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: { local: localDevMasterKey }, | |
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": { "local": localDevMasterKey }, | |
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: { local: localDevMasterKey }, | |
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
/* | |
** Note: a local key file should only be used in a non-production test environment ** | |
Instructions for generate a local master key: | |
For Linux & Mac, from a terminal: | |
echo $(head -c 96 /dev/urandom | base64 | tr -d '\n') | |
For Windows 8.x/2012+, from a command prompt: | |
powershell -command "$r=[byte[]]::new(64);$g=[System.Security.Cryptography.RandomNumberGenerator]::Create();$g.GetBytes($r);[Convert]::ToBase64String($r)" | |
Paste the hex string generated above into the key string value below | |
*/ | |
env.keyString = "PASTE GENERATED KEY STRING HERE"; | |
env.connStr = "localhost" | |
// For Atlas: | |
// env.connStr = "mongodb+srv://USERNAME:[email protected]" | |
// For on-prem TLS: | |
// env.connStr = "mongodb://USERNAME:[email protected]:27017/?authMechanism=SCRAM-SHA-256&replicaSet=rs1" |
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_local.js | |
MongoDB shell version v4.2.0 | |
connecting to: mongodb://127.0.0.1:27017/localhost?compressors=disabled&gssapiServiceName=mongodb | |
Implicit session: session { "id" : UUID("1a03036b-1a82-4597-8518-09dc89188eb7") } | |
MongoDB server version: 4.2.0-82-g5eeba7b | |
Loading local key configuration 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: false | |
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("5d6956119a916c22f2b6db38"), | |
"firstName" : "Grace", | |
"lastName" : "Hopper", | |
"ssn" : BinData(6,"ASRaYbcf1E0zg2JinCp6GGwCw/Gk3MBpgu+gyEU64B/vWEXMDo0jZ6iu3sFqCbuE9KSg0t70LLICxBcQ4OXsJLz046HFYy/Sd/1tnxPXgrTfvQlKV3cBvIPGIEt19RCuFUU="), | |
"dob" : BinData(6,"AiRaYbcf1E0zg2JinCp6GGwJON2dV0lmckr0gOR9VZdr5drjhtIx3H2vc/W+3w+pnG9faPP5hWZj92qDJIrDhntriXt7Al5Dijtke+LKjQdEDg=="), | |
"address" : { | |
"street" : "123 Main Street", | |
"city" : "Omaha", | |
"state" : "Nebraska", | |
"zip" : "90210" | |
}, | |
"contact" : { | |
"mobile" : BinData(6,"ASsJPMjeiEVyp5zvrHwdpAcCPvWWGJRjIi4ZNGRD9UgtRLN5hv+Rk8i7KIkFQ3ITmnuOIFDr+L384s9Ukh9v1QOtVH2k2MYjlqLTK7+ejHDqEx40mD4rfOkX59LYcH6+VAs="), | |
"email" : BinData(6,"ASsJPMjeiEVyp5zvrHwdpAcCuy3r5pD3m3B4SXB+z3VGS4h7OzQHN63mDOjY14/sGj1w40x0bgnl+B/YJbLTT7caVbvOVqw/FNKmKLcX1UJ4IvjAgvfap6uLcuxD2s/LwOQ=") | |
} | |
} | |
{ | |
"_id" : ObjectId("5d6956119a916c22f2b6db3a"), | |
"firstName" : "Alan", | |
"lastName" : "Turing", | |
"ssn" : BinData(6,"ASRaYbcf1E0zg2JinCp6GGwCKL1IVykOA6ZfETtfXbmXX/dGHNKC1glTTVe8ut3ggskSGdKZ5H8eA6RyADyZAtlf+G6SsPnFTsmf1iNsHtEO9vS+Oc2v06rN2cdNXIiUbGo="), | |
"dob" : BinData(6,"AiRaYbcf1E0zg2JinCp6GGwJxiOCIFXyQ6+kb6w8ZjAl0FO0iPbH0bGSEGx45KvnW37zyhWtftCuRwoAFSKnPNDflcEMZ7evAw23QSjye9l8RA=="), | |
"address" : { | |
"street" : "123 Oak Lane", | |
"city" : "Cleveland", | |
"state" : "Ohio", | |
"zip" : "90210" | |
}, | |
"contact" : { | |
"mobile" : BinData(6,"ASsJPMjeiEVyp5zvrHwdpAcCM2eRrqWFp+byqc9f+XNEw3uhkQskAZvOHCzuFeCpqAugHq9c6H+aWygrRtv15NTfE3cRJ5U4LNUKTzoy5vv6CKzbkwp8mbSHYHp4iFemt8A="), | |
"email" : BinData(6,"ASsJPMjeiEVyp5zvrHwdpAcCa9CsILfy8Jd7jkr81bKht+Fk7Q9bwaAAeZi+i/HZ/7q38lpnrRzYEut53vbssstNd0GtcjjCgVGlGq4gypeY5y96SGdlbdRySllS+jtRUuw=") | |
} | |
} | |
Disabling session bypass for automatic encrypt/decrypt... | |
Dumping (automatic decrypted) records from `people`: | |
{ | |
"_id" : ObjectId("5d6956119a916c22f2b6db38"), | |
"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("5d6956119a916c22f2b6db3a"), | |
"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