mongo 2.11.4 → 2.12.3
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.tar.gz.sig +0 -0
- data/CONTRIBUTING.md +1 -1
- data/README.md +2 -1
- data/lib/mongo.rb +3 -0
- data/lib/mongo/address.rb +44 -19
- data/lib/mongo/auth.rb +1 -0
- data/lib/mongo/auth/credential_cache.rb +51 -0
- data/lib/mongo/auth/scram/conversation.rb +20 -16
- data/lib/mongo/auth/user.rb +0 -8
- data/lib/mongo/auth/user/view.rb +4 -4
- data/lib/mongo/background_thread.rb +1 -1
- data/lib/mongo/bulk_write.rb +5 -5
- data/lib/mongo/client.rb +143 -14
- data/lib/mongo/client_encryption.rb +103 -0
- data/lib/mongo/cluster.rb +8 -4
- data/lib/mongo/cluster/reapers/cursor_reaper.rb +18 -6
- data/lib/mongo/cluster/sdam_flow.rb +54 -58
- data/lib/mongo/collection.rb +3 -3
- data/lib/mongo/collection/view.rb +1 -1
- data/lib/mongo/collection/view/aggregation.rb +1 -1
- data/lib/mongo/collection/view/change_stream.rb +12 -3
- data/lib/mongo/collection/view/iterable.rb +14 -5
- data/lib/mongo/collection/view/map_reduce.rb +2 -2
- data/lib/mongo/collection/view/readable.rb +9 -7
- data/lib/mongo/collection/view/writable.rb +7 -7
- data/lib/mongo/crypt.rb +33 -0
- data/lib/mongo/crypt/auto_decryption_context.rb +40 -0
- data/lib/mongo/crypt/auto_encrypter.rb +179 -0
- data/lib/mongo/crypt/auto_encryption_context.rb +44 -0
- data/lib/mongo/crypt/binary.rb +155 -0
- data/lib/mongo/crypt/binding.rb +1229 -0
- data/lib/mongo/crypt/context.rb +135 -0
- data/lib/mongo/crypt/data_key_context.rb +162 -0
- data/lib/mongo/crypt/encryption_io.rb +289 -0
- data/lib/mongo/crypt/explicit_decryption_context.rb +40 -0
- data/lib/mongo/crypt/explicit_encrypter.rb +117 -0
- data/lib/mongo/crypt/explicit_encryption_context.rb +89 -0
- data/lib/mongo/crypt/handle.rb +315 -0
- data/lib/mongo/crypt/hooks.rb +90 -0
- data/lib/mongo/crypt/kms_context.rb +67 -0
- data/lib/mongo/crypt/status.rb +131 -0
- data/lib/mongo/cursor.rb +64 -32
- data/lib/mongo/database.rb +23 -6
- data/lib/mongo/database/view.rb +13 -4
- data/lib/mongo/dbref.rb +9 -2
- data/lib/mongo/error.rb +5 -1
- data/lib/mongo/error/bulk_write_error.rb +16 -14
- data/lib/mongo/error/crypt_error.rb +31 -0
- data/lib/mongo/error/{failed_stringprep_validation.rb → failed_string_prep_validation.rb} +0 -0
- data/lib/mongo/error/invalid_cursor_operation.rb +27 -0
- data/lib/mongo/error/kms_error.rb +22 -0
- data/lib/mongo/error/max_bson_size.rb +14 -3
- data/lib/mongo/error/mongocryptd_spawn_error.rb +22 -0
- data/lib/mongo/error/no_server_available.rb +8 -3
- data/lib/mongo/error/notable.rb +0 -15
- data/lib/mongo/error/operation_failure.rb +1 -0
- data/lib/mongo/error/parser.rb +1 -1
- data/lib/mongo/grid/file.rb +5 -0
- data/lib/mongo/grid/file/chunk.rb +2 -0
- data/lib/mongo/grid/file/info.rb +3 -2
- data/lib/mongo/grid/fs_bucket.rb +15 -13
- data/lib/mongo/grid/stream/write.rb +9 -3
- data/lib/mongo/index/view.rb +3 -3
- data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +1 -1
- data/lib/mongo/monitoring/event/command_started.rb +6 -1
- data/lib/mongo/operation/collections_info.rb +6 -3
- data/lib/mongo/operation/delete/op_msg.rb +1 -1
- data/lib/mongo/operation/find/op_msg.rb +4 -1
- data/lib/mongo/operation/get_more/op_msg.rb +4 -1
- data/lib/mongo/operation/insert/command.rb +3 -2
- data/lib/mongo/operation/insert/legacy.rb +3 -2
- data/lib/mongo/operation/insert/op_msg.rb +3 -3
- data/lib/mongo/operation/result.rb +36 -27
- data/lib/mongo/operation/shared/executable.rb +11 -9
- data/lib/mongo/operation/shared/executable_no_validate.rb +2 -2
- data/lib/mongo/operation/shared/op_msg_or_command.rb +2 -2
- data/lib/mongo/operation/shared/op_msg_or_find_command.rb +2 -2
- data/lib/mongo/operation/shared/op_msg_or_list_indexes_command.rb +2 -2
- data/lib/mongo/operation/shared/read_preference_supported.rb +68 -19
- data/lib/mongo/operation/shared/response_handling.rb +1 -1
- data/lib/mongo/operation/shared/sessions_supported.rb +44 -3
- data/lib/mongo/operation/shared/write.rb +17 -10
- data/lib/mongo/operation/update/op_msg.rb +1 -1
- data/lib/mongo/protocol/bit_vector.rb +2 -1
- data/lib/mongo/protocol/compressed.rb +6 -5
- data/lib/mongo/protocol/insert.rb +3 -1
- data/lib/mongo/protocol/message.rb +94 -15
- data/lib/mongo/protocol/msg.rb +207 -37
- data/lib/mongo/protocol/query.rb +7 -9
- data/lib/mongo/protocol/serializers.rb +43 -15
- data/lib/mongo/retryable.rb +1 -1
- data/lib/mongo/server.rb +10 -4
- data/lib/mongo/server/connection.rb +20 -9
- data/lib/mongo/server/connection_base.rb +118 -18
- data/lib/mongo/server/connection_common.rb +61 -0
- data/lib/mongo/server/connection_pool.rb +37 -1
- data/lib/mongo/server/connection_pool/populator.rb +1 -1
- data/lib/mongo/server/description.rb +9 -11
- data/lib/mongo/server/monitor.rb +2 -0
- data/lib/mongo/server/monitor/connection.rb +3 -18
- data/lib/mongo/server/pending_connection.rb +2 -1
- data/lib/mongo/session.rb +3 -3
- data/lib/mongo/session/session_pool.rb +8 -3
- data/lib/mongo/socket.rb +29 -16
- data/lib/mongo/socket/ssl.rb +23 -8
- data/lib/mongo/socket/tcp.rb +12 -3
- data/lib/mongo/srv/monitor.rb +73 -42
- data/lib/mongo/srv/result.rb +0 -1
- data/lib/mongo/timeout.rb +49 -0
- data/lib/mongo/uri.rb +30 -1
- data/lib/mongo/uri/srv_protocol.rb +1 -1
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +1 -3
- data/spec/README.md +228 -7
- data/spec/integration/auth_spec.rb +53 -0
- data/spec/integration/bulk_write_spec.rb +19 -0
- data/spec/integration/{client_options_spec.rb → client_authentication_options_spec.rb} +10 -10
- data/spec/integration/client_construction_spec.rb +100 -1
- data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +353 -0
- data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +303 -0
- data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +72 -0
- data/spec/integration/client_side_encryption/auto_encryption_old_wire_version_spec.rb +79 -0
- data/spec/integration/client_side_encryption/auto_encryption_reconnect_spec.rb +221 -0
- data/spec/integration/client_side_encryption/auto_encryption_spec.rb +601 -0
- data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +187 -0
- data/spec/integration/client_side_encryption/bypass_mongocryptd_spawn_spec.rb +78 -0
- data/spec/integration/client_side_encryption/client_close_spec.rb +63 -0
- data/spec/integration/client_side_encryption/corpus_spec.rb +233 -0
- data/spec/integration/client_side_encryption/custom_endpoint_spec.rb +132 -0
- data/spec/integration/client_side_encryption/data_key_spec.rb +165 -0
- data/spec/integration/client_side_encryption/explicit_encryption_spec.rb +114 -0
- data/spec/integration/client_side_encryption/external_key_vault_spec.rb +141 -0
- data/spec/integration/client_side_encryption/views_spec.rb +44 -0
- data/spec/integration/client_update_spec.rb +154 -0
- data/spec/integration/command_monitoring_spec.rb +3 -1
- data/spec/integration/command_spec.rb +44 -10
- data/spec/integration/connection_spec.rb +57 -0
- data/spec/integration/crud_spec.rb +89 -0
- data/spec/integration/grid_fs_bucket_spec.rb +48 -0
- data/spec/integration/read_preference_spec.rb +26 -0
- data/spec/integration/reconnect_spec.rb +7 -6
- data/spec/integration/size_limit_spec.rb +111 -0
- data/spec/integration/srv_monitoring_spec.rb +16 -8
- data/spec/integration/zlib_compression_spec.rb +25 -0
- data/spec/kerberos/kerberos_spec.rb +87 -0
- data/spec/lite_spec_helper.rb +34 -29
- data/spec/mongo/auth/cr_spec.rb +8 -0
- data/spec/mongo/auth/ldap_spec.rb +5 -1
- data/spec/mongo/auth/scram/conversation_spec.rb +5 -6
- data/spec/mongo/auth/scram/negotiation_spec.rb +74 -75
- data/spec/mongo/auth/scram_spec.rb +45 -35
- data/spec/mongo/auth/user/view_spec.rb +3 -6
- data/spec/mongo/auth/x509_spec.rb +5 -1
- data/spec/mongo/bulk_write/result_spec.rb +11 -7
- data/spec/mongo/client_construction_spec.rb +206 -2
- data/spec/mongo/client_encryption_spec.rb +405 -0
- data/spec/mongo/cluster/cursor_reaper_spec.rb +12 -8
- data/spec/mongo/cluster/socket_reaper_spec.rb +14 -3
- data/spec/mongo/collection/view/aggregation_spec.rb +0 -2
- data/spec/mongo/collection/view/change_stream_spec.rb +7 -7
- data/spec/mongo/collection/view/map_reduce_spec.rb +3 -3
- data/spec/mongo/collection/view_spec.rb +1 -1
- data/spec/mongo/collection_spec.rb +28 -9
- data/spec/mongo/crypt/auto_decryption_context_spec.rb +90 -0
- data/spec/mongo/crypt/auto_encrypter_spec.rb +187 -0
- data/spec/mongo/crypt/auto_encryption_context_spec.rb +107 -0
- data/spec/mongo/crypt/binary_spec.rb +115 -0
- data/spec/mongo/crypt/binding/binary_spec.rb +56 -0
- data/spec/mongo/crypt/binding/context_spec.rb +257 -0
- data/spec/mongo/crypt/binding/helpers_spec.rb +46 -0
- data/spec/mongo/crypt/binding/mongocrypt_spec.rb +144 -0
- data/spec/mongo/crypt/binding/status_spec.rb +99 -0
- data/spec/mongo/crypt/binding/version_spec.rb +22 -0
- data/spec/mongo/crypt/binding_unloaded_spec.rb +20 -0
- data/spec/mongo/crypt/data_key_context_spec.rb +213 -0
- data/spec/mongo/crypt/encryption_io_spec.rb +136 -0
- data/spec/mongo/crypt/explicit_decryption_context_spec.rb +72 -0
- data/spec/mongo/crypt/explicit_encryption_context_spec.rb +170 -0
- data/spec/mongo/crypt/handle_spec.rb +232 -0
- data/spec/mongo/crypt/helpers/mongo_crypt_spec_helper.rb +108 -0
- data/spec/mongo/crypt/status_spec.rb +152 -0
- data/spec/mongo/cursor_spec.rb +24 -4
- data/spec/mongo/database_spec.rb +20 -0
- data/spec/mongo/error/bulk_write_error_spec.rb +49 -0
- data/spec/mongo/error/crypt_error_spec.rb +26 -0
- data/spec/mongo/error/max_bson_size_spec.rb +35 -0
- data/spec/mongo/error/no_server_available_spec.rb +11 -1
- data/spec/mongo/error/notable_spec.rb +59 -0
- data/spec/mongo/error/operation_failure_spec.rb +6 -6
- data/spec/mongo/operation/aggregate_spec.rb +1 -1
- data/spec/mongo/operation/collections_info_spec.rb +1 -1
- data/spec/mongo/operation/command_spec.rb +3 -3
- data/spec/mongo/operation/create_index_spec.rb +3 -3
- data/spec/mongo/operation/create_user_spec.rb +3 -3
- data/spec/mongo/operation/delete/bulk_spec.rb +6 -6
- data/spec/mongo/operation/delete/op_msg_spec.rb +1 -6
- data/spec/mongo/operation/delete_spec.rb +7 -7
- data/spec/mongo/operation/drop_index_spec.rb +2 -2
- data/spec/mongo/operation/find/legacy_spec.rb +2 -1
- data/spec/mongo/operation/get_more_spec.rb +1 -1
- data/spec/mongo/operation/indexes_spec.rb +1 -1
- data/spec/mongo/operation/insert/bulk_spec.rb +7 -7
- data/spec/mongo/operation/insert/op_msg_spec.rb +3 -6
- data/spec/mongo/operation/insert_spec.rb +12 -12
- data/spec/mongo/operation/map_reduce_spec.rb +2 -2
- data/spec/mongo/operation/read_preference_legacy_spec.rb +351 -0
- data/spec/mongo/operation/read_preference_op_msg_spec.rb +194 -0
- data/spec/mongo/operation/remove_user_spec.rb +3 -3
- data/spec/mongo/operation/update/bulk_spec.rb +6 -6
- data/spec/mongo/operation/update/op_msg_spec.rb +3 -6
- data/spec/mongo/operation/update_spec.rb +7 -7
- data/spec/mongo/operation/update_user_spec.rb +1 -1
- data/spec/mongo/protocol/compressed_spec.rb +2 -3
- data/spec/mongo/protocol/delete_spec.rb +9 -8
- data/spec/mongo/protocol/get_more_spec.rb +9 -8
- data/spec/mongo/protocol/insert_spec.rb +9 -8
- data/spec/mongo/protocol/kill_cursors_spec.rb +6 -5
- data/spec/mongo/protocol/msg_spec.rb +57 -53
- data/spec/mongo/protocol/query_spec.rb +12 -12
- data/spec/mongo/protocol/registry_spec.rb +1 -1
- data/spec/mongo/protocol/reply_spec.rb +1 -1
- data/spec/mongo/protocol/update_spec.rb +10 -9
- data/spec/mongo/server/connection_pool_spec.rb +1 -1
- data/spec/mongo/server/connection_spec.rb +28 -7
- data/spec/mongo/socket_spec.rb +1 -1
- data/spec/mongo/srv/monitor_spec.rb +88 -69
- data/spec/mongo/timeout_spec.rb +85 -0
- data/spec/mongo/uri/srv_protocol_spec.rb +2 -2
- data/spec/mongo/uri_spec.rb +52 -5
- data/spec/mongo/write_concern_spec.rb +13 -1
- data/spec/{support → runners}/auth.rb +14 -1
- data/spec/{support → runners}/change_streams.rb +1 -1
- data/spec/{support → runners}/change_streams/operation.rb +0 -0
- data/spec/{support → runners}/cmap.rb +1 -1
- data/spec/{support → runners}/cmap/verifier.rb +0 -0
- data/spec/{support → runners}/command_monitoring.rb +0 -0
- data/spec/runners/connection_string.rb +358 -4
- data/spec/{support → runners}/crud.rb +9 -9
- data/spec/{support → runners}/crud/context.rb +0 -0
- data/spec/{support → runners}/crud/operation.rb +7 -3
- data/spec/{support → runners}/crud/outcome.rb +0 -0
- data/spec/{support → runners}/crud/requirement.rb +1 -1
- data/spec/{support → runners}/crud/spec.rb +12 -1
- data/spec/{support → runners}/crud/test.rb +0 -0
- data/spec/{support → runners}/crud/test_base.rb +0 -0
- data/spec/{support → runners}/crud/verifier.rb +10 -12
- data/spec/{support → runners}/gridfs.rb +0 -0
- data/spec/{support → runners}/sdam_monitoring.rb +0 -0
- data/spec/{support → runners}/server_discovery_and_monitoring.rb +0 -0
- data/spec/{support → runners}/server_selection.rb +0 -0
- data/spec/{support → runners}/server_selection_rtt.rb +0 -0
- data/spec/{support → runners}/transactions.rb +9 -11
- data/spec/{support → runners}/transactions/context.rb +0 -0
- data/spec/{support → runners}/transactions/operation.rb +0 -0
- data/spec/{support → runners}/transactions/spec.rb +0 -0
- data/spec/{support → runners}/transactions/test.rb +37 -5
- data/spec/spec_helper.rb +0 -5
- data/spec/spec_tests/auth_spec.rb +3 -3
- data/spec/spec_tests/client_side_encryption_spec.rb +8 -0
- data/spec/spec_tests/connection_string_spec.rb +1 -1
- data/spec/spec_tests/data/auth/connection-string.yml +13 -0
- data/spec/spec_tests/data/client_side_encryption/aggregate.yml +134 -0
- data/spec/spec_tests/data/client_side_encryption/badQueries.yml +526 -0
- data/spec/spec_tests/data/client_side_encryption/badSchema.yml +73 -0
- data/spec/spec_tests/data/client_side_encryption/basic.yml +116 -0
- data/spec/spec_tests/data/client_side_encryption/bulk.yml +88 -0
- data/spec/spec_tests/data/client_side_encryption/bypassAutoEncryption.yml +100 -0
- data/spec/spec_tests/data/client_side_encryption/bypassedCommand.yml +42 -0
- data/spec/spec_tests/data/client_side_encryption/count.yml +61 -0
- data/spec/spec_tests/data/client_side_encryption/countDocuments.yml +59 -0
- data/spec/spec_tests/data/client_side_encryption/delete.yml +105 -0
- data/spec/spec_tests/data/client_side_encryption/distinct.yml +73 -0
- data/spec/spec_tests/data/client_side_encryption/explain.yml +64 -0
- data/spec/spec_tests/data/client_side_encryption/find.yml +119 -0
- data/spec/spec_tests/data/client_side_encryption/findOneAndDelete.yml +57 -0
- data/spec/spec_tests/data/client_side_encryption/findOneAndReplace.yml +57 -0
- data/spec/spec_tests/data/client_side_encryption/findOneAndUpdate.yml +57 -0
- data/spec/spec_tests/data/client_side_encryption/getMore.yml +68 -0
- data/spec/spec_tests/data/client_side_encryption/insert.yml +102 -0
- data/spec/spec_tests/data/client_side_encryption/keyAltName.yml +71 -0
- data/spec/spec_tests/data/client_side_encryption/localKMS.yml +54 -0
- data/spec/spec_tests/data/client_side_encryption/localSchema.yml +72 -0
- data/spec/spec_tests/data/client_side_encryption/malformedCiphertext.yml +69 -0
- data/spec/spec_tests/data/client_side_encryption/maxWireVersion.yml +20 -0
- data/spec/spec_tests/data/client_side_encryption/missingKey.yml +49 -0
- data/spec/spec_tests/data/client_side_encryption/replaceOne.yml +64 -0
- data/spec/spec_tests/data/client_side_encryption/types.yml +527 -0
- data/spec/spec_tests/data/client_side_encryption/unsupportedCommand.yml +25 -0
- data/spec/spec_tests/data/client_side_encryption/updateMany.yml +77 -0
- data/spec/spec_tests/data/client_side_encryption/updateOne.yml +171 -0
- data/spec/spec_tests/data/read_write_concern/connection-string/write-concern.yml +1 -4
- data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +21 -0
- data/spec/spec_tests/data/sdam/rs/incompatible_ghost.yml +2 -4
- data/spec/spec_tests/data/sdam/rs/incompatible_other.yml +1 -1
- data/spec/spec_tests/data/sdam/rs/primary_mismatched_me_not_removed.yml +73 -0
- data/spec/spec_tests/data/sdam/rs/primary_to_no_primary_mismatched_me.yml +1 -2
- data/spec/spec_tests/data/sdam/rs/repeated.yml +101 -0
- data/spec/spec_tests/data/sdam/rs/{primary_address_change.yml → ruby_primary_address_change.yml} +2 -0
- data/spec/spec_tests/data/sdam/rs/{secondary_wrong_set_name_with_primary_second.yml → ruby_secondary_wrong_set_name_with_primary_second.yml} +0 -0
- data/spec/spec_tests/data/sdam/sharded/ruby_discovered_single_mongos.yml +27 -0
- data/spec/spec_tests/data/sdam/sharded/{primary_address_change.yml → ruby_primary_different_address.yml} +1 -1
- data/spec/spec_tests/data/sdam/sharded/{primary_mismatched_me.yml → ruby_primary_mismatched_me.yml} +1 -1
- data/spec/spec_tests/data/sdam/single/{primary_address_change.yml → ruby_primary_different_address.yml} +1 -1
- data/spec/spec_tests/data/sdam/single/{primary_mismatched_me.yml → ruby_primary_mismatched_me.yml} +1 -1
- data/spec/spec_tests/data/sdam_monitoring/{replica_set_with_primary_change.yml → replica_set_primary_address_change.yml} +27 -5
- data/spec/spec_tests/data/sdam_monitoring/replica_set_with_me_mismatch.yml +26 -74
- data/spec/spec_tests/data/sdam_monitoring/replica_set_with_removal.yml +20 -16
- data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +73 -0
- data/spec/spec_tests/data/transactions/pin-mongos.yml +2 -3
- data/spec/spec_tests/data/uri_options/auth-options.yml +10 -0
- data/spec/spec_tests/data/uri_options/tls-options.yml +75 -4
- data/spec/spec_tests/read_write_concern_connection_string_spec.rb +1 -1
- data/spec/spec_tests/uri_options_spec.rb +6 -8
- data/spec/stress/connection_pool_timing_spec.rb +6 -3
- data/spec/support/certificates/README.md +4 -0
- data/spec/support/certificates/server-second-level-bundle.pem +77 -77
- data/spec/support/certificates/server-second-level.crt +52 -52
- data/spec/support/certificates/server-second-level.key +25 -25
- data/spec/support/certificates/server-second-level.pem +77 -77
- data/spec/support/client_registry.rb +19 -3
- data/spec/support/cluster_config.rb +9 -1
- data/spec/support/cluster_tools.rb +6 -1
- data/spec/support/common_shortcuts.rb +12 -0
- data/spec/support/constraints.rb +16 -0
- data/spec/support/crypt.rb +154 -0
- data/spec/support/crypt/corpus/corpus-key-aws.json +33 -0
- data/spec/support/crypt/corpus/corpus-key-local.json +31 -0
- data/spec/support/crypt/corpus/corpus-schema.json +2057 -0
- data/spec/support/crypt/corpus/corpus.json +3657 -0
- data/spec/support/crypt/corpus/corpus_encrypted.json +4152 -0
- data/spec/support/crypt/data_keys/key_document_aws.json +34 -0
- data/spec/support/crypt/data_keys/key_document_local.json +31 -0
- data/spec/support/crypt/external/external-key.json +31 -0
- data/spec/support/crypt/external/external-schema.json +19 -0
- data/spec/support/crypt/limits/limits-doc.json +102 -0
- data/spec/support/crypt/limits/limits-key.json +31 -0
- data/spec/support/crypt/limits/limits-schema.json +1405 -0
- data/spec/support/crypt/schema_maps/schema_map_aws.json +17 -0
- data/spec/support/crypt/schema_maps/schema_map_aws_key_alt_names.json +12 -0
- data/spec/support/crypt/schema_maps/schema_map_local.json +18 -0
- data/spec/support/crypt/schema_maps/schema_map_local_key_alt_names.json +12 -0
- data/spec/support/lite_constraints.rb +19 -1
- data/spec/support/matchers.rb +19 -0
- data/spec/support/shared/protocol.rb +2 -0
- data/spec/support/spec_config.rb +53 -13
- data/spec/support/utils.rb +140 -10
- metadata +894 -687
- metadata.gz.sig +0 -0
- data/lib/mongo/cluster/srv_monitor.rb +0 -127
- data/lib/mongo/srv/warning_result.rb +0 -35
- data/spec/enterprise_auth/kerberos_spec.rb +0 -58
- data/spec/mongo/cluster/srv_monitor_spec.rb +0 -214
- data/spec/mongo/operation/read_preference_spec.rb +0 -245
- data/spec/spec_tests/data/sdam/sharded/single_mongos.yml +0 -33
- data/spec/support/connection_string.rb +0 -354
@@ -0,0 +1,221 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Client with auto encryption #reconnect' do
|
4
|
+
require_libmongocrypt
|
5
|
+
min_server_fcv '4.2'
|
6
|
+
require_enterprise
|
7
|
+
|
8
|
+
# Diagnostics of leaked background threads only, these tests do not
|
9
|
+
# actually require a clean slate. https://jira.mongodb.org/browse/RUBY-2138
|
10
|
+
clean_slate
|
11
|
+
|
12
|
+
include_context 'define shared FLE helpers'
|
13
|
+
|
14
|
+
let(:client) do
|
15
|
+
new_local_client(
|
16
|
+
SpecConfig.instance.addresses,
|
17
|
+
SpecConfig.instance.test_options.merge(
|
18
|
+
{
|
19
|
+
auto_encryption_options: {
|
20
|
+
kms_providers: kms_providers,
|
21
|
+
key_vault_namespace: key_vault_namespace,
|
22
|
+
key_vault_client: key_vault_client_option,
|
23
|
+
schema_map: { 'auto_encryption.users': schema_map },
|
24
|
+
# Spawn mongocryptd on non-default port for sharded cluster tests
|
25
|
+
extra_options: extra_options,
|
26
|
+
},
|
27
|
+
database: 'auto_encryption'
|
28
|
+
}
|
29
|
+
)
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:unencrypted_client) { authorized_client.use('auto_encryption') }
|
34
|
+
|
35
|
+
let(:mongocryptd_client) { client.encrypter.mongocryptd_client }
|
36
|
+
let(:key_vault_client) { client.encrypter.key_vault_client }
|
37
|
+
let(:data_key_id) { data_key['_id'] }
|
38
|
+
|
39
|
+
shared_examples 'a functioning client' do
|
40
|
+
it 'can perform an encrypted find command' do
|
41
|
+
doc = client['users'].find(ssn: ssn).first
|
42
|
+
expect(doc).not_to be_nil
|
43
|
+
expect(doc['ssn']).to eq(ssn)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
shared_examples 'a functioning mongocryptd client' do
|
48
|
+
it 'can perform a schemaRequiresEncryption command' do
|
49
|
+
# A schemaRequiresEncryption command; mongocryptd should respond that
|
50
|
+
# this command requires encryption.
|
51
|
+
response = mongocryptd_client.database.command(
|
52
|
+
insert: 'users',
|
53
|
+
ordered: true,
|
54
|
+
lsid: { id: BSON::Binary.new("\x00" * 16, :uuid) },
|
55
|
+
documents: [{
|
56
|
+
ssn: '123-456-7890',
|
57
|
+
_id: BSON::ObjectId.new,
|
58
|
+
}],
|
59
|
+
jsonSchema: schema_map,
|
60
|
+
isRemoteSchema: false
|
61
|
+
)
|
62
|
+
|
63
|
+
expect(response).to be_ok
|
64
|
+
expect(response.documents.first['schemaRequiresEncryption']).to be true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
shared_examples 'a functioning key vault client' do
|
69
|
+
it 'can perform a find command' do
|
70
|
+
doc = key_vault_client.use(key_vault_db)[key_vault_coll, read_concern: { level: :majority}].find(_id: data_key_id).first
|
71
|
+
expect(doc).not_to be_nil
|
72
|
+
expect(doc['_id']).to eq(data_key_id)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
shared_examples 'an auto-encryption client that reconnects properly' do
|
77
|
+
before do
|
78
|
+
key_vault_collection.drop
|
79
|
+
key_vault_collection.insert_one(data_key)
|
80
|
+
|
81
|
+
unencrypted_client['users'].drop
|
82
|
+
# Use a client without auto_encryption_options to insert an
|
83
|
+
# encrypted document into the collection; this ensures that the
|
84
|
+
# client with auto_encryption_options must perform decryption
|
85
|
+
# to properly read the document.
|
86
|
+
unencrypted_client['users'].insert_one(
|
87
|
+
ssn: BSON::Binary.new(Base64.decode64(encrypted_ssn), :ciphertext)
|
88
|
+
)
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'after reconnecting without closing main client' do
|
92
|
+
before do
|
93
|
+
client.reconnect
|
94
|
+
end
|
95
|
+
|
96
|
+
it_behaves_like 'a functioning client'
|
97
|
+
it_behaves_like 'a functioning mongocryptd client'
|
98
|
+
it_behaves_like 'a functioning key vault client'
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'after closing and reconnecting main client' do
|
102
|
+
before do
|
103
|
+
client.close
|
104
|
+
client.reconnect
|
105
|
+
end
|
106
|
+
|
107
|
+
it_behaves_like 'a functioning client'
|
108
|
+
it_behaves_like 'a functioning mongocryptd client'
|
109
|
+
it_behaves_like 'a functioning key vault client'
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'after killing client monitor thread' do
|
113
|
+
before do
|
114
|
+
thread = client.cluster.servers.first.monitor.instance_variable_get('@thread')
|
115
|
+
expect(thread).to be_alive
|
116
|
+
|
117
|
+
thread.kill
|
118
|
+
|
119
|
+
sleep 0.1
|
120
|
+
expect(thread).not_to be_alive
|
121
|
+
|
122
|
+
client.reconnect
|
123
|
+
end
|
124
|
+
|
125
|
+
it_behaves_like 'a functioning client'
|
126
|
+
it_behaves_like 'a functioning mongocryptd client'
|
127
|
+
it_behaves_like 'a functioning key vault client'
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'after closing mongocryptd client and reconnecting' do
|
131
|
+
before do
|
132
|
+
mongocryptd_client.close
|
133
|
+
client.reconnect
|
134
|
+
end
|
135
|
+
|
136
|
+
it_behaves_like 'a functioning client'
|
137
|
+
it_behaves_like 'a functioning mongocryptd client'
|
138
|
+
it_behaves_like 'a functioning key vault client'
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'after killing mongocryptd client monitor thread and reconnecting' do
|
142
|
+
before do
|
143
|
+
thread = mongocryptd_client.cluster.servers.first.monitor.instance_variable_get('@thread')
|
144
|
+
expect(thread).to be_alive
|
145
|
+
|
146
|
+
thread.kill
|
147
|
+
|
148
|
+
sleep 0.1
|
149
|
+
expect(thread).not_to be_alive
|
150
|
+
|
151
|
+
client.reconnect
|
152
|
+
end
|
153
|
+
|
154
|
+
it_behaves_like 'a functioning client'
|
155
|
+
it_behaves_like 'a functioning mongocryptd client'
|
156
|
+
it_behaves_like 'a functioning key vault client'
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'after closing key_vault_client and reconnecting' do
|
160
|
+
before do
|
161
|
+
key_vault_client.close
|
162
|
+
client.reconnect
|
163
|
+
end
|
164
|
+
|
165
|
+
it_behaves_like 'a functioning client'
|
166
|
+
it_behaves_like 'a functioning mongocryptd client'
|
167
|
+
it_behaves_like 'a functioning key vault client'
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'after killing key_vault_client monitor thread and reconnecting' do
|
171
|
+
before do
|
172
|
+
thread = key_vault_client.cluster.servers.first.monitor.instance_variable_get('@thread')
|
173
|
+
expect(thread).to be_alive
|
174
|
+
|
175
|
+
thread.kill
|
176
|
+
|
177
|
+
sleep 0.1
|
178
|
+
expect(thread).not_to be_alive
|
179
|
+
|
180
|
+
client.reconnect
|
181
|
+
end
|
182
|
+
|
183
|
+
it_behaves_like 'a functioning client'
|
184
|
+
it_behaves_like 'a functioning mongocryptd client'
|
185
|
+
it_behaves_like 'a functioning key vault client'
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context 'with default key vault client option' do
|
190
|
+
let(:key_vault_client_option) { nil }
|
191
|
+
|
192
|
+
context 'with AWS KMS providers' do
|
193
|
+
include_context 'with AWS kms_providers'
|
194
|
+
it_behaves_like 'an auto-encryption client that reconnects properly'
|
195
|
+
end
|
196
|
+
|
197
|
+
context 'with local KMS providers' do
|
198
|
+
include_context 'with local kms_providers'
|
199
|
+
it_behaves_like 'an auto-encryption client that reconnects properly'
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
context 'with custom key vault client option' do
|
204
|
+
let(:key_vault_client_option) do
|
205
|
+
new_local_client(
|
206
|
+
SpecConfig.instance.addresses,
|
207
|
+
SpecConfig.instance.test_options
|
208
|
+
)
|
209
|
+
end
|
210
|
+
|
211
|
+
context 'with AWS KMS providers' do
|
212
|
+
include_context 'with AWS kms_providers'
|
213
|
+
it_behaves_like 'an auto-encryption client that reconnects properly'
|
214
|
+
end
|
215
|
+
|
216
|
+
context 'with local KMS providers' do
|
217
|
+
include_context 'with local kms_providers'
|
218
|
+
it_behaves_like 'an auto-encryption client that reconnects properly'
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
@@ -0,0 +1,601 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bson'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
describe 'Auto Encryption' do
|
6
|
+
require_libmongocrypt
|
7
|
+
min_server_fcv '4.2'
|
8
|
+
require_enterprise
|
9
|
+
|
10
|
+
# Diagnostics of leaked background threads only, these tests do not
|
11
|
+
# actually require a clean slate. https://jira.mongodb.org/browse/RUBY-2138
|
12
|
+
clean_slate
|
13
|
+
|
14
|
+
include_context 'define shared FLE helpers'
|
15
|
+
|
16
|
+
let(:encryption_client) do
|
17
|
+
new_local_client(
|
18
|
+
SpecConfig.instance.addresses,
|
19
|
+
SpecConfig.instance.test_options.merge(
|
20
|
+
auto_encryption_options: {
|
21
|
+
kms_providers: kms_providers,
|
22
|
+
key_vault_namespace: key_vault_namespace,
|
23
|
+
schema_map: local_schema,
|
24
|
+
bypass_auto_encryption: bypass_auto_encryption,
|
25
|
+
# Spawn mongocryptd on non-default port for sharded cluster tests
|
26
|
+
extra_options: extra_options,
|
27
|
+
},
|
28
|
+
database: 'auto_encryption'
|
29
|
+
),
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:client) { authorized_client.use('auto_encryption') }
|
34
|
+
|
35
|
+
let(:bypass_auto_encryption) { false }
|
36
|
+
|
37
|
+
let(:encrypted_ssn_binary) do
|
38
|
+
BSON::Binary.new(Base64.decode64(encrypted_ssn), :ciphertext)
|
39
|
+
end
|
40
|
+
|
41
|
+
shared_context 'bypass auto encryption' do
|
42
|
+
let(:bypass_auto_encryption) { true }
|
43
|
+
end
|
44
|
+
|
45
|
+
shared_context 'jsonSchema validator on collection' do
|
46
|
+
let(:local_schema) { nil }
|
47
|
+
|
48
|
+
before do
|
49
|
+
client['users',
|
50
|
+
{
|
51
|
+
'validator' => { '$jsonSchema' => schema_map }
|
52
|
+
}
|
53
|
+
].create
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
shared_context 'schema map in client options' do
|
58
|
+
let(:local_schema) { { "auto_encryption.users" => schema_map } }
|
59
|
+
|
60
|
+
before do
|
61
|
+
client['users'].create
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
shared_context 'encrypted document in collection' do
|
66
|
+
before do
|
67
|
+
client['users'].insert_one(ssn: encrypted_ssn_binary)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
shared_context 'multiple encrypted documents in collection' do
|
72
|
+
before do
|
73
|
+
client['users'].insert_one(ssn: encrypted_ssn_binary)
|
74
|
+
client['users'].insert_one(ssn: encrypted_ssn_binary)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
before(:each) do
|
79
|
+
client['users'].drop
|
80
|
+
key_vault_collection.drop
|
81
|
+
key_vault_collection.insert_one(data_key)
|
82
|
+
end
|
83
|
+
|
84
|
+
shared_examples 'an encrypted command' do
|
85
|
+
context 'with AWS KMS provider' do
|
86
|
+
include_context 'with AWS kms_providers'
|
87
|
+
|
88
|
+
context 'with validator' do
|
89
|
+
include_context 'jsonSchema validator on collection'
|
90
|
+
it_behaves_like 'it performs an encrypted command'
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'with schema map' do
|
94
|
+
include_context 'schema map in client options'
|
95
|
+
it_behaves_like 'it performs an encrypted command'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'with local KMS provider' do
|
100
|
+
include_context 'with local kms_providers'
|
101
|
+
|
102
|
+
context 'with validator' do
|
103
|
+
include_context 'jsonSchema validator on collection'
|
104
|
+
it_behaves_like 'it performs an encrypted command'
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'with schema map' do
|
108
|
+
include_context 'schema map in client options'
|
109
|
+
it_behaves_like 'it performs an encrypted command'
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe '#aggregate' do
|
115
|
+
shared_examples 'it performs an encrypted command' do
|
116
|
+
include_context 'encrypted document in collection'
|
117
|
+
|
118
|
+
let(:result) do
|
119
|
+
encryption_client['users'].aggregate([
|
120
|
+
{ '$match' => { 'ssn' => ssn } }
|
121
|
+
]).first
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'encrypts the command and decrypts the response' do
|
125
|
+
result.should_not be_nil
|
126
|
+
result['ssn'].should == ssn
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'when bypass_auto_encryption=true' do
|
130
|
+
include_context 'bypass auto encryption'
|
131
|
+
|
132
|
+
it 'does not encrypt the command' do
|
133
|
+
result.should be_nil
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'does auto decrypt the response' do
|
137
|
+
result = encryption_client['users'].aggregate([
|
138
|
+
{ '$match' => { 'ssn' => encrypted_ssn_binary } }
|
139
|
+
]).first
|
140
|
+
|
141
|
+
result.should_not be_nil
|
142
|
+
result['ssn'].should == ssn
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
it_behaves_like 'an encrypted command'
|
148
|
+
end
|
149
|
+
|
150
|
+
describe '#count' do
|
151
|
+
shared_examples 'it performs an encrypted command' do
|
152
|
+
include_context 'multiple encrypted documents in collection'
|
153
|
+
|
154
|
+
let(:result) { encryption_client['users'].count(ssn: ssn) }
|
155
|
+
|
156
|
+
it 'encrypts the command and finds the documents' do
|
157
|
+
expect(result).to eq(2)
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'with bypass_auto_encryption=true' do
|
161
|
+
include_context 'bypass auto encryption'
|
162
|
+
|
163
|
+
it 'does not encrypt the command' do
|
164
|
+
expect(result).to eq(0)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
it_behaves_like 'an encrypted command'
|
170
|
+
end
|
171
|
+
|
172
|
+
describe '#distinct' do
|
173
|
+
shared_examples 'it performs an encrypted command' do
|
174
|
+
include_context 'encrypted document in collection'
|
175
|
+
|
176
|
+
let(:result) { encryption_client['users'].distinct(:ssn) }
|
177
|
+
|
178
|
+
it 'decrypts the SSN field' do
|
179
|
+
expect(result.length).to eq(1)
|
180
|
+
expect(result).to include(ssn)
|
181
|
+
end
|
182
|
+
|
183
|
+
context 'with bypass_auto_encryption=true' do
|
184
|
+
include_context 'bypass auto encryption'
|
185
|
+
|
186
|
+
it 'still decrypts the SSN field' do
|
187
|
+
expect(result.length).to eq(1)
|
188
|
+
expect(result).to include(ssn)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
it_behaves_like 'an encrypted command'
|
194
|
+
end
|
195
|
+
|
196
|
+
describe '#delete_one' do
|
197
|
+
shared_examples 'it performs an encrypted command' do
|
198
|
+
include_context 'encrypted document in collection'
|
199
|
+
|
200
|
+
let(:result) { encryption_client['users'].delete_one(ssn: ssn) }
|
201
|
+
|
202
|
+
it 'encrypts the SSN field' do
|
203
|
+
expect(result.deleted_count).to eq(1)
|
204
|
+
end
|
205
|
+
|
206
|
+
context 'with bypass_auto_encryption=true' do
|
207
|
+
include_context 'bypass auto encryption'
|
208
|
+
|
209
|
+
it 'does not encrypt the SSN field' do
|
210
|
+
expect(result.deleted_count).to eq(0)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
it_behaves_like 'an encrypted command'
|
216
|
+
end
|
217
|
+
|
218
|
+
describe '#delete_many' do
|
219
|
+
shared_examples 'it performs an encrypted command' do
|
220
|
+
include_context 'multiple encrypted documents in collection'
|
221
|
+
|
222
|
+
let(:result) { encryption_client['users'].delete_many(ssn: ssn) }
|
223
|
+
|
224
|
+
it 'decrypts the SSN field' do
|
225
|
+
expect(result.deleted_count).to eq(2)
|
226
|
+
end
|
227
|
+
|
228
|
+
context 'with bypass_auto_encryption=true' do
|
229
|
+
include_context 'bypass auto encryption'
|
230
|
+
|
231
|
+
it 'does not encrypt the SSN field' do
|
232
|
+
expect(result.deleted_count).to eq(0)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
it_behaves_like 'an encrypted command'
|
238
|
+
end
|
239
|
+
|
240
|
+
describe '#find' do
|
241
|
+
shared_examples 'it performs an encrypted command' do
|
242
|
+
include_context 'encrypted document in collection'
|
243
|
+
|
244
|
+
let(:result) { encryption_client['users'].find(ssn: ssn).first }
|
245
|
+
|
246
|
+
it 'encrypts the command and decrypts the response' do
|
247
|
+
result.should_not be_nil
|
248
|
+
expect(result['ssn']).to eq(ssn)
|
249
|
+
end
|
250
|
+
|
251
|
+
context 'when bypass_auto_encryption=true' do
|
252
|
+
include_context 'bypass auto encryption'
|
253
|
+
|
254
|
+
it 'does not encrypt the command' do
|
255
|
+
expect(result).to be_nil
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
it_behaves_like 'an encrypted command'
|
261
|
+
end
|
262
|
+
|
263
|
+
describe '#find_one_and_delete' do
|
264
|
+
shared_examples 'it performs an encrypted command' do
|
265
|
+
include_context 'encrypted document in collection'
|
266
|
+
|
267
|
+
let(:result) { encryption_client['users'].find_one_and_delete(ssn: ssn) }
|
268
|
+
|
269
|
+
it 'encrypts the command and decrypts the response' do
|
270
|
+
expect(result['ssn']).to eq(ssn)
|
271
|
+
end
|
272
|
+
|
273
|
+
context 'when bypass_auto_encryption=true' do
|
274
|
+
include_context 'bypass auto encryption'
|
275
|
+
|
276
|
+
it 'does not encrypt the command' do
|
277
|
+
expect(result).to be_nil
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'still decrypts the command' do
|
281
|
+
result = encryption_client['users'].find_one_and_delete(ssn: encrypted_ssn_binary)
|
282
|
+
expect(result['ssn']).to eq(ssn)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
it_behaves_like 'an encrypted command'
|
288
|
+
end
|
289
|
+
|
290
|
+
describe '#find_one_and_replace' do
|
291
|
+
shared_examples 'it performs an encrypted command' do
|
292
|
+
let(:name) { 'Alan Turing' }
|
293
|
+
|
294
|
+
context 'with :return_document => :before' do
|
295
|
+
include_context 'encrypted document in collection'
|
296
|
+
|
297
|
+
let(:result) do
|
298
|
+
encryption_client['users'].find_one_and_replace(
|
299
|
+
{ ssn: ssn },
|
300
|
+
{ name: name },
|
301
|
+
return_document: :before
|
302
|
+
)
|
303
|
+
end
|
304
|
+
|
305
|
+
it 'encrypts the command and decrypts the response, returning original document' do
|
306
|
+
expect(result['ssn']).to eq(ssn)
|
307
|
+
|
308
|
+
documents = client['users'].find
|
309
|
+
expect(documents.count).to eq(1)
|
310
|
+
expect(documents.first['ssn']).to be_nil
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
context 'with :return_document => :after' do
|
315
|
+
before do
|
316
|
+
client['users'].insert_one(name: name)
|
317
|
+
end
|
318
|
+
|
319
|
+
let(:result) do
|
320
|
+
encryption_client['users'].find_one_and_replace(
|
321
|
+
{ name: name },
|
322
|
+
{ ssn: ssn },
|
323
|
+
return_document: :after
|
324
|
+
)
|
325
|
+
end
|
326
|
+
|
327
|
+
it 'encrypts the command and decrypts the response, returning new document' do
|
328
|
+
expect(result['ssn']).to eq(ssn)
|
329
|
+
|
330
|
+
documents = client['users'].find
|
331
|
+
expect(documents.count).to eq(1)
|
332
|
+
expect(documents.first['ssn']).to eq(encrypted_ssn_binary)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
context 'when bypass_auto_encryption=true' do
|
337
|
+
include_context 'bypass auto encryption'
|
338
|
+
include_context 'encrypted document in collection'
|
339
|
+
|
340
|
+
let(:result) do
|
341
|
+
encryption_client['users'].find_one_and_replace(
|
342
|
+
{ ssn: encrypted_ssn_binary },
|
343
|
+
{ name: name },
|
344
|
+
:return_document => :before
|
345
|
+
)
|
346
|
+
end
|
347
|
+
|
348
|
+
it 'does not encrypt the command but still decrypts the response, returning original document' do
|
349
|
+
expect(result['ssn']).to eq(ssn)
|
350
|
+
|
351
|
+
documents = client['users'].find
|
352
|
+
expect(documents.count).to eq(1)
|
353
|
+
expect(documents.first['ssn']).to be_nil
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
it_behaves_like 'an encrypted command'
|
359
|
+
end
|
360
|
+
|
361
|
+
describe '#find_one_and_update' do
|
362
|
+
shared_examples 'it performs an encrypted command' do
|
363
|
+
include_context 'encrypted document in collection'
|
364
|
+
|
365
|
+
let(:name) { 'Alan Turing' }
|
366
|
+
|
367
|
+
let(:result) do
|
368
|
+
encryption_client['users'].find_one_and_update(
|
369
|
+
{ ssn: ssn },
|
370
|
+
{ name: name }
|
371
|
+
)
|
372
|
+
end
|
373
|
+
|
374
|
+
it 'encrypts the command and decrypts the response' do
|
375
|
+
expect(result['ssn']).to eq(ssn)
|
376
|
+
|
377
|
+
documents = client['users'].find
|
378
|
+
expect(documents.count).to eq(1)
|
379
|
+
expect(documents.first['ssn']).to be_nil
|
380
|
+
end
|
381
|
+
|
382
|
+
context 'with bypass_auto_encryption=true' do
|
383
|
+
include_context 'bypass auto encryption'
|
384
|
+
|
385
|
+
it 'does not encrypt the command' do
|
386
|
+
expect(result).to be_nil
|
387
|
+
end
|
388
|
+
|
389
|
+
it 'still decrypts the response' do
|
390
|
+
# Query using the encrypted ssn value so the find will succeed
|
391
|
+
result = encryption_client['users'].find_one_and_update(
|
392
|
+
{ ssn: encrypted_ssn_binary },
|
393
|
+
{ name: name }
|
394
|
+
)
|
395
|
+
|
396
|
+
expect(result['ssn']).to eq(ssn)
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
it_behaves_like 'an encrypted command'
|
402
|
+
end
|
403
|
+
|
404
|
+
describe '#insert_one' do
|
405
|
+
let(:query) { { ssn: ssn } }
|
406
|
+
let(:result) { encryption_client['users'].insert_one(query) }
|
407
|
+
|
408
|
+
shared_examples 'it performs an encrypted command' do
|
409
|
+
it 'encrypts the ssn field' do
|
410
|
+
expect(result).to be_ok
|
411
|
+
expect(result.inserted_ids.length).to eq(1)
|
412
|
+
|
413
|
+
id = result.inserted_ids.first
|
414
|
+
|
415
|
+
document = client['users'].find(_id: id).first
|
416
|
+
document.should_not be_nil
|
417
|
+
expect(document['ssn']).to eq(encrypted_ssn_binary)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
shared_examples 'it obeys bypass_auto_encryption option' do
|
422
|
+
include_context 'bypass auto encryption'
|
423
|
+
|
424
|
+
it 'does not encrypt the command' do
|
425
|
+
result = encryption_client['users'].insert_one(ssn: ssn)
|
426
|
+
expect(result).to be_ok
|
427
|
+
expect(result.inserted_ids.length).to eq(1)
|
428
|
+
|
429
|
+
id = result.inserted_ids.first
|
430
|
+
|
431
|
+
document = client['users'].find(_id: id).first
|
432
|
+
expect(document['ssn']).to eq(ssn)
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
it_behaves_like 'an encrypted command'
|
437
|
+
|
438
|
+
context 'with jsonSchema in schema_map option' do
|
439
|
+
include_context 'schema map in client options'
|
440
|
+
|
441
|
+
context 'with AWS KMS provider' do
|
442
|
+
include_context 'with AWS kms_providers'
|
443
|
+
it_behaves_like 'it obeys bypass_auto_encryption option'
|
444
|
+
end
|
445
|
+
|
446
|
+
context 'with local KMS provider and ' do
|
447
|
+
include_context 'with local kms_providers'
|
448
|
+
it_behaves_like 'it obeys bypass_auto_encryption option'
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
context 'with schema_map client option pointing to wrong collection' do
|
453
|
+
let(:local_schema) { { 'wrong_db.wrong_coll' => schema_map } }
|
454
|
+
|
455
|
+
include_context 'with local kms_providers'
|
456
|
+
|
457
|
+
it 'does not raise an exception but doesn\'t encrypt either' do
|
458
|
+
expect do
|
459
|
+
result
|
460
|
+
end.not_to raise_error
|
461
|
+
|
462
|
+
expect(result).to be_ok
|
463
|
+
id = result.inserted_ids.first
|
464
|
+
|
465
|
+
document = client['users'].find(_id: id).first
|
466
|
+
document.should_not be_nil
|
467
|
+
# Document was not encrypted
|
468
|
+
expect(document['ssn']).to eq(ssn)
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
context 'encrypting using key alt name' do
|
473
|
+
include_context 'schema map in client options'
|
474
|
+
|
475
|
+
let(:query) { { ssn: ssn, altname: key_alt_name } }
|
476
|
+
|
477
|
+
context 'with AWS KMS provider' do
|
478
|
+
include_context 'with AWS kms_providers and key alt names'
|
479
|
+
it 'encrypts the ssn field' do
|
480
|
+
expect(result).to be_ok
|
481
|
+
expect(result.inserted_ids.length).to eq(1)
|
482
|
+
|
483
|
+
id = result.inserted_ids.first
|
484
|
+
|
485
|
+
document = client['users'].find(_id: id).first
|
486
|
+
document.should_not be_nil
|
487
|
+
# Auto-encryption with key alt names only works with random encryption,
|
488
|
+
# so it will not generate the same result on every test run.
|
489
|
+
expect(document['ssn']).to be_ciphertext
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
context 'with local KMS provider' do
|
494
|
+
include_context 'with local kms_providers and key alt names'
|
495
|
+
it 'encrypts the ssn field' do
|
496
|
+
expect(result).to be_ok
|
497
|
+
expect(result.inserted_ids.length).to eq(1)
|
498
|
+
|
499
|
+
id = result.inserted_ids.first
|
500
|
+
|
501
|
+
document = client['users'].find(_id: id).first
|
502
|
+
document.should_not be_nil
|
503
|
+
# Auto-encryption with key alt names only works with random encryption,
|
504
|
+
# so it will not generate the same result on every test run.
|
505
|
+
expect(document['ssn']).to be_a_kind_of(BSON::Binary)
|
506
|
+
end
|
507
|
+
end
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
describe '#replace_one' do
|
512
|
+
shared_examples 'it performs an encrypted command' do
|
513
|
+
include_context 'encrypted document in collection'
|
514
|
+
|
515
|
+
let(:replacement_ssn) { '098-765-4321' }
|
516
|
+
|
517
|
+
let(:result) do
|
518
|
+
encryption_client['users'].replace_one(
|
519
|
+
{ ssn: ssn },
|
520
|
+
{ ssn: replacement_ssn }
|
521
|
+
)
|
522
|
+
end
|
523
|
+
|
524
|
+
it 'encrypts the ssn field' do
|
525
|
+
expect(result.modified_count).to eq(1)
|
526
|
+
|
527
|
+
find_result = encryption_client['users'].find(ssn: '098-765-4321')
|
528
|
+
expect(find_result.count).to eq(1)
|
529
|
+
end
|
530
|
+
|
531
|
+
context 'with bypass_auto_encryption=true' do
|
532
|
+
include_context 'bypass auto encryption'
|
533
|
+
|
534
|
+
it 'does not encrypt the command' do
|
535
|
+
expect(result.modified_count).to eq(0)
|
536
|
+
end
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
it_behaves_like 'an encrypted command'
|
541
|
+
end
|
542
|
+
|
543
|
+
describe '#update_one' do
|
544
|
+
shared_examples 'it performs an encrypted command' do
|
545
|
+
include_context 'encrypted document in collection'
|
546
|
+
|
547
|
+
let(:result) do
|
548
|
+
encryption_client['users'].update_one({ ssn: ssn }, { ssn: '098-765-4321' })
|
549
|
+
end
|
550
|
+
|
551
|
+
it 'encrypts the ssn field' do
|
552
|
+
expect(result.n).to eq(1)
|
553
|
+
|
554
|
+
find_result = encryption_client['users'].find(ssn: '098-765-4321')
|
555
|
+
expect(find_result.count).to eq(1)
|
556
|
+
end
|
557
|
+
|
558
|
+
context 'with bypass_auto_encryption=true' do
|
559
|
+
include_context 'bypass auto encryption'
|
560
|
+
|
561
|
+
it 'does not encrypt the command' do
|
562
|
+
expect(result.n).to eq(0)
|
563
|
+
end
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
567
|
+
it_behaves_like 'an encrypted command'
|
568
|
+
end
|
569
|
+
|
570
|
+
describe '#update_many' do
|
571
|
+
shared_examples 'it performs an encrypted command' do
|
572
|
+
before do
|
573
|
+
client['users'].insert_one(ssn: encrypted_ssn_binary, age: 25)
|
574
|
+
client['users'].insert_one(ssn: encrypted_ssn_binary, age: 43)
|
575
|
+
end
|
576
|
+
|
577
|
+
let(:result) do
|
578
|
+
encryption_client['users'].update_many({ ssn: ssn }, { "$inc" => { :age => 1 } })
|
579
|
+
end
|
580
|
+
|
581
|
+
it 'encrypts the ssn field' do
|
582
|
+
expect(result.n).to eq(2)
|
583
|
+
|
584
|
+
updated_documents = encryption_client['users'].find(ssn: ssn)
|
585
|
+
ages = updated_documents.map { |doc| doc['age'] }
|
586
|
+
expect(ages).to include(26)
|
587
|
+
expect(ages).to include(44)
|
588
|
+
end
|
589
|
+
|
590
|
+
context 'with bypass_auto_encryption=true' do
|
591
|
+
include_context 'bypass auto encryption'
|
592
|
+
|
593
|
+
it 'does not encrypt the command' do
|
594
|
+
expect(result.n).to eq(0)
|
595
|
+
end
|
596
|
+
end
|
597
|
+
end
|
598
|
+
|
599
|
+
it_behaves_like 'an encrypted command'
|
600
|
+
end
|
601
|
+
end
|