ExportXMLWordPrintableJSON

    • Type: New Feature
    • Resolution: Fixed
    • Priority: Major - P3
    • 5.12.0
    • Affects Version/s: None
    • None
    • Needed
    • Hide

      This feature is not complete. Other tickets will be done as part of the epic.

      1. What would you like to communicate to the user about this feature?

      mongodb/laravel-mongodb now supports Queryable Encryption (QE), the MongoDB feature that encrypts fields client-side while keeping them queryable by the server. The integration is configuration-driven: you declare the fields to encrypt once on the connection, and the driver and the server encrypt and decrypt them transparently. There is no encryption metadata on your models, and no encrypt() or decrypt() call in your code.

      What the user needs to know:

      • Configure it once in config/database.php, under driver_options.autoEncryption: keyVaultNamespace, kmsProviders, extraOptions for crypt_shared, and encryptedFieldsMap.
      • encryptedFieldsMap is the single source of truth for the client-side configuration. It is optional on the connection, because the server can supply the configuration for server-side QE, but it is recommended for security and required to create an encrypted collection through this package.
      • Each field is bound to a data key by an alternate key name, not by an opaque base64 keyId. The default name is <database>.<collection>/<path>, and a per-field keyAltName overrides it. The key is generated on first create when it does not exist yet.
      • Create the encrypted collection with Schema::createEncrypted() or php artisan mongodb:encryption:create-collection <collection>. It is idempotent: an existing encrypted collection is returned as is, and an existing collection that is not encrypted is rejected.
      • Check the configuration with php artisan mongodb:encryption:status. Both commands accept --no-server to validate the configuration without contacting the server.
      • The connection table prefix is applied. The encryptedFieldsMap keeps the logical collection names, so you do not prefix the keys yourself.
      • QE forbids multi-document updates. On an encrypted collection, the package switches to single-document updates automatically, so save() and update() keep working, but an update that matches several documents now changes only the first one.
      • The server writes a reserved _safeContent_ array. The package rejects any attempt to write it, including through a dotted sub-path such as _safeContent_.0. It is still returned by toArray() and JSON output.
      • The bsonType declared in the map must match the value. The server rejects a value that does not match, and the package does not coerce. HTTP form values arrive as strings, so cast them before saving with (int) $request->field, a cast, or a validation rule.
      • An encrypted field cannot be compared to null or to a regex. $text, $where and $jsonSchema are unsupported. QE is incompatible with Atlas Search.
      • Dropping a collection keeps its data keys, so it can be recreated with the same map. Dropping the whole database also drops the key vault and every data key when the vault lives in that database, which is unrecoverable.
      • Note for the docs team: the existing package reference document states that QE requires MongoDB Enterprise Advanced or Atlas. The integration tests run against a community MongoDB 8.0 replica set with crypt_shared and pass, so this restriction is worth confirming with the product team before publishing.

      Requirements to state up front: MongoDB 8.0 or later for range queries, 7.0 or later for equality, on a replica set or a sharded cluster, with the Automatic Encryption Shared Library (crypt_shared).

      2. Would you like the user to see examples of the syntax and/or executable code and its output?

      Yes, examples are important here, because the feature is configuration-driven and the failure modes are not obvious. We suggest covering:

      • The config/database.php block, showing keyVaultNamespace, kmsProviders, extraOptions.cryptSharedLibPath, and a small encryptedFieldsMap with an equality field, a range field and a randomized object field.
      • A plain Eloquent model with no encryption metadata, to make the point that the map is the only declaration.
      • Creating the collection, both with the Artisan command and with Schema::createEncrypted(), including the idempotent second run.
      • The output of php artisan mongodb:encryption:status, and of mongodb:encryption:create-collection --no-server.
      • An insert and a read through a model, then the same document read through a plain connection to show the fields are Binary at rest.
      • An equality query and a range query.
      • The bsonType pitfall, with a failing string value and the working cast, since this is the error users will hit first.
      • Optionally, a before and after on update() showing that only the first matching document is updated on an encrypted collection.

      Executable output is useful for the two Artisan commands and for the ciphertext inspection. The rest reads better as annotated snippets.

      3. Which versions of the driver/connector does this apply to?

      This is the Laravel package, not a driver, so the answer is the package version plus its requirements:

      • mongodb/laravel-mongodb 5.12.0
      • mongodb/mongodb ^1.21.2 or ^2.1.1.
      • ext-mongodb 2.4.0 or later. The composer constraint allows ^1.21|^2, so this is not enforced at install time and is reported at runtime with an explicit message. Worth calling out in the requirements.
      • MongoDB server 8.0 or later for range queries, 7.0 or later for equality, on a replica set or sharded cluster.
      • The Automatic Encryption Shared Library (crypt_shared), or mongocryptd as a fallback.
      Show
      This feature is not complete. Other tickets will be done as part of the epic. 1. What would you like to communicate to the user about this feature? mongodb/laravel-mongodb now supports Queryable Encryption (QE), the MongoDB feature that encrypts fields client-side while keeping them queryable by the server. The integration is configuration-driven: you declare the fields to encrypt once on the connection, and the driver and the server encrypt and decrypt them transparently. There is no encryption metadata on your models, and no encrypt() or decrypt() call in your code. What the user needs to know: Configure it once in config/database.php, under driver_options.autoEncryption: keyVaultNamespace, kmsProviders, extraOptions for crypt_shared, and encryptedFieldsMap. encryptedFieldsMap is the single source of truth for the client-side configuration. It is optional on the connection, because the server can supply the configuration for server-side QE, but it is recommended for security and required to create an encrypted collection through this package. Each field is bound to a data key by an alternate key name, not by an opaque base64 keyId. The default name is <database>.<collection>/<path>, and a per-field keyAltName overrides it. The key is generated on first create when it does not exist yet. Create the encrypted collection with Schema::createEncrypted() or php artisan mongodb:encryption:create-collection <collection>. It is idempotent: an existing encrypted collection is returned as is, and an existing collection that is not encrypted is rejected. Check the configuration with php artisan mongodb:encryption:status. Both commands accept --no-server to validate the configuration without contacting the server. The connection table prefix is applied. The encryptedFieldsMap keeps the logical collection names, so you do not prefix the keys yourself. QE forbids multi-document updates. On an encrypted collection, the package switches to single-document updates automatically, so save() and update() keep working, but an update that matches several documents now changes only the first one. The server writes a reserved _ safeContent _ array. The package rejects any attempt to write it, including through a dotted sub-path such as _ safeContent _.0. It is still returned by toArray() and JSON output. The bsonType declared in the map must match the value. The server rejects a value that does not match, and the package does not coerce. HTTP form values arrive as strings, so cast them before saving with (int) $request->field, a cast, or a validation rule. An encrypted field cannot be compared to null or to a regex. $text, $where and $jsonSchema are unsupported. QE is incompatible with Atlas Search. Dropping a collection keeps its data keys, so it can be recreated with the same map. Dropping the whole database also drops the key vault and every data key when the vault lives in that database, which is unrecoverable. Note for the docs team: the existing package reference document states that QE requires MongoDB Enterprise Advanced or Atlas. The integration tests run against a community MongoDB 8.0 replica set with crypt_shared and pass, so this restriction is worth confirming with the product team before publishing. Requirements to state up front: MongoDB 8.0 or later for range queries, 7.0 or later for equality, on a replica set or a sharded cluster, with the Automatic Encryption Shared Library (crypt_shared). 2. Would you like the user to see examples of the syntax and/or executable code and its output? Yes, examples are important here, because the feature is configuration-driven and the failure modes are not obvious. We suggest covering: The config/database.php block, showing keyVaultNamespace, kmsProviders, extraOptions.cryptSharedLibPath, and a small encryptedFieldsMap with an equality field, a range field and a randomized object field. A plain Eloquent model with no encryption metadata, to make the point that the map is the only declaration. Creating the collection, both with the Artisan command and with Schema::createEncrypted(), including the idempotent second run. The output of php artisan mongodb:encryption:status, and of mongodb:encryption:create-collection --no-server. An insert and a read through a model, then the same document read through a plain connection to show the fields are Binary at rest. An equality query and a range query. The bsonType pitfall, with a failing string value and the working cast, since this is the error users will hit first. Optionally, a before and after on update() showing that only the first matching document is updated on an encrypted collection. Executable output is useful for the two Artisan commands and for the ciphertext inspection. The rest reads better as annotated snippets. 3. Which versions of the driver/connector does this apply to? This is the Laravel package, not a driver, so the answer is the package version plus its requirements: mongodb/laravel-mongodb 5.12.0 mongodb/mongodb ^1.21.2 or ^2.1.1. ext-mongodb 2.4.0 or later. The composer constraint allows ^1.21|^2, so this is not enforced at install time and is reported at runtime with an explicit message. Worth calling out in the requirements. MongoDB server 8.0 or later for range queries, 7.0 or later for equality, on a replica set or sharded cluster. The Automatic Encryption Shared Library (crypt_shared), or mongocryptd as a fallback.
    • None
    • None
    • None
    • None
    • None
    • None

      Summary

      Add first-class Queryable Encryption (QE) support to mongodb/laravel-mongodb, configuration-driven with no model metadata. The encryption schema is declared once in driver_options.autoEncryption.encryptedFieldsMap; the driver and the server handle encryption and decryption transparently.

      Scope: Queryable Encryption in Laravel
      https://docs.google.com/document/d/1d5rHlUQQBk8oG3xAKX58uKTLAmuT8CUBfTyZknVDvjE/edit?tab=t.eyxusmsiv22h

      Implemented

      • Connection: validation of driver_options.autoEncryption (keyVaultNamespace, kmsProviders, local key size, crypt_shared) plus getClientEncryption() and getEncryptionOptions().
      • encryptedFieldsMap: simplified keyed-by-path syntax and the list form, normalized to the driver format, with aggressive validation.
      • Data keys: each field resolves by an alternate key name, default ./, with a per-field keyAltName override. Generation delegated to libmongocrypt (>= 1.18). DRIVERS-3637.
      • Encrypted collection lifecycle: Schema::createEncrypted() and a plain Schema::create() on a mapped collection; transparent drop; dropAllTables() warns about key vault loss.
      • Models: the reserved _safeContent_ is hidden from serialization and protected from writes; encrypted collections use single-document updates.
      • Artisan: mongodb:encrypted:create and mongodb:encrypted:diagnose, each with a --no-server mode.
      • Safety guard: a write to a mapped collection not created as encrypted fails fast, never writing plaintext. DRIVERS-3647.
      • Internals: encryption logic in an internal MongoDB\Laravel\Encryption\AutoEncryption, created lazily and held weakly.
      • Requires mongodb/mongodb ^1.21.2|^2.1.1.

      Related

              Assignee:
              Jérôme Tamarelle
              Reporter:
              Jérôme Tamarelle
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated:
                Resolved: