mongo 2.18.0.beta1 → 2.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/mongo/bulk_write.rb +8 -2
- data/lib/mongo/client.rb +19 -5
- data/lib/mongo/client_encryption.rb +86 -4
- data/lib/mongo/cluster.rb +6 -4
- data/lib/mongo/collection/view/aggregation.rb +3 -0
- data/lib/mongo/collection/view/change_stream.rb +9 -0
- data/lib/mongo/collection/view/iterable.rb +1 -0
- data/lib/mongo/collection/view/readable.rb +11 -3
- data/lib/mongo/collection.rb +9 -1
- data/lib/mongo/config.rb +11 -0
- data/lib/mongo/crypt/auto_encrypter.rb +49 -21
- data/lib/mongo/crypt/binding.rb +73 -48
- data/lib/mongo/crypt/data_key_context.rb +6 -1
- data/lib/mongo/crypt/encryption_io.rb +66 -0
- data/lib/mongo/crypt/explicit_encrypter.rb +116 -5
- data/lib/mongo/crypt/explicit_encryption_context.rb +3 -8
- data/lib/mongo/crypt/handle.rb +26 -8
- data/lib/mongo/crypt/kms/aws.rb +11 -3
- data/lib/mongo/crypt/kms/azure.rb +14 -6
- data/lib/mongo/crypt/kms/gcp.rb +12 -5
- data/lib/mongo/crypt/kms/kmip.rb +15 -9
- data/lib/mongo/crypt/kms/local.rb +9 -1
- data/lib/mongo/crypt/kms/master_key_document.rb +1 -1
- data/lib/mongo/crypt/rewrap_many_data_key_context.rb +46 -0
- data/lib/mongo/crypt/rewrap_many_data_key_result.rb +37 -0
- data/lib/mongo/crypt/status.rb +8 -2
- data/lib/mongo/crypt.rb +2 -0
- data/lib/mongo/database.rb +10 -27
- data/lib/mongo/error/missing_file_chunk.rb +8 -2
- data/lib/mongo/grid/stream/read.rb +6 -0
- data/lib/mongo/index/view.rb +1 -0
- data/lib/mongo/operation/create/op_msg.rb +1 -13
- data/lib/mongo/operation/distinct/op_msg.rb +4 -1
- data/lib/mongo/protocol/msg.rb +0 -16
- data/lib/mongo/server/connection_pool.rb +5 -4
- data/lib/mongo/server/monitor/connection.rb +10 -4
- data/lib/mongo/server/monitor.rb +4 -0
- data/lib/mongo/server/push_monitor.rb +4 -0
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo.rb +2 -0
- data/spec/README.md +14 -0
- data/spec/integration/change_stream_spec.rb +1 -1
- data/spec/integration/client_construction_spec.rb +73 -7
- data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +165 -164
- data/spec/integration/client_side_encryption/decryption_events_prose_spec.rb +158 -0
- data/spec/integration/client_side_encryption/explicit_queryable_encryption_spec.rb +5 -5
- data/spec/integration/client_side_encryption/kms_tls_options_spec.rb +50 -8
- data/spec/integration/client_side_encryption/unique_index_on_key_alt_names_prose_spec.rb +85 -0
- data/spec/integration/ocsp_verifier_spec.rb +1 -1
- data/spec/integration/reconnect_spec.rb +2 -0
- data/spec/integration/sdam_events_spec.rb +40 -0
- data/spec/integration/srv_monitoring_spec.rb +1 -0
- data/spec/integration/srv_spec.rb +1 -0
- data/spec/lite_spec_helper.rb +5 -4
- data/spec/mongo/bulk_write_spec.rb +13 -0
- data/spec/mongo/client_construction_spec.rb +45 -2
- data/spec/mongo/client_encryption_spec.rb +0 -12
- data/spec/mongo/client_spec.rb +1 -1
- data/spec/mongo/collection/view/aggregation_spec.rb +119 -0
- data/spec/mongo/collection/view/readable_spec.rb +630 -5
- data/spec/mongo/collection_spec.rb +32 -0
- data/spec/mongo/crypt/auto_encrypter_spec.rb +110 -0
- data/spec/mongo/crypt/binding/context_spec.rb +3 -35
- data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
- data/spec/mongo/crypt/explicit_encryption_context_spec.rb +8 -3
- data/spec/mongo/crypt/handle_spec.rb +39 -3
- data/spec/mongo/crypt/kms/credentials_spec.rb +0 -47
- data/spec/mongo/index/view_spec.rb +56 -0
- data/spec/mongo/operation/create/op_msg_spec.rb +0 -42
- data/spec/mongo/server/connection_pool_spec.rb +26 -4
- data/spec/mongo/socket/ssl_spec.rb +3 -3
- data/spec/runners/crud/requirement.rb +6 -1
- data/spec/runners/crud/test.rb +1 -1
- data/spec/runners/transactions/spec.rb +2 -2
- data/spec/runners/transactions/test.rb +4 -20
- data/spec/runners/transactions.rb +2 -2
- data/spec/runners/unified/assertions.rb +32 -2
- data/spec/runners/unified/change_stream_operations.rb +3 -0
- data/spec/runners/unified/client_side_encryption_operations.rb +83 -0
- data/spec/runners/unified/crud_operations.rb +17 -2
- data/spec/runners/unified/ddl_operations.rb +27 -2
- data/spec/runners/unified/grid_fs_operations.rb +21 -0
- data/spec/runners/unified/test.rb +59 -1
- data/spec/shared/lib/mrss/docker_runner.rb +2 -0
- data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
- data/spec/shared/shlib/set_env.sh +3 -0
- data/spec/solo/clean_exit_spec.rb +5 -0
- data/spec/spec_tests/client_side_encryption_spec.rb +1 -1
- data/spec/spec_tests/client_side_encryption_unified_spec.rb +16 -0
- data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +298 -0
- data/spec/spec_tests/data/client_side_encryption/create-and-createIndexes.yml +58 -0
- data/spec/spec_tests/data/client_side_encryption/fle2-Delete.yml +1 -1
- data/spec/spec_tests/data/client_side_encryption/fle2-EncryptedFields-vs-jsonSchema.yml +1 -1
- data/spec/spec_tests/data/client_side_encryption/fle2-FindOneAndUpdate.yml +2 -2
- data/spec/spec_tests/data/client_side_encryption/fle2-InsertFind-Indexed.yml +1 -1
- data/spec/spec_tests/data/client_side_encryption/fle2-Update.yml +2 -2
- data/spec/spec_tests/data/client_side_encryption/unified/addKeyAltName.yml +194 -0
- data/spec/spec_tests/data/client_side_encryption/unified/createDataKey-kms_providers-invalid.yml +67 -0
- data/spec/spec_tests/data/client_side_encryption/unified/createDataKey.yml +309 -0
- data/spec/spec_tests/data/client_side_encryption/unified/deleteKey.yml +159 -0
- data/spec/spec_tests/data/client_side_encryption/unified/getKey.yml +105 -0
- data/spec/spec_tests/data/client_side_encryption/unified/getKeyByAltName.yml +104 -0
- data/spec/spec_tests/data/client_side_encryption/unified/getKeys.yml +122 -0
- data/spec/spec_tests/data/client_side_encryption/unified/removeKeyAltName.yml +157 -0
- data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-decrypt_failure.yml +69 -0
- data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-encrypt_failure.yml +122 -0
- data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey.yml +432 -0
- data/spec/spec_tests/data/client_side_encryption/validatorAndPartialFieldExpression.yml +166 -0
- data/spec/spec_tests/data/command_monitoring_unified/bulkWrite.yml +68 -0
- data/spec/spec_tests/data/command_monitoring_unified/command.yml +50 -0
- data/spec/spec_tests/data/command_monitoring_unified/deleteMany.yml +79 -0
- data/spec/spec_tests/data/command_monitoring_unified/deleteOne.yml +79 -0
- data/spec/spec_tests/data/command_monitoring_unified/find.yml +254 -0
- data/spec/spec_tests/data/command_monitoring_unified/insertMany.yml +79 -0
- data/spec/spec_tests/data/command_monitoring_unified/insertOne.yml +77 -0
- data/spec/spec_tests/data/command_monitoring_unified/unacknowledgedBulkWrite.yml +55 -0
- data/spec/spec_tests/data/command_monitoring_unified/updateMany.yml +87 -0
- data/spec/spec_tests/data/command_monitoring_unified/updateOne.yml +118 -0
- data/spec/spec_tests/data/crud_unified/distinct-comment.yml +98 -0
- data/spec/spec_tests/data/gridfs_unified/delete.yml +198 -0
- data/spec/spec_tests/data/gridfs_unified/download.yml +241 -0
- data/spec/spec_tests/data/gridfs_unified/downloadByName.yml +159 -0
- data/spec/spec_tests/data/gridfs_unified/upload-disableMD5.yml +92 -0
- data/spec/spec_tests/data/gridfs_unified/upload.yml +288 -0
- data/spec/spec_tests/gridfs_unified_spec.rb +13 -0
- data/spec/stress/connection_pool_timing_spec.rb +2 -2
- data/spec/support/background_thread_registry.rb +3 -13
- data/spec/support/certificates/atlas-ocsp-ca.crt +40 -47
- data/spec/support/certificates/atlas-ocsp.crt +101 -106
- data/spec/support/crypt.rb +57 -13
- data/spec/support/macros.rb +10 -0
- data/spec/support/spec_config.rb +4 -0
- data.tar.gz.sig +0 -0
- metadata +1271 -1219
- metadata.gz.sig +0 -0
- data/spec/spec_tests/command_monitoring_spec.rb +0 -71
- data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +0 -49
- data/spec/spec_tests/data/command_monitoring/command.yml +0 -61
- data/spec/spec_tests/data/command_monitoring/deleteMany.yml +0 -55
- data/spec/spec_tests/data/command_monitoring/deleteOne.yml +0 -55
- data/spec/spec_tests/data/command_monitoring/find.yml +0 -266
- data/spec/spec_tests/data/command_monitoring/insertMany.yml +0 -75
- data/spec/spec_tests/data/command_monitoring/insertOne.yml +0 -51
- data/spec/spec_tests/data/command_monitoring/unacknowledgedBulkWrite.yml +0 -34
- data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -65
- data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -90
data/lib/mongo/crypt/binding.rb
CHANGED
|
@@ -475,6 +475,38 @@ module Mongo
|
|
|
475
475
|
end
|
|
476
476
|
end
|
|
477
477
|
|
|
478
|
+
# @!method self.mongocrypt_ctx_setopt_key_material(ctx, binary)
|
|
479
|
+
# @api private
|
|
480
|
+
#
|
|
481
|
+
# When creating a data key, set a custom key material to use for
|
|
482
|
+
# encrypting data.
|
|
483
|
+
# @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object.
|
|
484
|
+
# @param [ FFI::Pointer ] binary A pointer to a mongocrypt_binary_t
|
|
485
|
+
# object that references the data encryption key to use.
|
|
486
|
+
# @return [ Boolean ] Whether the custom key material was successfully set.
|
|
487
|
+
# @note Do not initialize ctx before calling this method.
|
|
488
|
+
attach_function(
|
|
489
|
+
:mongocrypt_ctx_setopt_key_material,
|
|
490
|
+
[:pointer, :pointer],
|
|
491
|
+
:bool
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
# Set set a custom key material to use for
|
|
495
|
+
# encrypting data.
|
|
496
|
+
#
|
|
497
|
+
# @param [ Mongo::Crypt::Context ] context A DataKeyContext
|
|
498
|
+
# @param [ BSON::Binary ] key_material 96 bytes of custom key material
|
|
499
|
+
#
|
|
500
|
+
# @raise [ Mongo::Error::CryptError ] If the key material is not 96 bytes.
|
|
501
|
+
def self.ctx_setopt_key_material(context, key_material)
|
|
502
|
+
data = {'keyMaterial' => key_material}.to_bson.to_s
|
|
503
|
+
Binary.wrap_string(data) do |data_p|
|
|
504
|
+
check_ctx_status(context) do
|
|
505
|
+
mongocrypt_ctx_setopt_key_material(context.ctx_p, data_p)
|
|
506
|
+
end
|
|
507
|
+
end
|
|
508
|
+
end
|
|
509
|
+
|
|
478
510
|
# @!method self.mongocrypt_ctx_setopt_algorithm(ctx, algorithm, len)
|
|
479
511
|
# @api private
|
|
480
512
|
#
|
|
@@ -562,6 +594,40 @@ module Mongo
|
|
|
562
594
|
end
|
|
563
595
|
end
|
|
564
596
|
|
|
597
|
+
# @!method self.mongocrypt_ctx_datakey_init(ctx, filter)
|
|
598
|
+
# @api private
|
|
599
|
+
#
|
|
600
|
+
# Initialize a context to rewrap datakeys.
|
|
601
|
+
#
|
|
602
|
+
# @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object.
|
|
603
|
+
# @param [ FFI::Pointer ] filter A pointer to a mongocrypt_binary_t object
|
|
604
|
+
# that represents filter to use for the find command on the key vault
|
|
605
|
+
# collection to retrieve datakeys to rewrap.
|
|
606
|
+
#
|
|
607
|
+
# @return [ Boolean ] Whether the initialization was successful.
|
|
608
|
+
attach_function(
|
|
609
|
+
:mongocrypt_ctx_rewrap_many_datakey_init,
|
|
610
|
+
[:pointer, :pointer],
|
|
611
|
+
:bool
|
|
612
|
+
)
|
|
613
|
+
|
|
614
|
+
# Initialize a context to rewrap datakeys.
|
|
615
|
+
#
|
|
616
|
+
# @param [ Mongo::Crypt::Context ] context
|
|
617
|
+
# @param [ BSON::Document ] filter BSON Document
|
|
618
|
+
# that represents filter to use for the find command on the key vault
|
|
619
|
+
# collection to retrieve datakeys to rewrap.
|
|
620
|
+
#
|
|
621
|
+
# @return [ Boolean ] Whether the initialization was successful.
|
|
622
|
+
def self.ctx_rewrap_many_datakey_init(context, filter)
|
|
623
|
+
filter_data = filter.to_bson.to_s
|
|
624
|
+
Binary.wrap_string(filter_data) do |data_p|
|
|
625
|
+
check_ctx_status(context) do
|
|
626
|
+
mongocrypt_ctx_rewrap_many_datakey_init(context.ctx_p, data_p)
|
|
627
|
+
end
|
|
628
|
+
end
|
|
629
|
+
end
|
|
630
|
+
|
|
565
631
|
# @!method self.mongocrypt_ctx_encrypt_init(ctx, db, db_len, cmd)
|
|
566
632
|
# @api private
|
|
567
633
|
#
|
|
@@ -974,7 +1040,7 @@ module Mongo
|
|
|
974
1040
|
status = Status.new
|
|
975
1041
|
|
|
976
1042
|
mongocrypt_kms_ctx_status(kms_context.kms_ctx_p, status.ref)
|
|
977
|
-
status.raise_crypt_error
|
|
1043
|
+
status.raise_crypt_error(kms: true)
|
|
978
1044
|
end
|
|
979
1045
|
end
|
|
980
1046
|
|
|
@@ -1319,48 +1385,6 @@ module Mongo
|
|
|
1319
1385
|
end
|
|
1320
1386
|
end
|
|
1321
1387
|
|
|
1322
|
-
enum :mongocrypt_index_type, [
|
|
1323
|
-
:none, 1,
|
|
1324
|
-
:equality
|
|
1325
|
-
]
|
|
1326
|
-
|
|
1327
|
-
# @!method self.mongocrypt_ctx_setopt_index_type(ctx, mongocrypt_index_type)
|
|
1328
|
-
# @api private
|
|
1329
|
-
#
|
|
1330
|
-
# Set the index type used for explicit encryption.
|
|
1331
|
-
# The index type is only used for FLE 2 encryption.
|
|
1332
|
-
#
|
|
1333
|
-
# @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object.
|
|
1334
|
-
# @param[ mongocrypt_index_type ] index_type Type of the index.
|
|
1335
|
-
#
|
|
1336
|
-
# @return [ Boolean ] Whether setting this option succeeded.
|
|
1337
|
-
attach_function(
|
|
1338
|
-
:mongocrypt_ctx_setopt_index_type,
|
|
1339
|
-
[
|
|
1340
|
-
:pointer,
|
|
1341
|
-
:mongocrypt_index_type
|
|
1342
|
-
],
|
|
1343
|
-
:bool
|
|
1344
|
-
)
|
|
1345
|
-
|
|
1346
|
-
# Set the index type used for explicit encryption.
|
|
1347
|
-
# The index type is only used for FLE 2 encryption.
|
|
1348
|
-
#
|
|
1349
|
-
# @param [ Mongo::Crypt::Context ] context Explicit encryption context.
|
|
1350
|
-
# @param [ Symbol ] :mongocrypt_index_type index_type Type of the index.
|
|
1351
|
-
# Allowed values are :none, :equality.
|
|
1352
|
-
#
|
|
1353
|
-
# @raise [ Mongo::Error::CryptError ] If the operation failed.
|
|
1354
|
-
def self.ctx_setopt_index_type(context, index_type)
|
|
1355
|
-
check_ctx_status(context) do
|
|
1356
|
-
mongocrypt_ctx_setopt_index_type(context.ctx_p, index_type)
|
|
1357
|
-
end
|
|
1358
|
-
end
|
|
1359
|
-
|
|
1360
|
-
enum :mongocrypt_query_type, [
|
|
1361
|
-
:equality, 1
|
|
1362
|
-
]
|
|
1363
|
-
|
|
1364
1388
|
# @!method self.mongocrypt_ctx_setopt_query_type(ctx, mongocrypt_query_type)
|
|
1365
1389
|
# @api private
|
|
1366
1390
|
#
|
|
@@ -1368,14 +1392,16 @@ module Mongo
|
|
|
1368
1392
|
# The query type is only used for indexed FLE 2 encryption.
|
|
1369
1393
|
#
|
|
1370
1394
|
# @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object.
|
|
1371
|
-
# @param [
|
|
1395
|
+
# @param [ String ] query_type Type of the query.
|
|
1396
|
+
# @param [ Integer ] len The length of the query type string.
|
|
1372
1397
|
#
|
|
1373
1398
|
# @return [ Boolean ] Whether setting this option succeeded.
|
|
1374
1399
|
attach_function(
|
|
1375
1400
|
:mongocrypt_ctx_setopt_query_type,
|
|
1376
1401
|
[
|
|
1377
1402
|
:pointer,
|
|
1378
|
-
:
|
|
1403
|
+
:string,
|
|
1404
|
+
:int
|
|
1379
1405
|
],
|
|
1380
1406
|
:bool
|
|
1381
1407
|
)
|
|
@@ -1384,13 +1410,12 @@ module Mongo
|
|
|
1384
1410
|
# The query type is only used for indexed FLE 2 encryption.
|
|
1385
1411
|
#
|
|
1386
1412
|
# @param [ Mongo::Crypt::Context ] context Explicit encryption context.
|
|
1387
|
-
# @param [
|
|
1388
|
-
# Allowed value is :equality.
|
|
1413
|
+
# @param [ String ] :mongocrypt_query_type query_type Type of the query.
|
|
1389
1414
|
#
|
|
1390
1415
|
# @raise [ Mongo::Error::CryptError ] If the operation failed.
|
|
1391
1416
|
def self.ctx_setopt_query_type(context, query_type)
|
|
1392
1417
|
check_ctx_status(context) do
|
|
1393
|
-
mongocrypt_ctx_setopt_query_type(context.ctx_p, query_type)
|
|
1418
|
+
mongocrypt_ctx_setopt_query_type(context.ctx_p, query_type, -1)
|
|
1394
1419
|
end
|
|
1395
1420
|
end
|
|
1396
1421
|
|
|
@@ -34,10 +34,15 @@ module Mongo
|
|
|
34
34
|
# key document that contains master encryption key parameters.
|
|
35
35
|
# @param [ Array<String> | nil ] key_alt_names An optional array of strings specifying
|
|
36
36
|
# alternate names for the new data key.
|
|
37
|
-
|
|
37
|
+
# @param [ String | nil ] :key_material Optional
|
|
38
|
+
# 96 bytes to use as custom key material for the data key being created.
|
|
39
|
+
# If :key_material option is given, the custom key material is used
|
|
40
|
+
# for encrypting and decrypting data.
|
|
41
|
+
def initialize(mongocrypt, io, master_key_document, key_alt_names, key_material)
|
|
38
42
|
super(mongocrypt, io)
|
|
39
43
|
Binding.ctx_setopt_key_encryption_key(self, master_key_document.to_document)
|
|
40
44
|
set_key_alt_names(key_alt_names) if key_alt_names
|
|
45
|
+
Binding.ctx_setopt_key_material(self, BSON::Binary.new(key_material)) if key_material
|
|
41
46
|
initialize_ctx
|
|
42
47
|
end
|
|
43
48
|
|
|
@@ -158,6 +158,72 @@ module Mongo
|
|
|
158
158
|
end
|
|
159
159
|
end
|
|
160
160
|
|
|
161
|
+
# Adds a key_alt_name to the key_alt_names array of the key document
|
|
162
|
+
# in the key vault collection with the given id.
|
|
163
|
+
def add_key_alt_name(id, key_alt_name)
|
|
164
|
+
key_vault_collection.find_one_and_update(
|
|
165
|
+
{ _id: id },
|
|
166
|
+
{ '$addToSet' => { keyAltNames: key_alt_name } },
|
|
167
|
+
)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Removes the key document with the given id
|
|
171
|
+
# from the key vault collection.
|
|
172
|
+
def delete_key(id)
|
|
173
|
+
key_vault_collection.delete_one(_id: id)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Finds a single key document with the given id.
|
|
177
|
+
def get_key(id)
|
|
178
|
+
key_vault_collection.find(_id: id).first
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Returns a key document in the key vault collection with
|
|
182
|
+
# the given key_alt_name.
|
|
183
|
+
def get_key_by_alt_name(key_alt_name)
|
|
184
|
+
key_vault_collection.find(keyAltNames: key_alt_name).first
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Finds all documents in the key vault collection.
|
|
188
|
+
def get_keys
|
|
189
|
+
key_vault_collection.find
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Removes a key_alt_name from the key_alt_names array of the key document
|
|
193
|
+
# in the key vault collection with the given id.
|
|
194
|
+
def remove_key_alt_name(id, key_alt_name)
|
|
195
|
+
key_vault_collection.find_one_and_update(
|
|
196
|
+
{ _id: id },
|
|
197
|
+
[
|
|
198
|
+
{
|
|
199
|
+
'$set' => {
|
|
200
|
+
keyAltNames: {
|
|
201
|
+
'$cond' => [
|
|
202
|
+
{ '$eq' => [ '$keyAltNames', [ key_alt_name ] ] },
|
|
203
|
+
'$$REMOVE',
|
|
204
|
+
{
|
|
205
|
+
'$filter' => {
|
|
206
|
+
input: '$keyAltNames',
|
|
207
|
+
cond: { '$ne' => [ '$$this', key_alt_name ] }
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Apply given requests to the key vault collection using bulk write.
|
|
219
|
+
#
|
|
220
|
+
# @param [ Array<Hash> ] requests The bulk write requests.
|
|
221
|
+
#
|
|
222
|
+
# @return [ BulkWrite::Result ] The result of the operation.
|
|
223
|
+
def update_data_keys(updates)
|
|
224
|
+
key_vault_collection.bulk_write(updates)
|
|
225
|
+
end
|
|
226
|
+
|
|
161
227
|
private
|
|
162
228
|
|
|
163
229
|
def validate_key_vault_client!(key_vault_client)
|
|
@@ -40,7 +40,7 @@ module Mongo
|
|
|
40
40
|
@encryption_io = EncryptionIO.new(
|
|
41
41
|
key_vault_client: key_vault_client,
|
|
42
42
|
metadata_client: nil,
|
|
43
|
-
key_vault_namespace: key_vault_namespace
|
|
43
|
+
key_vault_namespace: key_vault_namespace,
|
|
44
44
|
)
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -52,15 +52,20 @@ module Mongo
|
|
|
52
52
|
# key document that contains master encryption key parameters.
|
|
53
53
|
# @param [ Array<String> | nil ] key_alt_names An optional array of strings specifying
|
|
54
54
|
# alternate names for the new data key.
|
|
55
|
+
# @param [ String | nil ] key_material Optional 96 bytes to use as
|
|
56
|
+
# custom key material for the data key being created.
|
|
57
|
+
# If key_material option is given, the custom key material is used
|
|
58
|
+
# for encrypting and decrypting data.
|
|
55
59
|
#
|
|
56
60
|
# @return [ BSON::Binary ] The 16-byte UUID of the new data key as a
|
|
57
61
|
# BSON::Binary object with type :uuid.
|
|
58
|
-
def create_and_insert_data_key(master_key_document, key_alt_names)
|
|
62
|
+
def create_and_insert_data_key(master_key_document, key_alt_names, key_material = nil)
|
|
59
63
|
data_key_document = Crypt::DataKeyContext.new(
|
|
60
64
|
@crypt_handle,
|
|
61
65
|
@encryption_io,
|
|
62
66
|
master_key_document,
|
|
63
|
-
key_alt_names
|
|
67
|
+
key_alt_names,
|
|
68
|
+
key_material
|
|
64
69
|
).run_state_machine
|
|
65
70
|
|
|
66
71
|
@encryption_io.insert_data_key(data_key_document).inserted_id
|
|
@@ -83,10 +88,10 @@ module Mongo
|
|
|
83
88
|
# to be applied if encryption algorithm is set to "Indexed". If not
|
|
84
89
|
# provided, it defaults to a value of 0. Contention factor should be set
|
|
85
90
|
# only if encryption algorithm is set to "Indexed".
|
|
86
|
-
# @option options [
|
|
91
|
+
# @option options [ String | nil ] query_type Query type to be applied
|
|
87
92
|
# if encryption algorithm is set to "Indexed". Query type should be set
|
|
88
93
|
# only if encryption algorithm is set to "Indexed". The only allowed
|
|
89
|
-
# value is
|
|
94
|
+
# value is "equality".
|
|
90
95
|
#
|
|
91
96
|
# @note The :key_id and :key_alt_name options are mutually exclusive. Only
|
|
92
97
|
# one is required to perform explicit encryption.
|
|
@@ -117,6 +122,112 @@ module Mongo
|
|
|
117
122
|
{ 'v': value },
|
|
118
123
|
).run_state_machine['v']
|
|
119
124
|
end
|
|
125
|
+
|
|
126
|
+
# Adds a key_alt_name for the key in the key vault collection with the given id.
|
|
127
|
+
#
|
|
128
|
+
# @param [ BSON::Binary ] id Id of the key to add new key alt name.
|
|
129
|
+
# @param [ String ] key_alt_name New key alt name to add.
|
|
130
|
+
#
|
|
131
|
+
# @return [ BSON::Document | nil ] Document describing the identified key
|
|
132
|
+
# before adding the key alt name, or nil if no such key.
|
|
133
|
+
def add_key_alt_name(id, key_alt_name)
|
|
134
|
+
@encryption_io.add_key_alt_name(id, key_alt_name)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Removes the key with the given id from the key vault collection.
|
|
138
|
+
#
|
|
139
|
+
# @param [ BSON::Binary ] id Id of the key to delete.
|
|
140
|
+
#
|
|
141
|
+
# @return [ Operation::Result ] The response from the database for the delete_one
|
|
142
|
+
# operation that deletes the key.
|
|
143
|
+
def delete_key(id)
|
|
144
|
+
@encryption_io.delete_key(id)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Finds a single key with the given id.
|
|
148
|
+
#
|
|
149
|
+
# @param [ BSON::Binary ] id Id of the key to get.
|
|
150
|
+
#
|
|
151
|
+
# @return [ BSON::Document | nil ] The found key document or nil
|
|
152
|
+
# if not found.
|
|
153
|
+
def get_key(id)
|
|
154
|
+
@encryption_io.get_key(id)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Returns a key in the key vault collection with the given key_alt_name.
|
|
158
|
+
#
|
|
159
|
+
# @param [ String ] key_alt_name Key alt name to find a key.
|
|
160
|
+
#
|
|
161
|
+
# @return [ BSON::Document | nil ] The found key document or nil
|
|
162
|
+
# if not found.
|
|
163
|
+
def get_key_by_alt_name(key_alt_name)
|
|
164
|
+
@encryption_io.get_key_by_alt_name(key_alt_name)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Returns all keys in the key vault collection.
|
|
168
|
+
#
|
|
169
|
+
# @return [ Collection::View ] Keys in the key vault collection.
|
|
170
|
+
def get_keys
|
|
171
|
+
@encryption_io.get_keys
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Removes a key_alt_name from a key in the key vault collection with the given id.
|
|
175
|
+
#
|
|
176
|
+
# @param [ BSON::Binary ] id Id of the key to remove key alt name.
|
|
177
|
+
# @param [ String ] key_alt_name Key alt name to remove.
|
|
178
|
+
#
|
|
179
|
+
# @return [ BSON::Document | nil ] Document describing the identified key
|
|
180
|
+
# before removing the key alt name, or nil if no such key.
|
|
181
|
+
def remove_key_alt_name(id, key_alt_name)
|
|
182
|
+
@encryption_io.remove_key_alt_name(id, key_alt_name)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Decrypts multiple data keys and (re-)encrypts them with a new master_key,
|
|
186
|
+
# or with their current master_key if a new one is not given.
|
|
187
|
+
#
|
|
188
|
+
# @param [ Hash ] filter Filter used to find keys to be updated.
|
|
189
|
+
# @param [ Hash ] options
|
|
190
|
+
#
|
|
191
|
+
# @option options [ String ] :provider KMS provider to encrypt keys.
|
|
192
|
+
# @option options [ Hash | nil ] :master_key Document describing master key
|
|
193
|
+
# to encrypt keys.
|
|
194
|
+
#
|
|
195
|
+
# @return [ Crypt::RewrapManyDataKeyResult ] Result of the operation.
|
|
196
|
+
def rewrap_many_data_key(filter, opts = {})
|
|
197
|
+
master_key_document = if opts[:provider]
|
|
198
|
+
options = opts.dup
|
|
199
|
+
provider = options.delete(:provider)
|
|
200
|
+
KMS::MasterKeyDocument.new(provider, options)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
rewrap_result = Crypt::RewrapManyDataKeyContext.new(
|
|
204
|
+
@crypt_handle,
|
|
205
|
+
@encryption_io,
|
|
206
|
+
filter,
|
|
207
|
+
master_key_document
|
|
208
|
+
).run_state_machine
|
|
209
|
+
if rewrap_result.nil?
|
|
210
|
+
return RewrapManyDataKeyResult.new(nil)
|
|
211
|
+
end
|
|
212
|
+
data_key_documents = rewrap_result.fetch('v')
|
|
213
|
+
updates = data_key_documents.map do |doc|
|
|
214
|
+
{
|
|
215
|
+
update_one: {
|
|
216
|
+
filter: { _id: doc[:_id] },
|
|
217
|
+
update: {
|
|
218
|
+
'$set' => {
|
|
219
|
+
masterKey: doc[:masterKey],
|
|
220
|
+
keyMaterial: doc[:keyMaterial]
|
|
221
|
+
},
|
|
222
|
+
'$currentDate' => { updateDate: true },
|
|
223
|
+
},
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
end
|
|
227
|
+
RewrapManyDataKeyResult.new(
|
|
228
|
+
@encryption_io.update_data_keys(updates)
|
|
229
|
+
)
|
|
230
|
+
end
|
|
120
231
|
end
|
|
121
232
|
end
|
|
122
233
|
end
|
|
@@ -44,10 +44,10 @@ module Mongo
|
|
|
44
44
|
# to be applied if encryption algorithm is set to "Indexed". If not
|
|
45
45
|
# provided, it defaults to a value of 0. Contention factor should be set
|
|
46
46
|
# only if encryption algorithm is set to "Indexed".
|
|
47
|
-
# @option options [
|
|
47
|
+
# @option options [ String | nil ] query_type Query type to be applied
|
|
48
48
|
# if encryption algorithm is set to "Indexed". Query type should be set
|
|
49
49
|
# only if encryption algorithm is set to "Indexed". The only allowed
|
|
50
|
-
# value is
|
|
50
|
+
# value is "equality".
|
|
51
51
|
#
|
|
52
52
|
# @raise [ ArgumentError|Mongo::Error::CryptError ] If invalid options are provided
|
|
53
53
|
def initialize(mongocrypt, io, doc, options={})
|
|
@@ -89,6 +89,7 @@ module Mongo
|
|
|
89
89
|
|
|
90
90
|
# Set the algorithm option on the mongocrypt_ctx_t object and raises
|
|
91
91
|
# an exception if the algorithm is invalid.
|
|
92
|
+
Binding.ctx_setopt_algorithm(self, options[:algorithm])
|
|
92
93
|
if options[:algorithm] == 'Indexed'
|
|
93
94
|
if options[:contention_factor]
|
|
94
95
|
Binding.ctx_setopt_contention_factor(self, options[:contention_factor])
|
|
@@ -96,7 +97,6 @@ module Mongo
|
|
|
96
97
|
if options[:query_type]
|
|
97
98
|
Binding.ctx_setopt_query_type(self, options[:query_type])
|
|
98
99
|
end
|
|
99
|
-
Binding.ctx_setopt_index_type(self, :equality)
|
|
100
100
|
else
|
|
101
101
|
if options[:contention_factor]
|
|
102
102
|
raise ArgumentError.new(':contention_factor is allowed only for "Indexed" algorithm')
|
|
@@ -104,11 +104,6 @@ module Mongo
|
|
|
104
104
|
if options[:query_type]
|
|
105
105
|
raise ArgumentError.new(':query_type is allowed only for "Indexed" algorithm')
|
|
106
106
|
end
|
|
107
|
-
if options[:algorithm] == 'Unindexed'
|
|
108
|
-
Binding.ctx_setopt_index_type(self, :none)
|
|
109
|
-
else
|
|
110
|
-
Binding.ctx_setopt_algorithm(self, options[:algorithm])
|
|
111
|
-
end
|
|
112
107
|
end
|
|
113
108
|
|
|
114
109
|
# Initializes the mongocrypt_ctx_t object for explicit encryption and
|
data/lib/mongo/crypt/handle.rb
CHANGED
|
@@ -39,7 +39,11 @@ module Mongo
|
|
|
39
39
|
#
|
|
40
40
|
# @param [ Hash ] options A hash of options.
|
|
41
41
|
# @option options [ Hash | nil ] :schema_map A hash representing the JSON schema
|
|
42
|
-
# of the collection that stores auto encrypted documents.
|
|
42
|
+
# of the collection that stores auto encrypted documents. This option is
|
|
43
|
+
# mutually exclusive with :schema_map_path.
|
|
44
|
+
# @option options [ String | nil ] :schema_map_path A path to a file contains the JSON schema
|
|
45
|
+
# of the collection that stores auto encrypted documents. This option is
|
|
46
|
+
# mutually exclusive with :schema_map.
|
|
43
47
|
# @option options [ Hash | nil ] :encrypted_fields_map maps a collection
|
|
44
48
|
# namespace to an encryptedFields.
|
|
45
49
|
# - Note: If a collection is present on both the encryptedFieldsMap
|
|
@@ -58,8 +62,7 @@ module Mongo
|
|
|
58
62
|
|
|
59
63
|
@kms_tls_options = kms_tls_options
|
|
60
64
|
|
|
61
|
-
|
|
62
|
-
set_schema_map if @schema_map
|
|
65
|
+
maybe_set_schema_map(options)
|
|
63
66
|
|
|
64
67
|
@encrypted_fields_map = options[:encrypted_fields_map]
|
|
65
68
|
set_encrypted_fields_map if @encrypted_fields_map
|
|
@@ -96,14 +99,29 @@ module Mongo
|
|
|
96
99
|
private
|
|
97
100
|
|
|
98
101
|
# Set the schema map option on the underlying mongocrypt_t object
|
|
99
|
-
def
|
|
100
|
-
|
|
102
|
+
def maybe_set_schema_map(options)
|
|
103
|
+
if !options[:schema_map] && !options[:schema_map_path]
|
|
104
|
+
@schema_map = nil
|
|
105
|
+
elsif options[:schema_map] && options[:schema_map_path]
|
|
101
106
|
raise ArgumentError.new(
|
|
102
|
-
"
|
|
107
|
+
"Cannot set both schema_map and schema_map_path options."
|
|
103
108
|
)
|
|
109
|
+
elsif options[:schema_map]
|
|
110
|
+
unless options[:schema_map].is_a?(Hash)
|
|
111
|
+
raise ArgumentError.new(
|
|
112
|
+
"#{@schema_map} is an invalid schema_map; schema_map must be a Hash or nil."
|
|
113
|
+
)
|
|
114
|
+
end
|
|
115
|
+
@schema_map = options[:schema_map]
|
|
116
|
+
Binding.setopt_schema_map(self, @schema_map)
|
|
117
|
+
elsif options[:schema_map_path]
|
|
118
|
+
@schema_map = BSON::ExtJSON.parse(File.read(options[:schema_map_path]))
|
|
119
|
+
Binding.setopt_schema_map(self, @schema_map)
|
|
104
120
|
end
|
|
105
|
-
|
|
106
|
-
|
|
121
|
+
rescue Errno::ENOENT
|
|
122
|
+
raise ArgumentError.new(
|
|
123
|
+
"#{@schema_map_path} is an invalid path to a file contains schema_map."
|
|
124
|
+
)
|
|
107
125
|
end
|
|
108
126
|
|
|
109
127
|
def set_encrypted_fields_map
|
data/lib/mongo/crypt/kms/aws.rb
CHANGED
|
@@ -24,6 +24,7 @@ module Mongo
|
|
|
24
24
|
#
|
|
25
25
|
# @api private
|
|
26
26
|
class Credentials
|
|
27
|
+
extend Forwardable
|
|
27
28
|
include KMS::Validations
|
|
28
29
|
|
|
29
30
|
# @return [ String ] AWS access key.
|
|
@@ -35,6 +36,9 @@ module Mongo
|
|
|
35
36
|
# @return [ String | nil ] AWS session token.
|
|
36
37
|
attr_reader :session_token
|
|
37
38
|
|
|
39
|
+
# @api private
|
|
40
|
+
def_delegator :@opts, :empty?
|
|
41
|
+
|
|
38
42
|
FORMAT_HINT = "AWS KMS provider options must be in the format: " +
|
|
39
43
|
"{ access_key_id: 'YOUR-ACCESS-KEY-ID', secret_access_key: 'SECRET-ACCESS-KEY' }"
|
|
40
44
|
|
|
@@ -49,15 +53,19 @@ module Mongo
|
|
|
49
53
|
# @raise [ ArgumentError ] If required options are missing or incorrectly
|
|
50
54
|
# formatted.
|
|
51
55
|
def initialize(opts)
|
|
52
|
-
@
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
@opts = opts
|
|
57
|
+
unless empty?
|
|
58
|
+
@access_key_id = validate_param(:access_key_id, opts, FORMAT_HINT)
|
|
59
|
+
@secret_access_key = validate_param(:secret_access_key, opts, FORMAT_HINT)
|
|
60
|
+
@session_token = validate_param(:session_token, opts, FORMAT_HINT, required: false)
|
|
61
|
+
end
|
|
55
62
|
end
|
|
56
63
|
|
|
57
64
|
# Convert credentials object to a BSON document in libmongocrypt format.
|
|
58
65
|
#
|
|
59
66
|
# @return [ BSON::Document ] AWS KMS credentials in libmongocrypt format.
|
|
60
67
|
def to_document
|
|
68
|
+
return BSON::Document.new if empty?
|
|
61
69
|
BSON::Document.new({
|
|
62
70
|
accessKeyId: access_key_id,
|
|
63
71
|
secretAccessKey: secret_access_key,
|
|
@@ -23,6 +23,7 @@ module Mongo
|
|
|
23
23
|
#
|
|
24
24
|
# @api private
|
|
25
25
|
class Credentials
|
|
26
|
+
extend Forwardable
|
|
26
27
|
include KMS::Validations
|
|
27
28
|
|
|
28
29
|
# @return [ String ] Azure tenant id.
|
|
@@ -37,6 +38,9 @@ module Mongo
|
|
|
37
38
|
# @return [ String | nil ] Azure identity platform endpoint.
|
|
38
39
|
attr_reader :identity_platform_endpoint
|
|
39
40
|
|
|
41
|
+
# @api private
|
|
42
|
+
def_delegator :@opts, :empty?
|
|
43
|
+
|
|
40
44
|
FORMAT_HINT = "Azure KMS provider options must be in the format: " +
|
|
41
45
|
"{ tenant_id: 'TENANT-ID', client_id: 'TENANT_ID', client_secret: 'CLIENT_SECRET' }"
|
|
42
46
|
|
|
@@ -53,18 +57,22 @@ module Mongo
|
|
|
53
57
|
# @raise [ ArgumentError ] If required options are missing or incorrectly
|
|
54
58
|
# formatted.
|
|
55
59
|
def initialize(opts)
|
|
56
|
-
@
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
:
|
|
61
|
-
|
|
60
|
+
@opts = opts
|
|
61
|
+
unless empty?
|
|
62
|
+
@tenant_id = validate_param(:tenant_id, opts, FORMAT_HINT)
|
|
63
|
+
@client_id = validate_param(:client_id, opts, FORMAT_HINT)
|
|
64
|
+
@client_secret = validate_param(:client_secret, opts, FORMAT_HINT)
|
|
65
|
+
@identity_platform_endpoint = validate_param(
|
|
66
|
+
:identity_platform_endpoint, opts, FORMAT_HINT, required: false
|
|
67
|
+
)
|
|
68
|
+
end
|
|
62
69
|
end
|
|
63
70
|
|
|
64
71
|
# Convert credentials object to a BSON document in libmongocrypt format.
|
|
65
72
|
#
|
|
66
73
|
# @return [ BSON::Document ] Azure KMS credentials in libmongocrypt format.
|
|
67
74
|
def to_document
|
|
75
|
+
return BSON::Document.new if empty?
|
|
68
76
|
BSON::Document.new({
|
|
69
77
|
tenantId: @tenant_id,
|
|
70
78
|
clientId: @client_id,
|
data/lib/mongo/crypt/kms/gcp.rb
CHANGED
|
@@ -24,6 +24,7 @@ module Mongo
|
|
|
24
24
|
#
|
|
25
25
|
# @api private
|
|
26
26
|
class Credentials
|
|
27
|
+
extend Forwardable
|
|
27
28
|
include KMS::Validations
|
|
28
29
|
|
|
29
30
|
# @return [ String ] GCP email to authenticate with.
|
|
@@ -35,6 +36,9 @@ module Mongo
|
|
|
35
36
|
# @return [ String | nil ] GCP KMS endpoint.
|
|
36
37
|
attr_reader :endpoint
|
|
37
38
|
|
|
39
|
+
# @api private
|
|
40
|
+
def_delegator :@opts, :empty?
|
|
41
|
+
|
|
38
42
|
FORMAT_HINT = "GCP KMS provider options must be in the format: " +
|
|
39
43
|
"{ email: 'EMAIL', private_key: 'PRIVATE-KEY' }"
|
|
40
44
|
|
|
@@ -50,8 +54,10 @@ module Mongo
|
|
|
50
54
|
# @raise [ ArgumentError ] If required options are missing or incorrectly
|
|
51
55
|
# formatted.
|
|
52
56
|
def initialize(opts)
|
|
53
|
-
@
|
|
57
|
+
@opts = opts
|
|
58
|
+
return if empty?
|
|
54
59
|
|
|
60
|
+
@email = validate_param(:email, opts, FORMAT_HINT)
|
|
55
61
|
@private_key = begin
|
|
56
62
|
private_key_opt = validate_param(:private_key, opts, FORMAT_HINT)
|
|
57
63
|
if BSON::Environment.jruby?
|
|
@@ -91,6 +97,7 @@ module Mongo
|
|
|
91
97
|
#
|
|
92
98
|
# @return [ BSON::Document ] Azure KMS credentials in libmongocrypt format.
|
|
93
99
|
def to_document
|
|
100
|
+
return BSON::Document.new if empty?
|
|
94
101
|
BSON::Document.new({
|
|
95
102
|
email: email,
|
|
96
103
|
privateKey: BSON::Binary.new(private_key, :generic),
|
|
@@ -143,10 +150,9 @@ module Mongo
|
|
|
143
150
|
#
|
|
144
151
|
# @raise [ ArgumentError ] If required options are missing or incorrectly.
|
|
145
152
|
def initialize(opts)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
)
|
|
153
|
+
if opts.empty?
|
|
154
|
+
@empty = true
|
|
155
|
+
return
|
|
150
156
|
end
|
|
151
157
|
@project_id = validate_param(:project_id, opts, FORMAT_HINT)
|
|
152
158
|
@location = validate_param(:location, opts, FORMAT_HINT)
|
|
@@ -160,6 +166,7 @@ module Mongo
|
|
|
160
166
|
#
|
|
161
167
|
# @return [ BSON::Document ] GCP KMS credentials in libmongocrypt format.
|
|
162
168
|
def to_document
|
|
169
|
+
return BSON::Document.new({}) if @empty
|
|
163
170
|
BSON::Document.new({
|
|
164
171
|
provider: 'gcp',
|
|
165
172
|
projectId: project_id,
|