Created
January 23, 2020 15:23
-
-
Save sarjarapu/37b11089c7d2f7b3e3c01b932b2e658c to your computer and use it in GitHub Desktop.
A JavaScript to show MongoDB client-side field-level encryption can help you implement solutions for California Consumer Privacy Act. The deletion of the data encryption key will render all the consumers' data permanently unreadable be it in current database or in historical snapshots.
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
// rules for automation encryption | |
var schemaMap = { | |
"health_care_app.patients": { | |
"bsonType": "object", | |
"properties": { | |
"medRecNum": { | |
"bsonType": "int" | |
}, | |
"firstName": { | |
"bsonType": "string" | |
}, | |
"lastName": { | |
"bsonType": "string" | |
}, | |
"ssn": { | |
"encrypt": { | |
"bsonType": "string", | |
"algorithm": SSN_ENCRYPTION_ALGORITHM, | |
"keyId": [SSN_ENCRYPTION_KEY_UUID] | |
} | |
}, | |
"mobile": { | |
"encrypt": { | |
"bsonType": "string", | |
"algorithm": MOBILE_ENCRYPTION_ALGORITHM, | |
"keyId": [MOBILE_ENCRYPTION_KEY_UUID] | |
} | |
}, | |
"comment": { | |
"bsonType": "string" | |
} | |
} | |
} | |
}; | |
// lets recreate the client-side Field-Level encryption options with schema | |
var csfleOptionsWithSchema = { | |
"keyVaultNamespace" : "encryption.__dataKeys", | |
"kmsProviders" : { | |
"local" : { | |
"key" : BinData(0, LOCAL_KEY) | |
} | |
}, | |
"schemaMap" : schemaMap | |
}; | |
// functions to create a patient document with unique data encryption key for each | |
function getOrCreateKey(client, keyName) { | |
if (client.getKeyVault().getKeyByAltName(keyName).toArray().length === 0) { | |
client.getKeyVault().createKey("local", "", [keyName]); | |
} | |
return client.getKeyVault().getKeyByAltName(keyName).toArray()[0]._id; | |
} | |
function getUserKeys(client, userId) { | |
return { | |
ssn: getOrCreateKey(client, `an-${userId}-ssn`), | |
mobile: getOrCreateKey(client, `an-${userId}-Mobile`) | |
} | |
} | |
function createUserWithSpecialKey(client, userid) { | |
var u = userid; | |
var userKeys = getUserKeys(client, u); | |
client.getDB("health_care_app").getCollection("patients").insert({ | |
"_id": u, | |
"medRecNum": u, | |
"firstName": `fname${u}`, | |
"lastName": `lname${u}`, | |
"city": 'city-' + u % 3, | |
"ssn": client.encrypt(userKeys.ssn, `${u}${u}${u}-${u}${u}-${u}${u}${u}${u}`, SSN_ENCRYPTION_ALGORITHM), | |
"mobile": client.encrypt(userKeys.mobile, `${u}${u}${u}-${u}${u}${u}-${u}${u}${u}${u}`, MOBILE_ENCRYPTION_ALGORITHM), | |
"comment": `User ${u} SSN/Phone are encrypted with user specific key.` | |
}); | |
} | |
var csfleClient = Mongo("mongodb://localhost:28000", csfleOptionsWithSchema); | |
var csfleDB = csfleClient.getDB("health_care_app"); | |
// drop the existing collection | |
csfleDB.getCollection("patients").drop(); | |
for(var i = 0; i < 10; i++) { | |
createUserWithSpecialKey(csfleClient, i); | |
} | |
// NOTE: Well I was hoping to see the documents to be encrypted for everyone unless I gave that key | |
csfleDB.getCollection("patients").findOne({_id: 9}); | |
// { "_id" : 9, "medRecNum" : 9, "firstName" : "fname9", "lastName" : "lname9", "ssn" : "999-99-9999", "mobile" : "999-999-9999", "comment" : "User 9 SSN/Phone are encrypted with user specific key." } | |
// fetch user 9 keys and delete them. | |
var userKeys = getUserKeys(csfleClient, 9); | |
csfleClient.getKeyVault().deleteKey(userKeys.ssn); | |
csfleClient.getKeyVault().deleteKey(userKeys.mobile); | |
// Record still exists but you cannot decrypt the encrypted values. | |
csfleDB.getCollection("patients").findOne({_id: 9}, {_id: 1, "medRecNum": 1, "firstName": 1, "lastName": 1, "city": 1, "comment": 1}); | |
// { | |
// "_id" : 9, | |
// "medRecNum" : 9, | |
// "firstName" : "fname9", | |
// "lastName" : "lname9", | |
// "city" : "city-0", | |
// "comment" : "User 9 SSN/Phone are encrypted with user specific key." | |
// } | |
// try to fetch all data including the encrypted fields | |
csfleDB.getCollection("patients").find({_id: 9}); | |
// Error: Invalid keyID |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment