def test_mongocrypt_aws_session_token(self): kms_providers = { 'aws': { 'accessKeyId': 'foo', 'secretAccessKey': 'foo', 'sessionToken': 'token' } } opts = MongoCryptOptions(kms_providers) mc = MongoCrypt(opts, MockCallback()) mc.close()
def test_mongocrypt(self): kms_providers = { 'aws': { 'accessKeyId': 'foo', 'secretAccessKey': 'foo' } } opts = MongoCryptOptions(kms_providers) mc = MongoCrypt(opts) mc.close() mc.close()
def test_setopt_kms_provider_base64_or_bytes(self): test_fields = [("local", "key"), ("gcp", "privateKey")] callback = MockCallback() base_kms_dict = { 'local': { 'key': b'\x00' * 96 }, 'gcp': { 'email': '*****@*****.**', 'privateKey': b'\x00' } } for f1, f2 in test_fields: kms_dict = copy.deepcopy(base_kms_dict) # Case 1: pass key as string containing bytes (valid) kms_dict[f1][f2] = b'\x00' * 96 options = MongoCryptOptions(kms_dict) mc = MongoCrypt(options, callback) mc.close() # Case 2: pass key as base64-encoded unicode literal (valid) kms_dict[f1][f2] = to_base64(b'\x00' * 96) options = MongoCryptOptions(kms_dict) mc = MongoCrypt(options, callback) mc.close() # Case 3: pass key as unicode string containing bytes (invalid) kms_dict[f1][f2] = unicode_type(b'\x00' * 96) options = MongoCryptOptions(kms_dict) with self.assertRaisesRegex( MongoCryptError, "unable to parse base64 from UTF-8 field %s.%s" % (f1, f2)): MongoCrypt(options, callback) # Case 4: pass key as base64-encoded string (invalid) # Only applicable to "local" as key length is not validated for gcp. kms_dict = copy.deepcopy(base_kms_dict) kms_dict['local']['key'] = base64.b64encode(b'\x00' * 96) options = MongoCryptOptions(kms_dict) with self.assertRaisesRegex(MongoCryptError, "local key must be 96 bytes"): MongoCrypt(options, callback)
class AutoEncrypter(object): def __init__(self, callback, mongo_crypt_opts): """Encrypts and decrypts MongoDB commands. This class is used by a driver to support automatic encryption and decryption of MongoDB commands. :Parameters: - `callback`: A :class:`MongoCryptCallback`. - `mongo_crypt_opts`: A :class:`MongoCryptOptions`. """ self.callback = callback self.mongocrypt = MongoCrypt(mongo_crypt_opts) def encrypt(self, database, cmd): """Encrypt a MongoDB command. :Parameters: - `database`: The database for this command. - `cmd`: A MongoDB command as BSON. :Returns: The encrypted command. """ with self.mongocrypt.encryption_context(database, cmd) as ctx: return run_state_machine(ctx, self.callback) def decrypt(self, response): """Decrypt a MongoDB command response. :Parameters: - `response`: A MongoDB command response as BSON. :Returns: The decrypted command response. """ with self.mongocrypt.decryption_context(response) as ctx: return run_state_machine(ctx, self.callback) def close(self): """Cleanup resources.""" self.mongocrypt.close() self.callback.close()
class ExplicitEncrypter(object): def __init__(self, callback, mongo_crypt_opts): """Encrypts and decrypts BSON values. This class is used by a driver to support explicit encryption and decryption of individual fields in a BSON document. :Parameters: - `callback`: A :class:`MongoCryptCallback`. - `mongo_crypt_opts`: A :class:`MongoCryptOptions`. """ self.callback = callback if mongo_crypt_opts.schema_map is not None: raise ValueError("mongo_crypt_opts.schema_map must be None") self.mongocrypt = MongoCrypt(mongo_crypt_opts, callback) def create_data_key(self, kms_provider, master_key=None, key_alt_names=None): """Creates a data key used for explicit encryption. :Parameters: - `kms_provider`: The KMS provider to use. Supported values are "aws", "azure", "gcp", "kmip", and "local". - `master_key`: See DataKeyOpts. - `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 ``_id``. :Returns: The _id of the created data key document. """ # CDRIVER-3275 each key_alt_name needs to be wrapped in a bson # document. encoded_names = [] if key_alt_names is not None: for name in key_alt_names: encoded_names.append( self.callback.bson_encode({'keyAltName': name})) opts = DataKeyOpts(master_key, encoded_names) with self.mongocrypt.data_key_context(kms_provider, opts) as ctx: key = run_state_machine(ctx, self.callback) return self.callback.insert_data_key(key) def encrypt(self, value, algorithm, key_id=None, key_alt_name=None): """Encrypts a BSON value. Note that exactly one of ``key_id`` or ``key_alt_name`` must be provided. :Parameters: - `value` (bytes): The BSON value to encrypt. - `algorithm` (string): The encryption algorithm to use. See :class:`Algorithm` for some valid options. - `key_id` (bytes): The bytes of the binary subtype 4 ``_id`` data key. For example, ``uuid.bytes`` or ``bytes(bson_binary)``. - `key_alt_name` (string): Identifies a key vault document by 'keyAltName'. :Returns: The encrypted BSON value. """ # CDRIVER-3275 key_alt_name needs to be wrapped in a bson document. if key_alt_name is not None: key_alt_name = self.callback.bson_encode( {'keyAltName': key_alt_name}) opts = ExplicitEncryptOpts(algorithm, key_id, key_alt_name) with self.mongocrypt.explicit_encryption_context(value, opts) as ctx: return run_state_machine(ctx, self.callback) def decrypt(self, value): """Decrypts a BSON value. :Parameters: - `value`: The encoded document to decrypt, which must be in the form { "v" : encrypted BSON value }}. :Returns: The decrypted BSON value. """ with self.mongocrypt.explicit_decryption_context(value) as ctx: return run_state_machine(ctx, self.callback) def close(self): """Cleanup resources.""" self.mongocrypt.close()