@@ -446,6 +446,106 @@ def create_key_vault(vault, *data_keys):
446
446
return vault
447
447
448
448
449
+ class TestDataKeyDoubleEncryption (EncryptionIntegrationTest ):
450
+
451
+ @classmethod
452
+ @unittest .skipUnless (all (AWS_CREDS .values ()),
453
+ 'AWS environment credentials are not set' )
454
+ def setUpClass (cls ):
455
+ super (TestDataKeyDoubleEncryption , cls ).setUpClass ()
456
+
457
+ @staticmethod
458
+ def kms_providers ():
459
+ return {'aws' : AWS_CREDS , 'local' : {'key' : LOCAL_MASTER_KEY }}
460
+
461
+ def test_data_key (self ):
462
+ self .client .db .coll .drop ()
463
+ vault = create_key_vault (self .client .admin .datakeys )
464
+ self .addCleanup (vault .drop )
465
+
466
+ # Configure the encrypted field via the local schema_map option.
467
+ schemas = {
468
+ "db.coll" : {
469
+ "bsonType" : "object" ,
470
+ "properties" : {
471
+ "encrypted_placeholder" : {
472
+ "encrypt" : {
473
+ "keyId" : "/placeholder" ,
474
+ "bsonType" : "string" ,
475
+ "algorithm" : "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
476
+ }
477
+ }
478
+ }
479
+ }
480
+ }
481
+ opts = AutoEncryptionOpts (
482
+ self .kms_providers (), 'admin.datakeys' , schema_map = schemas )
483
+ client_encrypted = rs_or_single_client (
484
+ auto_encryption_opts = opts , uuidRepresentation = 'standard' )
485
+ self .addCleanup (client_encrypted .close )
486
+
487
+ client_encryption = ClientEncryption (
488
+ self .kms_providers (), 'admin.datakeys' , client_context .client )
489
+ self .addCleanup (client_encryption .close )
490
+
491
+ # Local create data key.
492
+ local_datakey_id = client_encryption .create_data_key (
493
+ 'local' , key_alt_names = ['local_altname' ])
494
+ self .assertIsInstance (local_datakey_id , uuid .UUID )
495
+ docs = list (vault .find ({'_id' : local_datakey_id }))
496
+ self .assertEqual (len (docs ), 1 )
497
+ self .assertEqual (docs [0 ]['masterKey' ]['provider' ], 'local' )
498
+
499
+ # Local encrypt by key_id.
500
+ local_encrypted = client_encryption .encrypt (
501
+ 'hello local' , Algorithm .Deterministic , key_id = local_datakey_id )
502
+ self .assertEncrypted (local_encrypted )
503
+ client_encrypted .db .coll .insert_one (
504
+ {'_id' : 'local' , 'value' : local_encrypted })
505
+ doc_decrypted = client_encrypted .db .coll .find_one ({'_id' : 'local' })
506
+ self .assertEqual (doc_decrypted ['value' ], 'hello local' )
507
+
508
+ # Local encrypt by key_alt_name.
509
+ local_encrypted_altname = client_encryption .encrypt (
510
+ 'hello local' , Algorithm .Deterministic ,
511
+ key_alt_name = 'local_altname' )
512
+ self .assertEqual (local_encrypted_altname , local_encrypted )
513
+
514
+ # AWS create data key.
515
+ master_key = {
516
+ 'region' : 'us-east-1' ,
517
+ 'key' : 'arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-'
518
+ '9f25-e30687b580d0'
519
+ }
520
+ aws_datakey_id = client_encryption .create_data_key (
521
+ 'aws' , master_key = master_key , key_alt_names = ['aws_altname' ])
522
+ self .assertIsInstance (aws_datakey_id , uuid .UUID )
523
+ docs = list (vault .find ({'_id' : aws_datakey_id }))
524
+ self .assertEqual (len (docs ), 1 )
525
+ self .assertEqual (docs [0 ]['masterKey' ]['provider' ], 'aws' )
526
+
527
+ # AWS encrypt by key_id.
528
+ aws_encrypted = client_encryption .encrypt (
529
+ 'hello aws' , Algorithm .Deterministic , key_id = aws_datakey_id )
530
+ self .assertEncrypted (aws_encrypted )
531
+ client_encrypted .db .coll .insert_one (
532
+ {'_id' : 'aws' , 'value' : aws_encrypted })
533
+ doc_decrypted = client_encrypted .db .coll .find_one ({'_id' : 'aws' })
534
+ self .assertEqual (doc_decrypted ['value' ], 'hello aws' )
535
+
536
+ # AWS encrypt by key_alt_name.
537
+ aws_encrypted_altname = client_encryption .encrypt (
538
+ 'hello aws' , Algorithm .Deterministic , key_alt_name = 'aws_altname' )
539
+ self .assertEqual (aws_encrypted_altname , aws_encrypted )
540
+
541
+ # Explicitly encrypting an auto encrypted field.
542
+ msg = ('Cannot encrypt element of type binData because schema '
543
+ 'requires that type is one of: \[ string \]' )
544
+ with self .assertRaisesRegex (EncryptionError , msg ):
545
+ client_encrypted .db .coll .insert_one (
546
+ {'encrypted_placeholder' : local_encrypted })
547
+
548
+
449
549
class TestExternalKeyVault (EncryptionIntegrationTest ):
450
550
451
551
@staticmethod
0 commit comments