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
}
}
});
```

- 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
}
}
```

- 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`

- 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

- 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

- KMS Price

###### tags: `Mongodb` `Formpass`