From c541832dc55aeda1123ba4906c103d83e88c73cc Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Tue, 16 Jun 2026 12:14:49 +0100 Subject: [PATCH 1/6] DRIVERS-3547: Explicit Encryption Case 2 recreates collection with contention: 10 Case 2 uses contentionFactor: 10 but the shared Test Setup creates db.explicit_encryption with contention: 0. Servers implementing SERVER-91887 now reject payloads whose contentionFactor exceeds the collection's configured contention. Fix by dropping and recreating the collection with contention: 10 at the start of Case 2, matching the Python driver fix in PYTHON-5882. --- .../client-side-encryption.md | 4 ++++ source/client-side-encryption/tests/README.md | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/source/client-side-encryption/client-side-encryption.md b/source/client-side-encryption/client-side-encryption.md index 79005774ef..73cae71f61 100644 --- a/source/client-side-encryption/client-side-encryption.md +++ b/source/client-side-encryption/client-side-encryption.md @@ -2523,6 +2523,10 @@ explicit session parameter as described in the [Drivers Sessions Specification]( ## Changelog +- 2026-06-16: Explicit Encryption prose test Case 2 now recreates `db.explicit_encryption` + with `contention: 10` to match its `contentionFactor`, for compatibility with server-side + contention validation (SERVER-91887). + - 2026-05-29: Add stable support for prefix and suffix queries - Replace `prefixPreview` with `prefix`. diff --git a/source/client-side-encryption/tests/README.md b/source/client-side-encryption/tests/README.md index 8598833523..b0f8c94f7a 100644 --- a/source/client-side-encryption/tests/README.md +++ b/source/client-side-encryption/tests/README.md @@ -2002,6 +2002,19 @@ Assert one document is returned containing the field `{ "encryptedIndexed": "enc #### Case 2: can insert encrypted indexed and find with non-zero contention +> [!NOTE] +> The `Test Setup` creates `db.explicit_encryption` from `encryptedFields`, which configures the `encryptedIndexed` +> field with `contention: 0`. This case uses a `contentionFactor` of 10, so it must run against a collection whose +> configured contention is at least 10. Servers implementing +> [SERVER-91887](https://jira.mongodb.org/browse/SERVER-91887) reject payloads whose contention factor exceeds the +> collection's configured contention. + +Create a copy of `encryptedFields` named `encryptedFieldsContention10` and set the `contention` of the +`encryptedIndexed` field's `queries` to 10. + +Drop and create the collection `db.explicit_encryption` using `encryptedFieldsContention10` as an option. See +[FLE 2 CreateCollection() and Collection.Drop()](../client-side-encryption.md#create-collection-helper). + Use `clientEncryption` to encrypt the value "encrypted indexed value" with these `EncryptOpts`: ```typescript From d3457cc0c4207e1ab6c5cae0c0df5acc9214c63c Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Tue, 16 Jun 2026 14:31:51 +0100 Subject: [PATCH 2/6] DRIVERS-3547: Explicit Encryption Case 2 removes contention-0 find step Servers implementing SERVER-91887 require find payloads to exactly match the collection's configured contention factor, not just avoid exceeding it. Drop the find with contentionFactor=0 (which the server now rejects) and update the note to accurately describe the server behavior. --- .../client-side-encryption.md | 61 ++++++++++--------- source/client-side-encryption/tests/README.md | 27 ++------ 2 files changed, 35 insertions(+), 53 deletions(-) diff --git a/source/client-side-encryption/client-side-encryption.md b/source/client-side-encryption/client-side-encryption.md index 73cae71f61..5009447b16 100644 --- a/source/client-side-encryption/client-side-encryption.md +++ b/source/client-side-encryption/client-side-encryption.md @@ -635,34 +635,34 @@ Once requested, drivers MUST create a new [KMSProviders](#kmsproviders) $P$ acco 1. Let $K$ be the [kmsProviders](#kmsproviders) value provided by the user as part of the original [ClientEncryptionOpts](#ClientEncryptionOpts) or [AutoEncryptionOpts](#AutoEncryptionOpts). -2. Initialize $P$ to an empty [KMSProviders](#kmsproviders) object. -3. If $K$ contains an `aws` property, and that property is an empty map: +1. Initialize $P$ to an empty [KMSProviders](#kmsproviders) object. +1. If $K$ contains an `aws` property, and that property is an empty map: 1. If a custom credential provider is supplied via the `credentialProviders.aws` applicable encryption option, use that to fetch the credentials from AWS. - 2. Otherwise: + 1. Otherwise: 1. Attempt to obtain credentials $C$ from the environment using similar logic as is detailed in [the obtaining-AWS-credentials section from the Driver Authentication specification](../auth/auth.md#obtaining-credentials), but ignoring the case of loading the credentials from a URI - 2. If credentials $C$ were successfully loaded, create a new [AWSKMSOptions](#AWSKMSOptions) map from $C$ and + 1. If credentials $C$ were successfully loaded, create a new [AWSKMSOptions](#AWSKMSOptions) map from $C$ and insert that map onto $P$ as the `aws` property. -4. If $K$ contains an `gcp` property, and that property is an empty map: +1. If $K$ contains an `gcp` property, and that property is an empty map: 1. Attempt to obtain credentials $C$ from the environment logic as is detailed in [Obtaining GCP Credentials](#obtaining-gcp-credentials). - 2. If credentials $C$ were successfully loaded, create a new [GCPKMSOptions](#GCPKMSOptions) map from $C$ and insert + 1. If credentials $C$ were successfully loaded, create a new [GCPKMSOptions](#GCPKMSOptions) map from $C$ and insert that map onto $P$ as the `gcp` property. -5. If $K$ contains an `azure` property, and that property is an empty map: +1. If $K$ contains an `azure` property, and that property is an empty map: 1. If there is a `cachedAzureAccessToken` AND the duration until `azureAccessTokenExpireTime` is greater than one minute, insert `cachedAzureAccessToken` as the `azure` property on $P$. - 2. Otherwise: + 1. Otherwise: 1. Let $t_0$ be the current time. - 2. Attempt to obtain an Azure VM Managed Identity Access Token $T$ as detailed in + 1. Attempt to obtain an Azure VM Managed Identity Access Token $T$ as detailed in [Obtaining an Access Token for Azure Key Vault](#obtaining-an-access-token-for-azure-key-vault). - 3. If a token $T$ with expire duration $d\_{exp}$ were obtained successfully, create a new + 1. If a token $T$ with expire duration $d\_{exp}$ were obtained successfully, create a new [AzureAccessToken](#AzureAccessToken) object with $T$ as the `accessToken` property. Insert that [AzureAccessToken](#AzureAccessToken) object into $P$ as the `azure` property. Record the generated [AzureAccessToken](#AzureAccessToken) in `cachedAzureAccessToken`. Record the `azureAccessTokenExpireTime` as $t_0 + d\_{exp}$. -6. Return $P$ as the additional KMS providers to [libmongocrypt](#libmongocrypt). +1. Return $P$ as the additional KMS providers to [libmongocrypt](#libmongocrypt). @@ -697,31 +697,31 @@ The below steps should be taken: 1. Let $U$ be a new URL, initialized from the URL string `"http://169.254.169.254/metadata/identity/oauth2/token"` -2. Add a query parameter `api-version=2018-02-01` to $U$. +1. Add a query parameter `api-version=2018-02-01` to $U$. -3. Add a query parameter `resource=https://vault.azure.net/` to $U$. +1. Add a query parameter `resource=https://vault.azure.net/` to $U$. -4. Prepare an HTTP GET request $Req$ based on $U$. +1. Prepare an HTTP GET request $Req$ based on $U$. > [!NOTE] > All query parameters on $U$ should be appropriately percent-encoded -5. Add HTTP headers `Metadata: true` and `Accept: application/json` to $Req$. +1. Add HTTP headers `Metadata: true` and `Accept: application/json` to $Req$. -6. Issue $Req$ to the Azure IMDS server `169.254.169.254:80`. Let $Resp$ be the response from the server. If the HTTP +1. Issue $Req$ to the Azure IMDS server `169.254.169.254:80`. Let $Resp$ be the response from the server. If the HTTP response is not completely received within ten seconds, consider the request to have timed out, and return an error instead of an access token. -7. If $Resp\_{status} ≠ 200$, obtaining the access token has failed, and the HTTP response body of $Resp$ encodes +1. If $Resp\_{status} ≠ 200$, obtaining the access token has failed, and the HTTP response body of $Resp$ encodes information about the error that occurred. Return an error including the HTTP response body instead of an access token. -8. Otherwise, let $J$ be the JSON document encoded in the HTTP response body of $Resp$. +1. Otherwise, let $J$ be the JSON document encoded in the HTTP response body of $Resp$. -9. The result access token $T$ is given as the `access_token` string property of $J$. Return $T$ as the resulting +1. The result access token $T$ is given as the `access_token` string property of $J$. Return $T$ as the resulting access token. -10. The resulting "expires in" duration $d\_{exp}$ is a count of seconds given as an ASCII-encoded integer string +1. The resulting "expires in" duration $d\_{exp}$ is a count of seconds given as an ASCII-encoded integer string `expires_in` property of $J$. > [!NOTE] @@ -906,16 +906,16 @@ options, $collName$ is the name of the collection, $dbName$ is the name of the d and $askDb$ is a boolean value. The resulting `encryptedFields` $EF$ is found by: 1. Let $QualName$ be the string formed by joining $dbName$ and $collName$ with an ASCII dot `"."`. -2. If $opts$ contains an `"encryptedFields"` property, then $EF$ is the value of that property. -3. Otherwise, if `AutoEncryptionOptions.encryptedFieldsMap` contains an element named by $QualName$, then $EF$ is the +1. If $opts$ contains an `"encryptedFields"` property, then $EF$ is the value of that property. +1. Otherwise, if `AutoEncryptionOptions.encryptedFieldsMap` contains an element named by $QualName$, then $EF$ is the value of that element. -4. Otherwise, if $askDb$ is `true`: +1. Otherwise, if $askDb$ is `true`: 1. Issue a `listCollections` command against the database named by $dbName$, filtered by `{name: }`. Let the result be the document $L$. - 2. If $L$ contains an `options` document element, and that element contains an `encryptedFields` document element, + 1. If $L$ contains an `options` document element, and that element contains an `encryptedFields` document element, $EF$ is $L$ `["options"]["encryptedFields"]`. - 3. Otherwise, $EF$ is *not-found* -5. Otherwise, $EF$ is considered *not-found*. + 1. Otherwise, $EF$ is *not-found* +1. Otherwise, $EF$ is considered *not-found*. @@ -1627,7 +1627,7 @@ As noted in [Path Resolution Behavior](#path-resolution-behavior), [crypt_shared `libmongocrypt_handle` by omission: 1. Do not specify any [search paths](#search-paths), -2. AND do not specify a [crypt_shared](#crypt_shared) library [override path](#override-path) +1. AND do not specify a [crypt_shared](#crypt_shared) library [override path](#override-path) ([extraOptions.cryptSharedLibPath](#extraoptions.cryptsharedlibpath)). This will have the effect that [libmongocrypt](#libmongocrypt) will not attempt to search or load @@ -1650,7 +1650,7 @@ if: 1. The new `libmongocrypt_handle` wants [crypt_shared](#crypt_shared) (i.e. at least one [search path](#search-path) was specified or an [override path](#override-path) was specified). -2. AND the initialization of that `libmongocrypt_handle` does not successfully find and load the same +1. AND the initialization of that `libmongocrypt_handle` does not successfully find and load the same [crypt_shared](#crypt_shared) library that was loaded by the existing `libmongocrypt_handle` that is already using [crypt_shared](#crypt_shared). @@ -2524,8 +2524,9 @@ explicit session parameter as described in the [Drivers Sessions Specification]( ## Changelog - 2026-06-16: Explicit Encryption prose test Case 2 now recreates `db.explicit_encryption` - with `contention: 10` to match its `contentionFactor`, for compatibility with server-side - contention validation (SERVER-91887). + with `contention: 10` to match its `contentionFactor`, and removes the find with + `contentionFactor: 0`, for compatibility with server-side contention validation (SERVER-91887) + which requires find payloads to match the collection's configured contention. - 2026-05-29: Add stable support for prefix and suffix queries diff --git a/source/client-side-encryption/tests/README.md b/source/client-side-encryption/tests/README.md index b0f8c94f7a..8797014762 100644 --- a/source/client-side-encryption/tests/README.md +++ b/source/client-side-encryption/tests/README.md @@ -2005,9 +2005,9 @@ Assert one document is returned containing the field `{ "encryptedIndexed": "enc > [!NOTE] > The `Test Setup` creates `db.explicit_encryption` from `encryptedFields`, which configures the `encryptedIndexed` > field with `contention: 0`. This case uses a `contentionFactor` of 10, so it must run against a collection whose -> configured contention is at least 10. Servers implementing -> [SERVER-91887](https://jira.mongodb.org/browse/SERVER-91887) reject payloads whose contention factor exceeds the -> collection's configured contention. +> configured contention matches. Servers implementing +> [SERVER-91887](https://jira.mongodb.org/browse/SERVER-91887) reject find payloads whose contention factor does not +> match the collection's configured contention. Create a copy of `encryptedFields` named `encryptedFieldsContention10` and set the `contention` of the `encryptedIndexed` field's `queries` to 10. @@ -2038,7 +2038,7 @@ class EncryptOpts { keyId : , algorithm: "Indexed", queryType: "equality", - contentionFactor: 0, + contentionFactor: 10, } ``` @@ -2047,25 +2047,6 @@ Store the result in `findPayload`. Use `encryptedClient` to run a "find" operation on the `db.explicit_encryption` collection with the filter `{ "encryptedIndexed": }`. -Assert less than 10 documents are returned. 0 documents may be returned. Assert each returned document contains the -field `{ "encryptedIndexed": "encrypted indexed value" }`. - -Use `clientEncryption` to encrypt the value "encrypted indexed value" with these `EncryptOpts`: - -```typescript -class EncryptOpts { - keyId : , - algorithm: "Indexed", - queryType: "equality", - contentionFactor: 10, -} -``` - -Store the result in `findPayload2`. - -Use `encryptedClient` to run a "find" operation on the `db.explicit_encryption` collection with the filter -`{ "encryptedIndexed": }`. - Assert 10 documents are returned. Assert each returned document contains the field `{ "encryptedIndexed": "encrypted indexed value" }`. From 9f5027dc636c5b705064636d6e89a3ebc84dbaa4 Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Wed, 17 Jun 2026 09:24:04 +0100 Subject: [PATCH 3/6] Update source/client-side-encryption/client-side-encryption.md Co-authored-by: Kevin Albertson --- source/client-side-encryption/client-side-encryption.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/source/client-side-encryption/client-side-encryption.md b/source/client-side-encryption/client-side-encryption.md index 5009447b16..5ef2a60e7f 100644 --- a/source/client-side-encryption/client-side-encryption.md +++ b/source/client-side-encryption/client-side-encryption.md @@ -2523,10 +2523,7 @@ explicit session parameter as described in the [Drivers Sessions Specification]( ## Changelog -- 2026-06-16: Explicit Encryption prose test Case 2 now recreates `db.explicit_encryption` - with `contention: 10` to match its `contentionFactor`, and removes the find with - `contentionFactor: 0`, for compatibility with server-side contention validation (SERVER-91887) - which requires find payloads to match the collection's configured contention. +- 2026-06-16: Update tests in response to server-side validation of payloads ([SERVER-91887](https://jira.mongodb.org/browse/SERVER-91887)) - 2026-05-29: Add stable support for prefix and suffix queries From 3f4d599862d32e52371e553103986c2eaff4be63 Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Wed, 17 Jun 2026 10:34:41 +0100 Subject: [PATCH 4/6] DRIVERS-3547: Address PR review feedback - Use a pre-created db.explicit_encryption_c10 collection (contention: 10) in Test Setup rather than requiring Case 2 to reconstruct collection BSON - Add encryptedFields-c10.json fixture file - Add explicit contention: 0 to encryptedFields-prefix-suffix.json and encryptedFields-substring.json for SERVER-91887 compatibility --- .../etc/data/encryptedFields-c10.json | 30 +++++++++++++++++++ .../data/encryptedFields-prefix-suffix.json | 6 ++++ .../etc/data/encryptedFields-substring.json | 3 ++ source/client-side-encryption/tests/README.md | 24 ++++++--------- 4 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 source/client-side-encryption/etc/data/encryptedFields-c10.json diff --git a/source/client-side-encryption/etc/data/encryptedFields-c10.json b/source/client-side-encryption/etc/data/encryptedFields-c10.json new file mode 100644 index 0000000000..e9ed08bb39 --- /dev/null +++ b/source/client-side-encryption/etc/data/encryptedFields-c10.json @@ -0,0 +1,30 @@ +{ + "fields": [ + { + "keyId": { + "$binary": { + "base64": "EjRWeBI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedIndexed", + "bsonType": "string", + "queries": { + "queryType": "equality", + "contention": { + "$numberLong": "10" + } + } + }, + { + "keyId": { + "$binary": { + "base64": "q83vqxI0mHYSNBI0VniQEg==", + "subType": "04" + } + }, + "path": "encryptedUnindexed", + "bsonType": "string" + } + ] +} diff --git a/source/client-side-encryption/etc/data/encryptedFields-prefix-suffix.json b/source/client-side-encryption/etc/data/encryptedFields-prefix-suffix.json index 141c372dbe..a96e616723 100644 --- a/source/client-side-encryption/etc/data/encryptedFields-prefix-suffix.json +++ b/source/client-side-encryption/etc/data/encryptedFields-prefix-suffix.json @@ -18,6 +18,9 @@ "strMaxQueryLength": { "$numberInt": "10" }, + "contention": { + "$numberLong": "0" + }, "caseSensitive": true, "diacriticSensitive": true }, @@ -29,6 +32,9 @@ "strMaxQueryLength": { "$numberInt": "10" }, + "contention": { + "$numberLong": "0" + }, "caseSensitive": true, "diacriticSensitive": true } diff --git a/source/client-side-encryption/etc/data/encryptedFields-substring.json b/source/client-side-encryption/etc/data/encryptedFields-substring.json index ee22def77b..d321a32c5c 100644 --- a/source/client-side-encryption/etc/data/encryptedFields-substring.json +++ b/source/client-side-encryption/etc/data/encryptedFields-substring.json @@ -21,6 +21,9 @@ "strMaxQueryLength": { "$numberInt": "10" }, + "contention": { + "$numberLong": "0" + }, "caseSensitive": true, "diacriticSensitive": true } diff --git a/source/client-side-encryption/tests/README.md b/source/client-side-encryption/tests/README.md index 8797014762..c4c1540978 100644 --- a/source/client-side-encryption/tests/README.md +++ b/source/client-side-encryption/tests/README.md @@ -1940,6 +1940,13 @@ Read the `"_id"` field of `key1Document` as `key1ID`. Drop and create the collection `db.explicit_encryption` using `encryptedFields` as an option. See [FLE 2 CreateCollection() and Collection.Drop()](../client-side-encryption.md#create-collection-helper). +Load the file +[encryptedFields-c10.json](https://github.com/mongodb/specifications/tree/master/source/client-side-encryption/etc/data/encryptedFields-c10.json) +as `encryptedFields_c10`. + +Drop and create the collection `db.explicit_encryption_c10` using `encryptedFields_c10` as an option. See +[FLE 2 CreateCollection() and Collection.Drop()](../client-side-encryption.md#create-collection-helper). + Drop and create the collection `keyvault.datakeys`. Insert `key1Document` in `keyvault.datakeys` with majority write concern. @@ -2002,19 +2009,6 @@ Assert one document is returned containing the field `{ "encryptedIndexed": "enc #### Case 2: can insert encrypted indexed and find with non-zero contention -> [!NOTE] -> The `Test Setup` creates `db.explicit_encryption` from `encryptedFields`, which configures the `encryptedIndexed` -> field with `contention: 0`. This case uses a `contentionFactor` of 10, so it must run against a collection whose -> configured contention matches. Servers implementing -> [SERVER-91887](https://jira.mongodb.org/browse/SERVER-91887) reject find payloads whose contention factor does not -> match the collection's configured contention. - -Create a copy of `encryptedFields` named `encryptedFieldsContention10` and set the `contention` of the -`encryptedIndexed` field's `queries` to 10. - -Drop and create the collection `db.explicit_encryption` using `encryptedFieldsContention10` as an option. See -[FLE 2 CreateCollection() and Collection.Drop()](../client-side-encryption.md#create-collection-helper). - Use `clientEncryption` to encrypt the value "encrypted indexed value" with these `EncryptOpts`: ```typescript @@ -2027,7 +2021,7 @@ class EncryptOpts { Store the result in `insertPayload`. -Use `encryptedClient` to insert the document `{ "encryptedIndexed": }` into `db.explicit_encryption`. +Use `encryptedClient` to insert the document `{ "encryptedIndexed": }` into `db.explicit_encryption_c10`. Repeat the above steps 10 times to insert 10 total documents. The `insertPayload` must be regenerated each iteration. @@ -2044,7 +2038,7 @@ class EncryptOpts { Store the result in `findPayload`. -Use `encryptedClient` to run a "find" operation on the `db.explicit_encryption` collection with the filter +Use `encryptedClient` to run a "find" operation on the `db.explicit_encryption_c10` collection with the filter `{ "encryptedIndexed": }`. Assert 10 documents are returned. Assert each returned document contains the field From a495416c0e0d8f36639a7d5cdfc90fc08b516510 Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Wed, 17 Jun 2026 10:37:44 +0100 Subject: [PATCH 5/6] DRIVERS-3547: Revert unintended list renumbering in client-side-encryption.md --- .../client-side-encryption.md | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/source/client-side-encryption/client-side-encryption.md b/source/client-side-encryption/client-side-encryption.md index 5ef2a60e7f..1e07a97420 100644 --- a/source/client-side-encryption/client-side-encryption.md +++ b/source/client-side-encryption/client-side-encryption.md @@ -635,34 +635,34 @@ Once requested, drivers MUST create a new [KMSProviders](#kmsproviders) $P$ acco 1. Let $K$ be the [kmsProviders](#kmsproviders) value provided by the user as part of the original [ClientEncryptionOpts](#ClientEncryptionOpts) or [AutoEncryptionOpts](#AutoEncryptionOpts). -1. Initialize $P$ to an empty [KMSProviders](#kmsproviders) object. -1. If $K$ contains an `aws` property, and that property is an empty map: +2. Initialize $P$ to an empty [KMSProviders](#kmsproviders) object. +3. If $K$ contains an `aws` property, and that property is an empty map: 1. If a custom credential provider is supplied via the `credentialProviders.aws` applicable encryption option, use that to fetch the credentials from AWS. - 1. Otherwise: + 2. Otherwise: 1. Attempt to obtain credentials $C$ from the environment using similar logic as is detailed in [the obtaining-AWS-credentials section from the Driver Authentication specification](../auth/auth.md#obtaining-credentials), but ignoring the case of loading the credentials from a URI - 1. If credentials $C$ were successfully loaded, create a new [AWSKMSOptions](#AWSKMSOptions) map from $C$ and + 2. If credentials $C$ were successfully loaded, create a new [AWSKMSOptions](#AWSKMSOptions) map from $C$ and insert that map onto $P$ as the `aws` property. -1. If $K$ contains an `gcp` property, and that property is an empty map: +4. If $K$ contains an `gcp` property, and that property is an empty map: 1. Attempt to obtain credentials $C$ from the environment logic as is detailed in [Obtaining GCP Credentials](#obtaining-gcp-credentials). - 1. If credentials $C$ were successfully loaded, create a new [GCPKMSOptions](#GCPKMSOptions) map from $C$ and insert + 2. If credentials $C$ were successfully loaded, create a new [GCPKMSOptions](#GCPKMSOptions) map from $C$ and insert that map onto $P$ as the `gcp` property. -1. If $K$ contains an `azure` property, and that property is an empty map: +5. If $K$ contains an `azure` property, and that property is an empty map: 1. If there is a `cachedAzureAccessToken` AND the duration until `azureAccessTokenExpireTime` is greater than one minute, insert `cachedAzureAccessToken` as the `azure` property on $P$. - 1. Otherwise: + 2. Otherwise: 1. Let $t_0$ be the current time. - 1. Attempt to obtain an Azure VM Managed Identity Access Token $T$ as detailed in + 2. Attempt to obtain an Azure VM Managed Identity Access Token $T$ as detailed in [Obtaining an Access Token for Azure Key Vault](#obtaining-an-access-token-for-azure-key-vault). - 1. If a token $T$ with expire duration $d\_{exp}$ were obtained successfully, create a new + 3. If a token $T$ with expire duration $d\_{exp}$ were obtained successfully, create a new [AzureAccessToken](#AzureAccessToken) object with $T$ as the `accessToken` property. Insert that [AzureAccessToken](#AzureAccessToken) object into $P$ as the `azure` property. Record the generated [AzureAccessToken](#AzureAccessToken) in `cachedAzureAccessToken`. Record the `azureAccessTokenExpireTime` as $t_0 + d\_{exp}$. -1. Return $P$ as the additional KMS providers to [libmongocrypt](#libmongocrypt). +6. Return $P$ as the additional KMS providers to [libmongocrypt](#libmongocrypt). @@ -697,31 +697,31 @@ The below steps should be taken: 1. Let $U$ be a new URL, initialized from the URL string `"http://169.254.169.254/metadata/identity/oauth2/token"` -1. Add a query parameter `api-version=2018-02-01` to $U$. +2. Add a query parameter `api-version=2018-02-01` to $U$. -1. Add a query parameter `resource=https://vault.azure.net/` to $U$. +3. Add a query parameter `resource=https://vault.azure.net/` to $U$. -1. Prepare an HTTP GET request $Req$ based on $U$. +4. Prepare an HTTP GET request $Req$ based on $U$. > [!NOTE] > All query parameters on $U$ should be appropriately percent-encoded -1. Add HTTP headers `Metadata: true` and `Accept: application/json` to $Req$. +5. Add HTTP headers `Metadata: true` and `Accept: application/json` to $Req$. -1. Issue $Req$ to the Azure IMDS server `169.254.169.254:80`. Let $Resp$ be the response from the server. If the HTTP +6. Issue $Req$ to the Azure IMDS server `169.254.169.254:80`. Let $Resp$ be the response from the server. If the HTTP response is not completely received within ten seconds, consider the request to have timed out, and return an error instead of an access token. -1. If $Resp\_{status} ≠ 200$, obtaining the access token has failed, and the HTTP response body of $Resp$ encodes +7. If $Resp\_{status} ≠ 200$, obtaining the access token has failed, and the HTTP response body of $Resp$ encodes information about the error that occurred. Return an error including the HTTP response body instead of an access token. -1. Otherwise, let $J$ be the JSON document encoded in the HTTP response body of $Resp$. +8. Otherwise, let $J$ be the JSON document encoded in the HTTP response body of $Resp$. -1. The result access token $T$ is given as the `access_token` string property of $J$. Return $T$ as the resulting +9. The result access token $T$ is given as the `access_token` string property of $J$. Return $T$ as the resulting access token. -1. The resulting "expires in" duration $d\_{exp}$ is a count of seconds given as an ASCII-encoded integer string +10. The resulting "expires in" duration $d\_{exp}$ is a count of seconds given as an ASCII-encoded integer string `expires_in` property of $J$. > [!NOTE] @@ -906,16 +906,16 @@ options, $collName$ is the name of the collection, $dbName$ is the name of the d and $askDb$ is a boolean value. The resulting `encryptedFields` $EF$ is found by: 1. Let $QualName$ be the string formed by joining $dbName$ and $collName$ with an ASCII dot `"."`. -1. If $opts$ contains an `"encryptedFields"` property, then $EF$ is the value of that property. -1. Otherwise, if `AutoEncryptionOptions.encryptedFieldsMap` contains an element named by $QualName$, then $EF$ is the +2. If $opts$ contains an `"encryptedFields"` property, then $EF$ is the value of that property. +3. Otherwise, if `AutoEncryptionOptions.encryptedFieldsMap` contains an element named by $QualName$, then $EF$ is the value of that element. -1. Otherwise, if $askDb$ is `true`: +4. Otherwise, if $askDb$ is `true`: 1. Issue a `listCollections` command against the database named by $dbName$, filtered by `{name: }`. Let the result be the document $L$. - 1. If $L$ contains an `options` document element, and that element contains an `encryptedFields` document element, + 2. If $L$ contains an `options` document element, and that element contains an `encryptedFields` document element, $EF$ is $L$ `["options"]["encryptedFields"]`. - 1. Otherwise, $EF$ is *not-found* -1. Otherwise, $EF$ is considered *not-found*. + 3. Otherwise, $EF$ is *not-found* +5. Otherwise, $EF$ is considered *not-found*. @@ -1627,7 +1627,7 @@ As noted in [Path Resolution Behavior](#path-resolution-behavior), [crypt_shared `libmongocrypt_handle` by omission: 1. Do not specify any [search paths](#search-paths), -1. AND do not specify a [crypt_shared](#crypt_shared) library [override path](#override-path) +2. AND do not specify a [crypt_shared](#crypt_shared) library [override path](#override-path) ([extraOptions.cryptSharedLibPath](#extraoptions.cryptsharedlibpath)). This will have the effect that [libmongocrypt](#libmongocrypt) will not attempt to search or load @@ -1650,7 +1650,7 @@ if: 1. The new `libmongocrypt_handle` wants [crypt_shared](#crypt_shared) (i.e. at least one [search path](#search-path) was specified or an [override path](#override-path) was specified). -1. AND the initialization of that `libmongocrypt_handle` does not successfully find and load the same +2. AND the initialization of that `libmongocrypt_handle` does not successfully find and load the same [crypt_shared](#crypt_shared) library that was loaded by the existing `libmongocrypt_handle` that is already using [crypt_shared](#crypt_shared). From f0fac62b280d74fd6eb4f8a49e291a619bdb2312 Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Wed, 17 Jun 2026 11:51:59 +0100 Subject: [PATCH 6/6] DRIVERS-3547: Fix linter line-length violations --- source/client-side-encryption/client-side-encryption.md | 3 ++- source/client-side-encryption/tests/README.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/source/client-side-encryption/client-side-encryption.md b/source/client-side-encryption/client-side-encryption.md index 1e07a97420..437c84360b 100644 --- a/source/client-side-encryption/client-side-encryption.md +++ b/source/client-side-encryption/client-side-encryption.md @@ -2523,7 +2523,8 @@ explicit session parameter as described in the [Drivers Sessions Specification]( ## Changelog -- 2026-06-16: Update tests in response to server-side validation of payloads ([SERVER-91887](https://jira.mongodb.org/browse/SERVER-91887)) +- 2026-06-16: Update tests in response to server-side validation of payloads + ([SERVER-91887](https://jira.mongodb.org/browse/SERVER-91887)) - 2026-05-29: Add stable support for prefix and suffix queries diff --git a/source/client-side-encryption/tests/README.md b/source/client-side-encryption/tests/README.md index c4c1540978..7fcc963b2f 100644 --- a/source/client-side-encryption/tests/README.md +++ b/source/client-side-encryption/tests/README.md @@ -2021,7 +2021,8 @@ class EncryptOpts { Store the result in `insertPayload`. -Use `encryptedClient` to insert the document `{ "encryptedIndexed": }` into `db.explicit_encryption_c10`. +Use `encryptedClient` to insert the document `{ "encryptedIndexed": }` into +`db.explicit_encryption_c10`. Repeat the above steps 10 times to insert 10 total documents. The `insertPayload` must be regenerated each iteration.