Last active
August 11, 2024 14:26
-
-
Save mmarcon/27d54fbba234c1dc953cc16673e34275 to your computer and use it in GitHub Desktop.
Simple mongosh script to insert a document into MongoDB with Client-side Field-level Encryption and KMS in GCP.
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
// To run this script you can start the shell with `mongosh --nodb` | |
// Wrap everything into a function so we don't | |
// affect the shell's scope | |
(function insertTestData() { | |
// Config DB and Collection names | |
const dbName = '<TEST_DBNAME>'; | |
const collectionName = '<TEST_COLLNAME>'; | |
const mongoDBAtlasConnectionString = '<MONGODB_ATLAS_CONNECTION_STRING>'; | |
// Configure KMS Providers | |
// Using GCP | |
const kmsProviders = { | |
gcp: { | |
email: '<SERVICE_ACCOUNT>@<PROJECT_ID>.iam.gserviceaccount.com', | |
privateKey: '<BASE64\nPRIVATE\nKEY>', | |
} | |
}; | |
// Get a new Mongo object with the KMS provider configuration | |
const keyMongo = Mongo(mongoDBAtlasConnectionString, { | |
keyVaultNamespace: 'encryption.__keyVault', | |
kmsProviders | |
}); | |
// Get a reference to the Key Vault | |
const keyVault = keyMongo.getKeyVault(); | |
// Generate a key | |
// In this example, we will use the same key for all the test documents. | |
// However, this is a good use case for assigning one key per customer. | |
const keyId = keyVault.createKey('gcp', { | |
projectId: '<PROJECT_ID>', | |
location: 'global', | |
keyRing: '<KEYRING_NAME>', | |
keyName: '<KEY_NAME>' | |
}); | |
// Schema map for auto encryption | |
// See https://docs.mongodb.com/manual/core/security-automatic-client-side-encryption/ for | |
// the details on how automatic encryption works. | |
// The automatic feature of field level encryption is only available in | |
// MongoDB 4.2+ Enterprise and MongoDB Atlas 4.2+ clusters. | |
const schemaMap = {}; | |
schemaMap[`${dbName}.${collectionName}`] = { | |
bsonType: 'object', | |
properties: { | |
birthDate: { | |
encrypt: { | |
keyId: [keyId], | |
bsonType: 'string', | |
algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' | |
} | |
}, | |
email: { | |
encrypt: { | |
keyId: [keyId], | |
bsonType: 'string', | |
algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' | |
} | |
}, | |
phone: { | |
encrypt: { | |
keyId: [keyId], | |
bsonType: 'string', | |
algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' | |
} | |
}, | |
bankAccount: { | |
encrypt: { | |
keyId: [keyId], | |
bsonType: 'object', | |
algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Random' | |
} | |
} | |
} | |
}; | |
// Create a new instance of Mongo connected to the same | |
// cluster but this time with the schemaMap configured as well. | |
const autoMongo = Mongo(mongoDBAtlasConnectionString, { | |
keyVaultNamespace: 'encryption.__keyVault', | |
kmsProviders, | |
schemaMap | |
}); | |
sleep(1000); | |
// Generate a bunch of fake customer data... | |
const autoMongoDb = autoMongo.getDB(dbName); | |
// ... but first clean up old test data ... | |
autoMongoDb.getCollection(collectionName).drop(); | |
// ... finally, store the new data into the destination collection. | |
// Fields that the schema map indicates they should be encrypted | |
// will be encrypted client-side and then stored encrypted in MongoDB | |
autoMongoDb.getCollection(collectionName).insertOne({ | |
name: { | |
first: 'Mia', | |
last: 'Rolfson' | |
}, | |
email: '[email protected]', | |
phone: '(123) 456-789', | |
company: { | |
name: 'Ernser - Brekke' | |
}, | |
address: { | |
zip: '31854', | |
street: '3196 Era Place', | |
state: 'NJ' | |
}, | |
birthDate: '1980-02-18', | |
bankAccount: { | |
name: 'Auto Loan Account', | |
account: '17545520', | |
bic: 'EEAACUD1411' | |
}, | |
birthYear: 1980 | |
}); | |
// `email` is encrypted but I can still use it in a filter | |
// the document resulting from this find will have all the fields automatically decrypted | |
return autoMongoDb.getCollection(collectionName).find({email: '[email protected]'}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment