o Sbۅ@s^UdZddlZddlZddlZddlZddlmZmZmZm Z z"ddl m Z ddl m Z ddlmZddlmZddlmZd ZWn eyNd ZeZYnwdd lmZmZmZdd lmZmZmZdd lm Z ddl!m"Z"ddl#m$Z$m%Z%m&Z&ddl'm(Z(ddl)m*Z*ddl+m,Z,ddl-m.Z.ddl/m0Z0ddl1m2Z2m3Z3m4Z4m5Z5ddl6m7Z7ddl8m9Z9ddl:m;Z;ddlZ>ddl?m@Z@ddlAmBZBmCZCddlDmEZEddlFmGZGddlHmIZIdZJd ZKd!ZLe e(ed"ZMe eNd#<e e%d$ZOejPd%d&ZQGd'd(d(eZRGd)d*d*eZSGd+d,d,eZTGd-d.d.eUejVZWGd/d0d0eUejVZXGd1d2d2eZYdS)3z8Support for explicit client-side field level encryption.N)AnyMappingOptionalSequence) AutoEncrypter)MongoCryptError)ExplicitEncrypter)MongoCryptOptions)MongoCryptCallbackTF) _dict_to_bsondecodeencode)STANDARD UUID_SUBTYPEBinary) CodecOptions) BSONError)DEFAULT_RAW_BSON_OPTIONSRawBSONDocument _inflate_bson)SON)_csot)Cursor) _spawn_daemon)AutoEncryptionOpts)ConfigurationErrorEncryptionErrorInvalidOperationServerSelectionTimeoutError) MongoClient)BLOCKING_IO_ERRORS) UpdateOne) PoolOptions_configured_socket) ReadConcern)BulkWriteResult DeleteResult)get_ssl_context) parse_host) WriteConcerni i')document_classZuuid_representation_DATA_KEY_OPTS)r+c cs>zdVWdStyty}zt|d}~ww)z2Context manager to wrap encryption related errors.N)r Exceptionr)excr/9/tmp/pip-target-onvjaxws/lib/python/pymongo/encryption.py_wrap_encryption_errorsHs  r1c@sTeZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ dS) _EncryptionIOcCsT||dur t||_nd|_|jttddtddd|_||_||_ d|_ dS)z8Internal class to perform I/O on behalf of pymongocrypt.NZmajority)level)w) codec_optionsZ read_concernZ write_concernF) weakrefref client_refZ with_options_KEY_VAULT_OPTSr$r)key_vault_collmongocryptd_clientopts_spawned)selfclientr:r;r<r/r/r0__init__Vs z_EncryptionIO.__init__c Cs|j}|j}|j}|jj|}|durtddddddd}tt t d}t |||d}t |t \}} t|| f|} zAz-| ||jdkrh| tt t d| |j} | s^td|| |jdksGWn tyutdwW| dS| w)zComplete a KMS request. :Parameters: - `kms_context`: A :class:`MongoCryptKmsContext`. :Returns: None NFgMbP?)connect_timeoutsocket_timeout ssl_contextrzKMS connection closedz timed out)endpointmessage kms_providerr<Z_kms_ssl_contextsgetr'maxrZclamp_remaining_KMS_CONNECT_TIMEOUTr"r( _HTTPS_PORTr#sendallZ bytes_needed settimeoutrecvOSErrorfeedr sockettimeoutclose) r>Z kms_contextrDrEproviderctxrAr<hostportconndatar/r/r0 kms_requestgsJ         z_EncryptionIO.kms_requestcCsd||jt|d}|D]}t|dtWdSWddS1s+wYdS)aGet the collection info for a namespace. The returned collection info is passed to libmongocrypt which reads the JSON schema. :Parameters: - `database`: The database on which to run listCollections. - `filter`: The filter to pass to listCollections. :Returns: The first document from the listCollections command response as BSON. )filterFN)r8Zlist_collectionsrr r,)r>databaserZcursordocr/r/r0collection_infos  "z_EncryptionIO.collection_infocCs.d|_|jjpdg}||jjt|dS)z~Spawn mongocryptd. Note this method is thread safe; at most one mongocryptd will start successfully. TZ mongocryptdN)r=r<Z_mongocryptd_spawn_pathextendZ_mongocryptd_spawn_argsr)r>argsr/r/r0spawns z_EncryptionIO.spawncCsz|js |jjs |t|t}z|j|j|td}W|j Sty<|jjr*||j|j|td}Y|j Sw)zMark a command for encryption. :Parameters: - `database`: The database on which to run this command. - `cmd`: The BSON command to run. :Returns: The marked command response from mongocryptd. r5) r=r<Z_mongocryptd_bypass_spawnrarrr;commandrraw)r>r[cmdZ inflated_cmdresr/r/r0 mark_commands"     z_EncryptionIO.mark_commandccsJ|jt|}|D]}|jVq WddS1swYdS)zYields one or more keys from the key vault. :Parameters: - `filter`: The filter to pass to find. :Returns: A generator which yields the requested keys from the key vault. N)r:findrrd)r>rZr\keyr/r/r0 fetch_keyss   "z_EncryptionIO.fetch_keyscCs@t|t}|d}t|tr|jtkrtd|j ||S)zInsert a data key into the key vault. :Parameters: - `data_key`: The data key document to insert. :Returns: The _id of the inserted data key document. _idz/data_key _id must be Binary with a UUID subtype) rr9rG isinstancersubtyper TypeErrorr:Z insert_one)r>Zdata_keyraw_docZ data_key_idr/r/r0insert_data_keys  z_EncryptionIO.insert_data_keycCst|S)zEncode a document to BSON. A document can be any mapping type (like :class:`dict`). :Parameters: - `doc`: mapping type representing a document :Returns: The encoded BSON bytes. )r )r>r]r/r/r0 bson_encodes z_EncryptionIO.bson_encodecCs*d|_d|_|jr|jd|_dSdS)zjRelease resources. Note it is not safe to call this method from __del__ or any GC hooks. N)r8r:r;rRr>r/r/r0rRs   z_EncryptionIO.closeN) __name__ __module__ __qualname__r@rYr^rargrjrprqrRr/r/r/r0r2Us0   r2c@s>eZdZdZd deeddfddZedeefddZdS) RewrapManyDataKeyResultzuResult object returned by a :meth:`~ClientEncryption.rewrap_many_data_key` operation. .. versionadded:: 4.2 Nbulk_write_resultreturncCs ||_dSNZ_bulk_write_result)r>rwr/r/r0r@ s z RewrapManyDataKeyResult.__init__cCs|jS)aDThe result of the bulk write operation used to update the key vault collection with one or more rewrapped data keys. If :meth:`~ClientEncryption.rewrap_many_data_key` does not find any matching keys to rewrap, no bulk write operation will be executed and this field will be ``None``. rzrrr/r/r0rwsz)RewrapManyDataKeyResult.bulk_write_resultry) rsrtru__doc__rr%r@propertyrwr/r/r/r0rvs rvc@s8eZdZdZddZddZddZdd Zd d Zd S) _EncrypterzEncrypts and decrypts MongoDB commands. This class is used to support automatic encryption and decryption of MongoDB commands.c Cs|jdurd}nt|jdt}|jdurd}nt|jdt}|j|_d|_dd}|jdur2|j}n|||}|jr=d}n|||}|jdd\}} ||| } t |j dt d} t || | |} t | t|j||j|j|j||jd|_d|_dS) zCreate a _Encrypter for a client. :Parameters: - `client`: The encrypted MongoClient. - `opts`: The encrypted client's :class:`AutoEncryptionOpts`. NFcSs:|jjjdur |S|jdur|jS|jddd}||_|S)Nr)Z minPoolSizeZauto_encryption_opts)optionsZ pool_optionsZ max_pool_size_internal_clientZ _duplicate)Z encrypterZ mongo_clientZinternal_clientr/r/r0_get_internal_client3s z1_Encrypter.__init__.._get_internal_client.)connectZserverSelectionTimeoutMS)Zcrypt_shared_lib_pathZcrypt_shared_lib_requiredZbypass_encryptionencrypted_fields_mapZbypass_query_analysis)Z _schema_mapr r,Z_encrypted_fields_mapZ_bypass_auto_encryptionr_key_vault_client_key_vault_namespacesplitrZ_mongocryptd_uri_MONGOCRYPTD_TIMEOUT_MSr2rr _kms_providersZ_crypt_shared_lib_pathZ_crypt_shared_lib_requiredZ_bypass_query_analysis_auto_encrypter_closed) r>r?r<Z schema_maprrkey_vault_clientZmetadata_clientdbcollr:r;Z io_callbacksr/r/r0r@ sD       z_Encrypter.__init__cCsZ|t|d|}t|j||}t|t}|WdS1s&wYdS)a!Encrypt a MongoDB command. :Parameters: - `database`: The database for this command. - `cmd`: A command document. - `codec_options`: The CodecOptions to use while encoding `cmd`. :Returns: The encrypted command to execute. FN) _check_closedr r1rencryptrr)r>r[rer5Z encoded_cmdZ encrypted_cmdZ encrypt_cmdr/r/r0r^s  $z_Encrypter.encryptcCs>|t|j|WdS1swYdS)zDecrypt a MongoDB command response. :Parameters: - `response`: A MongoDB command response as BSON. :Returns: The decrypted command response. N)rr1rdecrypt)r>responser/r/r0rqs  $z_Encrypter.decryptcCs|jrtddS)Nz"Cannot use MongoClient after close)rrrrr/r/r0r~sz_Encrypter._check_closedcCs.d|_|j|jr|jd|_dSdS)zCleanup resources.TN)rrrRrrrr/r/r0rRs    z_Encrypter.closeN) rsrtrur{r@rrrrRr/r/r/r0r}s> r}c@s&eZdZdZdZ dZ dZ dZdS) Algorithmz9An enum that defines the supported encryption algorithms.z+AEAD_AES_256_CBC_HMAC_SHA_512-Deterministicz$AEAD_AES_256_CBC_HMAC_SHA_512-RandomZIndexedZ UnindexedN)rsrtrur{Z+AEAD_AES_256_CBC_HMAC_SHA_512_DeterministicZ$AEAD_AES_256_CBC_HMAC_SHA_512_RandomZINDEXEDZ UNINDEXEDr/r/r/r0rsrc@seZdZdZdZdS) QueryTypez**(BETA)** An enum that defines the supported values for explicit encryption query_type. .. note:: Support for Queryable Encryption is in beta. Backwards-breaking changes may be made before the final release. .. versionadded:: 4.2 ZequalityN)rsrtrur{ZEQUALITYr/r/r/r0rsrc@seZdZdZ d7deeefdededede eeefddf d d Z   d8d ed e eeefd e e ede e de f ddZ    d9dedede e de ede ede ede fddZde defddZde de efddZdeefddZde defd d!Zde dedefd"d#Zdede efd$d%Zde dede efd&d'Z  d:d(eeefd)e ed e eeefdefd*d+Zd;d,d-Zd.ed/ed0eddfd1d2Zd3d4Zdrrrr5rrrr:r<r/r/r0r@s,M   zClientEncryption.__init__rF master_key key_alt_names key_materialcCsF|t|jj||||dWdS1swYdS)a Create and insert a new data key into the key vault collection. :Parameters: - `kms_provider`: The KMS provider to use. Supported values are "aws", "azure", "gcp", "kmip", and "local". - `master_key`: Identifies a KMS-specific key used to encrypt the new data key. If the kmsProvider is "local" the `master_key` is not applicable and may be omitted. If the `kms_provider` is "aws" it is required and has the following fields:: - `region` (string): Required. The AWS region, e.g. "us-east-1". - `key` (string): Required. The Amazon Resource Name (ARN) to the AWS customer. - `endpoint` (string): Optional. An alternate host to send KMS requests to. May include port number, e.g. "kms.us-east-1.amazonaws.com:443". If the `kms_provider` is "azure" it is required and has the following fields:: - `keyVaultEndpoint` (string): Required. Host with optional port, e.g. "example.vault.azure.net". - `keyName` (string): Required. Key name in the key vault. - `keyVersion` (string): Optional. Version of the key to use. If the `kms_provider` is "gcp" it is required and has the following fields:: - `projectId` (string): Required. The Google cloud project ID. - `location` (string): Required. The GCP location, e.g. "us-east1". - `keyRing` (string): Required. Name of the key ring that contains the key to use. - `keyName` (string): Required. Name of the key to use. - `keyVersion` (string): Optional. Version of the key to use. - `endpoint` (string): Optional. Host with optional port. Defaults to "cloudkms.googleapis.com". If the `kms_provider` is "kmip" it is optional and has the following fields:: - `keyId` (string): Optional. `keyId` is the KMIP Unique Identifier to a 96 byte KMIP Secret Data managed object. If keyId is omitted, the driver creates a random 96 byte KMIP Secret Data managed object. - `endpoint` (string): Optional. Host with optional port, e.g. "example.vault.azure.net:". - `key_alt_names` (optional): An optional list of string alternate names used to reference a key. If a key is created with alternate names, then encryption may refer to the key by the unique alternate name instead of by ``key_id``. The following example shows creating and referring to a data key by alternate name:: client_encryption.create_data_key("local", keyAltNames=["name1"]) # reference the key with the alternate name client_encryption.encrypt("457-55-5462", keyAltName="name1", algorithm=Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Random) - `key_material` (optional): Sets the custom key material to be used by the data key for encryption and decryption. :Returns: The ``_id`` of the created data key document as a :class:`~bson.binary.Binary` with subtype :data:`~bson.binary.UUID_SUBTYPE`. .. versionchanged:: 4.2 Added the `key_material` parameter. )rrrN)rr1rcreate_data_key)r>rFrrrr/r/r0rsM$z ClientEncryption.create_data_keyvalue algorithmkey_id key_alt_name query_typecontention_factorc Cs||durt|tr|jtkstdtd|i|jd}t|j j ||||||d}t |dWdS1s?wYdS)aVEncrypt a BSON value with a given key and algorithm. Note that exactly one of ``key_id`` or ``key_alt_name`` must be provided. :Parameters: - `value`: The BSON value to encrypt. - `algorithm` (string): The encryption algorithm to use. See :class:`Algorithm` for some valid options. - `key_id`: Identifies a data key by ``_id`` which must be a :class:`~bson.binary.Binary` with subtype 4 ( :attr:`~bson.binary.UUID_SUBTYPE`). - `key_alt_name`: Identifies a key vault document by 'keyAltName'. - `query_type` (str): **(BETA)** The query type to execute. See :class:`QueryType` for valid options. - `contention_factor` (int): **(BETA)** The contention factor to use when the algorithm is :attr:`Algorithm.INDEXED`. An integer value *must* be given when the :attr:`Algorithm.INDEXED` algorithm is used. .. note:: `query_type` and `contention_factor` are part of the Queryable Encryption beta. Backwards-breaking changes may be made before the final release. :Returns: The encrypted value, a :class:`~bson.binary.Binary` with subtype 6. .. versionchanged:: 4.2 Added the `query_type` and `contention_factor` parameters. Nz2key_id must be a bson.binary.Binary with subtype 4vrb)rrrr) rrlrrmrrnr rr1rrr ) r>rrrrrrr]Z encrypted_docr/r/r0rus&( $zClientEncryption.encryptcCsx|t|tr|jdkstdttd|i}|j|}t ||j ddWdS1s5wYdS)zDecrypt an encrypted value. :Parameters: - `value` (Binary): The encrypted value, a :class:`~bson.binary.Binary` with subtype 6. :Returns: The decrypted BSON value. zrr]Z decrypted_docr/r/r0rs   $zClientEncryption.decryptidcC||jd|iS)a+Get a data key by id. :Parameters: - `id` (Binary): The UUID of a key a which must be a :class:`~bson.binary.Binary` with subtype 4 ( :attr:`~bson.binary.UUID_SUBTYPE`). :Returns: The key document. .. versionadded:: 4.2 rkrrZfind_oner>rr/r/r0get_key zClientEncryption.get_keycCs||jiS)zGet all of the data keys. :Returns: An instance of :class:`~pymongo.cursor.Cursor` over the data key documents. .. versionadded:: 4.2 )rrrhrrr/r/r0get_keyss zClientEncryption.get_keyscCr)agDelete a key document in the key vault collection that has the given ``key_id``. :Parameters: - `id` (Binary): The UUID of a key a which must be a :class:`~bson.binary.Binary` with subtype 4 ( :attr:`~bson.binary.UUID_SUBTYPE`). :Returns: The delete result. .. versionadded:: 4.2 rk)rrZ delete_onerr/r/r0 delete_keyrzClientEncryption.delete_keycCs&|dd|ii}|jd|i|S)aAdd ``key_alt_name`` to the set of alternate names in the key document with UUID ``key_id``. :Parameters: - ``id``: The UUID of a key a which must be a :class:`~bson.binary.Binary` with subtype 4 ( :attr:`~bson.binary.UUID_SUBTYPE`). - ``key_alt_name``: The key alternate name to add. :Returns: The previous version of the key document. .. versionadded:: 4.2 z $addToSet keyAltNamesrkrrZfind_one_and_update)r>rrupdater/r/r0add_key_alt_names z!ClientEncryption.add_key_alt_namecCr)a Get a key document in the key vault collection that has the given ``key_alt_name``. :Parameters: - `key_alt_name`: (str): The key alternate name of the key to get. :Returns: The key document. .. versionadded:: 4.2 rr)r>rr/r/r0get_key_by_alt_names z$ClientEncryption.get_key_by_alt_namec CsN|ddddd|ggiddddd |gid igiiig}|jd |i|S) a.Remove ``key_alt_name`` from the set of keyAltNames in the key document with UUID ``id``. Also removes the ``keyAltNames`` field from the key document if it would otherwise be empty. :Parameters: - ``id``: The UUID of a key a which must be a :class:`~bson.binary.Binary` with subtype 4 ( :attr:`~bson.binary.UUID_SUBTYPE`). - ``key_alt_name``: The key alternate name to remove. :Returns: Returns the previous version of the key document. .. versionadded:: 4.2 $setrz$condz$eqz $keyAltNamesz$$REMOVEz$filterz$nez$$this)inputZcondrkr)r>rrZpipeliner/r/r0remove_key_alt_names"  z$ClientEncryption.remove_key_alt_namerZrSc Cs|t|j|||}|durtWdSWdn1s(wYt|t}g}|dD]}|d|ddddid}td |d i|} || q8|s\tS|j |} t| S) a4Decrypts and encrypts all matching data keys in the key vault with a possibly new `master_key` value. :Parameters: - `filter`: A document used to filter the data keys. - `provider`: The new KMS provider to use to encrypt the data keys, or ``None`` to use the current KMS provider(s). - ``master_key``: The master key fields corresponding to the new KMS provider when ``provider`` is not ``None``. :Returns: A :class:`RewrapManyDataKeyResult`. .. versionadded:: 4.2 Nr keyMaterial masterKey)rrZ updateDateT)rz $currentDaterk) rr1rrewrap_many_data_keyrvrrr!appendrZ bulk_write) r>rZrSrZ raw_resultroZ replacementsriZ update_modelopresultr/r/r0r3s(    z%ClientEncryption.rewrap_many_data_keycCs|Sryr/rrr/r/r0 __enter__[szClientEncryption.__enter__exc_typeexc_valexc_tbcCs |dSry)rR)r>rrrr/r/r0__exit__^s zClientEncryption.__exit__cCs|jdur tddS)Nz"Cannot use closed ClientEncryption)rrrrr/r/r0ras zClientEncryption._check_closedcCs.|jr|j|jd|_d|_dSdS)aERelease resources. Note that using this class in a with-statement will automatically call :meth:`close`:: with ClientEncryption(...) as client_encryption: encrypted = client_encryption.encrypt(value, ...) decrypted = client_encryption.decrypt(encrypted) N)rrRrrrr/r/r0rRes    zClientEncryption.closery)NNN)NNNN)NN)rxr)rxN)!rsrtrur{rstrrrrrr@rbytesrrintrrrrrrr&rrrrrvrrrrrRr/r/r/r0rs  n  Z : (  (r)Zr{ contextlibenumrPr6typingrrrrZpymongocrypt.auto_encrypterrZpymongocrypt.errorsrZpymongocrypt.explicit_encrypterrZpymongocrypt.mongocryptr Zpymongocrypt.state_machiner r ImportErrorobjectZbsonr r r Z bson.binaryrrrZbson.codec_optionsrZ bson.errorsrZ bson.raw_bsonrrrZbson.sonrZpymongorZpymongo.cursorrZpymongo.daemonrZpymongo.encryption_optionsrZpymongo.errorsrrrrZpymongo.mongo_clientrZpymongo.networkr Zpymongo.operationsr!Z pymongo.poolr"r#Zpymongo.read_concernr$Zpymongo.resultsr%r&Zpymongo.ssl_supportr'Zpymongo.uri_parserr(Zpymongo.write_concernr)rJrIrr,__annotations__r9contextmanagerr1r2rvr}rEnumrrrr/r/r/r0sf                       2q