diff --git a/test/functional/spec/client-side-encryption/README.rst b/test/functional/spec/client-side-encryption/README.rst new file mode 100644 index 00000000000..fea2503432d --- /dev/null +++ b/test/functional/spec/client-side-encryption/README.rst @@ -0,0 +1,266 @@ +============================ +Client Side Encryption Tests +============================ + +.. contents:: + +---- + +Introduction +============ + +This document describes the format of the driver spec tests included in the JSON +and YAML files included in this directory. + +Additional prose tests, that are not represented in the spec tests, are described +and MUST be implemented by all drivers. + +Spec Test Format +================ + +The spec tests format is an extension of `transactions spec tests `_ with some additions: + +- A ``json_schema`` to set on the collection used for operations. + +- A ``key_vault_data`` of data that should be inserted in the key vault collection before each test. + +- Introduction ``client_side_encryption_opts`` to `clientOptions` + +- Addition of `$db` to command in `command_started_event` + +- Addition of `$$type` to command_started_event and outcome. + +The semantics of `$$type` is that any actual value matching the BSON type indicated by the BSON type string is considered a match. + +For example, the following matches a command_started_event for an insert of a document where `random` must be of type ``binData``: +``` +- command_started_event: + command: + insert: *collection_name + documents: + - { random: { $$type: "binData" } } + ordered: true + command_name: insert +``` + +The values of `$$type` correspond to `these documented string representations of BSON types `_. + + +Each YAML file has the following keys: + +.. |txn| replace:: Unchanged from Transactions spec tests. + +- ``runOn`` |txn| + +- ``database_name`` |txn| + +- ``collection_name`` |txn| + +- ``data`` |txn| + +- ``json_schema`` A JSON Schema that should be set on the collection (using ``createCollection``) before each test run. + +- ``key_vault_data`` The data that should exist in the key vault collection under test before each test run. + +- ``tests``: An array of tests that are to be run independently of each other. + Each test will have some or all of the following fields: + + - ``description``: |txn| + + - ``skipReason``: |txn| + + - ``clientOptions``: Optional, parameters to pass to MongoClient(). + + - ``auto_encrypt_opts``: Optional + + - ``kms_providers`` A dictionary of KMS providers to set on the key vault ("aws" or "local") + + - ``aws`` The AWS KMS provider. An empty object. Drivers MUST fill in AWS credentials from the environment. + + - ``local`` The local KMS provider. + + - ``key`` A 64 byte local key. + + - ``schema_map``: Optional, a map from namespaces to local JSON schemas. + + - ``operations``: Array of documents, each describing an operation to be + executed. Each document has the following fields: + + - ``name``: |txn| + + - ``object``: |txn| + + - ``collectionOptions``: |txn| + + - ``command_name``: |txn| + + - ``arguments``: |txn| + + - ``result``: |txn| + + - ``expectations``: |txn| + + - ``outcome``: |txn| + + + +Use as integration tests +======================== + +Do the following before running spec tests: + +- Start the mongocryptd process. +- Start a mongod process with **server version 4.1.9 or later**. +- Place credentials to an AWS IAM user (access key ID + secret access key) somewhere in the environment outside of tracked code. (If testing on evergreen, project variables are a good place). + +Load each YAML (or JSON) file using a Canonical Extended JSON parser. + +Then for each element in ``tests``: + +#. If the ``skipReason`` field is present, skip this test completely. +#. If the ``key_vault_data`` field is present: + + #. Drop the ``admin.datakeys`` collection using writeConcern "majority". + #. Insert the data specified into the ``admin.datakeys`` with write concern "majority". + +#. Create a MongoClient using ``clientOptions``. + + #. If ``client_side_encryption_opts`` includes ``aws`` as a KMS provider, pass in AWS credentials from the environment. + +#. Create a collection object from the MongoClient, using the ``database_name`` + and ``collection_name`` fields from the YAML file. +#. Drop the test collection, using writeConcern "majority". +#. If the YAML file contains a ``data`` array, insert the documents in ``data`` + into the test collection, using writeConcern "majority". + +#. Set Command Monitoring listeners on the MongoClient. +#. For each element in ``operations``: + + - Enter a "try" block or your programming language's closest equivalent. + - Create a Database object from the MongoClient, using the ``database_name`` + field at the top level of the test file. + - Create a Collection object from the Database, using the + ``collection_name`` field at the top level of the test file. + If ``collectionOptions`` is present create the Collection object with the + provided options. Otherwise create the object with the default options. + - Execute the named method on the provided ``object``, passing the + arguments listed. + - If the driver throws an exception / returns an error while executing this + series of operations, store the error message and server error code. + - If the result document has an "errorContains" field, verify that the + method threw an exception or returned an error, and that the value of the + "errorContains" field matches the error string. "errorContains" is a + substring (case-insensitive) of the actual error message. + + If the result document has an "errorCodeName" field, verify that the + method threw a command failed exception or returned an error, and that + the value of the "errorCodeName" field matches the "codeName" in the + server error response. + + If the result document has an "errorLabelsContain" field, verify that the + method threw an exception or returned an error. Verify that all of the + error labels in "errorLabelsContain" are present in the error or exception + using the ``hasErrorLabel`` method. + + If the result document has an "errorLabelsOmit" field, verify that the + method threw an exception or returned an error. Verify that none of the + error labels in "errorLabelsOmit" are present in the error or exception + using the ``hasErrorLabel`` method. + - If the operation returns a raw command response, eg from ``runCommand``, + then compare only the fields present in the expected result document. + Otherwise, compare the method's return value to ``result`` using the same + logic as the CRUD Spec Tests runner. + +#. If the test includes a list of command-started events in ``expectations``, + compare them to the actual command-started events using the + same logic as the Command Monitoring Spec Tests runner. + +#. For each element in ``outcome``: + + - If ``name`` is "collection", create a new MongoClient *without encryption* + and verify that the test collection contains exactly the documents in the + ``data`` array. Ensure this find reads the latest data by using + **primary read preference** with **local read concern** even when the + MongoClient is configured with another read preference or read concern. + +The spec test MUST be run with *and* without auth. + +Prose Tests +=========== + +Tests for the KeyVault type are not included as part of the YAML tests. Tests are described +as follows. + +#. Test creating a data key with the "local" KMS provider. + + - Create a `KeyVault` with a "local" KMS provider. + - Create a data key with the "local" KMS provider using `KeyVault.createDataKey()`. + - Expect a BSON binary with subtype 4 to be returned. + - Expect a `findOne` on the key vault collection with `_id` set to the returned binary to return a document. + - Expect that document to have "masterKey.provider" set to "local" + +#. Test creating a data key with the "aws" KMS provider. + + - Create a `KeyVault` with a "aws" KMS provider. + - Create a data key with the "aws" KMS provider using `KeyVault.createDataKey()`. + - Expect a BSON binary with subtype 4 to be returned. + - Expect a `findOne` on the key vault collection with `_id` set to the returned binary to return a document. + - Expect that document to have "masterKey.provider" set to "aws" + +#. Test explicit encrypt and decrypt with the "local" KMS provider. + + - Create a `KeyVault` with a "local" KMS provider. + - Insert the a key document in to the key vault. + - Use `KeyVault.encrypt` to encrypt the value "hello" with the following: + + - the algorithm "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + - the "local" KMS provider + + - Expect the value is equal to a known BSON binary of subtype 6 + - Use `KeyVault.decrypt` to decrypt the encrypted value + - Expect the value is equal to the string "hello" + +#. Test explicit encrypt and decrypt with the "aws" KMS provider. + + - Create a `KeyVault` with a "aws" KMS provider. + - Insert the a key document in to the key vault. + - Use `KeyVault.encrypt` to encrypt the value "hello" with the following: + + - the algorithm "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + - the "aws" KMS provider + + - Expect the value is equal to a known BSON binary of subtype 6 + - Use `KeyVault.decrypt` to decrypt the encrypted value + - Expect the value is equal to the string "hello" + +#. Test explicit encrypt of invalid values. + + - Create a `KeyVault` with either a "local" or "aws" KMS provider + - Use `KeyVault.encrypt` to attempt to encrypt each BSON type with deterministic encryption. + + - Expect a `string` to succeed. An exception MUST be thrown. + - Expect a `document` to fail. An exception MUST be thrown. + - Expect a `null` to fail. An exception MUST be thrown. + - Expect a BSON binary subtype 6 to fail. An exception MUST be thrown. + + - Use `KeyVault.encrypt` to attempt to encrypt a document using randomized encryption. + + - Expect a `document` to succeed. + - Expect a BSON binary subtype 6 to fail. An exception MUST be thrown. + - Expect a `null` to fail. An exception MUST be thrown. + +#. Test explicit encryption with auto decryption. + + - Create a `KeyVault` with either a "local" or "aws" KMS provider + - Use `KeyVault.encrypt` to encrypt a value. + - Create a document, setting some field to the value. + - Insert the document into a collection. + - Find the document. Verify both the value matches the originally set value. + +#. Test explicit encrypting an auto encrypted field. + + - Create a `KeyVault` with either a "local" or "aws" KMS provider + - Create a collection with a JSON Schema specifying an encrypted field. + - Use `KeyVault.encrypt` to encrypt a value. + - Create a document, setting the auto-encrypted field to the value. + - Insert the document. Verify an exception is thrown. \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/aggregate.json b/test/functional/spec/client-side-encryption/aggregate.json new file mode 100644 index 00000000000..02f4b6fa42e --- /dev/null +++ b/test/functional/spec/client-side-encryption/aggregate.json @@ -0,0 +1,412 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "Aggregate with deterministic encryption", + "skipReason": "SERVER-39395", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "encrypted_string": "457-55-5642" + } + } + ] + }, + "result": [ + { + "_id": 1, + "encrypted_string": "string0" + } + ] + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "aggregate": "default", + "pipeline": [ + { + "$match": { + "encrypted_string": "457-55-5642" + } + } + ] + }, + "command_name": "aggregate" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "Aggregate with empty pipeline", + "skipReason": "SERVER-40829 hides agg support behind enableTestCommands flag.", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "aggregate", + "arguments": { + "pipeline": [] + }, + "result": [ + { + "_id": 1, + "encrypted_string": "string0" + } + ] + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "aggregate": "default", + "pipeline": [], + "cursor": {} + }, + "command_name": "aggregate" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "Aggregate should fail with random encryption", + "skipReason": "SERVER-39395", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "aggregate", + "arguments": { + "pipeline": [ + { + "$match": { + "random": "abc" + } + } + ] + }, + "result": { + "errorContains": "Cannot query on fields encrypted with the randomized encryption" + } + } + ] + }, + { + "description": "Database aggregate should fail", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "aggregate", + "object": "database", + "arguments": { + "pipeline": [ + { + "$currentOp": { + "allUsers": false, + "idleConnections": false, + "localOps": true + } + }, + { + "$match": { + "command.aggregate": { + "$eq": 1 + } + } + }, + { + "$project": { + "command": 1 + } + }, + { + "$project": { + "command.lsid": 0 + } + } + ] + }, + "result": { + "errorContains": "non-collection command not supported for auto encryption: aggregate" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/aggregate.yml b/test/functional/spec/client-side-encryption/aggregate.yml new file mode 100644 index 00000000000..df9d5729d7f --- /dev/null +++ b/test/functional/spec/client-side-encryption/aggregate.yml @@ -0,0 +1,136 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "Aggregate with deterministic encryption" + skipReason: "SERVER-39395" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: aggregate + arguments: + pipeline: + - { $match: { encrypted_string: "457-55-5642" } } + result: + - &doc0 { _id: 1, encrypted_string: "string0" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + aggregate: *collection_name + pipeline: + - { $match: { encrypted_string: "457-55-5642" } } + command_name: aggregate + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "Aggregate with empty pipeline" + skipReason: "SERVER-40829 hides agg support behind enableTestCommands flag." + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: aggregate + arguments: + pipeline: [] + result: + - { _id: 1, encrypted_string: "string0" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + aggregate: *collection_name + pipeline: [] + cursor: {} + command_name: aggregate + # Needs to fetch key when decrypting results + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "Aggregate should fail with random encryption" + skipReason: "SERVER-39395" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: aggregate + arguments: + pipeline: + - { $match: { random: "abc" } } + result: + errorContains: "Cannot query on fields encrypted with the randomized encryption" + - description: "Database aggregate should fail" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: aggregate + object: database + arguments: + pipeline: + - $currentOp: { allUsers: false, idleConnections: false, localOps: true } + - $match: { command.aggregate: { $eq: 1 } } + - $project: { command: 1 } + - $project: { command.lsid: 0 } + result: + errorContains: "non-collection command not supported for auto encryption: aggregate" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/aggregate.yml.template b/test/functional/spec/client-side-encryption/aggregate.yml.template new file mode 100644 index 00000000000..5da35aa31e5 --- /dev/null +++ b/test/functional/spec/client-side-encryption/aggregate.yml.template @@ -0,0 +1,136 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "Aggregate with deterministic encryption" + skipReason: "SERVER-39395" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: aggregate + arguments: + pipeline: + - { $match: { encrypted_string: "457-55-5642" } } + result: + - &doc0 { _id: 1, encrypted_string: "string0" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + aggregate: *collection_name + pipeline: + - { $match: { encrypted_string: "457-55-5642" } } + command_name: aggregate + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "Aggregate with empty pipeline" + skipReason: "SERVER-40829 hides agg support behind enableTestCommands flag." + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: aggregate + arguments: + pipeline: [] + result: + - { _id: 1, encrypted_string: "string0" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + aggregate: *collection_name + pipeline: [] + cursor: {} + command_name: aggregate + # Needs to fetch key when decrypting results + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "Aggregate should fail with random encryption" + skipReason: "SERVER-39395" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: aggregate + arguments: + pipeline: + - { $match: { random: "abc" } } + result: + errorContains: "Cannot query on fields encrypted with the randomized encryption" + - description: "Database aggregate should fail" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: aggregate + object: database + arguments: + pipeline: + - $currentOp: { allUsers: false, idleConnections: false, localOps: true } + - $match: { command.aggregate: { $eq: 1 } } + - $project: { command: 1 } + - $project: { command.lsid: 0 } + result: + errorContains: "non-collection command not supported for auto encryption: aggregate" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/badQueries.json b/test/functional/spec/client-side-encryption/badQueries.json new file mode 100644 index 00000000000..57a0c1ee74d --- /dev/null +++ b/test/functional/spec/client-side-encryption/badQueries.json @@ -0,0 +1,1474 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "$expr unconditionally fails", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "filter": { + "$expr": { + "$eq": [ + 1, + 1 + ] + } + } + }, + "result": { + "errorContains": "Unsupported match expression operator for encryption" + } + } + ] + }, + { + "description": "$text unconditionally fails", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "filter": { + "$text": { + "$search": "search text" + } + } + }, + "result": { + "errorContains": "Unsupported match expression operator for encryption" + } + } + ] + }, + { + "description": "$where unconditionally fails", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "filter": { + "$where": { + "$code": "function() { return true }" + } + } + }, + "result": { + "errorContains": "Unsupported match expression operator for encryption" + } + } + ] + }, + { + "description": "$bit operators succeed on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$bitsAllClear": 35 + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$bitsAllClear": 35 + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$bitsAllSet": 35 + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$bitsAllSet": 35 + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$bitsAnyClear": 35 + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$bitsAnyClear": 35 + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$bitsAnySet": 35 + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$bitsAnySet": 35 + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + } + ] + }, + { + "description": "geo operators succeed on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$near": [ + 0, + 0 + ] + } + } + }, + "result": { + "errorContains": "unable to find index" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$near": [ + 0, + 0 + ] + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$nearSphere": [ + 0, + 0 + ] + } + } + }, + "result": { + "errorContains": "unable to find index" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$nearSphere": [ + 0, + 0 + ] + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$geoIntersects": { + "$geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 0, + 0 + ], + [ + 1, + 0 + ], + [ + 1, + 1 + ], + [ + 0, + 0 + ] + ] + ] + } + } + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$geoIntersects": { + "$geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 0, + 0 + ], + [ + 1, + 0 + ], + [ + 1, + 1 + ], + [ + 0, + 0 + ] + ] + ] + } + } + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$geoWithin": { + "$geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 0, + 0 + ], + [ + 1, + 0 + ], + [ + 1, + 1 + ], + [ + 0, + 0 + ] + ] + ] + } + } + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$geoWithin": { + "$geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 0, + 0 + ], + [ + 1, + 0 + ], + [ + 1, + 1 + ], + [ + 0, + 0 + ] + ] + ] + } + } + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + } + ] + }, + { + "description": "inequality operators succeed on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$gt": 1 + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$gt": 1 + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$lt": 1 + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$lt": 1 + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$gte": 1 + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$gte": 1 + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$lte": 1 + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$lte": 1 + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + } + ] + }, + { + "description": "other misc operators succeed on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$mod": [ + 3, + 1 + ] + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$mod": [ + 3, + 1 + ] + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$regex": "pattern", + "$options": "" + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$regex": "pattern", + "$options": "" + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$size": 2 + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$size": 2 + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$type": 2 + } + } + }, + "result": [] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$type": 2 + } + } + }, + "result": { + "errorContains": "Invalid match expression operator on encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$eq": null + } + } + }, + "result": [ + { + "_id": 1, + "encrypted_string": "string0" + }, + { + "_id": 2, + "encrypted_string": "string1" + } + ] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$eq": null + } + } + }, + "result": { + "errorContains": "Illegal equality to null predicate for encrypted field" + } + }, + { + "name": "find", + "arguments": { + "filter": { + "unencrypted": { + "$in": [ + null + ] + } + } + }, + "result": [ + { + "_id": 1, + "encrypted_string": "string0" + }, + { + "_id": 2, + "encrypted_string": "string1" + } + ] + }, + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$in": [ + null + ] + } + } + }, + "result": { + "errorContains": "Illegal equality to null inside $in against an encrypted field" + } + } + ] + }, + { + "description": "$addToSet succeeds on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$addToSet": { + "unencrypted": [ + "a" + ] + } + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + }, + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$addToSet": { + "encrypted_string": [ + "a" + ] + } + } + }, + "result": { + "errorContains": "$addToSet not allowed on encrypted values" + } + } + ] + }, + { + "description": "$inc succeeds on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$inc": { + "unencrypted": 1 + } + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + }, + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$inc": { + "encrypted_string": 1 + } + } + }, + "result": { + "errorContains": "$inc and $mul not allowed on encrypted values" + } + } + ] + }, + { + "description": "$mul succeeds on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$mul": { + "unencrypted": 1 + } + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + }, + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$mul": { + "encrypted_string": 1 + } + } + }, + "result": { + "errorContains": "$inc and $mul not allowed on encrypted values" + } + } + ] + }, + { + "description": "$max succeeds on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$max": { + "unencrypted": 1 + } + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + }, + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$max": { + "encrypted_string": 1 + } + } + }, + "result": { + "errorContains": "$max and $min not allowed on encrypted values" + } + } + ] + }, + { + "description": "$min succeeds on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$min": { + "unencrypted": 1 + } + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + }, + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$min": { + "encrypted_string": 1 + } + } + }, + "result": { + "errorContains": "$max and $min not allowed on encrypted values" + } + } + ] + }, + { + "description": "$currentDate succeeds on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$currentDate": { + "unencrypted": true + } + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + }, + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$currentDate": { + "encrypted_string": true + } + } + }, + "result": { + "errorContains": "$currentDate not allowed on encrypted values" + } + } + ] + }, + { + "description": "$pop succeeds on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$pop": { + "unencrypted": 1 + } + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 0, + "upsertedCount": 0 + } + }, + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$pop": { + "encrypted_string": 1 + } + } + }, + "result": { + "errorContains": "$pop not allowed on encrypted values" + } + } + ] + }, + { + "description": "$pull succeeds on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$pull": { + "unencrypted": 1 + } + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 0, + "upsertedCount": 0 + } + }, + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$pull": { + "encrypted_string": 1 + } + } + }, + "result": { + "errorContains": "$pull not allowed on encrypted values" + } + } + ] + }, + { + "description": "$pullAll succeeds on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$pullAll": { + "unencrypted": [ + 1 + ] + } + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 0, + "upsertedCount": 0 + } + }, + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$pullAll": { + "encrypted_string": [ + 1 + ] + } + } + }, + "result": { + "errorContains": "$pullAll not allowed on encrypted values" + } + } + ] + }, + { + "description": "$push succeeds on unencrypted, error on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$push": { + "unencrypted": 1 + } + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + }, + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$push": { + "encrypted_string": 1 + } + } + }, + "result": { + "errorContains": "$push not allowed on encrypted values" + } + } + ] + }, + { + "description": "array filters on encrypted fields does not error in mongocryptd, but errors in mongod", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$set": { + "encrypted_string.$[i].x": 1 + } + }, + "arrayFilters": [ + { + "i.x": 1 + } + ] + }, + "result": { + "errorContains": "Array update operations not allowed on encrypted values" + } + } + ] + }, + { + "description": "positional operator succeeds on unencrypted, errors on encrypted", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": { + "unencrypted": 1 + }, + "update": { + "$set": { + "unencrypted.$": 1 + } + } + }, + "result": { + "matchedCount": 0, + "modifiedCount": 0, + "upsertedCount": 0 + } + }, + { + "name": "updateOne", + "arguments": { + "filter": { + "encrypted_string": "abc" + }, + "update": { + "$set": { + "encrypted_string.$": "abc" + } + } + }, + "result": { + "errorContains": "Cannot encrypt fields below '$' positional update operator" + } + } + ] + }, + { + "description": "an update that would produce an array on an encrypted field errors", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$set": { + "encrypted_string": [ + 1, + 2 + ] + } + } + }, + "result": { + "errorContains": "Cannot encrypt element of type array" + } + } + ] + }, + { + "description": "an insert with encrypted field on _id errors", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + }, + "schemaMap": { + "default.default": { + "properties": { + "_id": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + } + } + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1 + } + }, + "result": { + "errorContains": "Invalid schema containing the 'encrypt' keyword." + } + } + ] + }, + { + "description": "an insert with an array value for an encrypted field fails", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "encrypted_string": [ + "123", + "456" + ] + } + }, + "result": { + "errorContains": "Cannot encrypt element of type array" + } + } + ] + }, + { + "description": "an insert with a Timestamp(0,0) value in the top-level fails", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "random": { + "$timestamp": { + "t": 0, + "i": 0 + } + } + } + }, + "result": { + "errorContains": "A command that inserts cannot supply Timestamp(0, 0) for an encrypted" + } + } + ] + }, + { + "description": "distinct with the key referring to a field where the keyID is a JSON Pointer errors", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "distinct", + "arguments": { + "filter": {}, + "fieldName": "encrypted_w_altname" + }, + "result": { + "errorContains": "The distinct key is not allowed to be marked for encryption with a non-UUID keyId" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/badQueries.yml b/test/functional/spec/client-side-encryption/badQueries.yml new file mode 100644 index 00000000000..166fd52e2e1 --- /dev/null +++ b/test/functional/spec/client-side-encryption/badQueries.yml @@ -0,0 +1,538 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - &doc1_encrypted { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +# TODO: I could see an argument against having these tests of mongocryptd as part +# of driver tests. When mongocryptd introduces support for these operators, these +# tests will fail. But it's also easy enough to remove these tests when that happens. + +tests: + - description: "$expr unconditionally fails" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: + { $expr: { $eq: [1, 1] } } + result: + errorContains: "Unsupported match expression operator for encryption" + - description: "$text unconditionally fails" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: + { $text: { $search: "search text" } } + result: + errorContains: "Unsupported match expression operator for encryption" + - description: "$where unconditionally fails" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: + { $where: { $code: "function() { return true }" } } + result: + errorContains: "Unsupported match expression operator for encryption" + - description: "$bit operators succeed on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { unencrypted: { $bitsAllClear: 35 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $bitsAllClear: 35 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $bitsAllSet: 35 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $bitsAllSet: 35 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $bitsAnyClear: 35 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $bitsAnyClear: 35 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $bitsAnySet: 35 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $bitsAnySet: 35 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - description: "geo operators succeed on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { unencrypted: { $near: [0,0] }} + result: + # Still an error because no geo index, but from mongod - not mongocryptd. + errorContains: "unable to find index" + - name: find + arguments: + filter: { encrypted_string: { $near: [0,0] }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $nearSphere: [0,0] }} + result: + # Still an error because no geo index, but from mongod - not mongocryptd. + errorContains: "unable to find index" + - name: find + arguments: + filter: { encrypted_string: { $nearSphere: [0,0] }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $geoIntersects: { $geometry: { type: "Polygon", coordinates: [[ [0,0], [1,0], [1,1], [0,0] ]] }} }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $geoIntersects: { $geometry: { type: "Polygon", coordinates: [[ [0,0], [1,0], [1,1], [0,0] ]] }} }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [[ [0,0], [1,0], [1,1], [0,0] ]] }} }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [[ [0,0], [1,0], [1,1], [0,0] ]] }} }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - description: "inequality operators succeed on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { unencrypted: { $gt: 1 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $gt: 1 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $lt: 1 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $lt: 1 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $gte: 1 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $gte: 1 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $lte: 1 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $lte: 1 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - description: "other misc operators succeed on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { unencrypted: { $mod: [3, 1] }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $mod: [3, 1] }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $regex: "pattern", $options: "" }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $regex: "pattern", $options: "" }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $size: 2 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $size: 2 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $type: 2 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $type: 2 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $eq: null }} + result: + - &doc0 { _id: 1, encrypted_string: "string0" } + - &doc1 { _id: 2, encrypted_string: "string1" } + - name: find + arguments: + filter: { encrypted_string: { $eq: null }} + result: + errorContains: "Illegal equality to null predicate for encrypted field" + - name: find + arguments: + filter: { unencrypted: { $in: [null] }} + result: + - *doc0 + - *doc1 + - name: find + arguments: + filter: { encrypted_string: { $in: [null] }} + result: + errorContains: "Illegal equality to null inside $in against an encrypted field" + - description: "$addToSet succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $addToSet: { "unencrypted": ["a"]}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $addToSet: { "encrypted_string": ["a"]}} + result: + errorContains: "$addToSet not allowed on encrypted values" + - description: "$inc succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $inc: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $inc: { "encrypted_string": 1}} + result: + errorContains: "$inc and $mul not allowed on encrypted values" + - description: "$mul succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $mul: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $mul: { "encrypted_string": 1}} + result: + errorContains: "$inc and $mul not allowed on encrypted values" + - description: "$max succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $max: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $max: { "encrypted_string": 1}} + result: + errorContains: "$max and $min not allowed on encrypted values" + - description: "$min succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $min: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $min: { "encrypted_string": 1}} + result: + errorContains: "$max and $min not allowed on encrypted values" + - description: "$currentDate succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $currentDate: { "unencrypted": true}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $currentDate: { "encrypted_string": true }} + result: + errorContains: "$currentDate not allowed on encrypted values" + - description: "$pop succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $pop: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 0 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $pop: { "encrypted_string": 1 }} + result: + errorContains: "$pop not allowed on encrypted values" + - description: "$pull succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $pull: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 0 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $pull: { "encrypted_string": 1 }} + result: + errorContains: "$pull not allowed on encrypted values" + - description: "$pullAll succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $pullAll: { "unencrypted": [1] }} + result: + matchedCount: 1 + modifiedCount: 0 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $pullAll: { "encrypted_string": [1] }} + result: + errorContains: "$pullAll not allowed on encrypted values" + - description: "$push succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $push: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $push: { "encrypted_string": 1 }} + result: + errorContains: "$push not allowed on encrypted values" + - description: "array filters on encrypted fields does not error in mongocryptd, but errors in mongod" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $set : { "encrypted_string.$[i].x": 1 }} + arrayFilters: [{ i.x: 1 }] + result: + errorContains: "Array update operations not allowed on encrypted values" + - description: "positional operator succeeds on unencrypted, errors on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { "unencrypted": 1 } + update: { $set : { "unencrypted.$": 1 }} + result: + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { "encrypted_string": "abc" } + update: { $set : { "encrypted_string.$": "abc" }} + result: + errorContains: "Cannot encrypt fields below '$' positional update operator" + - description: "an update that would produce an array on an encrypted field errors" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $set : { "encrypted_string": [1,2] }} + result: + errorContains: "Cannot encrypt element of type array" + - description: "an insert with encrypted field on _id errors" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + schemaMap: + "default.default": {'properties': {'_id': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}} + operations: + - name: insertOne + arguments: + document: { _id: 1 } + result: + errorContains: "Invalid schema containing the 'encrypt' keyword." + - description: "an insert with an array value for an encrypted field fails" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: { encrypted_string: [ "123", "456"] } + result: + errorContains: "Cannot encrypt element of type array" + - description: "an insert with a Timestamp(0,0) value in the top-level fails" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: { random: {"$timestamp": {"t": 0, "i": 0 }} } + result: + errorContains: "A command that inserts cannot supply Timestamp(0, 0) for an encrypted" + - description: "distinct with the key referring to a field where the keyID is a JSON Pointer errors" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: distinct + arguments: + filter: {} + fieldName: "encrypted_w_altname" + result: + errorContains: "The distinct key is not allowed to be marked for encryption with a non-UUID keyId" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/badQueries.yml.template b/test/functional/spec/client-side-encryption/badQueries.yml.template new file mode 100644 index 00000000000..97648fee2c7 --- /dev/null +++ b/test/functional/spec/client-side-encryption/badQueries.yml.template @@ -0,0 +1,538 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - &doc1_encrypted { _id: 2, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +# TODO: I could see an argument against having these tests of mongocryptd as part +# of driver tests. When mongocryptd introduces support for these operators, these +# tests will fail. But it's also easy enough to remove these tests when that happens. + +tests: + - description: "$expr unconditionally fails" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: + { $expr: { $eq: [1, 1] } } + result: + errorContains: "Unsupported match expression operator for encryption" + - description: "$text unconditionally fails" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: + { $text: { $search: "search text" } } + result: + errorContains: "Unsupported match expression operator for encryption" + - description: "$where unconditionally fails" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: + { $where: { $code: "function() { return true }" } } + result: + errorContains: "Unsupported match expression operator for encryption" + - description: "$bit operators succeed on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { unencrypted: { $bitsAllClear: 35 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $bitsAllClear: 35 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $bitsAllSet: 35 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $bitsAllSet: 35 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $bitsAnyClear: 35 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $bitsAnyClear: 35 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $bitsAnySet: 35 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $bitsAnySet: 35 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - description: "geo operators succeed on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { unencrypted: { $near: [0,0] }} + result: + # Still an error because no geo index, but from mongod - not mongocryptd. + errorContains: "unable to find index" + - name: find + arguments: + filter: { encrypted_string: { $near: [0,0] }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $nearSphere: [0,0] }} + result: + # Still an error because no geo index, but from mongod - not mongocryptd. + errorContains: "unable to find index" + - name: find + arguments: + filter: { encrypted_string: { $nearSphere: [0,0] }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $geoIntersects: { $geometry: { type: "Polygon", coordinates: [[ [0,0], [1,0], [1,1], [0,0] ]] }} }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $geoIntersects: { $geometry: { type: "Polygon", coordinates: [[ [0,0], [1,0], [1,1], [0,0] ]] }} }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [[ [0,0], [1,0], [1,1], [0,0] ]] }} }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [[ [0,0], [1,0], [1,1], [0,0] ]] }} }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - description: "inequality operators succeed on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { unencrypted: { $gt: 1 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $gt: 1 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $lt: 1 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $lt: 1 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $gte: 1 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $gte: 1 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $lte: 1 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $lte: 1 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - description: "other misc operators succeed on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { unencrypted: { $mod: [3, 1] }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $mod: [3, 1] }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $regex: "pattern", $options: "" }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $regex: "pattern", $options: "" }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $size: 2 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $size: 2 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $type: 2 }} + result: [] + - name: find + arguments: + filter: { encrypted_string: { $type: 2 }} + result: + errorContains: "Invalid match expression operator on encrypted field" + - name: find + arguments: + filter: { unencrypted: { $eq: null }} + result: + - &doc0 { _id: 1, encrypted_string: "string0" } + - &doc1 { _id: 2, encrypted_string: "string1" } + - name: find + arguments: + filter: { encrypted_string: { $eq: null }} + result: + errorContains: "Illegal equality to null predicate for encrypted field" + - name: find + arguments: + filter: { unencrypted: { $in: [null] }} + result: + - *doc0 + - *doc1 + - name: find + arguments: + filter: { encrypted_string: { $in: [null] }} + result: + errorContains: "Illegal equality to null inside $in against an encrypted field" + - description: "$addToSet succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $addToSet: { "unencrypted": ["a"]}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $addToSet: { "encrypted_string": ["a"]}} + result: + errorContains: "$addToSet not allowed on encrypted values" + - description: "$inc succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $inc: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $inc: { "encrypted_string": 1}} + result: + errorContains: "$inc and $mul not allowed on encrypted values" + - description: "$mul succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $mul: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $mul: { "encrypted_string": 1}} + result: + errorContains: "$inc and $mul not allowed on encrypted values" + - description: "$max succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $max: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $max: { "encrypted_string": 1}} + result: + errorContains: "$max and $min not allowed on encrypted values" + - description: "$min succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $min: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $min: { "encrypted_string": 1}} + result: + errorContains: "$max and $min not allowed on encrypted values" + - description: "$currentDate succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $currentDate: { "unencrypted": true}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $currentDate: { "encrypted_string": true }} + result: + errorContains: "$currentDate not allowed on encrypted values" + - description: "$pop succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $pop: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 0 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $pop: { "encrypted_string": 1 }} + result: + errorContains: "$pop not allowed on encrypted values" + - description: "$pull succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $pull: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 0 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $pull: { "encrypted_string": 1 }} + result: + errorContains: "$pull not allowed on encrypted values" + - description: "$pullAll succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $pullAll: { "unencrypted": [1] }} + result: + matchedCount: 1 + modifiedCount: 0 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $pullAll: { "encrypted_string": [1] }} + result: + errorContains: "$pullAll not allowed on encrypted values" + - description: "$push succeeds on unencrypted, error on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $push: { "unencrypted": 1}} + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { } + update: { $push: { "encrypted_string": 1 }} + result: + errorContains: "$push not allowed on encrypted values" + - description: "array filters on encrypted fields does not error in mongocryptd, but errors in mongod" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $set : { "encrypted_string.$[i].x": 1 }} + arrayFilters: [{ i.x: 1 }] + result: + errorContains: "Array update operations not allowed on encrypted values" + - description: "positional operator succeeds on unencrypted, errors on encrypted" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { "unencrypted": 1 } + update: { $set : { "unencrypted.$": 1 }} + result: + matchedCount: 0 + modifiedCount: 0 + upsertedCount: 0 + - name: updateOne + arguments: + filter: { "encrypted_string": "abc" } + update: { $set : { "encrypted_string.$": "abc" }} + result: + errorContains: "Cannot encrypt fields below '$' positional update operator" + - description: "an update that would produce an array on an encrypted field errors" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $set : { "encrypted_string": [1,2] }} + result: + errorContains: "Cannot encrypt element of type array" + - description: "an insert with encrypted field on _id errors" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + schemaMap: + "default.default": {{schema("encrypted_id")}} + operations: + - name: insertOne + arguments: + document: { _id: 1 } + result: + errorContains: "Invalid schema containing the 'encrypt' keyword." + - description: "an insert with an array value for an encrypted field fails" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: { encrypted_string: [ "123", "456"] } + result: + errorContains: "Cannot encrypt element of type array" + - description: "an insert with a Timestamp(0,0) value in the top-level fails" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: { random: {"$timestamp": {"t": 0, "i": 0 }} } + result: + errorContains: "A command that inserts cannot supply Timestamp(0, 0) for an encrypted" + - description: "distinct with the key referring to a field where the keyID is a JSON Pointer errors" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: distinct + arguments: + filter: {} + fieldName: "encrypted_w_altname" + result: + errorContains: "The distinct key is not allowed to be marked for encryption with a non-UUID keyId" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/badSchema.json b/test/functional/spec/client-side-encryption/badSchema.json new file mode 100644 index 00000000000..6284bdbeee8 --- /dev/null +++ b/test/functional/spec/client-side-encryption/badSchema.json @@ -0,0 +1,254 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [], + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "Schema with an encrypted field in an array", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_string": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" + } + } + }, + "bsonType": "array" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_string": "string0" + } + }, + "result": { + "errorContains": "Invalid schema" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + }, + { + "description": "Schema without specifying parent object types", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "foo": { + "properties": { + "bar": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" + } + } + } + } + } + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_string": "string0" + } + }, + "result": { + "errorContains": "Invalid schema" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + }, + { + "description": "Schema with siblings of encrypt document", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_string": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" + }, + "bsonType": "object" + } + } + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_string": "string0" + } + }, + "result": { + "errorContains": "'encrypt' cannot be used in conjunction with 'bsonType'" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + }, + { + "description": "Schema with logical keywords", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "anyOf": [ + { + "properties": { + "encrypted_string": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" + } + } + } + } + ] + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_string": "string0" + } + }, + "result": { + "errorContains": "Invalid schema" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/badSchema.yml b/test/functional/spec/client-side-encryption/badSchema.yml new file mode 100644 index 00000000000..db67cae8497 --- /dev/null +++ b/test/functional/spec/client-side-encryption/badSchema.yml @@ -0,0 +1,73 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "Schema with an encrypted field in an array" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_string': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'}}}, 'bsonType': 'array'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0" } + result: + errorContains: "Invalid schema" + outcome: + collection: + data: [] + - description: "Schema without specifying parent object types" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'foo': {'properties': {'bar': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'}}}}}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: *doc0 + result: + errorContains: "Invalid schema" + outcome: + collection: + data: [] + - description: "Schema with siblings of encrypt document" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_string': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'}, 'bsonType': 'object'}}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: *doc0 + result: + errorContains: "'encrypt' cannot be used in conjunction with 'bsonType'" + outcome: + collection: + data: [] + - description: "Schema with logical keywords" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'anyOf': [{'properties': {'encrypted_string': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Random'}}}}]} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: *doc0 + result: + errorContains: "Invalid schema" + outcome: + collection: + data: [] \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/badSchema.yml.template b/test/functional/spec/client-side-encryption/badSchema.yml.template new file mode 100644 index 00000000000..e7604243748 --- /dev/null +++ b/test/functional/spec/client-side-encryption/badSchema.yml.template @@ -0,0 +1,73 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +key_vault_data: [{{key()}}] + +tests: + - description: "Schema with an encrypted field in an array" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema('invalid_array')}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0" } + result: + errorContains: "Invalid schema" + outcome: + collection: + data: [] + - description: "Schema without specifying parent object types" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema('invalid_omitted_type')}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: *doc0 + result: + errorContains: "Invalid schema" + outcome: + collection: + data: [] + - description: "Schema with siblings of encrypt document" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema('invalid_siblings')}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: *doc0 + result: + errorContains: "'encrypt' cannot be used in conjunction with 'bsonType'" + outcome: + collection: + data: [] + - description: "Schema with logical keywords" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema('logical_keywords')}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: *doc0 + result: + errorContains: "Invalid schema" + outcome: + collection: + data: [] \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/basic.json b/test/functional/spec/client-side-encryption/basic.json new file mode 100644 index 00000000000..0b13ea14794 --- /dev/null +++ b/test/functional/spec/client-side-encryption/basic.json @@ -0,0 +1,372 @@ +{ + "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-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "Insert with deterministic encryption, then find it", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_string": "string0" + } + } + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + } + }, + "result": [ + { + "_id": 1, + "encrypted_string": "string0" + } + ] + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "_id": 1 + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "Insert with randomized encryption, then find it", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "random": "123" + } + } + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + } + }, + "result": [ + { + "_id": 1, + "random": "123" + } + ] + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "random": { + "$$type": "binData" + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "_id": 1 + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "random": { + "$$type": "binData" + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/basic.yml b/test/functional/spec/client-side-encryption/basic.yml new file mode 100644 index 00000000000..012e37b0733 --- /dev/null +++ b/test/functional/spec/client-side-encryption/basic.yml @@ -0,0 +1,118 @@ +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-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', '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. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0" } + - name: find + arguments: + filter: { _id: 1 } + result: [*doc0] + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: { _id: 1 } + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "Insert with randomized encryption, then find it" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc1 { _id: 1, random: "123" } + - name: find + arguments: + filter: { _id: 1 } + result: [*doc1] + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - { _id: 1, random: { $$type: "binData" } } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: { _id: 1 } + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, random: { $$type: "binData" } } \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/basic.yml.template b/test/functional/spec/client-side-encryption/basic.yml.template new file mode 100644 index 00000000000..3a39cf84985 --- /dev/null +++ b/test/functional/spec/client-side-encryption/basic.yml.template @@ -0,0 +1,118 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "Insert with deterministic encryption, then find it" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0" } + - name: find + arguments: + filter: { _id: 1 } + result: [*doc0] + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: { _id: 1 } + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "Insert with randomized encryption, then find it" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc1 { _id: 1, random: "123" } + - name: find + arguments: + filter: { _id: 1 } + result: [*doc1] + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - { _id: 1, random: { $$type: "binData" } } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: { _id: 1 } + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, random: { $$type: "binData" } } \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/bulk.json b/test/functional/spec/client-side-encryption/bulk.json new file mode 100644 index 00000000000..3f5bdf3b78e --- /dev/null +++ b/test/functional/spec/client-side-encryption/bulk.json @@ -0,0 +1,338 @@ +{ + "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-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "Bulk write with encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_string": "string0", + "random": "abc" + } + } + }, + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2, + "encrypted_string": "string1" + } + } + }, + { + "name": "updateOne", + "arguments": { + "filter": { + "encrypted_string": "string0" + }, + "update": { + "$set": { + "encrypted_string": "string1" + } + } + } + }, + { + "name": "deleteOne", + "arguments": { + "filter": { + "encrypted_string": "string1", + "_id": 2 + } + } + } + ], + "options": { + "ordered": true + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "update": "default", + "updates": [ + { + "q": { + "encrypted_string": { + "$eq": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + }, + "u": { + "$set": { + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + } + } + ], + "ordered": true + }, + "command_name": "update" + } + }, + { + "command_started_event": { + "command": { + "delete": "default", + "deletes": [ + { + "q": { + "$and": [ + { + "encrypted_string": { + "$eq": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + }, + { + "_id": { + "$eq": 2 + } + } + ] + }, + "limit": 1 + } + ], + "ordered": true + }, + "command_name": "delete" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/bulk.yml b/test/functional/spec/client-side-encryption/bulk.yml new file mode 100644 index 00000000000..8d5b42808f4 --- /dev/null +++ b/test/functional/spec/client-side-encryption/bulk.yml @@ -0,0 +1,86 @@ +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-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "Bulk write with encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: bulkWrite + arguments: + requests: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0", random: "abc" } + - name: insertOne + arguments: + document: &doc1 { _id: 2, encrypted_string: "string1" } + - name: updateOne + arguments: + filter: { encrypted_string: "string0" } + update: { $set: { encrypted_string: "string1" } } + - name: deleteOne + arguments: + filter: { encrypted_string: "string1", _id: 2 } + options: { ordered: true } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}}, random: { $$type: "binData" } } + - &doc1_encrypted { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } + ordered: true + command_name: insert + - command_started_event: + command: + update: *collection_name + updates: + - q: { encrypted_string: { $eq: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} }} + u: {$set: { encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} }} + ordered: true + command_name: update + - command_started_event: + command: + delete: *collection_name + deletes: + - q: { "$and": [ { "encrypted_string": { "$eq": {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} }}, { "_id": { "$eq": 2 }} ] } + limit: 1 + ordered: true + command_name: delete + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}}, random: { $$type: "binData" } } \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/bulk.yml.template b/test/functional/spec/client-side-encryption/bulk.yml.template new file mode 100644 index 00000000000..f0cd4a717e2 --- /dev/null +++ b/test/functional/spec/client-side-encryption/bulk.yml.template @@ -0,0 +1,86 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "Bulk write with encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: bulkWrite + arguments: + requests: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0", random: "abc" } + - name: insertOne + arguments: + document: &doc1 { _id: 2, encrypted_string: "string1" } + - name: updateOne + arguments: + filter: { encrypted_string: "string0" } + update: { $set: { encrypted_string: "string1" } } + - name: deleteOne + arguments: + filter: { encrypted_string: "string1", _id: 2 } + options: { ordered: true } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}}, random: { $$type: "binData" } } + - &doc1_encrypted { _id: 2, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } + ordered: true + command_name: insert + - command_started_event: + command: + update: *collection_name + updates: + - q: { encrypted_string: { $eq: {{ciphertext("string0", field="encrypted_string")}} }} + u: {$set: { encrypted_string: {{ciphertext("string1", field="encrypted_string")}} }} + ordered: true + command_name: update + - command_started_event: + command: + delete: *collection_name + deletes: + - q: { "$and": [ { "encrypted_string": { "$eq": {{ciphertext("string1", field="encrypted_string")}} }}, { "_id": { "$eq": 2 }} ] } + limit: 1 + ordered: true + command_name: delete + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {{ciphertext("string1", field="encrypted_string")}}, random: { $$type: "binData" } } diff --git a/test/functional/spec/client-side-encryption/bypassAutoEncryption.json b/test/functional/spec/client-side-encryption/bypassAutoEncryption.json new file mode 100644 index 00000000000..d248a313462 --- /dev/null +++ b/test/functional/spec/client-side-encryption/bypassAutoEncryption.json @@ -0,0 +1,396 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "Insert with bypassAutoEncryption", + "clientOptions": { + "autoEncryptOpts": { + "bypassAutoEncryption": true, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2, + "encrypted_string": "string0" + }, + "bypassDocumentValidation": true + } + }, + { + "name": "find", + "arguments": { + "filter": {} + }, + "result": [ + { + "_id": 1, + "encrypted_string": "string0" + }, + { + "_id": 2, + "encrypted_string": "string0" + } + ] + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 2, + "encrypted_string": "string0" + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": {} + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": "string0" + } + ] + } + } + }, + { + "description": "Insert with bypassAutoEncryption for local schema", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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" + } + }, + "bypassAutoEncryption": true, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 2, + "encrypted_string": "string0" + }, + "bypassDocumentValidation": true + } + }, + { + "name": "find", + "arguments": { + "filter": {} + }, + "result": [ + { + "_id": 1, + "encrypted_string": "string0" + }, + { + "_id": 2, + "encrypted_string": "string0" + } + ] + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 2, + "encrypted_string": "string0" + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": {} + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": "string0" + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/bypassAutoEncryption.yml b/test/functional/spec/client-side-encryption/bypassAutoEncryption.yml new file mode 100644 index 00000000000..aa8fb27e07d --- /dev/null +++ b/test/functional/spec/client-side-encryption/bypassAutoEncryption.yml @@ -0,0 +1,98 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [{_id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} }] +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "Insert with bypassAutoEncryption" + clientOptions: + autoEncryptOpts: + bypassAutoEncryption: true + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: { _id: 2, encrypted_string: "string0" } + bypassDocumentValidation: true + - name: find + arguments: + filter: { } + result: + - { _id: 1, encrypted_string: "string0" } + - { _id: 2, encrypted_string: "string0" } + expectations: + - command_started_event: + command: + insert: *collection_name + documents: + # No encryption. + - { _id: 2, encrypted_string: "string0" } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: { } + command_name: find + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - { _id: 2, encrypted_string: "string0" } + - description: "Insert with bypassAutoEncryption for local schema" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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'} + bypassAutoEncryption: true + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: { _id: 2, encrypted_string: "string0" } + bypassDocumentValidation: true + - name: find + arguments: + filter: { } + result: + - { _id: 1, encrypted_string: "string0" } + - { _id: 2, encrypted_string: "string0" } + expectations: + - command_started_event: + command: + insert: *collection_name + documents: + # No encryption. + - { _id: 2, encrypted_string: "string0" } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: { } + command_name: find + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - { _id: 2, encrypted_string: "string0" } \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/bypassAutoEncryption.yml.template b/test/functional/spec/client-side-encryption/bypassAutoEncryption.yml.template new file mode 100644 index 00000000000..17b35023c6d --- /dev/null +++ b/test/functional/spec/client-side-encryption/bypassAutoEncryption.yml.template @@ -0,0 +1,98 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [{_id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} }] +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "Insert with bypassAutoEncryption" + clientOptions: + autoEncryptOpts: + bypassAutoEncryption: true + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: { _id: 2, encrypted_string: "string0" } + bypassDocumentValidation: true + - name: find + arguments: + filter: { } + result: + - { _id: 1, encrypted_string: "string0" } + - { _id: 2, encrypted_string: "string0" } + expectations: + - command_started_event: + command: + insert: *collection_name + documents: + # No encryption. + - { _id: 2, encrypted_string: "string0" } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: { } + command_name: find + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - { _id: 2, encrypted_string: "string0" } + - description: "Insert with bypassAutoEncryption for local schema" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{ schema() }} + bypassAutoEncryption: true + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: { _id: 2, encrypted_string: "string0" } + bypassDocumentValidation: true + - name: find + arguments: + filter: { } + result: + - { _id: 1, encrypted_string: "string0" } + - { _id: 2, encrypted_string: "string0" } + expectations: + - command_started_event: + command: + insert: *collection_name + documents: + # No encryption. + - { _id: 2, encrypted_string: "string0" } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: { } + command_name: find + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - { _id: 2, encrypted_string: "string0" } \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/bypassedCommand.json b/test/functional/spec/client-side-encryption/bypassedCommand.json new file mode 100644 index 00000000000..6f7fdd9762e --- /dev/null +++ b/test/functional/spec/client-side-encryption/bypassedCommand.json @@ -0,0 +1,81 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [], + "json_schema": {}, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "ping is bypassed", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "runCommand", + "object": "database", + "command_name": "ping", + "arguments": { + "command": { + "ping": 1 + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "ping": 1 + }, + "command_name": "ping" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/bypassedCommand.yml b/test/functional/spec/client-side-encryption/bypassedCommand.yml new file mode 100644 index 00000000000..d92eac2bba8 --- /dev/null +++ b/test/functional/spec/client-side-encryption/bypassedCommand.yml @@ -0,0 +1,28 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +json_schema: {} +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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "ping is bypassed" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: runCommand + object: database + command_name: ping + arguments: + command: + ping: 1 + expectations: + # No listCollections, no mongocryptd command, just the ping. + - command_started_event: + command: + ping: 1 + command_name: ping \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/bypassedCommand.yml.template b/test/functional/spec/client-side-encryption/bypassedCommand.yml.template new file mode 100644 index 00000000000..3f47a431d05 --- /dev/null +++ b/test/functional/spec/client-side-encryption/bypassedCommand.yml.template @@ -0,0 +1,28 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +json_schema: {} +key_vault_data: [{{key()}}] + +tests: + - description: "ping is bypassed" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: runCommand + object: database + command_name: ping + arguments: + command: + ping: 1 + expectations: + # No listCollections, no mongocryptd command, just the ping. + - command_started_event: + command: + ping: 1 + command_name: ping \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/count.json b/test/functional/spec/client-side-encryption/count.json new file mode 100644 index 00000000000..a93229b10b5 --- /dev/null +++ b/test/functional/spec/client-side-encryption/count.json @@ -0,0 +1,240 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "Count with deterministic encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "count", + "arguments": { + "filter": { + "encrypted_string": "string0" + } + }, + "result": 2 + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "count": "default", + "query": { + "encrypted_string": { + "$eq": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + } + }, + "command_name": "count" + } + } + ] + }, + { + "description": "Count fails when filtering on a random encrypted field", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "count", + "arguments": { + "filter": { + "random": "abc" + } + }, + "result": { + "errorContains": "Cannot query on fields encrypted with the randomized encryption" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/count.yml b/test/functional/spec/client-side-encryption/count.yml new file mode 100644 index 00000000000..bdd50cb2091 --- /dev/null +++ b/test/functional/spec/client-side-encryption/count.yml @@ -0,0 +1,62 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - &doc1_encrypted { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "Count with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: count + arguments: + filter: { encrypted_string: "string0" } + result: 2 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + count: *collection_name + query: { encrypted_string: { $eq: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } } + command_name: count + - description: "Count fails when filtering on a random encrypted field" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment + operations: + - name: count + arguments: + filter: { random: "abc" } + result: + errorContains: "Cannot query on fields encrypted with the randomized encryption" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/count.yml.template b/test/functional/spec/client-side-encryption/count.yml.template new file mode 100644 index 00000000000..e4be281a81c --- /dev/null +++ b/test/functional/spec/client-side-encryption/count.yml.template @@ -0,0 +1,62 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - &doc1_encrypted { _id: 2, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "Count with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: count + arguments: + filter: { encrypted_string: "string0" } + result: 2 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + count: *collection_name + query: { encrypted_string: { $eq: {{ciphertext("string0", field="encrypted_string")}} } } + command_name: count + - description: "Count fails when filtering on a random encrypted field" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment + operations: + - name: count + arguments: + filter: { random: "abc" } + result: + errorContains: "Cannot query on fields encrypted with the randomized encryption" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/countDocuments.json b/test/functional/spec/client-side-encryption/countDocuments.json new file mode 100644 index 00000000000..3608d519079 --- /dev/null +++ b/test/functional/spec/client-side-encryption/countDocuments.json @@ -0,0 +1,252 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "countDocuments with deterministic encryption", + "skipReason": "waiting on SERVER-39395", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "countDocuments", + "arguments": { + "filter": { + "encrypted_string": "string0" + } + }, + "result": 1 + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "aggregate": "default", + "pipeline": [ + { + "$match": { + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + }, + { + "$group": { + "_id": 1, + "n": { + "$sum": 1 + } + } + } + ] + }, + "command_name": "aggregate" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/countDocuments.yml b/test/functional/spec/client-side-encryption/countDocuments.yml new file mode 100644 index 00000000000..d9f11c90e95 --- /dev/null +++ b/test/functional/spec/client-side-encryption/countDocuments.yml @@ -0,0 +1,60 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - &doc1_encrypted { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "countDocuments with deterministic encryption" + skipReason: "waiting on SERVER-39395" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: countDocuments + arguments: + filter: { encrypted_string: "string0" } + result: 1 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + aggregate: *collection_name + pipeline: + - { $match: { encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} }} + - { $group: { _id: 1, n: { $sum: 1 }}} + command_name: aggregate + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/countDocuments.yml.template b/test/functional/spec/client-side-encryption/countDocuments.yml.template new file mode 100644 index 00000000000..44c03089693 --- /dev/null +++ b/test/functional/spec/client-side-encryption/countDocuments.yml.template @@ -0,0 +1,60 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - &doc1_encrypted { _id: 2, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "countDocuments with deterministic encryption" + skipReason: "waiting on SERVER-39395" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: countDocuments + arguments: + filter: { encrypted_string: "string0" } + result: 1 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + aggregate: *collection_name + pipeline: + - { $match: { encrypted_string: {{ciphertext("string0", field="encrypted_string")}} }} + - { $group: { _id: 1, n: { $sum: 1 }}} + command_name: aggregate + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/delete.json b/test/functional/spec/client-side-encryption/delete.json new file mode 100644 index 00000000000..6e722c219ba --- /dev/null +++ b/test/functional/spec/client-side-encryption/delete.json @@ -0,0 +1,362 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "deleteOne with deterministic encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "deleteOne", + "arguments": { + "filter": { + "encrypted_string": "string0" + } + }, + "result": { + "deletedCount": 1 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "delete": "default", + "deletes": [ + { + "q": { + "encrypted_string": { + "$eq": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + }, + "limit": 1 + } + ], + "ordered": true + }, + "command_name": "delete" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "deleteMany with deterministic encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "deleteMany", + "arguments": { + "filter": { + "encrypted_string": { + "$in": [ + "string0", + "string1" + ] + } + } + }, + "result": { + "deletedCount": 2 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "delete": "default", + "deletes": [ + { + "q": { + "encrypted_string": { + "$in": [ + { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + }, + { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + ] + } + }, + "limit": 0 + } + ], + "ordered": true + }, + "command_name": "delete" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/delete.yml b/test/functional/spec/client-side-encryption/delete.yml new file mode 100644 index 00000000000..43d7830de7c --- /dev/null +++ b/test/functional/spec/client-side-encryption/delete.yml @@ -0,0 +1,107 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - &doc1_encrypted { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "deleteOne with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: deleteOne + arguments: + filter: { encrypted_string: "string0" } + result: + deletedCount: 1 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + delete: *collection_name + deletes: + - q: { encrypted_string: { $eq: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } } + limit: 1 + ordered: true + command_name: delete + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc1_encrypted + - description: "deleteMany with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: deleteMany + arguments: + filter: { encrypted_string: { $in: [ "string0", "string1" ] } } + result: + deletedCount: 2 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + delete: *collection_name + deletes: + - q: { encrypted_string: { $in : [ {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}}, {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} ] } } + limit: 0 + ordered: true + command_name: delete + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: [] \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/delete.yml.template b/test/functional/spec/client-side-encryption/delete.yml.template new file mode 100644 index 00000000000..10084a0e250 --- /dev/null +++ b/test/functional/spec/client-side-encryption/delete.yml.template @@ -0,0 +1,107 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - &doc1_encrypted { _id: 2, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "deleteOne with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: deleteOne + arguments: + filter: { encrypted_string: "string0" } + result: + deletedCount: 1 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + delete: *collection_name + deletes: + - q: { encrypted_string: { $eq: {{ciphertext("string0", field="encrypted_string")}} } } + limit: 1 + ordered: true + command_name: delete + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc1_encrypted + - description: "deleteMany with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: deleteMany + arguments: + filter: { encrypted_string: { $in: [ "string0", "string1" ] } } + result: + deletedCount: 2 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + delete: *collection_name + deletes: + - q: { encrypted_string: { $in : [ {{ciphertext("string0", field="encrypted_string")}}, {{ciphertext("string1", field="encrypted_string")}} ] } } + limit: 0 + ordered: true + command_name: delete + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: [] \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/distinct.json b/test/functional/spec/client-side-encryption/distinct.json new file mode 100644 index 00000000000..5ac3e3df11c --- /dev/null +++ b/test/functional/spec/client-side-encryption/distinct.json @@ -0,0 +1,287 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 3, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "distinct with deterministic encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "distinct", + "arguments": { + "filter": { + "encrypted_string": "string0" + }, + "fieldName": "encrypted_string" + }, + "result": [ + "string0" + ] + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "distinct": "default", + "key": "encrypted_string", + "query": { + "encrypted_string": { + "$eq": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + } + }, + "command_name": "distinct" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 3, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "Distinct fails when filtering on a random encrypted field", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "distinct", + "arguments": { + "filter": { + "random": "abc" + }, + "fieldName": "encrypted_string" + }, + "result": { + "errorContains": "Cannot query on fields encrypted with the randomized encryption" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/distinct.yml b/test/functional/spec/client-side-encryption/distinct.yml new file mode 100644 index 00000000000..ec032ccd265 --- /dev/null +++ b/test/functional/spec/client-side-encryption/distinct.yml @@ -0,0 +1,74 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - &doc1_encrypted { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - &doc2_encrypted { _id: 3, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "distinct with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: distinct + arguments: + filter: { encrypted_string: "string0" } + fieldName: "encrypted_string" + result: + - "string0" + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + distinct: *collection_name + key: encrypted_string + query: { encrypted_string: {$eq: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } } + command_name: distinct + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted + - *doc2_encrypted + - description: "Distinct fails when filtering on a random encrypted field" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment + operations: + - name: distinct + arguments: + filter: { random: "abc" } + fieldName: "encrypted_string" + result: + errorContains: "Cannot query on fields encrypted with the randomized encryption" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/distinct.yml.template b/test/functional/spec/client-side-encryption/distinct.yml.template new file mode 100644 index 00000000000..ea1e0b13a11 --- /dev/null +++ b/test/functional/spec/client-side-encryption/distinct.yml.template @@ -0,0 +1,74 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - &doc1_encrypted { _id: 2, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - &doc2_encrypted { _id: 3, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "distinct with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: distinct + arguments: + filter: { encrypted_string: "string0" } + fieldName: "encrypted_string" + result: + - "string0" + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + distinct: *collection_name + key: encrypted_string + query: { encrypted_string: {$eq: {{ciphertext("string0", field="encrypted_string")}} } } + command_name: distinct + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted + - *doc2_encrypted + - description: "Distinct fails when filtering on a random encrypted field" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment + operations: + - name: distinct + arguments: + filter: { random: "abc" } + fieldName: "encrypted_string" + result: + errorContains: "Cannot query on fields encrypted with the randomized encryption" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/explain.json b/test/functional/spec/client-side-encryption/explain.json new file mode 100644 index 00000000000..ec7baf5913a --- /dev/null +++ b/test/functional/spec/client-side-encryption/explain.json @@ -0,0 +1,250 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "Explain a find with deterministic encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "runCommand", + "object": "database", + "command_name": "explain", + "arguments": { + "command": { + "explain": { + "find": "default", + "filter": { + "encrypted_string": "string1" + } + } + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "explain": { + "find": "default", + "filter": { + "encrypted_string": { + "$eq": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + } + }, + "verbosity": "allPlansExecution" + }, + "command_name": "explain" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/explain.yml b/test/functional/spec/client-side-encryption/explain.yml new file mode 100644 index 00000000000..c6428ff4f6f --- /dev/null +++ b/test/functional/spec/client-side-encryption/explain.yml @@ -0,0 +1,65 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - &doc1_encrypted { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "Explain a find with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: runCommand + object: database + command_name: explain + arguments: + command: + explain: + find: *collection_name + filter: { encrypted_string : "string1" } + + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + explain: + find: *collection_name + filter: + { encrypted_string: { $eq: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } } + verbosity: "allPlansExecution" + command_name: explain + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/explain.yml.template b/test/functional/spec/client-side-encryption/explain.yml.template new file mode 100644 index 00000000000..731a4a7e0cc --- /dev/null +++ b/test/functional/spec/client-side-encryption/explain.yml.template @@ -0,0 +1,65 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - &doc1_encrypted { _id: 2, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "Explain a find with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: runCommand + object: database + command_name: explain + arguments: + command: + explain: + find: *collection_name + filter: { encrypted_string : "string1" } + + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + explain: + find: *collection_name + filter: + { encrypted_string: { $eq: {{ciphertext("string1", field="encrypted_string")}} } } + verbosity: "allPlansExecution" + command_name: explain + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/find.json b/test/functional/spec/client-side-encryption/find.json new file mode 100644 index 00000000000..98959cbdb28 --- /dev/null +++ b/test/functional/spec/client-side-encryption/find.json @@ -0,0 +1,411 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "Find with deterministic encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": "string0" + } + }, + "result": [ + { + "_id": 1, + "encrypted_string": "string0" + } + ] + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "encrypted_string": { + "$eq": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "Find with $in with deterministic encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "filter": { + "encrypted_string": { + "$in": [ + "string0", + "string1" + ] + } + } + }, + "result": [ + { + "_id": 1, + "encrypted_string": "string0" + }, + { + "_id": 2, + "encrypted_string": "string1" + } + ] + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "encrypted_string": { + "$in": [ + { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + }, + { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + ] + } + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "Find fails when filtering on a random encrypted field", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "filter": { + "random": "abc" + } + }, + "result": { + "errorContains": "Cannot query on fields encrypted with the randomized encryption" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/find.yml b/test/functional/spec/client-side-encryption/find.yml new file mode 100644 index 00000000000..453365b8c0b --- /dev/null +++ b/test/functional/spec/client-side-encryption/find.yml @@ -0,0 +1,121 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - &doc1_encrypted { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "Find with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: + { encrypted_string: "string0" } + result: + - &doc0 { _id: 1, encrypted_string: "string0" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + find: *collection_name + filter: + { encrypted_string: { $eq: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } } + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted + - description: "Find with $in with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: + { encrypted_string: { $in: [ "string0", "string1" ] } } + result: + - { _id: 1, encrypted_string: "string0" } + - &doc1 { _id: 2, encrypted_string: "string1" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + find: *collection_name + filter: + # Note, the values are re-ordered, but this is logically equivalent. + { encrypted_string: { $in: [ {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}}, {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} ] } } + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted + - description: "Find fails when filtering on a random encrypted field" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment + operations: + - name: find + arguments: + filter: { random: "abc" } + result: + errorContains: "Cannot query on fields encrypted with the randomized encryption" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/find.yml.template b/test/functional/spec/client-side-encryption/find.yml.template new file mode 100644 index 00000000000..b1e16922638 --- /dev/null +++ b/test/functional/spec/client-side-encryption/find.yml.template @@ -0,0 +1,121 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - &doc1_encrypted { _id: 2, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "Find with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: + { encrypted_string: "string0" } + result: + - &doc0 { _id: 1, encrypted_string: "string0" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + find: *collection_name + filter: + { encrypted_string: { $eq: {{ciphertext("string0", field="encrypted_string")}} } } + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted + - description: "Find with $in with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: + { encrypted_string: { $in: [ "string0", "string1" ] } } + result: + - { _id: 1, encrypted_string: "string0" } + - &doc1 { _id: 2, encrypted_string: "string1" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + find: *collection_name + filter: + # Note, the values are re-ordered, but this is logically equivalent. + { encrypted_string: { $in: [ {{ciphertext("string0", field="encrypted_string")}}, {{ciphertext("string1", field="encrypted_string")}} ] } } + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted + - description: "Find fails when filtering on a random encrypted field" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment + operations: + - name: find + arguments: + filter: { random: "abc" } + result: + errorContains: "Cannot query on fields encrypted with the randomized encryption" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/findOneAndDelete.json b/test/functional/spec/client-side-encryption/findOneAndDelete.json new file mode 100644 index 00000000000..15c01451fad --- /dev/null +++ b/test/functional/spec/client-side-encryption/findOneAndDelete.json @@ -0,0 +1,232 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "findOneAndDelete with deterministic encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "findOneAndDelete", + "arguments": { + "filter": { + "encrypted_string": "string0" + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "findAndModify": "default", + "query": { + "encrypted_string": { + "$eq": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + }, + "remove": true + }, + "command_name": "findAndModify" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/findOneAndDelete.yml b/test/functional/spec/client-side-encryption/findOneAndDelete.yml new file mode 100644 index 00000000000..5a27a61cc4a --- /dev/null +++ b/test/functional/spec/client-side-encryption/findOneAndDelete.yml @@ -0,0 +1,58 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - &doc1_encrypted { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "findOneAndDelete with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: findOneAndDelete + arguments: + filter: + { encrypted_string: "string0" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + findAndModify: *collection_name + query: + { encrypted_string: { $eq: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } } + remove: true + command_name: findAndModify + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc1_encrypted \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/findOneAndDelete.yml.template b/test/functional/spec/client-side-encryption/findOneAndDelete.yml.template new file mode 100644 index 00000000000..b2c8ee604be --- /dev/null +++ b/test/functional/spec/client-side-encryption/findOneAndDelete.yml.template @@ -0,0 +1,58 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - &doc1_encrypted { _id: 2, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "findOneAndDelete with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: findOneAndDelete + arguments: + filter: + { encrypted_string: "string0" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + findAndModify: *collection_name + query: + { encrypted_string: { $eq: {{ciphertext("string0", field="encrypted_string")}} } } + remove: true + command_name: findAndModify + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc1_encrypted \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/findOneAndReplace.json b/test/functional/spec/client-side-encryption/findOneAndReplace.json new file mode 100644 index 00000000000..5f23a999b96 --- /dev/null +++ b/test/functional/spec/client-side-encryption/findOneAndReplace.json @@ -0,0 +1,238 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "findOneAndReplace with deterministic encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "findOneAndReplace", + "arguments": { + "filter": { + "encrypted_string": "string0" + }, + "replacement": { + "encrypted_string": "string1" + }, + "returnDocument": "Before" + }, + "result": { + "_id": 1, + "encrypted_string": "string0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "findAndModify": "default", + "query": { + "encrypted_string": { + "$eq": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + }, + "update": { + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + }, + "command_name": "findAndModify" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/findOneAndReplace.yml b/test/functional/spec/client-side-encryption/findOneAndReplace.yml new file mode 100644 index 00000000000..7c2b80fee31 --- /dev/null +++ b/test/functional/spec/client-side-encryption/findOneAndReplace.yml @@ -0,0 +1,58 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "findOneAndReplace with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: findOneAndReplace + arguments: + filter: { encrypted_string: "string0" } + replacement: { encrypted_string: "string1" } + returnDocument: Before + result: { _id: 1, encrypted_string: "string0" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + findAndModify: *collection_name + query: { encrypted_string: { $eq: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } } + update: { encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } + command_name: findAndModify + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/findOneAndReplace.yml.template b/test/functional/spec/client-side-encryption/findOneAndReplace.yml.template new file mode 100644 index 00000000000..dc8d185d148 --- /dev/null +++ b/test/functional/spec/client-side-encryption/findOneAndReplace.yml.template @@ -0,0 +1,58 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "findOneAndReplace with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: findOneAndReplace + arguments: + filter: { encrypted_string: "string0" } + replacement: { encrypted_string: "string1" } + returnDocument: Before + result: { _id: 1, encrypted_string: "string0" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + findAndModify: *collection_name + query: { encrypted_string: { $eq: {{ciphertext("string0", field="encrypted_string")}} } } + update: { encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } + command_name: findAndModify + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/findOneAndUpdate.json b/test/functional/spec/client-side-encryption/findOneAndUpdate.json new file mode 100644 index 00000000000..45ee35ebb6d --- /dev/null +++ b/test/functional/spec/client-side-encryption/findOneAndUpdate.json @@ -0,0 +1,242 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "findOneAndUpdate with deterministic encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "findOneAndUpdate", + "arguments": { + "filter": { + "encrypted_string": "string0" + }, + "update": { + "$set": { + "encrypted_string": "string1" + } + }, + "returnDocument": "Before" + }, + "result": { + "_id": 1, + "encrypted_string": "string0" + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "findAndModify": "default", + "query": { + "encrypted_string": { + "$eq": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + }, + "update": { + "$set": { + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + } + }, + "command_name": "findAndModify" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/findOneAndUpdate.yml b/test/functional/spec/client-side-encryption/findOneAndUpdate.yml new file mode 100644 index 00000000000..57ad75b27ec --- /dev/null +++ b/test/functional/spec/client-side-encryption/findOneAndUpdate.yml @@ -0,0 +1,58 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "findOneAndUpdate with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: findOneAndUpdate + arguments: + filter: { encrypted_string: "string0" } + update: { $set: { encrypted_string: "string1" } } + returnDocument: Before + result: { _id: 1, encrypted_string: "string0" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + findAndModify: *collection_name + query: { encrypted_string: { $eq: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } } + update: { $set: { encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } } + command_name: findAndModify + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/findOneAndUpdate.yml.template b/test/functional/spec/client-side-encryption/findOneAndUpdate.yml.template new file mode 100644 index 00000000000..f70a83aeeed --- /dev/null +++ b/test/functional/spec/client-side-encryption/findOneAndUpdate.yml.template @@ -0,0 +1,58 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "findOneAndUpdate with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: findOneAndUpdate + arguments: + filter: { encrypted_string: "string0" } + update: { $set: { encrypted_string: "string1" } } + returnDocument: Before + result: { _id: 1, encrypted_string: "string0" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + findAndModify: *collection_name + query: { encrypted_string: { $eq: {{ciphertext("string0", field="encrypted_string")}} } } + update: { $set: { encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } } + command_name: findAndModify + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/generate.py b/test/functional/spec/client-side-encryption/generate.py new file mode 100644 index 00000000000..62c13cecce8 --- /dev/null +++ b/test/functional/spec/client-side-encryption/generate.py @@ -0,0 +1,432 @@ +from bson import json_util +import bson +import os +import sys +import json +import yaml +from jinja2 import Template +description = """Generates YAML/JSON tests from a template file. + +This keeps key documents, JSONSchemas, and ciphertexts out of the +handwritten test files to make them more readable and easier +to change. +""" + + +if sys.version_info < (3, 0): + print("Use Python 3") + sys.exit(1) + +if len(sys.argv) != 2: + print(description) + print("usage: python generate.py /path/to/.yml.template") + sys.exit(1) + +filepath = sys.argv[1] +filedir = os.path.dirname(filepath) +(filename, ext) = os.path.splitext(os.path.basename(filepath)) +if ext != ".template": + print("Input file must end with .yml.template") + sys.exit(1) +(filename, ext) = os.path.splitext(filename) +if ext != ".yml": + print("Input file must end with .yml.template") + sys.exit(1) + +master_keys = { + "aws": { + "provider": "aws", + "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", + "region": "us-east-1" + }, + "local": {} +} + +keys = { + "basic": { + "status": 1, + "_id": { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + }, + "masterKey": master_keys["aws"], + "updateDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyMaterial": { + "$binary": { + "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": ["altname", "another_altname"] + }, + "local": { + "_id": { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + }, + "keyMaterial": { + "$binary": { + "base64": "db27rshiqK4Jqhb2xnwK4RfdFb9JuKeUe6xt5aYQF4o62tS75b7B4wxVN499gND9UVLUbpVKoyUoaZAeA895OENP335b8n8OwchcTFqS44t+P3zmhteYUQLIWQXaIgon7gEgLeJbaDHmSXS6/7NbfDDFlB37N7BP/2hx1yCOTN6NG/8M1ppw3LYT3CfP6EfXVEttDYtPbJpbb7nBVlxD7w==", + "subType": "00" + } + }, + "creationDate": {"$date": {"$numberLong": "1232739599082000"}}, + "updateDate": {"$date": {"$numberLong": "1232739599082000"}}, + "status": {"$numberInt": "0"}, + "masterKey": {"provider": "local"} + } +} + +schemas = { + "basic": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "encrypted_string": { + "encrypt": { + "keyId": [keys["basic"]["_id"]], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "random": { + "encrypt": { + "keyId": [keys["basic"]["_id"]], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", + } + }, + # Same exact as fields as "encrypted_string" + "encrypted_string_equivalent": { + "encrypt": { + "keyId": [keys["basic"]["_id"]], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + }, + "encrypted_id": { + "properties": { + "_id": { + "encrypt": { + "keyId": [keys["basic"]["_id"]], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + } + }, + "local": { + "properties": { + "encrypted_string": { + "encrypt": { + "keyId": [keys["local"]["_id"]], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "random": { + "encrypt": { + "keyId": [keys["local"]["_id"]], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", + } + } + }, + "bsonType": "object" + }, + "invalid_array": { + "properties": { + "encrypted_string": { + "encrypt": { + "keyId": [keys["basic"]["_id"]], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" + } + } + }, + "bsonType": "array" + }, + "invalid_omitted_type": { + "properties": { + "foo": { + "properties": { + "bar": { + "encrypt": { + "keyId": [keys["basic"]["_id"]], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" + } + } + } + } + } + }, + "invalid_siblings": { + "properties": { + "encrypted_string": { + "encrypt": { + "keyId": [keys["basic"]["_id"]], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" + }, + "bsonType": "object" + } + } + }, + "logical_keywords": { + "anyOf": [ + { + "properties": { + "encrypted_string": { + "encrypt": { + "keyId": [keys["basic"]["_id"]], + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" + } + } + } + } + ] + }, + "noencryption": { + "properties": { + "test": { + "bsonType": "string" + } + }, + "bsonType": "object", + "required": ["test"] + }, +} + +ciphertexts = [ + { + "schema": "basic", + "field": "encrypted_string", + "plaintext": "string0", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "schema": "basic", + "field": "encrypted_string", + "plaintext": "string1", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + }, + { + "schema": "basic", + "field": "encrypted_string", + "plaintext": "string2", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACKScltsm9Kw6AsyC/GQ8HZosvXZkixhFqNimPmzaSKu1b0IdTubAjsEG3TAxL5aTsQfT5mtr63hvvXpjMef8jzQ==", + "subType": "06" + } + } + }, + { + "schema": "local", + "field": "encrypted_string", + "plaintext": "string0", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACKWM29kOcLsfSLfJJ3SSmLr+wgrTtpu1lads1NzDz80AjMyrstw/GMdCuzX+AS+JS84Si2cT1WPMemTkBdVdGAw==", + "subType": "06" + } + } + }, + { + "schema": "basic", + "field": "encrypted_objectId", + "plaintext": "test", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAHIwWYUBoGNSA7MnAqobBNVYee0mqtNZF1AQiTvXkR1B9a6XXEJR32Ttbbe2PLR/us/dmcne84BEYSq8h+j26lIA==", + "subType": "06" + } + } + }, + { + "schema": "basic", + "field": "encrypted_symbol", + "plaintext": "test", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAOEpZwd/k1BQjT1owTq9NgQAoANKKQFbpfwDllEyFxjehyN/pTt1Rav51OAgbA5Bgg90Zpcvd0kHhA/S40bHZxXw==", + "subType": "06" + } + } + }, + { + "schema": "basic", + "field": "encrypted_int32", + "plaintext": "test", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAQWPxV7BQ88Q5vW9HnPheOJyN29G/M7hhnCFmKL4oa+yzSPJhy4Xyxdbn4U80RXvDQMNz03ij5zbXFgrLz8BJIpg==", + "subType": "06" + } + } + }, + { + "schema": "basic", + "field": "encrypted_int64", + "plaintext": "test", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAASHSS/JTyJK5d4CErUaVyI4F/Tl00a6J7KdTfgzXQKGhxKVupFpaanbuEvMOUiMbQfaWD4kv+uHrJxdm1Oyl46cg==", + "subType": "06" + } + } + }, + { + "schema": "basic", + "field": "encrypted_binData", + "plaintext": "test", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAF22b7ESSyoBVv1Igu5PRd0Ya/WZ4QPWzB1D/HZ4dmA/Zl7+FunNK5jnG2AjYxfdijpskLfjFSclvuolPwTiTrig==", + "subType": "06" + } + } + }, + { + "schema": "basic", + "field": "encrypted_javascript", + "plaintext": "test", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAANRHRbeR9tKL4SzZmgcMZXiGNBk/Kb7CKG72rAnwywbq45V3Upy2kK9royiRQR9Gwqm/3Idw5U86Zp/kXdQuzXng==", + "subType": "06" + } + } + }, + { + "schema": "basic", + "field": "encrypted_timestamp", + "plaintext": "test", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAARlcbjVBI9YtvKM/ZuonWoF3mXV9C8LuYRNh0CM9nKjkmAMoIZTtqfhWM78hS1UORnUwcnZT+YuuO3QjuVDy8Esw==", + "subType": "06" + } + } + }, + { + "schema": "basic", + "field": "encrypted_regex", + "plaintext": "test", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAALsSf4Z6nvjeVO7+AXjuYYamWMg/z8+W1HYdOaZfWuH24sCKSc1hvFm72acUJx77mTzQ8Ap94rzYMk1/FF7wbB/A==", + "subType": "06" + } + } + }, + { + "schema": "basic", + "field": "encrypted_dbPointer", + "plaintext": "test", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAMowf5nUEkdLoNHUa+xRaBpKZItT4x+u/29ZESu+jQoCcA/V42/nev8UVBnVNfEpQPos39HeuwieVBeK02V8iqDZEbWXWmzRKNw3YNU6GZafw=", + "subType": "06" + } + } + }, + { + "schema": "basic", + "field": "encrypted_date", + "plaintext": "test", + "data": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAJipr5TW6wma9Z0Xa90u+w4hcRLeEE99BNy45oyzM07NaO42g5lLzbqyIkSO1q3dIbqIHd1hJ4s3a53bUjrh+2lQ==", + "subType": "06" + } + } + } +] + + +def schema(name="basic"): + return schemas[name] + + +def schema_w_type(type): + schema = { + "properties": {}, + "bsonType": "object" + } + schema["properties"]["encrypted_" + type] = {"encrypt": { + "keyId": [keys["basic"]["_id"]], + "bsonType": type, + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + return schema + + +def key(name="basic"): + return keys[name] + + +def ciphertext(plaintext, field, schema="basic"): + for ciphertext in ciphertexts: + if schema == ciphertext["schema"] and field == ciphertext["field"] and plaintext == ciphertext["plaintext"]: + return ciphertext["data"] + raise Exception("Ciphertext needs to be pre-generated") + + +def local_provider(): + return { + "key": {"$binary": {"base64": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "subType": "00"}} + } + + +template = Template(open(filepath, "r").read()) +injections = { + "schema": schema, + "ciphertext": ciphertext, + "key": key, + "local_provider": local_provider, + "schema_w_type": schema_w_type +} + +rendered = template.render(**injections) +# check for valid YAML. +parsed = yaml.load(rendered) +# print as JSON. +as_json = json.dumps(parsed, indent=4) +open(f"{os.path.join(filedir,filename + '.yml')}", "w").write(rendered) +open(f"{os.path.join(filedir,filename + '.json')}", "w").write(as_json) +print(f"Generated {os.path.join(filedir,filename)}.yml|json") diff --git a/test/functional/spec/client-side-encryption/getMore.json b/test/functional/spec/client-side-encryption/getMore.json new file mode 100644 index 00000000000..fe1e3e98d19 --- /dev/null +++ b/test/functional/spec/client-side-encryption/getMore.json @@ -0,0 +1,274 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + }, + { + "_id": 3, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACKScltsm9Kw6AsyC/GQ8HZosvXZkixhFqNimPmzaSKu1b0IdTubAjsEG3TAxL5aTsQfT5mtr63hvvXpjMef8jzQ==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "getMore with encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "batchSize": 2, + "filter": {} + }, + "results": [ + { + "_id": 1, + "encrypted_string": "string0" + }, + { + "_id": 2, + "encrypted_string": "string1" + }, + { + "_id": 3, + "encrypted_string": "string2" + } + ] + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "batchSize": 2 + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "getMore": { + "$$type": "long" + }, + "collection": "default", + "batchSize": 2 + }, + "command_name": "getMore" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + }, + { + "_id": 3, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACKScltsm9Kw6AsyC/GQ8HZosvXZkixhFqNimPmzaSKu1b0IdTubAjsEG3TAxL5aTsQfT5mtr63hvvXpjMef8jzQ==", + "subType": "06" + } + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/getMore.yml b/test/functional/spec/client-side-encryption/getMore.yml new file mode 100644 index 00000000000..3d19f35a507 --- /dev/null +++ b/test/functional/spec/client-side-encryption/getMore.yml @@ -0,0 +1,69 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - &doc1_encrypted { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } + - &doc2_encrypted { _id: 3, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACKScltsm9Kw6AsyC/GQ8HZosvXZkixhFqNimPmzaSKu1b0IdTubAjsEG3TAxL5aTsQfT5mtr63hvvXpjMef8jzQ==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "getMore with encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + batchSize: 2 + filter: {} + results: + - { _id: 1, encrypted_string: "string0" } + - { _id: 2, encrypted_string: "string1" } + - { _id: 3, encrypted_string: "string2" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + find: *collection_name + batchSize: 2 + command_name: find + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + getMore: { $$type: "long" } + collection: *collection_name + batchSize: 2 + command_name: getMore + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted + - *doc2_encrypted \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/getMore.yml.template b/test/functional/spec/client-side-encryption/getMore.yml.template new file mode 100644 index 00000000000..476ec6fdbd0 --- /dev/null +++ b/test/functional/spec/client-side-encryption/getMore.yml.template @@ -0,0 +1,69 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - &doc1_encrypted { _id: 2, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } + - &doc2_encrypted { _id: 3, encrypted_string: {{ciphertext("string2", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "getMore with encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + batchSize: 2 + filter: {} + results: + - { _id: 1, encrypted_string: "string0" } + - { _id: 2, encrypted_string: "string1" } + - { _id: 3, encrypted_string: "string2" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + find: *collection_name + batchSize: 2 + command_name: find + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + getMore: { $$type: "long" } + collection: *collection_name + batchSize: 2 + command_name: getMore + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted + - *doc2_encrypted \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/insert.json b/test/functional/spec/client-side-encryption/insert.json new file mode 100644 index 00000000000..89236454cd2 --- /dev/null +++ b/test/functional/spec/client-side-encryption/insert.json @@ -0,0 +1,366 @@ +{ + "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-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "insertOne with encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_string": "string0", + "random": "abc" + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + } + ] + } + } + }, + { + "description": "insertMany with encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertMany", + "arguments": { + "documents": [ + { + "_id": 1, + "encrypted_string": "string0", + "random": "abc" + }, + { + "_id": 2, + "encrypted_string": "string1" + } + ] + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/insert.yml b/test/functional/spec/client-side-encryption/insert.yml new file mode 100644 index 00000000000..d8e4cdd133c --- /dev/null +++ b/test/functional/spec/client-side-encryption/insert.yml @@ -0,0 +1,104 @@ +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-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "insertOne with encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0", random: "abc" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}}, random: { $$type: "binData" } } + ordered: true + command_name: insert + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "insertMany with encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertMany + arguments: + documents: + - *doc0 + - &doc1 { _id: 2, encrypted_string: "string1" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - *doc0_encrypted + - &doc1_encrypted { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } + ordered: true + command_name: insert + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/insert.yml.template b/test/functional/spec/client-side-encryption/insert.yml.template new file mode 100644 index 00000000000..abc50e42e44 --- /dev/null +++ b/test/functional/spec/client-side-encryption/insert.yml.template @@ -0,0 +1,104 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "insertOne with encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0", random: "abc" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}}, random: { $$type: "binData" } } + ordered: true + command_name: insert + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "insertMany with encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertMany + arguments: + documents: + - *doc0 + - &doc1 { _id: 2, encrypted_string: "string1" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - *doc0_encrypted + - &doc1_encrypted { _id: 2, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } + ordered: true + command_name: insert + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - *doc1_encrypted \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/keyAltName.json b/test/functional/spec/client-side-encryption/keyAltName.json new file mode 100644 index 00000000000..9f0efe1be08 --- /dev/null +++ b/test/functional/spec/client-side-encryption/keyAltName.json @@ -0,0 +1,245 @@ +{ + "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-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "Insert with encryption using key alt name", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_w_altname": "string0", + "altname": "altname" + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [] + } + }, + { + "keyAltNames": { + "$in": [ + "altname" + ] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_w_altname": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + }, + "altname": "altname" + } + ], + "ordered": true + }, + "command_name": "insert" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_w_altname": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + }, + "altname": "altname" + } + ] + } + } + }, + { + "description": "Replace with key alt name fails", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$set": { + "encrypted_w_altname": "string0" + } + }, + "upsert": true + }, + "result": { + "errorContains": "A non-static (JSONPointer) keyId is not supported" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/keyAltName.yml b/test/functional/spec/client-side-encryption/keyAltName.yml new file mode 100644 index 00000000000..b521692e77e --- /dev/null +++ b/test/functional/spec/client-side-encryption/keyAltName.yml @@ -0,0 +1,72 @@ +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-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "Insert with encryption using key alt name" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_w_altname: "string0", altname: "altname" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {$or: [ { _id: { $in: [] } }, { keyAltNames: { $in: [ "altname" ] } } ] } + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_w_altname: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}}, altname: "altname" } + ordered: true + command_name: insert + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "Replace with key alt name fails" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: {} + update: { $set: { encrypted_w_altname: "string0" } } + upsert: true + result: + errorContains: "A non-static (JSONPointer) keyId is not supported" + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: [] \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/keyAltName.yml.template b/test/functional/spec/client-side-encryption/keyAltName.yml.template new file mode 100644 index 00000000000..cc653f11b15 --- /dev/null +++ b/test/functional/spec/client-side-encryption/keyAltName.yml.template @@ -0,0 +1,72 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "Insert with encryption using key alt name" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_w_altname: "string0", altname: "altname" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {$or: [ { _id: { $in: [] } }, { keyAltNames: { $in: [ "altname" ] } } ] } + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_w_altname: {{ciphertext("string0", field="encrypted_string")}}, altname: "altname" } + ordered: true + command_name: insert + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "Replace with key alt name fails" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: {} + update: { $set: { encrypted_w_altname: "string0" } } + upsert: true + result: + errorContains: "A non-static (JSONPointer) keyId is not supported" + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: [] \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/localKMS.json b/test/functional/spec/client-side-encryption/localKMS.json new file mode 100644 index 00000000000..1642cc221d0 --- /dev/null +++ b/test/functional/spec/client-side-encryption/localKMS.json @@ -0,0 +1,205 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [], + "json_schema": { + "properties": { + "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" + } + } + }, + "bsonType": "object" + }, + "key_vault_data": [ + { + "_id": { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + }, + "keyMaterial": { + "$binary": { + "base64": "db27rshiqK4Jqhb2xnwK4RfdFb9JuKeUe6xt5aYQF4o62tS75b7B4wxVN499gND9UVLUbpVKoyUoaZAeA895OENP335b8n8OwchcTFqS44t+P3zmhteYUQLIWQXaIgon7gEgLeJbaDHmSXS6/7NbfDDFlB37N7BP/2hx1yCOTN6NG/8M1ppw3LYT3CfP6EfXVEttDYtPbJpbb7nBVlxD7w==", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1232739599082000" + } + }, + "updateDate": { + "$date": { + "$numberLong": "1232739599082000" + } + }, + "status": { + "$numberInt": "0" + }, + "masterKey": { + "provider": "local" + } + } + ], + "tests": [ + { + "description": "Insert a document with auto encryption using local KMS provider", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {}, + "local": { + "key": { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "subType": "00" + } + } + } + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_string": "string0", + "random": "abc" + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACKWM29kOcLsfSLfJJ3SSmLr+wgrTtpu1lads1NzDz80AjMyrstw/GMdCuzX+AS+JS84Si2cT1WPMemTkBdVdGAw==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACKWM29kOcLsfSLfJJ3SSmLr+wgrTtpu1lads1NzDz80AjMyrstw/GMdCuzX+AS+JS84Si2cT1WPMemTkBdVdGAw==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/localKMS.yml b/test/functional/spec/client-side-encryption/localKMS.yml new file mode 100644 index 00000000000..93a41cfabf3 --- /dev/null +++ b/test/functional/spec/client-side-encryption/localKMS.yml @@ -0,0 +1,56 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +json_schema: {'properties': {'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'}}}, 'bsonType': 'object'} +key_vault_data: [{'_id': {'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}, 'keyMaterial': {'$binary': {'base64': 'db27rshiqK4Jqhb2xnwK4RfdFb9JuKeUe6xt5aYQF4o62tS75b7B4wxVN499gND9UVLUbpVKoyUoaZAeA895OENP335b8n8OwchcTFqS44t+P3zmhteYUQLIWQXaIgon7gEgLeJbaDHmSXS6/7NbfDDFlB37N7BP/2hx1yCOTN6NG/8M1ppw3LYT3CfP6EfXVEttDYtPbJpbb7nBVlxD7w==', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1232739599082000'}}, 'updateDate': {'$date': {'$numberLong': '1232739599082000'}}, 'status': {'$numberInt': '0'}, 'masterKey': {'provider': 'local'}}] + +tests: + - description: "Insert a document with auto encryption using local KMS provider" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + local: {'key': {'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', 'subType': '00'}}} + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0", random: "abc" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACKWM29kOcLsfSLfJJ3SSmLr+wgrTtpu1lads1NzDz80AjMyrstw/GMdCuzX+AS+JS84Si2cT1WPMemTkBdVdGAw==', 'subType': '06'}}, random: { $$type: "binData" } } + ordered: true + command_name: insert + 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/functional/spec/client-side-encryption/localKMS.yml.template b/test/functional/spec/client-side-encryption/localKMS.yml.template new file mode 100644 index 00000000000..1ff8acd25b1 --- /dev/null +++ b/test/functional/spec/client-side-encryption/localKMS.yml.template @@ -0,0 +1,56 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +json_schema: {{schema("local")}} +key_vault_data: [{{key("local")}}] + +tests: + - description: "Insert a document with auto encryption using local KMS provider" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + local: {{local_provider()}} + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0", random: "abc" } + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: { $or: [ { _id: { $in: [ {{key("local")["_id"]}} ] } }, { keyAltNames: { $in: [] } } ] } + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string", schema="local")}}, random: { $$type: "binData" } } + ordered: true + command_name: insert + 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/functional/spec/client-side-encryption/localSchema.json b/test/functional/spec/client-side-encryption/localSchema.json new file mode 100644 index 00000000000..8756e45b560 --- /dev/null +++ b/test/functional/spec/client-side-encryption/localSchema.json @@ -0,0 +1,268 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [], + "json_schema": {}, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "A local schema should override", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_string": "string0" + } + } + }, + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + } + }, + "result": [ + { + "_id": 1, + "encrypted_string": "string0" + } + ] + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "_id": 1 + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "A local schema with no encryption is an error", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "test": { + "bsonType": "string" + } + }, + "bsonType": "object", + "required": [ + "test" + ] + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_string": "string0" + } + }, + "result": { + "errorContains": "JSON schema keyword 'required' is only allowed with a remote schema" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/localSchema.yml b/test/functional/spec/client-side-encryption/localSchema.yml new file mode 100644 index 00000000000..019db0056f2 --- /dev/null +++ b/test/functional/spec/client-side-encryption/localSchema.yml @@ -0,0 +1,72 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +# configure an empty schema +json_schema: {} +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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "A local schema should override" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0" } + - name: find + arguments: + filter: { _id: 1 } + result: [*doc0] + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: { _id: 1 } + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "A local schema with no encryption is an error" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'test': {'bsonType': 'string'}}, 'bsonType': 'object', 'required': ['test']} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: { _id: 1, encrypted_string: "string0" } + result: + errorContains: "JSON schema keyword 'required' is only allowed with a remote schema" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/localSchema.yml.template b/test/functional/spec/client-side-encryption/localSchema.yml.template new file mode 100644 index 00000000000..09674d92694 --- /dev/null +++ b/test/functional/spec/client-side-encryption/localSchema.yml.template @@ -0,0 +1,72 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +# configure an empty schema +json_schema: {} +key_vault_data: [{{key()}}] + +tests: + - description: "A local schema should override" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema('basic')}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0" } + - name: find + arguments: + filter: { _id: 1 } + result: [*doc0] + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: { _id: 1 } + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "A local schema with no encryption is an error" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema('noencryption')}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: { _id: 1, encrypted_string: "string0" } + result: + errorContains: "JSON schema keyword 'required' is only allowed with a remote schema" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/malformedCiphertext.json b/test/functional/spec/client-side-encryption/malformedCiphertext.json new file mode 100644 index 00000000000..77be8473800 --- /dev/null +++ b/test/functional/spec/client-side-encryption/malformedCiphertext.json @@ -0,0 +1,321 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "00" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQ==", + "subType": "06" + } + } + }, + { + "_id": 3, + "encrypted_string": { + "$binary": { + "base64": "AQAAa2V2aW4gYWxiZXJ0c29uCg==", + "subType": "06" + } + } + } + ], + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "Wrong subtype", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "filter": { + "_id": 1 + } + }, + "result": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "00" + } + } + } + ] + } + ] + }, + { + "description": "Empty data", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "filter": { + "_id": 2 + } + }, + "result": { + "errorContains": "malformed ciphertext" + } + } + ] + }, + { + "description": "Malformed data", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "find", + "arguments": { + "filter": { + "_id": 3 + } + }, + "result": { + "errorContains": "did not provide all keys" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/malformedCiphertext.yml b/test/functional/spec/client-side-encryption/malformedCiphertext.yml new file mode 100644 index 00000000000..ff502b3f7ff --- /dev/null +++ b/test/functional/spec/client-side-encryption/malformedCiphertext.yml @@ -0,0 +1,69 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0 + _id: 1 + encrypted_string: + $binary: + base64: AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw== + subType: "00" + - _id: 2 + encrypted_string: + $binary: + base64: "AQ==" + subType: "06" + - _id: 3 + encrypted_string: + $binary: + base64: "AQAAa2V2aW4gYWxiZXJ0c29uCg==" + subType: "06" + +# Since test requires invalid data to be inserted, use a local schema. +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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "Wrong subtype" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { _id: 1 } + result: + # gets returned without decryption + - *doc0 + - description: "Empty data" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { _id: 2 } + result: + errorContains: "malformed ciphertext" + - description: "Malformed data" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { _id: 3 } + result: + # ciphertext can only validate subtype (which is correct) + # but takes the 16 byte UUID to look up key. Fails to find. + errorContains: "did not provide all keys" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/malformedCiphertext.yml.template b/test/functional/spec/client-side-encryption/malformedCiphertext.yml.template new file mode 100644 index 00000000000..801c71806db --- /dev/null +++ b/test/functional/spec/client-side-encryption/malformedCiphertext.yml.template @@ -0,0 +1,69 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0 + _id: 1 + encrypted_string: + $binary: + base64: {{ ciphertext("string1", field="encrypted_string")["$binary"]["base64"] }} + subType: "00" + - _id: 2 + encrypted_string: + $binary: + base64: "AQ==" + subType: "06" + - _id: 3 + encrypted_string: + $binary: + base64: "AQAAa2V2aW4gYWxiZXJ0c29uCg==" + subType: "06" + +# Since test requires invalid data to be inserted, use a local schema. +key_vault_data: [{{key()}}] + +tests: + - description: "Wrong subtype" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{ schema() }} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { _id: 1 } + result: + # gets returned without decryption + - *doc0 + - description: "Empty data" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{ schema() }} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { _id: 2 } + result: + errorContains: "malformed ciphertext" + - description: "Malformed data" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{ schema() }} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: find + arguments: + filter: { _id: 3 } + result: + # ciphertext can only validate subtype (which is correct) + # but takes the 16 byte UUID to look up key. Fails to find. + errorContains: "did not provide all keys" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/maxWireVersion.json b/test/functional/spec/client-side-encryption/maxWireVersion.json new file mode 100644 index 00000000000..ffd43e59599 --- /dev/null +++ b/test/functional/spec/client-side-encryption/maxWireVersion.json @@ -0,0 +1,71 @@ +{ + "runOn": [ + { + "maxServerVersion": "4.0" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [], + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "operation fails with maxWireVersion < 8", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "encrypted_string": "string0" + } + }, + "result": { + "errorContains": "Auto-encryption requires a minimum MongoDB version of 4.2" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/maxWireVersion.yml b/test/functional/spec/client-side-encryption/maxWireVersion.yml new file mode 100644 index 00000000000..5d833dbd117 --- /dev/null +++ b/test/functional/spec/client-side-encryption/maxWireVersion.yml @@ -0,0 +1,20 @@ +runOn: + - maxServerVersion: "4.0" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "operation fails with maxWireVersion < 8" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: { encrypted_string: "string0" } + result: + errorContains: "Auto-encryption requires a minimum MongoDB version of 4.2" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/maxWireVersion.yml.template b/test/functional/spec/client-side-encryption/maxWireVersion.yml.template new file mode 100644 index 00000000000..59ecddea425 --- /dev/null +++ b/test/functional/spec/client-side-encryption/maxWireVersion.yml.template @@ -0,0 +1,20 @@ +runOn: + - maxServerVersion: "4.0" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +key_vault_data: [{{key()}}] + +tests: + - description: "operation fails with maxWireVersion < 8" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: { encrypted_string: "string0" } + result: + errorContains: "Auto-encryption requires a minimum MongoDB version of 4.2" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/missingKey.json b/test/functional/spec/client-side-encryption/missingKey.json new file mode 100644 index 00000000000..35c3b0f4460 --- /dev/null +++ b/test/functional/spec/client-side-encryption/missingKey.json @@ -0,0 +1,97 @@ +{ + "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-Deterministic" + } + }, + "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": [], + "tests": [ + { + "description": "Insert with encryption on a missing key", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_string": "string0", + "random": "abc" + } + }, + "result": { + "errorContains": "did not provide all keys" + } + } + ], + "outcome": { + "collection": { + "data": [] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/missingKey.yml b/test/functional/spec/client-side-encryption/missingKey.yml new file mode 100644 index 00000000000..bdc568a92eb --- /dev/null +++ b/test/functional/spec/client-side-encryption/missingKey.yml @@ -0,0 +1,25 @@ +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-Deterministic'}}, '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: [] # key vault data is empty + +tests: + - description: "Insert with encryption on a missing key" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0", random: "abc" } + result: + errorContains: "did not provide all keys" + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: [] \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/missingKey.yml.template b/test/functional/spec/client-side-encryption/missingKey.yml.template new file mode 100644 index 00000000000..7011526d8c1 --- /dev/null +++ b/test/functional/spec/client-side-encryption/missingKey.yml.template @@ -0,0 +1,25 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +json_schema: {{schema()}} +key_vault_data: [] # key vault data is empty + +tests: + - description: "Insert with encryption on a missing key" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_string: "string0", random: "abc" } + result: + errorContains: "did not provide all keys" + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: [] \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/replaceOne.json b/test/functional/spec/client-side-encryption/replaceOne.json new file mode 100644 index 00000000000..951f1245a7c --- /dev/null +++ b/test/functional/spec/client-side-encryption/replaceOne.json @@ -0,0 +1,252 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "replaceOne with encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "replaceOne", + "arguments": { + "filter": { + "encrypted_string": "string0" + }, + "replacement": { + "encrypted_string": "string1", + "random": "abc" + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "update": "default", + "updates": [ + { + "q": { + "encrypted_string": { + "$eq": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + }, + "u": { + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + }, + "multi": false, + "upsert": false + } + ], + "ordered": true + }, + "command_name": "update" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/replaceOne.yml b/test/functional/spec/client-side-encryption/replaceOne.yml new file mode 100644 index 00000000000..73a9b2f077a --- /dev/null +++ b/test/functional/spec/client-side-encryption/replaceOne.yml @@ -0,0 +1,64 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "replaceOne with encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: replaceOne + arguments: + filter: { encrypted_string: "string0" } + replacement: { encrypted_string: "string1", random: "abc" } + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + update: *collection_name + updates: + - q: { encrypted_string: { $eq: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } } + u: { encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}}, random: { $$type: "binData" } } + multi: false + upsert: false + ordered: true + command_name: update + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}}, random: { $$type: "binData" } } \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/replaceOne.yml.template b/test/functional/spec/client-side-encryption/replaceOne.yml.template new file mode 100644 index 00000000000..b6f2152cc35 --- /dev/null +++ b/test/functional/spec/client-side-encryption/replaceOne.yml.template @@ -0,0 +1,64 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "replaceOne with encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: replaceOne + arguments: + filter: { encrypted_string: "string0" } + replacement: { encrypted_string: "string1", random: "abc" } + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + update: *collection_name + updates: + - q: { encrypted_string: { $eq: {{ciphertext("string0", field="encrypted_string")}} } } + u: { encrypted_string: {{ciphertext("string1", field="encrypted_string")}}, random: { $$type: "binData" } } + multi: false + upsert: false + ordered: true + command_name: update + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {{ciphertext("string1", field="encrypted_string")}}, random: { $$type: "binData" } } \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/types.json b/test/functional/spec/client-side-encryption/types.json new file mode 100644 index 00000000000..18914a966cf --- /dev/null +++ b/test/functional/spec/client-side-encryption/types.json @@ -0,0 +1,1726 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [], + "json_schema": {}, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "type=objectId", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_objectId": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "objectId", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_objectId": { + "$oid": "AAAAAAAAAAAAAAAAAAAAAAAA" + } + } + } + }, + { + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + }, + "result": { + "_id": 1, + "encrypted_objectId": { + "$oid": "AAAAAAAAAAAAAAAAAAAAAAAA" + } + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_objectId": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAHIwWYUBoGNSA7MnAqobBNVYee0mqtNZF1AQiTvXkR1B9a6XXEJR32Ttbbe2PLR/us/dmcne84BEYSq8h+j26lIA==", + "subType": "06" + } + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "_id": 1 + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_objectId": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAHIwWYUBoGNSA7MnAqobBNVYee0mqtNZF1AQiTvXkR1B9a6XXEJR32Ttbbe2PLR/us/dmcne84BEYSq8h+j26lIA==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "type=symbol", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_symbol": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "symbol", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_symbol": { + "$symbol": "test" + } + } + } + }, + { + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + }, + "result": { + "_id": 1, + "encrypted_symbol": { + "$symbol": "test" + } + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_symbol": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAOEpZwd/k1BQjT1owTq9NgQAoANKKQFbpfwDllEyFxjehyN/pTt1Rav51OAgbA5Bgg90Zpcvd0kHhA/S40bHZxXw==", + "subType": "06" + } + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "_id": 1 + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_symbol": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAOEpZwd/k1BQjT1owTq9NgQAoANKKQFbpfwDllEyFxjehyN/pTt1Rav51OAgbA5Bgg90Zpcvd0kHhA/S40bHZxXw==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "type=int", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_int": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "int", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_int": { + "$numberInt": "123" + } + } + } + }, + { + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + }, + "result": { + "_id": 1, + "encrypted_int": { + "$numberInt": "123" + } + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_int": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAQWPxV7BQ88Q5vW9HnPheOJyN29G/M7hhnCFmKL4oa+yzSPJhy4Xyxdbn4U80RXvDQMNz03ij5zbXFgrLz8BJIpg==", + "subType": "06" + } + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "_id": 1 + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_int": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAQWPxV7BQ88Q5vW9HnPheOJyN29G/M7hhnCFmKL4oa+yzSPJhy4Xyxdbn4U80RXvDQMNz03ij5zbXFgrLz8BJIpg==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "type=double", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_double": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "double", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_double": { + "$numberDouble": "1.23" + } + } + }, + "result": { + "errorContains": "Cannot use deterministic encryption for element of type: double" + } + } + ] + }, + { + "description": "type=decimal", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_decimal": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "decimal", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_decimal": { + "$numberDecimal": "1.23" + } + } + }, + "result": { + "errorContains": "Cannot use deterministic encryption for element of type: decimal" + } + } + ] + }, + { + "description": "type=binData", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_binData": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "binData", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_binData": { + "$binary": { + "base64": "AAAA", + "subType": "00" + } + } + } + } + }, + { + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + }, + "result": { + "_id": 1, + "encrypted_binData": { + "$binary": { + "base64": "AAAA", + "subType": "00" + } + } + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_binData": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAF22b7ESSyoBVv1Igu5PRd0Ya/WZ4QPWzB1D/HZ4dmA/Zl7+FunNK5jnG2AjYxfdijpskLfjFSclvuolPwTiTrig==", + "subType": "06" + } + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "_id": 1 + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_binData": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAF22b7ESSyoBVv1Igu5PRd0Ya/WZ4QPWzB1D/HZ4dmA/Zl7+FunNK5jnG2AjYxfdijpskLfjFSclvuolPwTiTrig==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "type=javascript", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_javascript": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "javascript", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_javascript": { + "$code": "var x = 1;" + } + } + } + }, + { + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + }, + "result": { + "_id": 1, + "encrypted_javascript": { + "$code": "var x = 1;" + } + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_javascript": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAANRHRbeR9tKL4SzZmgcMZXiGNBk/Kb7CKG72rAnwywbq45V3Upy2kK9royiRQR9Gwqm/3Idw5U86Zp/kXdQuzXng==", + "subType": "06" + } + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "_id": 1 + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_javascript": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAANRHRbeR9tKL4SzZmgcMZXiGNBk/Kb7CKG72rAnwywbq45V3Upy2kK9royiRQR9Gwqm/3Idw5U86Zp/kXdQuzXng==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "type=javascriptWithScope", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_javascriptWithScope": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "javascriptWithScope", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_javascriptWithScope": { + "$code": "var x = 1;", + "$scope": {} + } + } + }, + "result": { + "errorContains": "Cannot use deterministic encryption for element of type: javascriptWithScope" + } + } + ] + }, + { + "description": "type=object", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_object": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "object", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_object": {} + } + }, + "result": { + "errorContains": "Cannot use deterministic encryption for element of type: object" + } + } + ] + }, + { + "description": "type=timestamp", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_timestamp": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "timestamp", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_timestamp": { + "$timestamp": { + "t": 123, + "i": 456 + } + } + } + } + }, + { + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + }, + "result": { + "_id": 1, + "encrypted_timestamp": { + "$timestamp": { + "t": 123, + "i": 456 + } + } + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_timestamp": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAARlcbjVBI9YtvKM/ZuonWoF3mXV9C8LuYRNh0CM9nKjkmAMoIZTtqfhWM78hS1UORnUwcnZT+YuuO3QjuVDy8Esw==", + "subType": "06" + } + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "_id": 1 + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_timestamp": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAARlcbjVBI9YtvKM/ZuonWoF3mXV9C8LuYRNh0CM9nKjkmAMoIZTtqfhWM78hS1UORnUwcnZT+YuuO3QjuVDy8Esw==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "type=regex", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_regex": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "regex", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_regex": { + "$regularExpression": { + "pattern": "test", + "options": "" + } + } + } + } + }, + { + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + }, + "result": { + "_id": 1, + "encrypted_regex": { + "$regularExpression": { + "pattern": "test", + "options": "" + } + } + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_regex": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAALsSf4Z6nvjeVO7+AXjuYYamWMg/z8+W1HYdOaZfWuH24sCKSc1hvFm72acUJx77mTzQ8Ap94rzYMk1/FF7wbB/A==", + "subType": "06" + } + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "_id": 1 + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_regex": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAALsSf4Z6nvjeVO7+AXjuYYamWMg/z8+W1HYdOaZfWuH24sCKSc1hvFm72acUJx77mTzQ8Ap94rzYMk1/FF7wbB/A==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "type=date", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_date": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "date", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_date": { + "$date": { + "$numberLong": "123" + } + } + } + } + }, + { + "name": "findOne", + "arguments": { + "filter": { + "_id": 1 + }, + "result": { + "_id": 1, + "encrypted_date": { + "$date": { + "$numberLong": "123" + } + } + } + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "insert": "default", + "documents": [ + { + "_id": 1, + "encrypted_date": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAJipr5TW6wma9Z0Xa90u+w4hcRLeEE99BNy45oyzM07NaO42g5lLzbqyIkSO1q3dIbqIHd1hJ4s3a53bUjrh+2lQ==", + "subType": "06" + } + } + } + ], + "ordered": true + }, + "command_name": "insert" + } + }, + { + "command_started_event": { + "command": { + "find": "default", + "filter": { + "_id": 1 + } + }, + "command_name": "find" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_date": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAJipr5TW6wma9Z0Xa90u+w4hcRLeEE99BNy45oyzM07NaO42g5lLzbqyIkSO1q3dIbqIHd1hJ4s3a53bUjrh+2lQ==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "type=minKey", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_minKey": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "minKey", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_minKey": { + "$minKey": 1 + } + } + }, + "result": { + "errorContains": "Cannot encrypt element of type: minKey" + } + } + ] + }, + { + "description": "type=maxKey", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_maxKey": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "maxKey", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_maxKey": { + "$maxKey": 1 + } + } + }, + "result": { + "errorContains": "Cannot encrypt element of type: maxKey" + } + } + ] + }, + { + "description": "type=undefined", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_undefined": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "undefined", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_undefined": { + "$undefined": true + } + } + }, + "result": { + "errorContains": "Cannot encrypt element of type: undefined" + } + } + ] + }, + { + "description": "type=array", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_array": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "array", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_array": [] + } + }, + "result": { + "errorContains": "Cannot use deterministic encryption for element of type: array" + } + } + ] + }, + { + "description": "type=bool", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_bool": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "bool", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_bool": true + } + }, + "result": { + "errorContains": "Cannot use deterministic encryption for element of type: bool" + } + } + ] + }, + { + "description": "type=null", + "clientOptions": { + "autoEncryptOpts": { + "schemaMap": { + "default.default": { + "properties": { + "encrypted_null": { + "encrypt": { + "keyId": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ], + "bsonType": "null", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + } + }, + "bsonType": "object" + } + }, + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "insertOne", + "arguments": { + "document": { + "_id": 1, + "encrypted_null": true + } + }, + "result": { + "errorContains": "Cannot encrypt element of type: null" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/types.yml b/test/functional/spec/client-side-encryption/types.yml new file mode 100644 index 00000000000..0b38a789550 --- /dev/null +++ b/test/functional/spec/client-side-encryption/types.yml @@ -0,0 +1,527 @@ +# Attempt to round trip some BSON types. +# Note: db pointer is excluded since it is deprecated and numberlong is excluded due to different driver interpretations of { $numberLong: '123' } in relaxed JSON parsing. + +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +json_schema: {} +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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "type=objectId" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_objectId': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'objectId', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_objectId: {"$oid": "AAAAAAAAAAAAAAAAAAAAAAAA"} } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc0 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_objectId: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAHIwWYUBoGNSA7MnAqobBNVYee0mqtNZF1AQiTvXkR1B9a6XXEJR32Ttbbe2PLR/us/dmcne84BEYSq8h+j26lIA==', 'subType': '06'}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "type=symbol" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_symbol': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'symbol', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc1 { _id: 1, encrypted_symbol: {"$symbol": "test"} } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc1 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc1_encrypted { _id: 1, encrypted_symbol: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAOEpZwd/k1BQjT1owTq9NgQAoANKKQFbpfwDllEyFxjehyN/pTt1Rav51OAgbA5Bgg90Zpcvd0kHhA/S40bHZxXw==', 'subType': '06'}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc1_encrypted + - description: "type=int" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_int': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'int', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc2 { _id: 1, encrypted_int: {"$numberInt": "123"} } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc2 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc2_encrypted { _id: 1, encrypted_int: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAQWPxV7BQ88Q5vW9HnPheOJyN29G/M7hhnCFmKL4oa+yzSPJhy4Xyxdbn4U80RXvDQMNz03ij5zbXFgrLz8BJIpg==', 'subType': '06'}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc2_encrypted + - description: "type=double" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_double': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'double', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc4 { _id: 1, encrypted_double: {"$numberDouble": "1.23"} } + result: + errorContains: "Cannot use deterministic encryption for element of type: double" + - description: "type=decimal" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_decimal': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'decimal', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc5 { _id: 1, encrypted_decimal: {"$numberDecimal": "1.23"} } + result: + errorContains: "Cannot use deterministic encryption for element of type: decimal" + - description: "type=binData" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_binData': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'binData', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc6 { _id: 1, encrypted_binData: {"$binary": { base64: "AAAA", subType: "00" } } } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc6 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc6_encrypted { _id: 1, encrypted_binData: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAF22b7ESSyoBVv1Igu5PRd0Ya/WZ4QPWzB1D/HZ4dmA/Zl7+FunNK5jnG2AjYxfdijpskLfjFSclvuolPwTiTrig==', 'subType': '06'}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc6_encrypted + - description: "type=javascript" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_javascript': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'javascript', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc7 { _id: 1, encrypted_javascript: {"$code": "var x = 1;" } } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc7 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc7_encrypted { _id: 1, encrypted_javascript: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAANRHRbeR9tKL4SzZmgcMZXiGNBk/Kb7CKG72rAnwywbq45V3Upy2kK9royiRQR9Gwqm/3Idw5U86Zp/kXdQuzXng==', 'subType': '06'}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc7_encrypted + - description: "type=javascriptWithScope" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_javascriptWithScope': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'javascriptWithScope', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc8 { _id: 1, encrypted_javascriptWithScope: {"$code": "var x = 1;", "$scope": {} } } + result: + errorContains: "Cannot use deterministic encryption for element of type: javascriptWithScope" + - description: "type=object" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_object': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'object', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc9 { _id: 1, encrypted_object: {} } + result: + errorContains: "Cannot use deterministic encryption for element of type: object" + - description: "type=timestamp" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_timestamp': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'timestamp', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc10 { _id: 1, encrypted_timestamp: {$timestamp: {t: 123, i: 456}} } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc10 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc10_encrypted { _id: 1, encrypted_timestamp: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAARlcbjVBI9YtvKM/ZuonWoF3mXV9C8LuYRNh0CM9nKjkmAMoIZTtqfhWM78hS1UORnUwcnZT+YuuO3QjuVDy8Esw==', 'subType': '06'}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc10_encrypted + - description: "type=regex" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_regex': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'regex', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc11 { _id: 1, encrypted_regex: {$regularExpression: { pattern: "test", options: ""}} } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc11 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc11_encrypted { _id: 1, encrypted_regex: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAALsSf4Z6nvjeVO7+AXjuYYamWMg/z8+W1HYdOaZfWuH24sCKSc1hvFm72acUJx77mTzQ8Ap94rzYMk1/FF7wbB/A==', 'subType': '06'}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc11_encrypted + - description: "type=date" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_date': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'date', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc13 { _id: 1, encrypted_date: {$date: { $numberLong: "123" }} } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc13 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc13_encrypted { _id: 1, encrypted_date: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAJipr5TW6wma9Z0Xa90u+w4hcRLeEE99BNy45oyzM07NaO42g5lLzbqyIkSO1q3dIbqIHd1hJ4s3a53bUjrh+2lQ==', 'subType': '06'}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc13_encrypted + - description: "type=minKey" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_minKey': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'minKey', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc14 { _id: 1, encrypted_minKey: {$minKey: 1} } + result: + errorContains: "Cannot encrypt element of type: minKey" + - description: "type=maxKey" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_maxKey': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'maxKey', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc15 { _id: 1, encrypted_maxKey: {$maxKey: 1} } + result: + errorContains: "Cannot encrypt element of type: maxKey" + - description: "type=undefined" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_undefined': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'undefined', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc16 { _id: 1, encrypted_undefined: {$undefined: true} } + result: + errorContains: "Cannot encrypt element of type: undefined" + - description: "type=array" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_array': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'array', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc17 { _id: 1, encrypted_array: [] } + result: + errorContains: "Cannot use deterministic encryption for element of type: array" + - description: "type=bool" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_bool': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'bool', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc18 { _id: 1, encrypted_bool: true } + result: + errorContains: "Cannot use deterministic encryption for element of type: bool" + - description: "type=null" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {'properties': {'encrypted_null': {'encrypt': {'keyId': [{'$binary': {'base64': 'AAAAAAAAAAAAAAAAAAAAAA==', 'subType': '04'}}], 'bsonType': 'null', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}}, 'bsonType': 'object'} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc19 { _id: 1, encrypted_null: true } + result: + errorContains: "Cannot encrypt element of type: null" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/types.yml.template b/test/functional/spec/client-side-encryption/types.yml.template new file mode 100644 index 00000000000..0208de52ea7 --- /dev/null +++ b/test/functional/spec/client-side-encryption/types.yml.template @@ -0,0 +1,527 @@ +# Attempt to round trip some BSON types. +# Note: db pointer is excluded since it is deprecated and numberlong is excluded due to different driver interpretations of { $numberLong: '123' } in relaxed JSON parsing. + +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: [] +json_schema: {} +key_vault_data: [{{key()}}] + +tests: + - description: "type=objectId" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("objectId")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc0 { _id: 1, encrypted_objectId: {"$oid": "AAAAAAAAAAAAAAAAAAAAAAAA"} } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc0 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc0_encrypted { _id: 1, encrypted_objectId: {{ciphertext("test", field="encrypted_objectId")}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc0_encrypted + - description: "type=symbol" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("symbol")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc1 { _id: 1, encrypted_symbol: {"$symbol": "test"} } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc1 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc1_encrypted { _id: 1, encrypted_symbol: {{ciphertext("test", field="encrypted_symbol")}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc1_encrypted + - description: "type=int" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("int")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc2 { _id: 1, encrypted_int: {"$numberInt": "123"} } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc2 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc2_encrypted { _id: 1, encrypted_int: {{ciphertext("test", field="encrypted_int32")}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc2_encrypted + - description: "type=double" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("double")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc4 { _id: 1, encrypted_double: {"$numberDouble": "1.23"} } + result: + errorContains: "Cannot use deterministic encryption for element of type: double" + - description: "type=decimal" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("decimal")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc5 { _id: 1, encrypted_decimal: {"$numberDecimal": "1.23"} } + result: + errorContains: "Cannot use deterministic encryption for element of type: decimal" + - description: "type=binData" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("binData")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc6 { _id: 1, encrypted_binData: {"$binary": { base64: "AAAA", subType: "00" } } } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc6 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc6_encrypted { _id: 1, encrypted_binData: {{ciphertext("test", field="encrypted_binData")}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc6_encrypted + - description: "type=javascript" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("javascript")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc7 { _id: 1, encrypted_javascript: {"$code": "var x = 1;" } } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc7 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc7_encrypted { _id: 1, encrypted_javascript: {{ciphertext("test", field="encrypted_javascript")}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc7_encrypted + - description: "type=javascriptWithScope" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("javascriptWithScope")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc8 { _id: 1, encrypted_javascriptWithScope: {"$code": "var x = 1;", "$scope": {} } } + result: + errorContains: "Cannot use deterministic encryption for element of type: javascriptWithScope" + - description: "type=object" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("object")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc9 { _id: 1, encrypted_object: {} } + result: + errorContains: "Cannot use deterministic encryption for element of type: object" + - description: "type=timestamp" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("timestamp")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc10 { _id: 1, encrypted_timestamp: {$timestamp: {t: 123, i: 456}} } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc10 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc10_encrypted { _id: 1, encrypted_timestamp: {{ciphertext("test", field="encrypted_timestamp")}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc10_encrypted + - description: "type=regex" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("regex")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc11 { _id: 1, encrypted_regex: {$regularExpression: { pattern: "test", options: ""}} } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc11 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc11_encrypted { _id: 1, encrypted_regex: {{ciphertext("test", field="encrypted_regex")}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc11_encrypted + - description: "type=date" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("date")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc13 { _id: 1, encrypted_date: {$date: { $numberLong: "123" }} } + - name: findOne + arguments: + filter: { _id: 1 } + result: *doc13 + expectations: + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + insert: *collection_name + documents: + - &doc13_encrypted { _id: 1, encrypted_date: {{ciphertext("test", field="encrypted_date")}} } + ordered: true + command_name: insert + - command_started_event: + command: + find: *collection_name + filter: {_id: 1} + command_name: find + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - *doc13_encrypted + - description: "type=minKey" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("minKey")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc14 { _id: 1, encrypted_minKey: {$minKey: 1} } + result: + errorContains: "Cannot encrypt element of type: minKey" + - description: "type=maxKey" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("maxKey")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc15 { _id: 1, encrypted_maxKey: {$maxKey: 1} } + result: + errorContains: "Cannot encrypt element of type: maxKey" + - description: "type=undefined" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("undefined")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc16 { _id: 1, encrypted_undefined: {$undefined: true} } + result: + errorContains: "Cannot encrypt element of type: undefined" + - description: "type=array" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("array")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc17 { _id: 1, encrypted_array: [] } + result: + errorContains: "Cannot use deterministic encryption for element of type: array" + - description: "type=bool" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("bool")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc18 { _id: 1, encrypted_bool: true } + result: + errorContains: "Cannot use deterministic encryption for element of type: bool" + - description: "type=null" + clientOptions: + autoEncryptOpts: + schemaMap: + "default.default": {{schema_w_type("null")}} + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: insertOne + arguments: + document: &doc19 { _id: 1, encrypted_null: true } + result: + errorContains: "Cannot encrypt element of type: null" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/unsupportedCommand.json b/test/functional/spec/client-side-encryption/unsupportedCommand.json new file mode 100644 index 00000000000..aba22a21438 --- /dev/null +++ b/test/functional/spec/client-side-encryption/unsupportedCommand.json @@ -0,0 +1,152 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "x": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "x": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "mapReduce deterministic encryption (unsupported)", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "mapReduce", + "arguments": { + "map": { + "$code": "function inc() { return emit(0, this.x + 1) }" + }, + "reduce": { + "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" + }, + "out": { + "inline": 1 + } + }, + "result": { + "errorContains": "command not supported for auto encryption: mapreduce" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/unsupportedCommand.yml b/test/functional/spec/client-side-encryption/unsupportedCommand.yml new file mode 100644 index 00000000000..d366ff59773 --- /dev/null +++ b/test/functional/spec/client-side-encryption/unsupportedCommand.yml @@ -0,0 +1,25 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, x: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - &doc1_encrypted { _id: 2, x: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "mapReduce deterministic encryption (unsupported)" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: mapReduce + arguments: + map: { $code: "function inc() { return emit(0, this.x + 1) }" } + reduce: { $code: "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" } + out: { inline: 1 } + result: + errorContains: "command not supported for auto encryption: mapreduce" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/unsupportedCommand.yml.template b/test/functional/spec/client-side-encryption/unsupportedCommand.yml.template new file mode 100644 index 00000000000..ca20a0e4d70 --- /dev/null +++ b/test/functional/spec/client-side-encryption/unsupportedCommand.yml.template @@ -0,0 +1,25 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, x: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - &doc1_encrypted { _id: 2, x: 2, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "mapReduce deterministic encryption (unsupported)" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: mapReduce + arguments: + map: { $code: "function inc() { return emit(0, this.x + 1) }" } + reduce: { $code: "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" } + out: { inline: 1 } + result: + errorContains: "command not supported for auto encryption: mapreduce" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/updateMany.json b/test/functional/spec/client-side-encryption/updateMany.json new file mode 100644 index 00000000000..9416b28e296 --- /dev/null +++ b/test/functional/spec/client-side-encryption/updateMany.json @@ -0,0 +1,318 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "updateMany with deterministic encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateMany", + "arguments": { + "filter": { + "encrypted_string": { + "$in": [ + "string0", + "string1" + ] + } + }, + "update": { + "$set": { + "encrypted_string": "string2", + "random": "abc" + } + } + }, + "result": { + "matchedCount": 2, + "modifiedCount": 2, + "upsertedCount": 0 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "update": "default", + "updates": [ + { + "q": { + "encrypted_string": { + "$in": [ + { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + }, + { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + } + ] + } + }, + "u": { + "$set": { + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACKScltsm9Kw6AsyC/GQ8HZosvXZkixhFqNimPmzaSKu1b0IdTubAjsEG3TAxL5aTsQfT5mtr63hvvXpjMef8jzQ==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + } + }, + "multi": true, + "upsert": false + } + ], + "ordered": true + }, + "command_name": "update" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACKScltsm9Kw6AsyC/GQ8HZosvXZkixhFqNimPmzaSKu1b0IdTubAjsEG3TAxL5aTsQfT5mtr63hvvXpjMef8jzQ==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + }, + { + "_id": 2, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACKScltsm9Kw6AsyC/GQ8HZosvXZkixhFqNimPmzaSKu1b0IdTubAjsEG3TAxL5aTsQfT5mtr63hvvXpjMef8jzQ==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + } + ] + } + } + }, + { + "description": "updateMany fails when filtering on a random field", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateMany", + "arguments": { + "filter": { + "random": "abc" + }, + "update": { + "$set": { + "encrypted_string": "string1" + } + } + }, + "result": { + "errorContains": "Cannot query on fields encrypted with the randomized encryption" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/updateMany.yml b/test/functional/spec/client-side-encryption/updateMany.yml new file mode 100644 index 00000000000..5ad5f0b206a --- /dev/null +++ b/test/functional/spec/client-side-encryption/updateMany.yml @@ -0,0 +1,78 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - &doc1_encrypted { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "updateMany with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateMany + arguments: + filter: { encrypted_string: { $in: [ "string0", "string1" ] } } + update: { $set: { encrypted_string: "string2", random: "abc" } } + result: + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 0 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + update: *collection_name + updates: + - q: { encrypted_string: { $in: [ {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}}, {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}} ] } } + u: { $set: { encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACKScltsm9Kw6AsyC/GQ8HZosvXZkixhFqNimPmzaSKu1b0IdTubAjsEG3TAxL5aTsQfT5mtr63hvvXpjMef8jzQ==', 'subType': '06'}}, random: { $$type: "binData" } } } + multi: true + upsert: false + ordered: true + command_name: update + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACKScltsm9Kw6AsyC/GQ8HZosvXZkixhFqNimPmzaSKu1b0IdTubAjsEG3TAxL5aTsQfT5mtr63hvvXpjMef8jzQ==', 'subType': '06'}}, random: { $$type: "binData" } } + - { _id: 2, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACKScltsm9Kw6AsyC/GQ8HZosvXZkixhFqNimPmzaSKu1b0IdTubAjsEG3TAxL5aTsQfT5mtr63hvvXpjMef8jzQ==', 'subType': '06'}}, random: { $$type: "binData" } } + - description: "updateMany fails when filtering on a random field" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateMany + arguments: + filter: { random: "abc" } + update: { $set: { encrypted_string: "string1" } } + result: + errorContains: "Cannot query on fields encrypted with the randomized encryption" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/updateMany.yml.template b/test/functional/spec/client-side-encryption/updateMany.yml.template new file mode 100644 index 00000000000..fedc0636b00 --- /dev/null +++ b/test/functional/spec/client-side-encryption/updateMany.yml.template @@ -0,0 +1,78 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } + - &doc1_encrypted { _id: 2, encrypted_string: {{ciphertext("string1", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "updateMany with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateMany + arguments: + filter: { encrypted_string: { $in: [ "string0", "string1" ] } } + update: { $set: { encrypted_string: "string2", random: "abc" } } + result: + matchedCount: 2 + modifiedCount: 2 + upsertedCount: 0 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + update: *collection_name + updates: + - q: { encrypted_string: { $in: [ {{ciphertext("string0", field="encrypted_string")}}, {{ciphertext("string1", field="encrypted_string")}} ] } } + u: { $set: { encrypted_string: {{ciphertext("string2", field="encrypted_string")}}, random: { $$type: "binData" } } } + multi: true + upsert: false + ordered: true + command_name: update + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {{ciphertext("string2", field="encrypted_string")}}, random: { $$type: "binData" } } + - { _id: 2, encrypted_string: {{ciphertext("string2", field="encrypted_string")}}, random: { $$type: "binData" } } + - description: "updateMany fails when filtering on a random field" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateMany + arguments: + filter: { random: "abc" } + update: { $set: { encrypted_string: "string1" } } + result: + errorContains: "Cannot query on fields encrypted with the randomized encryption" \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/updateOne.json b/test/functional/spec/client-side-encryption/updateOne.json new file mode 100644 index 00000000000..11a2b6764c8 --- /dev/null +++ b/test/functional/spec/client-side-encryption/updateOne.json @@ -0,0 +1,484 @@ +{ + "runOn": [ + { + "minServerVersion": "4.1.10" + } + ], + "database_name": "default", + "collection_name": "default", + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ], + "json_schema": { + "properties": { + "encrypted_w_altname": { + "encrypt": { + "keyId": "/altname", + "bsonType": "string", + "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + } + }, + "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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW", + "subType": "00" + } + }, + "creationDate": { + "$date": { + "$numberLong": "1552949630483" + } + }, + "keyAltNames": [ + "altname", + "another_altname" + ] + } + ], + "tests": [ + { + "description": "updateOne with deterministic encryption", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": { + "encrypted_string": "string0" + }, + "update": { + "$set": { + "encrypted_string": "string1", + "random": "abc" + } + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "datakeys" + }, + "$db": "admin" + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "find": "datakeys", + "filter": { + "$or": [ + { + "_id": { + "$in": [ + { + "$binary": { + "base64": "AAAAAAAAAAAAAAAAAAAAAA==", + "subType": "04" + } + } + ] + } + }, + { + "keyAltNames": { + "$in": [] + } + } + ] + }, + "$db": "admin" + }, + "command_name": "find" + } + }, + { + "command_started_event": { + "command": { + "update": "default", + "updates": [ + { + "q": { + "encrypted_string": { + "$eq": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + }, + "u": { + "$set": { + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + } + }, + "multi": false, + "upsert": false + } + ], + "ordered": true + }, + "command_name": "update" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==", + "subType": "06" + } + }, + "random": { + "$$type": "binData" + } + } + ] + } + } + }, + { + "description": "updateOne fails when filtering on a random field", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": { + "random": "abc" + }, + "update": { + "$set": { + "encrypted_string": "string1" + } + } + }, + "result": { + "errorContains": "Cannot query on fields encrypted with the randomized encryption" + } + } + ] + }, + { + "description": "$unset works with an encrypted field", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$unset": { + "encrypted_string": "" + } + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "update": "default", + "updates": [ + { + "q": {}, + "u": { + "$unset": { + "encrypted_string": "" + } + }, + "multi": false, + "upsert": false + } + ], + "ordered": true + }, + "command_name": "update" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1 + } + ] + } + } + }, + { + "description": "$rename works if target value has same encryption options", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$rename": { + "encrypted_string": "encrypted_string_equivalent" + } + } + }, + "result": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "expectations": [ + { + "command_started_event": { + "command": { + "listCollections": 1, + "cursor": {}, + "filter": { + "name": "default" + } + }, + "command_name": "listCollections" + } + }, + { + "command_started_event": { + "command": { + "update": "default", + "updates": [ + { + "q": {}, + "u": { + "$rename": { + "encrypted_string": "encrypted_string_equivalent" + } + }, + "multi": false, + "upsert": false + } + ], + "ordered": true + }, + "command_name": "update" + } + } + ], + "outcome": { + "collection": { + "data": [ + { + "_id": 1, + "encrypted_string_equivalent": { + "$binary": { + "base64": "AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==", + "subType": "06" + } + } + } + ] + } + } + }, + { + "description": "$rename fails if target value has different encryption options", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "$rename": { + "encrypted_string": "random" + } + } + }, + "result": { + "errorContains": "$rename between two encrypted fields must have the same metadata or both be unencrypted" + } + } + ] + }, + { + "description": "an invalid update (no $ operators) is validated and errors", + "clientOptions": { + "autoEncryptOpts": { + "kmsProviders": { + "aws": {} + } + } + }, + "operations": [ + { + "name": "updateOne", + "arguments": { + "filter": {}, + "update": { + "encrypted_string": "random" + } + }, + "result": { + "errorContains": "" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/updateOne.yml b/test/functional/spec/client-side-encryption/updateOne.yml new file mode 100644 index 00000000000..02ff9136799 --- /dev/null +++ b/test/functional/spec/client-side-encryption/updateOne.yml @@ -0,0 +1,176 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } +json_schema: {'properties': {'encrypted_w_altname': {'encrypt': {'keyId': '/altname', 'bsonType': 'string', 'algorithm': 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'}}, '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+iDUZhEqnhJwH9wZVpuZ94A8gF9FSYZL9Ze8TvTA3WBd3nmAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDLV3GHktEO8AlpsYBwIBEIB7ho0DQF7hEQPRz/8b61AHm2czX53Y9BNu5z+oyGYsoP643M58aTGsaHQzkTaAmGKlZTAEOjJkRJ4gZoabVuv4g6aJqf4k4w8pK7iIgHwMNy4nbUAqOWmqtnKpHZgy6jcFN2DzZzHIi4SNFsCkFc6Aw30ixtvqIDQPAXMW', 'subType': '00'}}, 'creationDate': {'$date': {'$numberLong': '1552949630483'}}, 'keyAltNames': ['altname', 'another_altname']}] + +tests: + - description: "updateOne with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { encrypted_string: "string0" } + update: { $set: { encrypted_string: "string1", random: "abc" } } + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + 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: admin + command_name: find + - command_started_event: + command: + update: *collection_name + updates: + - q: { encrypted_string: { $eq: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } } + u: { $set: {encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}}, random: { $$type: "binData" } } } + multi: false + upsert: false + ordered: true + command_name: update + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAAC1ijPpI+oG1mNiFChFAz7heo3R150yDhxZ7nOnPUwDM+aEvPRBuU6rXtgkVt7mgLd2H9rq9iChCAV46YKcpNrFw==', 'subType': '06'}}, random: { $$type: "binData"} } + - description: "updateOne fails when filtering on a random field" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { random: "abc" } + update: { $set: { encrypted_string: "string1" } } + result: + errorContains: "Cannot query on fields encrypted with the randomized encryption" + - description: "$unset works with an encrypted field" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $unset: { encrypted_string: "" } } + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + update: *collection_name + updates: + - q: { } + u: { $unset: {encrypted_string: "" } } + multi: false + upsert: false + ordered: true + command_name: update + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1 } + - description: "$rename works if target value has same encryption options" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $rename: { encrypted_string: "encrypted_string_equivalent" } } + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + update: *collection_name + updates: + - q: { } + u: { $rename: {encrypted_string: "encrypted_string_equivalent" } } + multi: false + upsert: false + ordered: true + command_name: update + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string_equivalent: {'$binary': {'base64': 'AQAAAAAAAAAAAAAAAAAAAAACtsdOjHK3CkpNjAAMznkYbeR6Z+yLzCRv4zOb7VfKnJdmU0W5MD8GVODx8K+KuBoCbE1SfGfPgX6NhS/RKpQ12w==', 'subType': '06'}} } + - description: "$rename fails if target value has different encryption options" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $rename: { encrypted_string: "random" } } + result: + errorContains: "$rename between two encrypted fields must have the same metadata or both be unencrypted" + - description: "an invalid update (no $ operators) is validated and errors" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { encrypted_string: "random" } + result: + errorContains: "" # Note, drivers differ in the error message. Just ensure an error is thrown. \ No newline at end of file diff --git a/test/functional/spec/client-side-encryption/updateOne.yml.template b/test/functional/spec/client-side-encryption/updateOne.yml.template new file mode 100644 index 00000000000..803e73c8097 --- /dev/null +++ b/test/functional/spec/client-side-encryption/updateOne.yml.template @@ -0,0 +1,176 @@ +runOn: + - minServerVersion: "4.1.10" +database_name: &database_name "default" +collection_name: &collection_name "default" + +data: + - &doc0_encrypted { _id: 1, encrypted_string: {{ciphertext("string0", field="encrypted_string")}} } +json_schema: {{schema()}} +key_vault_data: [{{key()}}] + +tests: + - description: "updateOne with deterministic encryption" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { encrypted_string: "string0" } + update: { $set: { encrypted_string: "string1", random: "abc" } } + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: "datakeys" + $db: admin + command_name: listCollections + # Then key is fetched from the key vault. + - command_started_event: + command: + find: datakeys + filter: {"$or": [{"_id": {"$in": [ {{key()["_id"]}} ] }}, {"keyAltNames": {"$in": []}}]} + $db: admin + command_name: find + - command_started_event: + command: + update: *collection_name + updates: + - q: { encrypted_string: { $eq: {{ciphertext("string0", field="encrypted_string")}} } } + u: { $set: {encrypted_string: {{ciphertext("string1", field="encrypted_string")}}, random: { $$type: "binData" } } } + multi: false + upsert: false + ordered: true + command_name: update + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string: {{ciphertext("string1", field="encrypted_string")}}, random: { $$type: "binData"} } + - description: "updateOne fails when filtering on a random field" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { random: "abc" } + update: { $set: { encrypted_string: "string1" } } + result: + errorContains: "Cannot query on fields encrypted with the randomized encryption" + - description: "$unset works with an encrypted field" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $unset: { encrypted_string: "" } } + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + update: *collection_name + updates: + - q: { } + u: { $unset: {encrypted_string: "" } } + multi: false + upsert: false + ordered: true + command_name: update + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1 } + - description: "$rename works if target value has same encryption options" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $rename: { encrypted_string: "encrypted_string_equivalent" } } + result: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + expectations: + # Auto encryption will request the collection info. + - command_started_event: + command: + listCollections: 1 + cursor: {} + filter: + name: *collection_name + command_name: listCollections + - command_started_event: + command: + update: *collection_name + updates: + - q: { } + u: { $rename: {encrypted_string: "encrypted_string_equivalent" } } + multi: false + upsert: false + ordered: true + command_name: update + outcome: + collection: + # Outcome is checked using a separate MongoClient without auto encryption. + data: + - { _id: 1, encrypted_string_equivalent: {{ciphertext("string0", field="encrypted_string")}} } + - description: "$rename fails if target value has different encryption options" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { $rename: { encrypted_string: "random" } } + result: + errorContains: "$rename between two encrypted fields must have the same metadata or both be unencrypted" + - description: "an invalid update (no $ operators) is validated and errors" + clientOptions: + autoEncryptOpts: + kmsProviders: + aws: {} # Credentials filled in from environment. + operations: + - name: updateOne + arguments: + filter: { } + update: { encrypted_string: "random" } + result: + errorContains: "" # Note, drivers differ in the error message. Just ensure an error is thrown. \ No newline at end of file