diff --git a/doc/api/pymongo/encryption.rst b/doc/api/pymongo/encryption.rst
index 1501ef98a..3a8c3c5cc 100644
--- a/doc/api/pymongo/encryption.rst
+++ b/doc/api/pymongo/encryption.rst
@@ -1,5 +1,5 @@
-:mod:`encryption` -- Client side encryption
-===========================================
+:mod:`encryption` -- Client-Side Field Level Encryption
+=======================================================
.. automodule:: pymongo.encryption
:members:
diff --git a/doc/api/pymongo/encryption_options.rst b/doc/api/pymongo/encryption_options.rst
index 492139faa..08bfc157a 100644
--- a/doc/api/pymongo/encryption_options.rst
+++ b/doc/api/pymongo/encryption_options.rst
@@ -1,8 +1,8 @@
-:mod:`encryption_options` -- Support for automatic client side encryption
+:mod:`encryption_options` -- Automatic Client-Side Field Level Encryption
=========================================================================
.. automodule:: pymongo.encryption_options
- :synopsis: Support for automatic client side encryption
+ :synopsis: Support for automatic client-side field level encryption
.. autoclass:: pymongo.encryption_options.AutoEncryptionOpts
:members:
diff --git a/doc/examples/encryption.rst b/doc/examples/encryption.rst
new file mode 100644
index 000000000..540a6f806
--- /dev/null
+++ b/doc/examples/encryption.rst
@@ -0,0 +1,498 @@
+Client-Side Field Level Encryption
+==================================
+
+New in MongoDB 4.2, client-side field level encryption allows an application
+to encrypt specific data fields in addition to pre-existing MongoDB
+encryption features such as `Encryption at Rest
+`_ and
+`TLS/SSL (Transport Encryption)
+`_.
+
+With field level encryption, applications can encrypt fields in documents
+*prior* to transmitting data over the wire to the server. Client-side field
+level encryption supports workloads where applications must guarantee that
+unauthorized parties, including server administrators, cannot read the
+encrypted data.
+
+.. seealso:: The MongoDB documentation for `Client-Side Field Level Encryption
+ `_.
+
+Dependencies
+------------
+
+To get started using client-side field level encryption in your project,
+you will need to install the
+`pymongocrypt `_ library
+as well as the driver itself. Install both the driver and a compatible
+version of pymongocrypt like this::
+
+ $ python -m pip install 'pymongo[encryption]'
+
+Note that installing on Linux requires pip 19 or later for manylinux2010 wheel
+support. For more information about installing pymongocrypt see
+`the installation instructions on the project's PyPI page
+`_.
+
+mongocryptd
+-----------
+
+The ``mongocryptd`` binary is required for automatic client-side encryption
+and is included as a component in the `MongoDB Enterprise Server package
+`_.
+For detailed installation instructions see
+`the MongoDB documentation on mongocryptd
+`_.
+
+``mongocryptd`` performs the following:
+
+- Parses the automatic encryption rules specified to the database connection.
+ If the JSON schema contains invalid automatic encryption syntax or any
+ document validation syntax, ``mongocryptd`` returns an error.
+- Uses the specified automatic encryption rules to mark fields in read and
+ write operations for encryption.
+- Rejects read/write operations that may return unexpected or incorrect results
+ when applied to an encrypted field. For supported and unsupported operations,
+ see `Read/Write Support with Automatic Field Level Encryption
+ `_.
+
+A MongoClient configured with auto encryption will automatically spawn the
+``mongocryptd`` process from the application's ``PATH``. Applications can
+control the spawning behavior as part of the automatic encryption options.
+For example to set the path to the ``mongocryptd`` process::
+
+ auto_encryption_opts = AutoEncryptionOpts(
+ ...,
+ mongocryptd_spawn_path='/path/to/mongocryptd')
+
+To control the logging output of ``mongocryptd`` pass options using
+``mongocryptd_spawn_args``::
+
+ auto_encryption_opts = AutoEncryptionOpts(
+ ...,
+ mongocryptd_spawn_args=['--logpath=/path/to/mongocryptd.log', '--logappend'])
+
+If your application wishes to manage the ``mongocryptd`` process manually,
+it is possible to disable spawning ``mongocryptd``::
+
+ auto_encryption_opts = AutoEncryptionOpts(
+ ...,
+ mongocryptd_bypass_spawn=True,
+ # URI of the local ``mongocryptd`` process.
+ mongocryptd_uri='mongodb://localhost:27020')
+
+``mongocryptd`` is only responsible for supporting automatic client-side field
+level encryption and does not itself perform any encryption or decryption.
+
+.. _automatic-client-side-encryption:
+
+Automatic Client-Side Field Level Encryption
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Automatic client-side field level encryption is enabled by creating a
+:class:`~pymongo.mongo_client.MongoClient` with the ``auto_encryption_opts``
+option set to an instance of
+:class:`~pymongo.encryption_options.AutoEncryptionOpts`. The following
+examples show how to setup automatic client-side field level encryption
+using :class:`~pymongo.encryption.ClientEncryption` to create a new
+encryption data key.
+
+.. note:: Automatic client-side field level encryption requires MongoDB 4.2
+ enterprise or a MongoDB 4.2 Atlas cluster. The community version of the
+ server supports automatic decryption as well as
+ :ref:`explicit-client-side-encryption`.
+
+Providing Local Automatic Encryption Rules
+``````````````````````````````````````````
+
+The following example shows how to specify automatic encryption rules via the
+``schema_map`` option. The automatic encryption rules are expressed using a
+`strict subset of the JSON Schema syntax
+`_.
+
+Supplying a ``schema_map`` provides more security than relying on
+JSON Schemas obtained from the server. It protects against a
+malicious server advertising a false JSON Schema, which could trick
+the client into sending unencrypted data that should be encrypted.
+
+JSON Schemas supplied in the ``schema_map`` only apply to configuring
+automatic client-side field level encryption. Other validation
+rules in the JSON schema will not be enforced by the driver and
+will result in an error.::
+
+ import os
+
+ from bson.codec_options import CodecOptions
+ from bson import json_util
+
+ from pymongo import MongoClient
+ from pymongo.encryption import (Algorithm,
+ ClientEncryption)
+ from pymongo.encryption_options import AutoEncryptionOpts
+
+
+ def create_json_schema_file(kms_providers, key_vault_namespace,
+ key_vault_client):
+ client_encryption = ClientEncryption(
+ kms_providers,
+ key_vault_namespace,
+ key_vault_client,
+ # The CodecOptions class used for encrypting and decrypting.
+ # This should be the same CodecOptions instance you have configured
+ # on MongoClient, Database, or Collection. We will not be calling
+ # encrypt() or decrypt() in this example so we can use any
+ # CodecOptions.
+ CodecOptions())
+
+ # Create a new data key and json schema for the encryptedField.
+ # https://docs.mongodb.com/manual/reference/security-client-side-automatic-json-schema/
+ data_key_id = client_encryption.create_data_key(
+ 'local', key_alt_names=['pymongo_encryption_example_1'])
+ schema = {
+ "properties": {
+ "encryptedField": {
+ "encrypt": {
+ "keyId": [data_key_id],
+ "bsonType": "string",
+ "algorithm":
+ Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic
+ }
+ }
+ },
+ "bsonType": "object"
+ }
+ # Use CANONICAL_JSON_OPTIONS so that other drivers and tools will be
+ # able to parse the MongoDB extended JSON file.
+ json_schema_string = json_util.dumps(
+ schema, json_options=json_util.CANONICAL_JSON_OPTIONS)
+
+ with open('jsonSchema.json', 'w') as file:
+ file.write(json_schema_string)
+
+
+ def main():
+ # The MongoDB namespace (db.collection) used to store the
+ # encrypted documents in this example.
+ encrypted_namespace = "test.coll"
+
+ # This must be the same master key that was used to create
+ # the encryption key.
+ local_master_key = os.urandom(96)
+ kms_providers = {"local": {"key": local_master_key}}
+
+ # The MongoDB namespace (db.collection) used to store
+ # the encryption data keys.
+ key_vault_namespace = "encryption.__pymongoTestKeyVault"
+ key_vault_db_name, key_vault_coll_name = key_vault_namespace.split(".", 1)
+
+ # The MongoClient used to access the key vault (key_vault_namespace).
+ key_vault_client = MongoClient()
+ key_vault = key_vault_client[key_vault_db_name][key_vault_coll_name]
+ # Ensure that two data keys cannot share the same keyAltName.
+ key_vault.drop()
+ key_vault.create_index(
+ "keyAltNames",
+ unique=True,
+ partialFilterExpression={"keyAltNames": {"$exists": True}})
+
+ create_json_schema_file(
+ kms_providers, key_vault_namespace, key_vault_client)
+
+ # Load the JSON Schema and construct the local schema_map option.
+ with open('jsonSchema.json', 'r') as file:
+ json_schema_string = file.read()
+ json_schema = json_util.loads(json_schema_string)
+ schema_map = {encrypted_namespace: json_schema}
+
+ auto_encryption_opts = AutoEncryptionOpts(
+ kms_providers, key_vault_namespace, schema_map=schema_map)
+
+ client = MongoClient(auto_encryption_opts=auto_encryption_opts)
+ db_name, coll_name = encrypted_namespace.split(".", 1)
+ coll = client[db_name][coll_name]
+ # Clear old data
+ coll.drop()
+
+ coll.insert_one({"encryptedField": "123456789"})
+ print('Decrypted document: %s' % (coll.find_one(),))
+ unencrypted_coll = MongoClient()[db_name][coll_name]
+ print('Encrypted document: %s' % (unencrypted_coll.find_one(),))
+
+
+ if __name__ == "__main__":
+ main()
+
+Server-Side Field Level Encryption Enforcement
+``````````````````````````````````````````````
+
+The MongoDB 4.2 server supports using schema validation to enforce encryption
+of specific fields in a collection. This schema validation will prevent an
+application from inserting unencrypted values for any fields marked with the
+``"encrypt"`` JSON schema keyword.
+
+The following example shows how to setup automatic client-side field level
+encryption using
+:class:`~pymongo.encryption.ClientEncryption` to create a new encryption
+data key and create a collection with the
+`Automatic Encryption JSON Schema Syntax
+`_::
+
+ import os
+
+ from bson.codec_options import CodecOptions
+ from bson.binary import STANDARD
+
+ from pymongo import MongoClient
+ from pymongo.encryption import (Algorithm,
+ ClientEncryption)
+ from pymongo.encryption_options import AutoEncryptionOpts
+ from pymongo.errors import OperationFailure
+ from pymongo.write_concern import WriteConcern
+
+
+ def main():
+ # The MongoDB namespace (db.collection) used to store the
+ # encrypted documents in this example.
+ encrypted_namespace = "test.coll"
+
+ # This must be the same master key that was used to create
+ # the encryption key.
+ local_master_key = os.urandom(96)
+ kms_providers = {"local": {"key": local_master_key}}
+
+ # The MongoDB namespace (db.collection) used to store
+ # the encryption data keys.
+ key_vault_namespace = "encryption.__pymongoTestKeyVault"
+ key_vault_db_name, key_vault_coll_name = key_vault_namespace.split(".", 1)
+
+ # The MongoClient used to access the key vault (key_vault_namespace).
+ key_vault_client = MongoClient()
+ key_vault = key_vault_client[key_vault_db_name][key_vault_coll_name]
+ # Ensure that two data keys cannot share the same keyAltName.
+ key_vault.drop()
+ key_vault.create_index(
+ "keyAltNames",
+ unique=True,
+ partialFilterExpression={"keyAltNames": {"$exists": True}})
+
+ client_encryption = ClientEncryption(
+ kms_providers,
+ key_vault_namespace,
+ key_vault_client,
+ # The CodecOptions class used for encrypting and decrypting.
+ # This should be the same CodecOptions instance you have configured
+ # on MongoClient, Database, or Collection. We will not be calling
+ # encrypt() or decrypt() in this example so we can use any
+ # CodecOptions.
+ CodecOptions())
+
+ # Create a new data key and json schema for the encryptedField.
+ data_key_id = client_encryption.create_data_key(
+ 'local', key_alt_names=['pymongo_encryption_example_2'])
+ json_schema = {
+ "properties": {
+ "encryptedField": {
+ "encrypt": {
+ "keyId": [data_key_id],
+ "bsonType": "string",
+ "algorithm":
+ Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic
+ }
+ }
+ },
+ "bsonType": "object"
+ }
+
+ auto_encryption_opts = AutoEncryptionOpts(
+ kms_providers, key_vault_namespace)
+ client = MongoClient(auto_encryption_opts=auto_encryption_opts)
+ db_name, coll_name = encrypted_namespace.split(".", 1)
+ db = client[db_name]
+ # Clear old data
+ db.drop_collection(coll_name)
+ # Create the collection with the encryption JSON Schema.
+ db.create_collection(
+ coll_name,
+ # uuid_representation=STANDARD is required to ensure that any
+ # UUIDs in the $jsonSchema document are encoded to BSON Binary
+ # with the standard UUID subtype 4. This is only needed when
+ # running the "create" collection command with an encryption
+ # JSON Schema.
+ codec_options=CodecOptions(uuid_representation=STANDARD),
+ write_concern=WriteConcern(w="majority"),
+ validator={"$jsonSchema": json_schema})
+ coll = client[db_name][coll_name]
+
+ coll.insert_one({"encryptedField": "123456789"})
+ print('Decrypted document: %s' % (coll.find_one(),))
+ unencrypted_coll = MongoClient()[db_name][coll_name]
+ print('Encrypted document: %s' % (unencrypted_coll.find_one(),))
+ try:
+ unencrypted_coll.insert_one({"encryptedField": "123456789"})
+ except OperationFailure as exc:
+ print('Unencrypted insert failed: %s' % (exc.details,))
+
+
+ if __name__ == "__main__":
+ main()
+
+.. _explicit-client-side-encryption:
+
+Explicit Encryption
+~~~~~~~~~~~~~~~~~~~
+
+Explicit encryption is a MongoDB community feature and does not use the
+``mongocryptd`` process. Explicit encryption is provided by the
+:class:`~pymongo.encryption.ClientEncryption` class, for example::
+
+ import os
+
+ from pymongo import MongoClient
+ from pymongo.encryption import (Algorithm,
+ ClientEncryption)
+
+
+ def main():
+ # This must be the same master key that was used to create
+ # the encryption key.
+ local_master_key = os.urandom(96)
+ kms_providers = {"local": {"key": local_master_key}}
+
+ # The MongoDB namespace (db.collection) used to store
+ # the encryption data keys.
+ key_vault_namespace = "encryption.__pymongoTestKeyVault"
+ key_vault_db_name, key_vault_coll_name = key_vault_namespace.split(".", 1)
+
+ # The MongoClient used to read/write application data.
+ client = MongoClient()
+ coll = client.test.coll
+ # Clear old data
+ coll.drop()
+
+ # Set up the key vault (key_vault_namespace) for this example.
+ key_vault = client[key_vault_db_name][key_vault_coll_name]
+ # Ensure that two data keys cannot share the same keyAltName.
+ key_vault.drop()
+ key_vault.create_index(
+ "keyAltNames",
+ unique=True,
+ partialFilterExpression={"keyAltNames": {"$exists": True}})
+
+ client_encryption = ClientEncryption(
+ kms_providers,
+ key_vault_namespace,
+ # The MongoClient to use for reading/writing to the key vault.
+ # This can be the same MongoClient used by the main application.
+ client,
+ # The CodecOptions class used for encrypting and decrypting.
+ # This should be the same CodecOptions instance you have configured
+ # on MongoClient, Database, or Collection.
+ coll.codec_options)
+
+ # Create a new data key and json schema for the encryptedField.
+ data_key_id = client_encryption.create_data_key(
+ 'local', key_alt_names=['pymongo_encryption_example_3'])
+
+ # Explicitly encrypt a field:
+ encrypted_field = client_encryption.encrypt(
+ "123456789",
+ Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic,
+ key_id=data_key_id)
+ coll.insert_one({"encryptedField": encrypted_field})
+ doc = coll.find_one()
+ print('Encrypted document: %s' % (doc,))
+
+ # Explicitly decrypt the field:
+ doc["encryptedField"] = client_encryption.decrypt(doc["encryptedField"])
+ print('Decrypted document: %s' % (doc,))
+
+ # Cleanup resources.
+ client_encryption.close()
+ client.close()
+
+
+ if __name__ == "__main__":
+ main()
+
+
+Explicit Encryption with Automatic Decryption
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Although automatic encryption requires MongoDB 4.2 enterprise or a
+MongoDB 4.2 Atlas cluster, automatic *decryption* is supported for all users.
+To configure automatic *decryption* without automatic *encryption* set
+``bypass_auto_encryption=True`` in
+:class:`~pymongo.encryption_options.AutoEncryptionOpts`::
+
+ import os
+
+ from pymongo import MongoClient
+ from pymongo.encryption import (Algorithm,
+ ClientEncryption)
+ from pymongo.encryption_options import AutoEncryptionOpts
+
+
+ def main():
+ # This must be the same master key that was used to create
+ # the encryption key.
+ local_master_key = os.urandom(96)
+ kms_providers = {"local": {"key": local_master_key}}
+
+ # The MongoDB namespace (db.collection) used to store
+ # the encryption data keys.
+ key_vault_namespace = "encryption.__pymongoTestKeyVault"
+ key_vault_db_name, key_vault_coll_name = key_vault_namespace.split(".", 1)
+
+ # bypass_auto_encryption=True disable automatic encryption but keeps
+ # the automatic _decryption_ behavior. bypass_auto_encryption will
+ # also disable spawning mongocryptd.
+ auto_encryption_opts = AutoEncryptionOpts(
+ kms_providers, key_vault_namespace, bypass_auto_encryption=True)
+
+ client = MongoClient(auto_encryption_opts=auto_encryption_opts)
+ coll = client.test.coll
+ # Clear old data
+ coll.drop()
+
+ # Set up the key vault (key_vault_namespace) for this example.
+ key_vault = client[key_vault_db_name][key_vault_coll_name]
+ # Ensure that two data keys cannot share the same keyAltName.
+ key_vault.drop()
+ key_vault.create_index(
+ "keyAltNames",
+ unique=True,
+ partialFilterExpression={"keyAltNames": {"$exists": True}})
+
+ client_encryption = ClientEncryption(
+ kms_providers,
+ key_vault_namespace,
+ # The MongoClient to use for reading/writing to the key vault.
+ # This can be the same MongoClient used by the main application.
+ client,
+ # The CodecOptions class used for encrypting and decrypting.
+ # This should be the same CodecOptions instance you have configured
+ # on MongoClient, Database, or Collection.
+ coll.codec_options)
+
+ # Create a new data key and json schema for the encryptedField.
+ data_key_id = client_encryption.create_data_key(
+ 'local', key_alt_names=['pymongo_encryption_example_4'])
+
+ # Explicitly encrypt a field:
+ encrypted_field = client_encryption.encrypt(
+ "123456789",
+ Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic,
+ key_alt_name='pymongo_encryption_example_4')
+ coll.insert_one({"encryptedField": encrypted_field})
+ # Automatically decrypts any encrypted fields.
+ doc = coll.find_one()
+ print('Decrypted document: %s' % (doc,))
+ unencrypted_coll = MongoClient().test.coll
+ print('Encrypted document: %s' % (unencrypted_coll.find_one(),))
+
+ # Cleanup resources.
+ client_encryption.close()
+ client.close()
+
+
+ if __name__ == "__main__":
+ main()
diff --git a/doc/examples/index.rst b/doc/examples/index.rst
index 7431acd9e..baadd7446 100644
--- a/doc/examples/index.rst
+++ b/doc/examples/index.rst
@@ -31,3 +31,4 @@ MongoDB, you can start it like so:
server_selection
tailable
tls
+ encryption
diff --git a/doc/index.rst b/doc/index.rst
index 051b68d1a..3a4aa316b 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -25,6 +25,9 @@ everything you need to know to use **PyMongo**.
:doc:`examples/tls`
Using PyMongo with TLS / SSL.
+:doc:`examples/encryption`
+ Using PyMongo with client side encryption.
+
:doc:`faq`
Some questions that come up often.
diff --git a/pymongo/encryption.py b/pymongo/encryption.py
index bdbd4fc72..e782a9f13 100644
--- a/pymongo/encryption.py
+++ b/pymongo/encryption.py
@@ -12,11 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Support for explicit client side encryption.
-
-**Support for client side encryption is in beta. Backwards-breaking changes
-may be made before the final release.**
-"""
+"""Support for explicit client-side field level encryption."""
import contextlib
import os
@@ -35,7 +31,7 @@ except ImportError:
_HAVE_PYMONGOCRYPT = False
MongoCryptCallback = object
-from bson import _bson_to_dict, _dict_to_bson, decode, encode
+from bson import _dict_to_bson, decode, encode
from bson.codec_options import CodecOptions
from bson.binary import (Binary,
STANDARD,
@@ -204,13 +200,13 @@ class _EncryptionIO(MongoCryptCallback):
:Returns:
The _id of the inserted data key document.
"""
- # insert does not return the inserted _id when given a RawBSONDocument.
- doc = _bson_to_dict(data_key, _DATA_KEY_OPTS)
- if not isinstance(doc.get('_id'), uuid.UUID):
- raise TypeError(
- 'data_key _id must be a bson.binary.Binary with subtype 4')
- res = self.key_vault_coll.insert_one(doc)
- return Binary(res.inserted_id.bytes, subtype=UUID_SUBTYPE)
+ raw_doc = RawBSONDocument(data_key)
+ data_key_id = raw_doc.get('_id')
+ if not isinstance(data_key_id, uuid.UUID):
+ raise TypeError('data_key _id must be a UUID')
+
+ self.key_vault_coll.insert_one(raw_doc)
+ return Binary(data_key_id.bytes, subtype=UUID_SUBTYPE)
def bson_encode(self, doc):
"""Encode a document to BSON.
@@ -338,11 +334,11 @@ class Algorithm(object):
class ClientEncryption(object):
- """Explicit client side encryption."""
+ """Explicit client-side field level encryption."""
def __init__(self, kms_providers, key_vault_namespace, key_vault_client,
codec_options):
- """Explicit client side encryption.
+ """Explicit client-side field level encryption.
The ClientEncryption class encapsulates explicit operations on a key
vault collection that cannot be done directly on a MongoClient. Similar
@@ -353,8 +349,7 @@ class ClientEncryption(object):
creating data keys. It does not provide an API to query keys from the
key vault collection, as this can be done directly on the MongoClient.
- .. note:: Support for client side encryption is in beta.
- Backwards-breaking changes may be made before the final release.
+ See :ref:`explicit-client-side-encryption` for an example.
:Parameters:
- `kms_providers`: Map of KMS provider options. Two KMS providers
@@ -377,14 +372,17 @@ class ClientEncryption(object):
containing the `key_vault_namespace` collection.
- `codec_options`: An instance of
:class:`~bson.codec_options.CodecOptions` to use when encoding a
- value for encryption and decoding the decrypted BSON value.
+ value for encryption and decoding the decrypted BSON value. This
+ should be the same CodecOptions instance configured on the
+ MongoClient, Database, or Collection used to access application
+ data.
.. versionadded:: 3.9
"""
if not _HAVE_PYMONGOCRYPT:
raise ConfigurationError(
- "client side encryption requires the pymongocrypt library: "
- "install a compatible version with: "
+ "client-side field level encryption requires the pymongocrypt "
+ "library: install a compatible version with: "
"python -m pip install 'pymongo[encryption]'")
if not isinstance(codec_options, CodecOptions):
diff --git a/pymongo/encryption_options.py b/pymongo/encryption_options.py
index 60bb41e33..3158b3e84 100644
--- a/pymongo/encryption_options.py
+++ b/pymongo/encryption_options.py
@@ -12,11 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Support for automatic client side encryption.
-
-**Support for client side encryption is in beta. Backwards-breaking changes
-may be made before the final release.**
-"""
+"""Support for automatic client-side field level encryption."""
import copy
@@ -30,7 +26,7 @@ from pymongo.errors import ConfigurationError
class AutoEncryptionOpts(object):
- """Options to configure automatic encryption."""
+ """Options to configure automatic client-side field level encryption."""
def __init__(self, kms_providers, key_vault_namespace,
key_vault_client=None, schema_map=None,
@@ -39,21 +35,21 @@ class AutoEncryptionOpts(object):
mongocryptd_bypass_spawn=False,
mongocryptd_spawn_path='mongocryptd',
mongocryptd_spawn_args=None):
- """Options to configure automatic encryption.
+ """Options to configure automatic client-side field level encryption.
- Automatic encryption is an enterprise only feature that only
- applies to operations on a collection. Automatic encryption is not
+ Automatic client-side field level encryption requires MongoDB 4.2
+ enterprise or a MongoDB 4.2 Atlas cluster. Automatic encryption is not
supported for operations on a database or view and will result in
- error. To bypass automatic encryption (but enable automatic
- decryption), set ``bypass_auto_encryption=True`` in
- AutoEncryptionOpts.
+ error.
- Explicit encryption/decryption and automatic decryption is a
- community feature. A MongoClient configured with
- bypassAutoEncryption=true will still automatically decrypt.
+ Although automatic encryption requires MongoDB 4.2 enterprise or a
+ MongoDB 4.2 Atlas cluster, automatic *decryption* is supported for all
+ users. To configure automatic *decryption* without automatic
+ *encryption* set ``bypass_auto_encryption=True``. Explicit
+ encryption and explicit decryption is also supported for all users
+ with the :class:`~pymongo.encryption.ClientEncryption` class.
- .. note:: Support for client side encryption is in beta.
- Backwards-breaking changes may be made before the final release.
+ See :ref:`automatic-client-side-encryption` for an example.
:Parameters:
- `kms_providers`: Map of KMS provider options. Two KMS providers
diff --git a/pymongo/mongo_client.py b/pymongo/mongo_client.py
index 8220a5e44..08a381f53 100644
--- a/pymongo/mongo_client.py
+++ b/pymongo/mongo_client.py
@@ -481,9 +481,8 @@ class MongoClient(common.BaseObject):
- `auto_encryption_opts`: A
:class:`~pymongo.encryption_options.AutoEncryptionOpts` which
configures this client to automatically encrypt collection commands
- and automatically decrypt results. **Support for client side
- encryption is in beta. Backwards-breaking changes may be made
- before the final release.**
+ and automatically decrypt results. See
+ :ref:`automatic-client-side-encryption` for an example.
.. mongodoc:: connections
diff --git a/setup.py b/setup.py
index 68d9c3e89..4167c3c7a 100755
--- a/setup.py
+++ b/setup.py
@@ -318,7 +318,7 @@ ext_modules = [Extension('bson._cbson',
'bson/buffer.c'])]
extras_require = {
- 'encryption': ['pymongocrypt'], # For client side field level encryption.
+ 'encryption': ['pymongocrypt<2.0.0'],
'snappy': ['python-snappy'],
'zstd': ['zstandard'],
}