From 3d22a227a7559b2bf7f7beda100bb06bc3e3e30f Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Fri, 9 May 2025 23:06:08 +0200 Subject: [PATCH 1/8] feat(NODE-6952): add support for configuring DEK cache expiration --- package-lock.json | 8 +- package.json | 2 +- src/client-side-encryption/auto_encrypter.ts | 8 + .../client_encryption.ts | 5 + .../tests/legacy/keyCache.json | 270 ++++++++++++++++++ .../tests/legacy/keyCache.yml | 69 +++++ .../tests/unified/keyCache.json | 198 +++++++++++++ .../tests/unified/keyCache.yml | 85 ++++++ 8 files changed, 640 insertions(+), 5 deletions(-) create mode 100644 test/spec/client-side-encryption/tests/legacy/keyCache.json create mode 100644 test/spec/client-side-encryption/tests/legacy/keyCache.yml create mode 100644 test/spec/client-side-encryption/tests/unified/keyCache.json create mode 100644 test/spec/client-side-encryption/tests/unified/keyCache.yml diff --git a/package-lock.json b/package-lock.json index 9f5a780e27b..c2637b74bd1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,7 +48,7 @@ "js-yaml": "^4.1.0", "mocha": "^10.8.2", "mocha-sinon": "^2.1.2", - "mongodb-client-encryption": "^6.3.0", + "mongodb-client-encryption": "^6.4.0", "mongodb-legacy": "^6.1.3", "nyc": "^15.1.0", "prettier": "^3.5.3", @@ -6676,9 +6676,9 @@ } }, "node_modules/mongodb-client-encryption": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/mongodb-client-encryption/-/mongodb-client-encryption-6.3.0.tgz", - "integrity": "sha512-OaOg02vglPxxrfY01alC0ER0W4WMuNO2ZJR3ehAUcuGYreJaJ+aX+rUQiQkdQHiXvnVPDUx/4QDr2CR1/FvpcQ==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/mongodb-client-encryption/-/mongodb-client-encryption-6.4.0.tgz", + "integrity": "sha512-Un1W/5P4KjcUBPeJeSKFNaWH0/8PVsoSatDqyWM2bMK0Vu2Jjxy7ZTgDj1g+uChuqroB09s8LvppdsHpwxSTVA==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", diff --git a/package.json b/package.json index 2033effd862..53af3665ef1 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "js-yaml": "^4.1.0", "mocha": "^10.8.2", "mocha-sinon": "^2.1.2", - "mongodb-client-encryption": "^6.3.0", + "mongodb-client-encryption": "^6.4.0", "mongodb-legacy": "^6.1.3", "nyc": "^15.1.0", "prettier": "^3.5.3", diff --git a/src/client-side-encryption/auto_encrypter.ts b/src/client-side-encryption/auto_encrypter.ts index caca83e367f..9886a7636fc 100644 --- a/src/client-side-encryption/auto_encrypter.ts +++ b/src/client-side-encryption/auto_encrypter.ts @@ -52,6 +52,10 @@ export interface AutoEncryptionOptions { bypassAutoEncryption?: boolean; /** Allows users to bypass query analysis */ bypassQueryAnalysis?: boolean; + /** + * Sets the expiration time for the DEK in the cache in milliseconds. Defaults to 60000. + */ + keyExpirationMS?: number; options?: { /** An optional hook to catch logging messages from the underlying encryption engine */ logger?: (level: AutoEncryptionLoggerLevel, message: string) => void; @@ -285,6 +289,10 @@ export class AutoEncrypter { mongoCryptOptions.bypassQueryAnalysis = options.bypassQueryAnalysis; } + if (options.keyExpirationMS) { + mongoCryptOptions.keyExpirationMS = options.keyExpirationMS; + } + this._bypassMongocryptdAndCryptShared = this._bypassEncryption || !!options.bypassQueryAnalysis; if (options.extraOptions && options.extraOptions.cryptSharedLibSearchPaths) { diff --git a/src/client-side-encryption/client_encryption.ts b/src/client-side-encryption/client_encryption.ts index b5968fd0d76..198adfd5022 100644 --- a/src/client-side-encryption/client_encryption.ts +++ b/src/client-side-encryption/client_encryption.ts @@ -885,6 +885,11 @@ export interface ClientEncryptionOptions { */ tlsOptions?: CSFLEKMSTlsOptions; + /** + * Sets the expiration time for the DEK in the cache in milliseconds. Defaults to 60000. + */ + keyExpirationMS?: number; + /** * @experimental * diff --git a/test/spec/client-side-encryption/tests/legacy/keyCache.json b/test/spec/client-side-encryption/tests/legacy/keyCache.json new file mode 100644 index 00000000000..912ce800206 --- /dev/null +++ b/test/spec/client-side-encryption/tests/legacy/keyCache.json @@ -0,0 +1,270 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" + } + }, + "encrypted_string": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "random": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" + } + }, + "encrypted_string_equivalent": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + }, + "key_vault_data": [ + { + "status": 1, + "_id": { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + }, + "masterKey": { + "provider": "aws", + "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", + "region": "us-east-1" + }, + "updateDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyMaterial": { + "$binary": { + "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "Insert with deterministic encryption, then find it", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + }, + "keyExpirationMS": 1 + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_string": "string0" + } + } + }, + { + "name": "wait", + "object": "testRunner", + "arguments": { + "ms": 50 + } + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + } + }, + "result": [ + { + "_id": 1, + "encrypted_string": "string0" + } + ] + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "keyvault", + "readConcern": { + "level": "majority" + } + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", + "subType": "06" + } + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "_id": 1 + } + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "keyvault", + "readConcern": { + "level": "majority" + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", + "subType": "06" + } + } + } + ] + } + } + } + ] +} diff --git a/test/spec/client-side-encryption/tests/legacy/keyCache.yml b/test/spec/client-side-encryption/tests/legacy/keyCache.yml new file mode 100644 index 00000000000..3af117ca810 --- /dev/null +++ b/test/spec/client-side-encryption/tests/legacy/keyCache.yml @@ -0,0 +1,69 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'}}, 'encrypted_string': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, 'random': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'}}, 'encrypted_string_equivalent': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} +key_vault_data: [{'status': 1, '_id': {'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}, 'masterKey': {'provider': 'aws', 'key': 'arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0', 'region': 'us-east-1'}, 'updateDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyMaterial': {'$binary': {'base64': 'AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "Insert with deterministic encryption, then find it" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + keyExpirationMS: 1 + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0" } + - name: wait + object: testRunner + arguments: + ms: 50 # Wait long enough to account for coarse time resolution on Windows (CDRIVER-4526). + - name: find + arguments: + filter: { _id: 1 } + result: [*doc0] + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + filter: + name: *collection_name + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: keyvault + readConcern: { level: "majority" } + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==', 'subType': '06'}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: { _id: 1 } + command_name: find + # The cache has expired and the key must be fetched again + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: keyvault + readConcern: { level: "majority" } + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted \ No newline at end of file diff --git a/test/spec/client-side-encryption/tests/unified/keyCache.json b/test/spec/client-side-encryption/tests/unified/keyCache.json new file mode 100644 index 00000000000..a39701e2861 --- /dev/null +++ b/test/spec/client-side-encryption/tests/unified/keyCache.json @@ -0,0 +1,198 @@ +{ + "description": "keyCache-explicit", + "schemaVersion": "1.22", + "runOnRequirements": [ + { + "csfle": true + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent" + ] + } + }, + { + "clientEncryption": { + "id": "clientEncryption0", + "clientEncryptionOpts": { + "keyVaultClient": "client0", + "keyVaultNamespace": "keyvault.datakeys", + "kmsProviders": { + "local": { + "key": "OCTP9uKPPmvuqpHlqq83gPk4U6rUPxKVRRyVtrjFmVjdoa4Xzm1SzUbr7aIhNI42czkUBmrCtZKF31eaaJnxEBkqf0RFukA9Mo3NEHQWgAQ2cn9duOcRbaFUQo2z0/rB" + } + }, + "keyExpirationMS": 1 + } + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "keyvault" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "datakeys" + } + } + ], + "initialData": [ + { + "databaseName": "keyvault", + "collectionName": "datakeys", + "documents": [ + { + "_id": { + "$binary": { + "base64": "a+YWzdygTAG62/cNUkqZiQ==", + "subType": "04" + } + }, + "keyAltNames": [], + "keyMaterial": { + "$binary": { + "base64": "iocBkhO3YBokiJ+FtxDTS71/qKXQ7tSWhWbcnFTXBcMjarsepvALeJ5li+SdUd9ePuatjidxAdMo7vh1V2ZESLMkQWdpPJ9PaJjA67gKQKbbbB4Ik5F2uKjULvrMBnFNVRMup4JNUwWFQJpqbfMveXnUVcD06+pUpAkml/f+DSXrV3e5rxciiNVtz03dAG8wJrsKsFXWj6vTjFhsfknyBA==", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "updateDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "status": { + "$numberInt": "0" + }, + "masterKey": { + "provider": "local" + } + } + ] + } + ], + "tests": [ + { + "description": "decrypt, wait, and decrypt again", + "operations": [ + { + "name": "decrypt", + "object": "clientEncryption0", + "arguments": { + "value": { + "$binary": { + "base64": "AWvmFs3coEwButv3DVJKmYkCJ6lUzRX9R28WNlw5uyndb+8gurA+p8q14s7GZ04K2ZvghieRlAr5UwZbow3PMq27u5EIhDDczwBFcbdP1amllw==", + "subType": "06" + } + } + }, + "expectResult": "foobar" + }, + { + "name": "wait", + "object": "testRunner", + "arguments": { + "ms": 50 + } + }, + { + "name": "decrypt", + "object": "clientEncryption0", + "arguments": { + "value": { + "$binary": { + "base64": "AWvmFs3coEwButv3DVJKmYkCJ6lUzRX9R28WNlw5uyndb+8gurA+p8q14s7GZ04K2ZvghieRlAr5UwZbow3PMq27u5EIhDDczwBFcbdP1amllw==", + "subType": "06" + } + } + }, + "expectResult": "foobar" + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "a+YWzdygTAG62/cNUkqZiQ==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "keyvault", + "readConcern": { + "level": "majority" + } + } + } + }, + { + "commandStartedEvent": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "a+YWzdygTAG62/cNUkqZiQ==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "keyvault", + "readConcern": { + "level": "majority" + } + } + } + } + ] + } + ] + } + ] +} diff --git a/test/spec/client-side-encryption/tests/unified/keyCache.yml b/test/spec/client-side-encryption/tests/unified/keyCache.yml new file mode 100644 index 00000000000..d6e747ba097 --- /dev/null +++ b/test/spec/client-side-encryption/tests/unified/keyCache.yml @@ -0,0 +1,85 @@ +description: keyCache-explicit + +schemaVersion: "1.22" + +runOnRequirements: + - csfle: true + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - clientEncryption: + id: &clientEncryption0 clientEncryption0 + clientEncryptionOpts: + keyVaultClient: *client0 + keyVaultNamespace: keyvault.datakeys + kmsProviders: + "local" : { key: "OCTP9uKPPmvuqpHlqq83gPk4U6rUPxKVRRyVtrjFmVjdoa4Xzm1SzUbr7aIhNI42czkUBmrCtZKF31eaaJnxEBkqf0RFukA9Mo3NEHQWgAQ2cn9duOcRbaFUQo2z0/rB" } + keyExpirationMS: 1 + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name keyvault + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name datakeys + +initialData: + - databaseName: *database0Name + collectionName: *collection0Name + documents: + - { + "_id": { + "$binary": { + "base64": "a+YWzdygTAG62/cNUkqZiQ==", + "subType": "04" + } + }, + "keyAltNames": [], + "keyMaterial": { + "$binary": { + "base64": "iocBkhO3YBokiJ+FtxDTS71/qKXQ7tSWhWbcnFTXBcMjarsepvALeJ5li+SdUd9ePuatjidxAdMo7vh1V2ZESLMkQWdpPJ9PaJjA67gKQKbbbB4Ik5F2uKjULvrMBnFNVRMup4JNUwWFQJpqbfMveXnUVcD06+pUpAkml/f+DSXrV3e5rxciiNVtz03dAG8wJrsKsFXWj6vTjFhsfknyBA==", + "subType": "00" + } + }, + "creationDate": {"$date": {"$numberLong": "1552949630483"}}, + "updateDate": {"$date": {"$numberLong": "1552949630483"}}, + "status": {"$numberInt": "0"}, + "masterKey": {"provider": "local"} + } + +tests: + - description: decrypt, wait, and decrypt again + operations: + - name: decrypt + object: *clientEncryption0 + arguments: + value: { "$binary" : { "base64" : "AWvmFs3coEwButv3DVJKmYkCJ6lUzRX9R28WNlw5uyndb+8gurA+p8q14s7GZ04K2ZvghieRlAr5UwZbow3PMq27u5EIhDDczwBFcbdP1amllw==", "subType" : "06" } } + expectResult: "foobar" + - name: wait + object: testRunner + arguments: + ms: 50 # Wait long enough to account for coarse time resolution on Windows (CDRIVER-4526). + - name: decrypt + object: *clientEncryption0 + arguments: + value: { "$binary" : { "base64" : "AWvmFs3coEwButv3DVJKmYkCJ6lUzRX9R28WNlw5uyndb+8gurA+p8q14s7GZ04K2ZvghieRlAr5UwZbow3PMq27u5EIhDDczwBFcbdP1amllw==", "subType" : "06" } } + expectResult: "foobar" + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {'$binary': {'base64': 'a+YWzdygTAG62/cNUkqZiQ==', 'subType': '04'}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: keyvault + readConcern: { level: "majority" } + - commandStartedEvent: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {'$binary': {'base64': 'a+YWzdygTAG62/cNUkqZiQ==', 'subType': '04'}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: keyvault + readConcern: { level: "majority" } From 30b0611c7ee88003ea55d6fde5a1c222c87a1e15 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Fri, 9 May 2025 23:31:14 +0200 Subject: [PATCH 2/8] test: fix runner --- test/tools/unified-spec-runner/schema.ts | 1 + test/tools/unified-spec-runner/unified-utils.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/test/tools/unified-spec-runner/schema.ts b/test/tools/unified-spec-runner/schema.ts index ce722b2e706..6f9bba3d8ea 100644 --- a/test/tools/unified-spec-runner/schema.ts +++ b/test/tools/unified-spec-runner/schema.ts @@ -221,6 +221,7 @@ export interface ClientEncryptionEntity { | UnnamedKMSProviders['local'] | undefined; }; + keyExpirationMS?: number; }; } diff --git a/test/tools/unified-spec-runner/unified-utils.ts b/test/tools/unified-spec-runner/unified-utils.ts index 56c9a54e92e..156e230241e 100644 --- a/test/tools/unified-spec-runner/unified-utils.ts +++ b/test/tools/unified-spec-runner/unified-utils.ts @@ -520,6 +520,7 @@ export async function createClientEncryption( const { keyVaultClient, keyVaultNamespace, + keyExpirationMS, kmsProviders: kmsProvidersFromTest } = clientEncryptionOpts; @@ -571,6 +572,7 @@ export async function createClientEncryption( keyVaultClient: clientEntity, kmsProviders, keyVaultNamespace, + keyExpirationMS, tlsOptions: parseTLSOptions() }; From 173b44fefbfd615c3bd3da0c1859f3b584e28c38 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Fri, 9 May 2025 23:57:44 +0200 Subject: [PATCH 3/8] test: skip unless 6.4.0 installed --- .../client_side_encryption.spec.test.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/integration/client-side-encryption/client_side_encryption.spec.test.ts b/test/integration/client-side-encryption/client_side_encryption.spec.test.ts index 58fe5bb19bc..08c189c9ce8 100644 --- a/test/integration/client-side-encryption/client_side_encryption.spec.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.spec.test.ts @@ -109,6 +109,13 @@ describe('Client Side Encryption (Legacy)', function () { if (typeof result === 'string') return result; } + if (['Insert with deterministic encryption, then find it'].includes(description)) { + const result = configuration.filters.ClientSideEncryptionFilter.filter({ + metadata: { requires: { clientSideEncryption: '>=6.4.0' } } + }); + + if (typeof result === 'string') return result; + } return true; }); }); @@ -142,12 +149,19 @@ describe('Client Side Encryption (Unified)', function () { 'rewrap from aws:name1 to aws:name2', 'can explicitly encrypt with a named KMS provider' ]; + const dekExpirationTests = ['decrypt, wait, and decrypt again']; if (delegatedKMIPTests.includes(description)) { const shouldSkip = configuration.filters.ClientSideEncryptionFilter.filter({ metadata: { requires: { clientSideEncryption: '>=6.0.1' } } }); if (typeof shouldSkip === 'string') return shouldSkip; } + if (dekExpirationTests.includes(description)) { + const shouldSkip = configuration.filters.ClientSideEncryptionFilter.filter({ + metadata: { requires: { clientSideEncryption: '>=6.4.0' } } + }); + if (typeof shouldSkip === 'string') return shouldSkip; + } return isServerless ? 'Unified CSFLE tests to not run on serverless' : false; } From a7fbe943dadf3e1862524f28c49deecf25543ef6 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Mon, 12 May 2025 15:25:19 +0200 Subject: [PATCH 4/8] Update src/client-side-encryption/auto_encrypter.ts Co-authored-by: Anna Henningsen --- src/client-side-encryption/auto_encrypter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client-side-encryption/auto_encrypter.ts b/src/client-side-encryption/auto_encrypter.ts index 9886a7636fc..19fb4791db6 100644 --- a/src/client-side-encryption/auto_encrypter.ts +++ b/src/client-side-encryption/auto_encrypter.ts @@ -289,7 +289,7 @@ export class AutoEncrypter { mongoCryptOptions.bypassQueryAnalysis = options.bypassQueryAnalysis; } - if (options.keyExpirationMS) { + if (options.keyExpirationMS != null) { mongoCryptOptions.keyExpirationMS = options.keyExpirationMS; } From 04c6271d137c96fe65a2ac6b745e6316a6fae284 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Mon, 12 May 2025 22:53:49 +0200 Subject: [PATCH 5/8] Update src/client-side-encryption/auto_encrypter.ts Co-authored-by: Bailey Pearson --- src/client-side-encryption/auto_encrypter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client-side-encryption/auto_encrypter.ts b/src/client-side-encryption/auto_encrypter.ts index 19fb4791db6..84ad34b5200 100644 --- a/src/client-side-encryption/auto_encrypter.ts +++ b/src/client-side-encryption/auto_encrypter.ts @@ -53,7 +53,7 @@ export interface AutoEncryptionOptions { /** Allows users to bypass query analysis */ bypassQueryAnalysis?: boolean; /** - * Sets the expiration time for the DEK in the cache in milliseconds. Defaults to 60000. + * Sets the expiration time for the DEK in the cache in milliseconds. Defaults to 60000. 0 means no timeout. */ keyExpirationMS?: number; options?: { From b6fb2c2b13491bd344ad770422d78d32fca1018e Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Mon, 12 May 2025 22:58:35 +0200 Subject: [PATCH 6/8] fix: comments --- src/client-side-encryption/client_encryption.ts | 2 +- .../client_side_encryption.spec.test.ts | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/client-side-encryption/client_encryption.ts b/src/client-side-encryption/client_encryption.ts index 198adfd5022..82a804c9356 100644 --- a/src/client-side-encryption/client_encryption.ts +++ b/src/client-side-encryption/client_encryption.ts @@ -886,7 +886,7 @@ export interface ClientEncryptionOptions { tlsOptions?: CSFLEKMSTlsOptions; /** - * Sets the expiration time for the DEK in the cache in milliseconds. Defaults to 60000. + * Sets the expiration time for the DEK in the cache in milliseconds. Defaults to 60000. 0 means no timeout. */ keyExpirationMS?: number; diff --git a/test/integration/client-side-encryption/client_side_encryption.spec.test.ts b/test/integration/client-side-encryption/client_side_encryption.spec.test.ts index 08c189c9ce8..fdbd57fbe39 100644 --- a/test/integration/client-side-encryption/client_side_encryption.spec.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.spec.test.ts @@ -109,13 +109,6 @@ describe('Client Side Encryption (Legacy)', function () { if (typeof result === 'string') return result; } - if (['Insert with deterministic encryption, then find it'].includes(description)) { - const result = configuration.filters.ClientSideEncryptionFilter.filter({ - metadata: { requires: { clientSideEncryption: '>=6.4.0' } } - }); - - if (typeof result === 'string') return result; - } return true; }); }); From 9402735f5f1497718a94fe4891eade5c8f89fadd Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Mon, 12 May 2025 23:35:07 +0200 Subject: [PATCH 7/8] test: unskip and cross fingers --- .../client-side-encryption/client_side_encryption.spec.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/integration/client-side-encryption/client_side_encryption.spec.test.ts b/test/integration/client-side-encryption/client_side_encryption.spec.test.ts index fdbd57fbe39..e220418bbfd 100644 --- a/test/integration/client-side-encryption/client_side_encryption.spec.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.spec.test.ts @@ -15,8 +15,6 @@ const skippedAuthTests = [ 'Insert a document with auto encryption using the AWS provider with temporary credentials', 'Insert a document with auto encryption using Azure KMS provider', '$rename works if target value has same encryption options', - 'Insert with deterministic encryption, then find it', - 'Insert with randomized encryption, then find it', 'Bulk write with encryption', 'Insert with bypassAutoEncryption', 'Insert with bypassAutoEncryption for local schema', From e4f6d13f4ffcc171384e3dc47f4f1da22cd43b31 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 13 May 2025 16:12:26 +0200 Subject: [PATCH 8/8] test: re add 6.4.0 skip --- .../client_side_encryption.spec.test.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/integration/client-side-encryption/client_side_encryption.spec.test.ts b/test/integration/client-side-encryption/client_side_encryption.spec.test.ts index e220418bbfd..2dcfa518bee 100644 --- a/test/integration/client-side-encryption/client_side_encryption.spec.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.spec.test.ts @@ -107,6 +107,13 @@ describe('Client Side Encryption (Legacy)', function () { if (typeof result === 'string') return result; } + if (['Insert with deterministic encryption, then find it'].includes(description)) { + const result = configuration.filters.ClientSideEncryptionFilter.filter({ + metadata: { requires: { clientSideEncryption: '>=6.4.0' } } + }); + + if (typeof result === 'string') return result; + } return true; }); });