PYTHON-5456 Support text indexes with auto encryption (#2500)

This commit is contained in:
Steven Silvester 2025-08-21 10:55:48 -05:00 committed by GitHub
parent 5e96353797
commit e08284bdca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 1727 additions and 4 deletions

View File

@ -159,6 +159,14 @@ async def is_run_on_requirement_satisfied(requirement):
if req_csfle is True:
min_version_satisfied = Version.from_string("4.2") <= server_version
csfle_satisfied = _HAVE_PYMONGOCRYPT and min_version_satisfied
elif isinstance(req_csfle, dict) and "minLibmongocryptVersion" in req_csfle:
csfle_satisfied = False
req_version = req_csfle["minLibmongocryptVersion"]
if _HAVE_PYMONGOCRYPT:
from pymongocrypt import libmongocrypt_version
if Version.from_string(libmongocrypt_version()) >= Version.from_string(req_version):
csfle_satisfied = True
return (
topology_satisfied
@ -450,7 +458,7 @@ class UnifiedSpecTestMixinV1(AsyncIntegrationTest):
a class attribute ``TEST_SPEC``.
"""
SCHEMA_VERSION = Version.from_string("1.23")
SCHEMA_VERSION = Version.from_string("1.25")
RUN_ON_LOAD_BALANCER = True
TEST_SPEC: Any
TEST_PATH = "" # This gets filled in by generate_test_classes
@ -1545,7 +1553,7 @@ def generate_test_classes(
# Add "encryption" marker if the "csfle" runOnRequirement is set.
for req in test_spec.get("runOnRequirements", []):
if req.get("csfle", False):
if "csfle" in req:
base = pytest.mark.encryption(base)
return base

View File

@ -0,0 +1,219 @@
{
"description": "QE-Text-cleanupStructuredEncryptionData",
"schemaVersion": "1.25",
"runOnRequirements": [
{
"minServerVersion": "8.2.0",
"topologies": [
"replicaset",
"sharded",
"load-balanced"
],
"csfle": {
"minLibmongocryptVersion": "1.15.0"
}
}
],
"createEntities": [
{
"client": {
"id": "client",
"autoEncryptOpts": {
"keyVaultNamespace": "keyvault.datakeys",
"kmsProviders": {
"local": {
"key": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk"
}
}
},
"observeEvents": [
"commandStartedEvent"
]
}
},
{
"database": {
"id": "db",
"client": "client",
"databaseName": "db"
}
},
{
"collection": {
"id": "coll",
"database": "db",
"collectionName": "coll"
}
}
],
"initialData": [
{
"databaseName": "keyvault",
"collectionName": "datakeys",
"documents": [
{
"_id": {
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
},
"keyMaterial": {
"$binary": {
"base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==",
"subType": "00"
}
},
"creationDate": {
"$date": {
"$numberLong": "1648914851981"
}
},
"updateDate": {
"$date": {
"$numberLong": "1648914851981"
}
},
"status": {
"$numberInt": "0"
},
"masterKey": {
"provider": "local"
}
}
]
},
{
"databaseName": "db",
"collectionName": "coll",
"documents": [],
"createOptions": {
"encryptedFields": {
"fields": [
{
"keyId": {
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
},
"path": "encryptedText",
"bsonType": "string",
"queries": [
{
"queryType": "suffixPreview",
"contention": {
"$numberLong": "0"
},
"strMinQueryLength": {
"$numberLong": "3"
},
"strMaxQueryLength": {
"$numberLong": "30"
},
"caseSensitive": true,
"diacriticSensitive": true
}
]
}
]
}
}
}
],
"tests": [
{
"description": "QE Text cleanupStructuredEncryptionData works",
"operations": [
{
"name": "runCommand",
"object": "db",
"arguments": {
"command": {
"cleanupStructuredEncryptionData": "coll"
},
"commandName": "cleanupStructuredEncryptionData"
},
"expectResult": {
"ok": 1
}
}
],
"expectEvents": [
{
"client": "client",
"events": [
{
"commandStartedEvent": {
"command": {
"listCollections": 1,
"filter": {
"name": "coll"
}
},
"commandName": "listCollections"
}
},
{
"commandStartedEvent": {
"command": {
"find": "datakeys",
"filter": {
"$or": [
{
"_id": {
"$in": [
{
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
}
]
}
},
{
"keyAltNames": {
"$in": []
}
}
]
},
"$db": "keyvault",
"readConcern": {
"level": "majority"
}
},
"commandName": "find"
}
},
{
"commandStartedEvent": {
"command": {
"cleanupStructuredEncryptionData": "coll",
"cleanupTokens": {
"encryptedText": {
"ecoc": {
"$binary": {
"base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=",
"subType": "00"
}
},
"anchorPaddingToken": {
"$binary": {
"base64": "YAiF7Iwhqq1UyfxPvm70xfQJtrIRPrjfD2yRLG1+saQ=",
"subType": "00"
}
}
}
}
},
"commandName": "cleanupStructuredEncryptionData"
}
}
]
}
]
}
]
}

View File

@ -0,0 +1,261 @@
{
"description": "QE-Text-compactStructuredEncryptionData",
"schemaVersion": "1.25",
"runOnRequirements": [
{
"minServerVersion": "8.2.0",
"topologies": [
"replicaset",
"sharded",
"load-balanced"
],
"csfle": {
"minLibmongocryptVersion": "1.15.0"
}
}
],
"createEntities": [
{
"client": {
"id": "client",
"autoEncryptOpts": {
"keyVaultNamespace": "keyvault.datakeys",
"kmsProviders": {
"local": {
"key": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk"
}
}
},
"observeEvents": [
"commandStartedEvent"
]
}
},
{
"database": {
"id": "db",
"client": "client",
"databaseName": "db"
}
},
{
"collection": {
"id": "coll",
"database": "db",
"collectionName": "coll"
}
}
],
"initialData": [
{
"databaseName": "keyvault",
"collectionName": "datakeys",
"documents": [
{
"_id": {
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
},
"keyMaterial": {
"$binary": {
"base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==",
"subType": "00"
}
},
"creationDate": {
"$date": {
"$numberLong": "1648914851981"
}
},
"updateDate": {
"$date": {
"$numberLong": "1648914851981"
}
},
"status": {
"$numberInt": "0"
},
"masterKey": {
"provider": "local"
}
}
]
},
{
"databaseName": "db",
"collectionName": "coll",
"documents": [],
"createOptions": {
"encryptedFields": {
"fields": [
{
"keyId": {
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
},
"path": "encryptedText",
"bsonType": "string",
"queries": [
{
"queryType": "suffixPreview",
"contention": {
"$numberLong": "0"
},
"strMinQueryLength": {
"$numberLong": "3"
},
"strMaxQueryLength": {
"$numberLong": "30"
},
"caseSensitive": true,
"diacriticSensitive": true
}
]
}
]
}
}
}
],
"tests": [
{
"description": "QE Text compactStructuredEncryptionData works",
"operations": [
{
"name": "runCommand",
"object": "db",
"arguments": {
"command": {
"compactStructuredEncryptionData": "coll"
},
"commandName": "compactStructuredEncryptionData"
},
"expectResult": {
"ok": 1
}
}
],
"expectEvents": [
{
"client": "client",
"events": [
{
"commandStartedEvent": {
"command": {
"listCollections": 1,
"filter": {
"name": "coll"
}
},
"commandName": "listCollections"
}
},
{
"commandStartedEvent": {
"command": {
"find": "datakeys",
"filter": {
"$or": [
{
"_id": {
"$in": [
{
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
}
]
}
},
{
"keyAltNames": {
"$in": []
}
}
]
},
"$db": "keyvault",
"readConcern": {
"level": "majority"
}
},
"commandName": "find"
}
},
{
"commandStartedEvent": {
"command": {
"compactStructuredEncryptionData": "coll",
"encryptionInformation": {
"type": {
"$numberInt": "1"
},
"schema": {
"db.coll": {
"fields": [
{
"keyId": {
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
},
"path": "encryptedText",
"bsonType": "string",
"queries": [
{
"queryType": "suffixPreview",
"contention": {
"$numberLong": "0"
},
"strMinQueryLength": {
"$numberLong": "3"
},
"strMaxQueryLength": {
"$numberLong": "30"
},
"caseSensitive": true,
"diacriticSensitive": true
}
]
}
],
"strEncodeVersion": {
"$numberInt": "1"
},
"escCollection": "enxcol_.coll.esc",
"ecocCollection": "enxcol_.coll.ecoc"
}
}
},
"compactionTokens": {
"encryptedText": {
"ecoc": {
"$binary": {
"base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=",
"subType": "00"
}
},
"anchorPaddingToken": {
"$binary": {
"base64": "YAiF7Iwhqq1UyfxPvm70xfQJtrIRPrjfD2yRLG1+saQ=",
"subType": "00"
}
}
}
}
},
"commandName": "compactStructuredEncryptionData"
}
}
]
}
]
}
]
}

View File

@ -0,0 +1,338 @@
{
"description": "QE-Text-prefixPreview",
"schemaVersion": "1.25",
"runOnRequirements": [
{
"minServerVersion": "8.2.0",
"topologies": [
"replicaset",
"sharded",
"load-balanced"
],
"csfle": {
"minLibmongocryptVersion": "1.15.0"
}
}
],
"createEntities": [
{
"client": {
"id": "client",
"autoEncryptOpts": {
"keyVaultNamespace": "keyvault.datakeys",
"kmsProviders": {
"local": {
"key": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk"
}
}
},
"observeEvents": [
"commandStartedEvent"
]
}
},
{
"database": {
"id": "db",
"client": "client",
"databaseName": "db"
}
},
{
"collection": {
"id": "coll",
"database": "db",
"collectionName": "coll"
}
}
],
"initialData": [
{
"databaseName": "keyvault",
"collectionName": "datakeys",
"documents": [
{
"_id": {
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
},
"keyMaterial": {
"$binary": {
"base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==",
"subType": "00"
}
},
"creationDate": {
"$date": {
"$numberLong": "1648914851981"
}
},
"updateDate": {
"$date": {
"$numberLong": "1648914851981"
}
},
"status": {
"$numberInt": "0"
},
"masterKey": {
"provider": "local"
}
}
]
},
{
"databaseName": "db",
"collectionName": "coll",
"documents": [],
"createOptions": {
"encryptedFields": {
"fields": [
{
"keyId": {
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
},
"path": "encryptedText",
"bsonType": "string",
"queries": [
{
"queryType": "prefixPreview",
"contention": {
"$numberLong": "0"
},
"strMinQueryLength": {
"$numberLong": "3"
},
"strMaxQueryLength": {
"$numberLong": "30"
},
"caseSensitive": true,
"diacriticSensitive": true
}
]
}
]
}
}
}
],
"tests": [
{
"description": "Insert QE prefixPreview",
"operations": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 1,
"encryptedText": "foobar"
}
},
"object": "coll"
}
],
"expectEvents": [
{
"client": "client",
"events": [
{
"commandStartedEvent": {
"command": {
"listCollections": 1,
"filter": {
"name": "coll"
}
},
"commandName": "listCollections"
}
},
{
"commandStartedEvent": {
"command": {
"find": "datakeys",
"filter": {
"$or": [
{
"_id": {
"$in": [
{
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
}
]
}
},
{
"keyAltNames": {
"$in": []
}
}
]
},
"$db": "keyvault",
"readConcern": {
"level": "majority"
}
},
"commandName": "find"
}
},
{
"commandStartedEvent": {
"command": {
"insert": "coll",
"documents": [
{
"_id": 1,
"encryptedText": {
"$$type": "binData"
}
}
],
"ordered": true
},
"commandName": "insert"
}
}
]
}
]
},
{
"description": "Query with matching $encStrStartsWith",
"operations": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 1,
"encryptedText": "foobar"
}
},
"object": "coll"
},
{
"name": "find",
"arguments": {
"filter": {
"$expr": {
"$encStrStartsWith": {
"input": "$encryptedText",
"prefix": "foo"
}
}
}
},
"object": "coll",
"expectResult": [
{
"_id": {
"$numberInt": "1"
},
"encryptedText": "foobar",
"__safeContent__": [
{
"$binary": {
"base64": "wpaMBVDjL4bHf9EtSP52PJFzyNn1R19+iNI/hWtvzdk=",
"subType": "00"
}
},
{
"$binary": {
"base64": "fmUMXTMV/XRiN0IL3VXxSEn6SQG9E6Po30kJKB8JJlQ=",
"subType": "00"
}
},
{
"$binary": {
"base64": "vZIDMiFDgjmLNYVrrbnq1zT4hg7sGpe/PMtighSsnRc=",
"subType": "00"
}
},
{
"$binary": {
"base64": "26Z5G+sHTzV3D7F8Y0m08389USZ2afinyFV3ez9UEBQ=",
"subType": "00"
}
},
{
"$binary": {
"base64": "q/JEq8of7bE0QE5Id0XuOsNQ4qVpANYymcPQDUL2Ywk=",
"subType": "00"
}
},
{
"$binary": {
"base64": "Uvvv46LkfbgLoPqZ6xTBzpgoYRTM6FUgRdqZ9eaVojI=",
"subType": "00"
}
},
{
"$binary": {
"base64": "nMxdq2lladuBJA3lv3JC2MumIUtRJBNJVLp3PVE6nQk=",
"subType": "00"
}
},
{
"$binary": {
"base64": "hS3V0qq5CF/SkTl3ZWWWgXcAJ8G5yGtkY2RwcHNc5Oc=",
"subType": "00"
}
},
{
"$binary": {
"base64": "McgwYUxfKj5+4D0vskZymy4KA82s71MR25iV/Enutww=",
"subType": "00"
}
},
{
"$binary": {
"base64": "Ciqdk1b+t+Vrr6oIlFFk0Zdym5BPmwN3glQ0/VcsVdM=",
"subType": "00"
}
}
]
}
]
}
]
},
{
"description": "Query with non-matching $encStrStartsWith",
"operations": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 1,
"encryptedText": "foobar"
}
},
"object": "coll"
},
{
"name": "find",
"arguments": {
"filter": {
"$expr": {
"$encStrStartsWith": {
"input": "$encryptedText",
"prefix": "bar"
}
}
}
},
"object": "coll",
"expectResult": []
}
]
}
]
}

View File

@ -0,0 +1,551 @@
{
"description": "QE-Text-substringPreview",
"schemaVersion": "1.25",
"runOnRequirements": [
{
"minServerVersion": "8.2.0",
"topologies": [
"replicaset",
"sharded",
"load-balanced"
],
"csfle": {
"minLibmongocryptVersion": "1.15.0"
}
}
],
"createEntities": [
{
"client": {
"id": "client",
"autoEncryptOpts": {
"keyVaultNamespace": "keyvault.datakeys",
"kmsProviders": {
"local": {
"key": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk"
}
}
},
"observeEvents": [
"commandStartedEvent"
]
}
},
{
"database": {
"id": "db",
"client": "client",
"databaseName": "db"
}
},
{
"collection": {
"id": "coll",
"database": "db",
"collectionName": "coll"
}
}
],
"initialData": [
{
"databaseName": "keyvault",
"collectionName": "datakeys",
"documents": [
{
"_id": {
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
},
"keyMaterial": {
"$binary": {
"base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==",
"subType": "00"
}
},
"creationDate": {
"$date": {
"$numberLong": "1648914851981"
}
},
"updateDate": {
"$date": {
"$numberLong": "1648914851981"
}
},
"status": {
"$numberInt": "0"
},
"masterKey": {
"provider": "local"
}
}
]
},
{
"databaseName": "db",
"collectionName": "coll",
"documents": [],
"createOptions": {
"encryptedFields": {
"fields": [
{
"keyId": {
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
},
"path": "encryptedText",
"bsonType": "string",
"queries": [
{
"queryType": "substringPreview",
"contention": {
"$numberLong": "0"
},
"strMinQueryLength": {
"$numberLong": "3"
},
"strMaxQueryLength": {
"$numberLong": "10"
},
"strMaxLength": {
"$numberLong": "20"
},
"caseSensitive": true,
"diacriticSensitive": true
}
]
}
]
}
}
}
],
"tests": [
{
"description": "Insert QE suffixPreview",
"operations": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 1,
"encryptedText": "foobar"
}
},
"object": "coll"
}
],
"expectEvents": [
{
"client": "client",
"events": [
{
"commandStartedEvent": {
"command": {
"listCollections": 1,
"filter": {
"name": "coll"
}
},
"commandName": "listCollections"
}
},
{
"commandStartedEvent": {
"command": {
"find": "datakeys",
"filter": {
"$or": [
{
"_id": {
"$in": [
{
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
}
]
}
},
{
"keyAltNames": {
"$in": []
}
}
]
},
"$db": "keyvault",
"readConcern": {
"level": "majority"
}
},
"commandName": "find"
}
},
{
"commandStartedEvent": {
"command": {
"insert": "coll",
"documents": [
{
"_id": 1,
"encryptedText": {
"$$type": "binData"
}
}
],
"ordered": true
},
"commandName": "insert"
}
}
]
}
]
},
{
"description": "Query with matching $encStrContains",
"operations": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 1,
"encryptedText": "foobar"
}
},
"object": "coll"
},
{
"name": "find",
"arguments": {
"filter": {
"$expr": {
"$encStrContains": {
"input": "$encryptedText",
"substring": "oba"
}
}
}
},
"object": "coll",
"expectResult": [
{
"_id": {
"$numberInt": "1"
},
"encryptedText": "foobar",
"__safeContent__": [
{
"$binary": {
"base64": "wpaMBVDjL4bHf9EtSP52PJFzyNn1R19+iNI/hWtvzdk=",
"subType": "00"
}
},
{
"$binary": {
"base64": "IpY3x/jjm8j/74jAdUhgxdM5hk68zR0zv/lTKm/72Vg=",
"subType": "00"
}
},
{
"$binary": {
"base64": "G+ky260C6QiOfIxKz14FmaMbAxvui1BKJO/TnLOHlGk=",
"subType": "00"
}
},
{
"$binary": {
"base64": "7dv3gAKe9vwJMZmpB40pRCwRTmc7ds9UkGhxH8j084E=",
"subType": "00"
}
},
{
"$binary": {
"base64": "o0V+Efn6x8XQdE80F1tztNaT3qxHjcsd9DOQ47BtmQk=",
"subType": "00"
}
},
{
"$binary": {
"base64": "sJvrCjyVot7PIZFsdRehWFANKAj6fmBaj3FLbz/dZLE=",
"subType": "00"
}
},
{
"$binary": {
"base64": "e98auxFmu02h5MfBIARk29MI7hSmvN3F9DaQ0xjqoEM=",
"subType": "00"
}
},
{
"$binary": {
"base64": "US83krGNov/ezL6IhsY5eEOCxv1xUPDIEL/nmY0IKi0=",
"subType": "00"
}
},
{
"$binary": {
"base64": "P2Aq5+OHZPG0CWIdmZvWq9c/18ZKVYW3vbxd+WU/TXU=",
"subType": "00"
}
},
{
"$binary": {
"base64": "8AdPRPnSzcd5uhq4TZfNvNeF0XjLNVwAsJJMTtktw84=",
"subType": "00"
}
},
{
"$binary": {
"base64": "9O6u/G51I4ZHFLhL4ZLuudbr0s202A2QnPfThmOXPhI=",
"subType": "00"
}
},
{
"$binary": {
"base64": "N7AjYVyVlv6+lVSTM+cIxRL3SMgs3G5LgxSs+jrgDkI=",
"subType": "00"
}
},
{
"$binary": {
"base64": "RbGF7dQbPGYQFd9DDO1hPz1UlLOJ77FAC6NsjGwJeos=",
"subType": "00"
}
},
{
"$binary": {
"base64": "m7srHMgKm6kZwsNx8rc45pmw0/9Qro6xuQ8lZS3+RYk=",
"subType": "00"
}
},
{
"$binary": {
"base64": "K75CNU3JyKFqZWPiIsVi4+n7DhYmcPl/nEhQ3d88mVI=",
"subType": "00"
}
},
{
"$binary": {
"base64": "c7bwGpUZc/7JzEnMS7qQ/TPuXZyrmMihFaAV6zIqbZc=",
"subType": "00"
}
},
{
"$binary": {
"base64": "rDvEdUgEk8u4Srt3ETokWs2FXcnyJaRGQ+NbkFwi2rQ=",
"subType": "00"
}
},
{
"$binary": {
"base64": "VcdZj9zfveRBRlpCR2OYWau2+GokOFb73TE3gpElNiU=",
"subType": "00"
}
},
{
"$binary": {
"base64": "eOa9o2xfA6OgkbYUxd6wQJicaeN6guhy2V66W3ALsaA=",
"subType": "00"
}
},
{
"$binary": {
"base64": "1xGkJh+um70XiRd8lKLDtyHgDqrf7/59Mg7X0+KZh8k=",
"subType": "00"
}
},
{
"$binary": {
"base64": "OSvllqHxycbcZN4phR6NDujY3ttA59o7nQJ6V9eJpX0=",
"subType": "00"
}
},
{
"$binary": {
"base64": "ZTX1pyk8Vdw0BSbJx7GeJNcQf3tGKxbrrNSTqBqUWkg=",
"subType": "00"
}
},
{
"$binary": {
"base64": "cn7V05zb5iXwYrePGMHztC+GRq+Tj8IMpRDraauPhSE=",
"subType": "00"
}
},
{
"$binary": {
"base64": "E9bV9KyrZxHJSUmMg0HrDK4gGN+75ruelAnrM6hXQgY=",
"subType": "00"
}
},
{
"$binary": {
"base64": "WrssTNmdgXoTGpbaF0JLRCGH6cDQuz1XEFNTy98nrb0=",
"subType": "00"
}
},
{
"$binary": {
"base64": "jZmyOJP35dsxQ/OY5U4ISpVRIYr8iedNfcwZiKt29Qc=",
"subType": "00"
}
},
{
"$binary": {
"base64": "d2mocORMbX9MX+/itAW8r1kxVw2/uii4vzXtc+2CIRQ=",
"subType": "00"
}
},
{
"$binary": {
"base64": "JBnJy58eRPhDo3DuZvsHbvQDiHXxdtAx1Eif66k5SfA=",
"subType": "00"
}
},
{
"$binary": {
"base64": "OjbDulC8s62v0pgweBSsQqtJjJBwH5JinfJpj7nVr+A=",
"subType": "00"
}
},
{
"$binary": {
"base64": "85i7KT2GP9nSda3Gsil5LKubhq0LDtc22pxBxHpR+nE=",
"subType": "00"
}
},
{
"$binary": {
"base64": "u9Fvsclwrs9lwIcMPV/fMZD7L3d5anSfJQVjQb9mgLg=",
"subType": "00"
}
},
{
"$binary": {
"base64": "LZ32ttmLJGOIw9oFaUCn3Sx5uHPTYJPSFpeGRWNqlUc=",
"subType": "00"
}
},
{
"$binary": {
"base64": "mMsZvGEePTqtl0FJAL/jAdyWNQIlpwN61YIlZsSIZ6s=",
"subType": "00"
}
},
{
"$binary": {
"base64": "XZcu1a/ZGsIzAl3j4MXQlLo4v2p7kvIqRHtIQYFmL6k=",
"subType": "00"
}
},
{
"$binary": {
"base64": "Zse27LinlYCEnX6iTmJceI33mEJxFb0LdPxp0RiMOaQ=",
"subType": "00"
}
},
{
"$binary": {
"base64": "vOv2Hgb2/sBpnX9XwFbIN6yDxhjchwlmczUf82W2tp4=",
"subType": "00"
}
},
{
"$binary": {
"base64": "oQxZ9A6j3x5j6x1Jqw/N9tpP4rfWMjcV3y+a3PkrL7c=",
"subType": "00"
}
},
{
"$binary": {
"base64": "/D7ew3EijyUnmT22awVFspcuyo3JChJcDeCPwpljzVM=",
"subType": "00"
}
},
{
"$binary": {
"base64": "BEmmwqyamt9X3bcWDld61P01zquy8fBHAXq3SHAPP0M=",
"subType": "00"
}
},
{
"$binary": {
"base64": "wygD9/kAo1KsRvtr1v+9/lvqoWdKwgh6gDHvAQfXPPk=",
"subType": "00"
}
},
{
"$binary": {
"base64": "pRTKgF/uksrF1c1AcfSTY6ZhqBKVud1vIztQ4/36SLs=",
"subType": "00"
}
},
{
"$binary": {
"base64": "C4iUo8oNJsjJ37BqnBgIgSQpf99X2Bb4W5MZEAmakHU=",
"subType": "00"
}
},
{
"$binary": {
"base64": "icoE53jIq6Fu/YGKUiSUTYyZ8xdiTQY9jJiGxVJObpw=",
"subType": "00"
}
},
{
"$binary": {
"base64": "oubCwk0V6G2RFWtcOnYDU4uUBoXBrhBRi4nZgrYj9JY=",
"subType": "00"
}
},
{
"$binary": {
"base64": "IyqhQ9nGhzEi5YW2W6v1kGU5DY2u2qSqbM/qXdLdWVU=",
"subType": "00"
}
}
]
}
]
}
]
},
{
"description": "Query with non-matching $encStrContains",
"operations": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 1,
"encryptedText": "foobar"
}
},
"object": "coll"
},
{
"name": "find",
"arguments": {
"filter": {
"$expr": {
"$encStrContains": {
"input": "$encryptedText",
"substring": "blah"
}
}
}
},
"object": "coll",
"expectResult": []
}
]
}
]
}

View File

@ -0,0 +1,338 @@
{
"description": "QE-Text-suffixPreview",
"schemaVersion": "1.25",
"runOnRequirements": [
{
"minServerVersion": "8.2.0",
"topologies": [
"replicaset",
"sharded",
"load-balanced"
],
"csfle": {
"minLibmongocryptVersion": "1.15.0"
}
}
],
"createEntities": [
{
"client": {
"id": "client",
"autoEncryptOpts": {
"keyVaultNamespace": "keyvault.datakeys",
"kmsProviders": {
"local": {
"key": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk"
}
}
},
"observeEvents": [
"commandStartedEvent"
]
}
},
{
"database": {
"id": "db",
"client": "client",
"databaseName": "db"
}
},
{
"collection": {
"id": "coll",
"database": "db",
"collectionName": "coll"
}
}
],
"initialData": [
{
"databaseName": "keyvault",
"collectionName": "datakeys",
"documents": [
{
"_id": {
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
},
"keyMaterial": {
"$binary": {
"base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==",
"subType": "00"
}
},
"creationDate": {
"$date": {
"$numberLong": "1648914851981"
}
},
"updateDate": {
"$date": {
"$numberLong": "1648914851981"
}
},
"status": {
"$numberInt": "0"
},
"masterKey": {
"provider": "local"
}
}
]
},
{
"databaseName": "db",
"collectionName": "coll",
"documents": [],
"createOptions": {
"encryptedFields": {
"fields": [
{
"keyId": {
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
},
"path": "encryptedText",
"bsonType": "string",
"queries": [
{
"queryType": "suffixPreview",
"contention": {
"$numberLong": "0"
},
"strMinQueryLength": {
"$numberLong": "3"
},
"strMaxQueryLength": {
"$numberLong": "30"
},
"caseSensitive": true,
"diacriticSensitive": true
}
]
}
]
}
}
}
],
"tests": [
{
"description": "Insert QE suffixPreview",
"operations": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 1,
"encryptedText": "foobar"
}
},
"object": "coll"
}
],
"expectEvents": [
{
"client": "client",
"events": [
{
"commandStartedEvent": {
"command": {
"listCollections": 1,
"filter": {
"name": "coll"
}
},
"commandName": "listCollections"
}
},
{
"commandStartedEvent": {
"command": {
"find": "datakeys",
"filter": {
"$or": [
{
"_id": {
"$in": [
{
"$binary": {
"base64": "q83vqxI0mHYSNBI0VniQEg==",
"subType": "04"
}
}
]
}
},
{
"keyAltNames": {
"$in": []
}
}
]
},
"$db": "keyvault",
"readConcern": {
"level": "majority"
}
},
"commandName": "find"
}
},
{
"commandStartedEvent": {
"command": {
"insert": "coll",
"documents": [
{
"_id": 1,
"encryptedText": {
"$$type": "binData"
}
}
],
"ordered": true
},
"commandName": "insert"
}
}
]
}
]
},
{
"description": "Query with matching $encStrStartsWith",
"operations": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 1,
"encryptedText": "foobar"
}
},
"object": "coll"
},
{
"name": "find",
"arguments": {
"filter": {
"$expr": {
"$encStrEndsWith": {
"input": "$encryptedText",
"suffix": "bar"
}
}
}
},
"object": "coll",
"expectResult": [
{
"_id": {
"$numberInt": "1"
},
"encryptedText": "foobar",
"__safeContent__": [
{
"$binary": {
"base64": "wpaMBVDjL4bHf9EtSP52PJFzyNn1R19+iNI/hWtvzdk=",
"subType": "00"
}
},
{
"$binary": {
"base64": "uDCWsucUsJemUP7pmeb+Kd8B9qupVzI8wnLFqX1rkiU=",
"subType": "00"
}
},
{
"$binary": {
"base64": "W3E1x4bHZ8SEHFz4zwXM0G5Z5WSwBhnxE8x5/qdP6JM=",
"subType": "00"
}
},
{
"$binary": {
"base64": "6g/TXVDDf6z+ntResIvTKWdmIy4ajQ1rhwdNZIiEG7A=",
"subType": "00"
}
},
{
"$binary": {
"base64": "hU+u/T3D6dHDpT3d/v5AlgtRoAufCXCAyO2jQlgsnCw=",
"subType": "00"
}
},
{
"$binary": {
"base64": "vrPnq0AtBIURNgNGA6HJL+5/p5SBWe+qz8505TRo/dE=",
"subType": "00"
}
},
{
"$binary": {
"base64": "W5pylBxdv2soY2NcBfPiHDVLTS6tx+0ULkI8gysBeFY=",
"subType": "00"
}
},
{
"$binary": {
"base64": "oWO3xX3x0bYUJGK2S1aPAmlU3Xtfsgb9lTZ6flGAlsg=",
"subType": "00"
}
},
{
"$binary": {
"base64": "SjZGucTEUbdpd86O8yj1pyMyBOOKxvAQ9C8ngZ9C5UE=",
"subType": "00"
}
},
{
"$binary": {
"base64": "CEaMZkxVDVbnXr+To0DOyvsva04UQkIYP3KtgYVVwf8=",
"subType": "00"
}
}
]
}
]
}
]
},
{
"description": "Query with non-matching $encStrEndsWith",
"operations": [
{
"name": "insertOne",
"arguments": {
"document": {
"_id": 1,
"encryptedText": "foobar"
}
},
"object": "coll"
},
{
"name": "find",
"arguments": {
"filter": {
"$expr": {
"$encStrEndsWith": {
"input": "$encryptedText",
"suffix": "foo"
}
}
}
},
"object": "coll",
"expectResult": []
}
]
}
]
}

View File

@ -158,6 +158,14 @@ def is_run_on_requirement_satisfied(requirement):
if req_csfle is True:
min_version_satisfied = Version.from_string("4.2") <= server_version
csfle_satisfied = _HAVE_PYMONGOCRYPT and min_version_satisfied
elif isinstance(req_csfle, dict) and "minLibmongocryptVersion" in req_csfle:
csfle_satisfied = False
req_version = req_csfle["minLibmongocryptVersion"]
if _HAVE_PYMONGOCRYPT:
from pymongocrypt import libmongocrypt_version
if Version.from_string(libmongocrypt_version()) >= Version.from_string(req_version):
csfle_satisfied = True
return (
topology_satisfied
@ -449,7 +457,7 @@ class UnifiedSpecTestMixinV1(IntegrationTest):
a class attribute ``TEST_SPEC``.
"""
SCHEMA_VERSION = Version.from_string("1.23")
SCHEMA_VERSION = Version.from_string("1.25")
RUN_ON_LOAD_BALANCER = True
TEST_SPEC: Any
TEST_PATH = "" # This gets filled in by generate_test_classes
@ -1530,7 +1538,7 @@ def generate_test_classes(
# Add "encryption" marker if the "csfle" runOnRequirement is set.
for req in test_spec.get("runOnRequirements", []):
if req.get("csfle", False):
if "csfle" in req:
base = pytest.mark.encryption(base)
return base