Mongodb Client-Side-Encryption === ## Demo Git https://github.com/tinnguyenhuuletrong/Learning/tree/master/mongodb-encryption-playground ## Target - Mongodb 4.2 + NodeJS Driver 3.3+ has already support (https://github.com/mongodb/node-mongodb-native/releases) - Plugin: `mongodb-client-encryption` - beta - It is JS wrapper for `libmongocrypt` - [official C Driver](https://github.com/mongodb/libmongocrypt) ## How it work - Plugin wrapped MongodbClient + provide configuration for KMS ### 1. KMS-Local mode - Manual Encrypt - Keys store inside mongodb server - must provide **masterKey**(96 bytes) - Wrong key => error will throw when init - Good ! ``` javascript // Local mode new ClientEncryption(mongoClient, { keyVaultNamespace: 'client.encryption', // <---- Collection name to store key kmsProviders: { local: { key: masterKey // The master key used for encryption/decryption. A 96-byte long Buffer } } }); ``` ![](https://i.imgur.com/ibF0StT.png) - Key create with `keyAltNames` - Which is slug for `keyId` ``` javascript await clientEncrypion.createDataKey('local', { keyAltNames: ['key-1'] }) ``` - Encrypt data (required `keyAltNames`) - Two algorithm now: - **AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic**: Deterministic output but **only support** `string` type [official doc](https://docs.mongodb.com/manual/reference/method/ClientEncryption.encrypt/#unsupported-bson-types): - - **AEAD_AES_256_CBC_HMAC_SHA_512-Random**: not Deterministic, Work on any data types ``` javascript const ecryptObject = async (obj, keyAltName = 'key-1') => { let res = await clientEncrypion.encrypt(obj, { keyAltName, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Random' }) return { encrypted: res } } ``` ![](https://i.imgur.com/1e3DEsw.png) - Decrypt data - Auto pick key ``` javascript const decyptObject = async obj => { let res = await clientEncrypion.decrypt(obj.encrypted) return { ...obj, decrypted: res } } ``` ### 2. Auto encrypt by JSON Schema - Can not test - It required `mongocryptd` - Which only require *MongoDB Enterprise* :-1: [link](https://docs.mongodb.com/manual/core/security-client-side-encryption/#automatic-field-level-encryption) - Tried to init but got error ``` javascript // Can not connect to local mongocryptd process. // Defaults to 'mongodb://localhost:27020' Error { Error: connect ECONNREFUSED 127.0.0.1:27020 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1097:14) name: 'MongoNetworkError', errorLabels: [ 'TransientTransactionError' ], [Symbol(mongoErrorContextSymbol)]: {} } ``` - Overview (from document - [link](https://docs.mongodb.com/manual/reference/security-client-side-automatic-json-schema/#field-level-encryption-json-schema)) - Working mechanism and algorithm constraint same as **Manual Encrypt** - JSON Schema using mongodb extend rules [JSON Schema](https://docs.mongodb.com/manual/reference/mongodb-extended-json/) and setup per collections ``` javascript db.createCollection("students", { validator: { $jsonSchema: { // .... } } }) ``` - It base on schema define automatically transform data (both save and load) *Example Document Structure* ``` json { "fname" : "Jo", "lname" : "Doe", "ssn" : "123-45-6789", "ssn-last" : "6789", "position" : { "compensation" : 250000, "title" : "MongoDB Expert" } } ``` *Example JSON Schema config* ``` javascript { { "bsonType" : "object", "encryptMetadata" : { // Default Key UUID (alias don't work!!!) "keyId" : [ { "$binary" : { "base64" : "M2IyNDExMDEtZTJiYi00MjU1LThjYWYtNDEzNmM1NjZhOTYy", "type" : 4 } } ] }, "properties" : { "ssn" : { "encrypt" : { // Override Key UUID "keyId" : [ { "$binary" : { "base64" : "OTk2MmIwNTctMzcxOC00YmNmLTg5ODgtMGJjNTE5NzM4ZTA=", "type" : 4 } } ], "algorithm" : "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "ssn-last" : { // using default Key UUID "encrypt" :{ "algorithm" : "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType" : "string" } } } } } ``` ### 3. KMS-AWS mode - Configuration - AWS_ACCESS_KEY - AWS_SECRET_KEY - MASTER_KEY_ARN: (ARN) - Amazon Resource ID - AWS Permission scopes `kms:Encrypt` `kms:Decrypt` for `AWS_ACCESS_KEY` ![](https://i.imgur.com/Nvut7r4.png) - Overview - Create Data Key (DK): Driver -> AWS (api:Encrypt) -> **Enveloped DK** -> Store inside Local DB - When we call Encrypt/Decrypt data: Driver -> AWS(**Enveloped DK**) -> DK - **Enveloped DK** store inside DB with Master Key 's ARN attachment ![](https://i.imgur.com/SdXzu1H.png) - AWS Traffic *Base on AWS API Log - can not find official document for this* - AWS Api call when: - Create Data Key - Every Encrypt AND Decrypt data - Example for (Create 3 Key -> Encrypt 10 records-> Decrypt 10 records) - API Encrypt = 3 - API Decrypt = 10 + 10 = 20 ![](https://i.imgur.com/lFpUCe0.png) - KMS Price ![](https://i.imgur.com/5Q1OSJz.png) ###### tags: `Mongodb` `Formpass`