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.
Files changed (357) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CONTRIBUTING.md +1 -1
  5. data/README.md +2 -1
  6. data/lib/mongo.rb +3 -0
  7. data/lib/mongo/address.rb +44 -19
  8. data/lib/mongo/auth.rb +1 -0
  9. data/lib/mongo/auth/credential_cache.rb +51 -0
  10. data/lib/mongo/auth/scram/conversation.rb +20 -16
  11. data/lib/mongo/auth/user.rb +0 -8
  12. data/lib/mongo/auth/user/view.rb +4 -4
  13. data/lib/mongo/background_thread.rb +1 -1
  14. data/lib/mongo/bulk_write.rb +5 -5
  15. data/lib/mongo/client.rb +143 -14
  16. data/lib/mongo/client_encryption.rb +103 -0
  17. data/lib/mongo/cluster.rb +8 -4
  18. data/lib/mongo/cluster/reapers/cursor_reaper.rb +18 -6
  19. data/lib/mongo/cluster/sdam_flow.rb +54 -58
  20. data/lib/mongo/collection.rb +3 -3
  21. data/lib/mongo/collection/view.rb +1 -1
  22. data/lib/mongo/collection/view/aggregation.rb +1 -1
  23. data/lib/mongo/collection/view/change_stream.rb +12 -3
  24. data/lib/mongo/collection/view/iterable.rb +14 -5
  25. data/lib/mongo/collection/view/map_reduce.rb +2 -2
  26. data/lib/mongo/collection/view/readable.rb +9 -7
  27. data/lib/mongo/collection/view/writable.rb +7 -7
  28. data/lib/mongo/crypt.rb +33 -0
  29. data/lib/mongo/crypt/auto_decryption_context.rb +40 -0
  30. data/lib/mongo/crypt/auto_encrypter.rb +179 -0
  31. data/lib/mongo/crypt/auto_encryption_context.rb +44 -0
  32. data/lib/mongo/crypt/binary.rb +155 -0
  33. data/lib/mongo/crypt/binding.rb +1229 -0
  34. data/lib/mongo/crypt/context.rb +135 -0
  35. data/lib/mongo/crypt/data_key_context.rb +162 -0
  36. data/lib/mongo/crypt/encryption_io.rb +289 -0
  37. data/lib/mongo/crypt/explicit_decryption_context.rb +40 -0
  38. data/lib/mongo/crypt/explicit_encrypter.rb +117 -0
  39. data/lib/mongo/crypt/explicit_encryption_context.rb +89 -0
  40. data/lib/mongo/crypt/handle.rb +315 -0
  41. data/lib/mongo/crypt/hooks.rb +90 -0
  42. data/lib/mongo/crypt/kms_context.rb +67 -0
  43. data/lib/mongo/crypt/status.rb +131 -0
  44. data/lib/mongo/cursor.rb +64 -32
  45. data/lib/mongo/database.rb +23 -6
  46. data/lib/mongo/database/view.rb +13 -4
  47. data/lib/mongo/dbref.rb +9 -2
  48. data/lib/mongo/error.rb +5 -1
  49. data/lib/mongo/error/bulk_write_error.rb +16 -14
  50. data/lib/mongo/error/crypt_error.rb +31 -0
  51. data/lib/mongo/error/{failed_stringprep_validation.rb → failed_string_prep_validation.rb} +0 -0
  52. data/lib/mongo/error/invalid_cursor_operation.rb +27 -0
  53. data/lib/mongo/error/kms_error.rb +22 -0
  54. data/lib/mongo/error/max_bson_size.rb +14 -3
  55. data/lib/mongo/error/mongocryptd_spawn_error.rb +22 -0
  56. data/lib/mongo/error/no_server_available.rb +8 -3
  57. data/lib/mongo/error/notable.rb +0 -15
  58. data/lib/mongo/error/operation_failure.rb +1 -0
  59. data/lib/mongo/error/parser.rb +1 -1
  60. data/lib/mongo/grid/file.rb +5 -0
  61. data/lib/mongo/grid/file/chunk.rb +2 -0
  62. data/lib/mongo/grid/file/info.rb +3 -2
  63. data/lib/mongo/grid/fs_bucket.rb +15 -13
  64. data/lib/mongo/grid/stream/write.rb +9 -3
  65. data/lib/mongo/index/view.rb +3 -3
  66. data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +1 -1
  67. data/lib/mongo/monitoring/event/command_started.rb +6 -1
  68. data/lib/mongo/operation/collections_info.rb +6 -3
  69. data/lib/mongo/operation/delete/op_msg.rb +1 -1
  70. data/lib/mongo/operation/find/op_msg.rb +4 -1
  71. data/lib/mongo/operation/get_more/op_msg.rb +4 -1
  72. data/lib/mongo/operation/insert/command.rb +3 -2
  73. data/lib/mongo/operation/insert/legacy.rb +3 -2
  74. data/lib/mongo/operation/insert/op_msg.rb +3 -3
  75. data/lib/mongo/operation/result.rb +36 -27
  76. data/lib/mongo/operation/shared/executable.rb +11 -9
  77. data/lib/mongo/operation/shared/executable_no_validate.rb +2 -2
  78. data/lib/mongo/operation/shared/op_msg_or_command.rb +2 -2
  79. data/lib/mongo/operation/shared/op_msg_or_find_command.rb +2 -2
  80. data/lib/mongo/operation/shared/op_msg_or_list_indexes_command.rb +2 -2
  81. data/lib/mongo/operation/shared/read_preference_supported.rb +68 -19
  82. data/lib/mongo/operation/shared/response_handling.rb +1 -1
  83. data/lib/mongo/operation/shared/sessions_supported.rb +44 -3
  84. data/lib/mongo/operation/shared/write.rb +17 -10
  85. data/lib/mongo/operation/update/op_msg.rb +1 -1
  86. data/lib/mongo/protocol/bit_vector.rb +2 -1
  87. data/lib/mongo/protocol/compressed.rb +6 -5
  88. data/lib/mongo/protocol/insert.rb +3 -1
  89. data/lib/mongo/protocol/message.rb +94 -15
  90. data/lib/mongo/protocol/msg.rb +207 -37
  91. data/lib/mongo/protocol/query.rb +7 -9
  92. data/lib/mongo/protocol/serializers.rb +43 -15
  93. data/lib/mongo/retryable.rb +1 -1
  94. data/lib/mongo/server.rb +10 -4
  95. data/lib/mongo/server/connection.rb +20 -9
  96. data/lib/mongo/server/connection_base.rb +118 -18
  97. data/lib/mongo/server/connection_common.rb +61 -0
  98. data/lib/mongo/server/connection_pool.rb +37 -1
  99. data/lib/mongo/server/connection_pool/populator.rb +1 -1
  100. data/lib/mongo/server/description.rb +9 -11
  101. data/lib/mongo/server/monitor.rb +2 -0
  102. data/lib/mongo/server/monitor/connection.rb +3 -18
  103. data/lib/mongo/server/pending_connection.rb +2 -1
  104. data/lib/mongo/session.rb +3 -3
  105. data/lib/mongo/session/session_pool.rb +8 -3
  106. data/lib/mongo/socket.rb +29 -16
  107. data/lib/mongo/socket/ssl.rb +23 -8
  108. data/lib/mongo/socket/tcp.rb +12 -3
  109. data/lib/mongo/srv/monitor.rb +73 -42
  110. data/lib/mongo/srv/result.rb +0 -1
  111. data/lib/mongo/timeout.rb +49 -0
  112. data/lib/mongo/uri.rb +30 -1
  113. data/lib/mongo/uri/srv_protocol.rb +1 -1
  114. data/lib/mongo/version.rb +1 -1
  115. data/mongo.gemspec +1 -3
  116. data/spec/README.md +228 -7
  117. data/spec/integration/auth_spec.rb +53 -0
  118. data/spec/integration/bulk_write_spec.rb +19 -0
  119. data/spec/integration/{client_options_spec.rb → client_authentication_options_spec.rb} +10 -10
  120. data/spec/integration/client_construction_spec.rb +100 -1
  121. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +353 -0
  122. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +303 -0
  123. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +72 -0
  124. data/spec/integration/client_side_encryption/auto_encryption_old_wire_version_spec.rb +79 -0
  125. data/spec/integration/client_side_encryption/auto_encryption_reconnect_spec.rb +221 -0
  126. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +601 -0
  127. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +187 -0
  128. data/spec/integration/client_side_encryption/bypass_mongocryptd_spawn_spec.rb +78 -0
  129. data/spec/integration/client_side_encryption/client_close_spec.rb +63 -0
  130. data/spec/integration/client_side_encryption/corpus_spec.rb +233 -0
  131. data/spec/integration/client_side_encryption/custom_endpoint_spec.rb +132 -0
  132. data/spec/integration/client_side_encryption/data_key_spec.rb +165 -0
  133. data/spec/integration/client_side_encryption/explicit_encryption_spec.rb +114 -0
  134. data/spec/integration/client_side_encryption/external_key_vault_spec.rb +141 -0
  135. data/spec/integration/client_side_encryption/views_spec.rb +44 -0
  136. data/spec/integration/client_update_spec.rb +154 -0
  137. data/spec/integration/command_monitoring_spec.rb +3 -1
  138. data/spec/integration/command_spec.rb +44 -10
  139. data/spec/integration/connection_spec.rb +57 -0
  140. data/spec/integration/crud_spec.rb +89 -0
  141. data/spec/integration/grid_fs_bucket_spec.rb +48 -0
  142. data/spec/integration/read_preference_spec.rb +26 -0
  143. data/spec/integration/reconnect_spec.rb +7 -6
  144. data/spec/integration/size_limit_spec.rb +111 -0
  145. data/spec/integration/srv_monitoring_spec.rb +16 -8
  146. data/spec/integration/zlib_compression_spec.rb +25 -0
  147. data/spec/kerberos/kerberos_spec.rb +87 -0
  148. data/spec/lite_spec_helper.rb +34 -29
  149. data/spec/mongo/auth/cr_spec.rb +8 -0
  150. data/spec/mongo/auth/ldap_spec.rb +5 -1
  151. data/spec/mongo/auth/scram/conversation_spec.rb +5 -6
  152. data/spec/mongo/auth/scram/negotiation_spec.rb +74 -75
  153. data/spec/mongo/auth/scram_spec.rb +45 -35
  154. data/spec/mongo/auth/user/view_spec.rb +3 -6
  155. data/spec/mongo/auth/x509_spec.rb +5 -1
  156. data/spec/mongo/bulk_write/result_spec.rb +11 -7
  157. data/spec/mongo/client_construction_spec.rb +206 -2
  158. data/spec/mongo/client_encryption_spec.rb +405 -0
  159. data/spec/mongo/cluster/cursor_reaper_spec.rb +12 -8
  160. data/spec/mongo/cluster/socket_reaper_spec.rb +14 -3
  161. data/spec/mongo/collection/view/aggregation_spec.rb +0 -2
  162. data/spec/mongo/collection/view/change_stream_spec.rb +7 -7
  163. data/spec/mongo/collection/view/map_reduce_spec.rb +3 -3
  164. data/spec/mongo/collection/view_spec.rb +1 -1
  165. data/spec/mongo/collection_spec.rb +28 -9
  166. data/spec/mongo/crypt/auto_decryption_context_spec.rb +90 -0
  167. data/spec/mongo/crypt/auto_encrypter_spec.rb +187 -0
  168. data/spec/mongo/crypt/auto_encryption_context_spec.rb +107 -0
  169. data/spec/mongo/crypt/binary_spec.rb +115 -0
  170. data/spec/mongo/crypt/binding/binary_spec.rb +56 -0
  171. data/spec/mongo/crypt/binding/context_spec.rb +257 -0
  172. data/spec/mongo/crypt/binding/helpers_spec.rb +46 -0
  173. data/spec/mongo/crypt/binding/mongocrypt_spec.rb +144 -0
  174. data/spec/mongo/crypt/binding/status_spec.rb +99 -0
  175. data/spec/mongo/crypt/binding/version_spec.rb +22 -0
  176. data/spec/mongo/crypt/binding_unloaded_spec.rb +20 -0
  177. data/spec/mongo/crypt/data_key_context_spec.rb +213 -0
  178. data/spec/mongo/crypt/encryption_io_spec.rb +136 -0
  179. data/spec/mongo/crypt/explicit_decryption_context_spec.rb +72 -0
  180. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +170 -0
  181. data/spec/mongo/crypt/handle_spec.rb +232 -0
  182. data/spec/mongo/crypt/helpers/mongo_crypt_spec_helper.rb +108 -0
  183. data/spec/mongo/crypt/status_spec.rb +152 -0
  184. data/spec/mongo/cursor_spec.rb +24 -4
  185. data/spec/mongo/database_spec.rb +20 -0
  186. data/spec/mongo/error/bulk_write_error_spec.rb +49 -0
  187. data/spec/mongo/error/crypt_error_spec.rb +26 -0
  188. data/spec/mongo/error/max_bson_size_spec.rb +35 -0
  189. data/spec/mongo/error/no_server_available_spec.rb +11 -1
  190. data/spec/mongo/error/notable_spec.rb +59 -0
  191. data/spec/mongo/error/operation_failure_spec.rb +6 -6
  192. data/spec/mongo/operation/aggregate_spec.rb +1 -1
  193. data/spec/mongo/operation/collections_info_spec.rb +1 -1
  194. data/spec/mongo/operation/command_spec.rb +3 -3
  195. data/spec/mongo/operation/create_index_spec.rb +3 -3
  196. data/spec/mongo/operation/create_user_spec.rb +3 -3
  197. data/spec/mongo/operation/delete/bulk_spec.rb +6 -6
  198. data/spec/mongo/operation/delete/op_msg_spec.rb +1 -6
  199. data/spec/mongo/operation/delete_spec.rb +7 -7
  200. data/spec/mongo/operation/drop_index_spec.rb +2 -2
  201. data/spec/mongo/operation/find/legacy_spec.rb +2 -1
  202. data/spec/mongo/operation/get_more_spec.rb +1 -1
  203. data/spec/mongo/operation/indexes_spec.rb +1 -1
  204. data/spec/mongo/operation/insert/bulk_spec.rb +7 -7
  205. data/spec/mongo/operation/insert/op_msg_spec.rb +3 -6
  206. data/spec/mongo/operation/insert_spec.rb +12 -12
  207. data/spec/mongo/operation/map_reduce_spec.rb +2 -2
  208. data/spec/mongo/operation/read_preference_legacy_spec.rb +351 -0
  209. data/spec/mongo/operation/read_preference_op_msg_spec.rb +194 -0
  210. data/spec/mongo/operation/remove_user_spec.rb +3 -3
  211. data/spec/mongo/operation/update/bulk_spec.rb +6 -6
  212. data/spec/mongo/operation/update/op_msg_spec.rb +3 -6
  213. data/spec/mongo/operation/update_spec.rb +7 -7
  214. data/spec/mongo/operation/update_user_spec.rb +1 -1
  215. data/spec/mongo/protocol/compressed_spec.rb +2 -3
  216. data/spec/mongo/protocol/delete_spec.rb +9 -8
  217. data/spec/mongo/protocol/get_more_spec.rb +9 -8
  218. data/spec/mongo/protocol/insert_spec.rb +9 -8
  219. data/spec/mongo/protocol/kill_cursors_spec.rb +6 -5
  220. data/spec/mongo/protocol/msg_spec.rb +57 -53
  221. data/spec/mongo/protocol/query_spec.rb +12 -12
  222. data/spec/mongo/protocol/registry_spec.rb +1 -1
  223. data/spec/mongo/protocol/reply_spec.rb +1 -1
  224. data/spec/mongo/protocol/update_spec.rb +10 -9
  225. data/spec/mongo/server/connection_pool_spec.rb +1 -1
  226. data/spec/mongo/server/connection_spec.rb +28 -7
  227. data/spec/mongo/socket_spec.rb +1 -1
  228. data/spec/mongo/srv/monitor_spec.rb +88 -69
  229. data/spec/mongo/timeout_spec.rb +85 -0
  230. data/spec/mongo/uri/srv_protocol_spec.rb +2 -2
  231. data/spec/mongo/uri_spec.rb +52 -5
  232. data/spec/mongo/write_concern_spec.rb +13 -1
  233. data/spec/{support → runners}/auth.rb +14 -1
  234. data/spec/{support → runners}/change_streams.rb +1 -1
  235. data/spec/{support → runners}/change_streams/operation.rb +0 -0
  236. data/spec/{support → runners}/cmap.rb +1 -1
  237. data/spec/{support → runners}/cmap/verifier.rb +0 -0
  238. data/spec/{support → runners}/command_monitoring.rb +0 -0
  239. data/spec/runners/connection_string.rb +358 -4
  240. data/spec/{support → runners}/crud.rb +9 -9
  241. data/spec/{support → runners}/crud/context.rb +0 -0
  242. data/spec/{support → runners}/crud/operation.rb +7 -3
  243. data/spec/{support → runners}/crud/outcome.rb +0 -0
  244. data/spec/{support → runners}/crud/requirement.rb +1 -1
  245. data/spec/{support → runners}/crud/spec.rb +12 -1
  246. data/spec/{support → runners}/crud/test.rb +0 -0
  247. data/spec/{support → runners}/crud/test_base.rb +0 -0
  248. data/spec/{support → runners}/crud/verifier.rb +10 -12
  249. data/spec/{support → runners}/gridfs.rb +0 -0
  250. data/spec/{support → runners}/sdam_monitoring.rb +0 -0
  251. data/spec/{support → runners}/server_discovery_and_monitoring.rb +0 -0
  252. data/spec/{support → runners}/server_selection.rb +0 -0
  253. data/spec/{support → runners}/server_selection_rtt.rb +0 -0
  254. data/spec/{support → runners}/transactions.rb +9 -11
  255. data/spec/{support → runners}/transactions/context.rb +0 -0
  256. data/spec/{support → runners}/transactions/operation.rb +0 -0
  257. data/spec/{support → runners}/transactions/spec.rb +0 -0
  258. data/spec/{support → runners}/transactions/test.rb +37 -5
  259. data/spec/spec_helper.rb +0 -5
  260. data/spec/spec_tests/auth_spec.rb +3 -3
  261. data/spec/spec_tests/client_side_encryption_spec.rb +8 -0
  262. data/spec/spec_tests/connection_string_spec.rb +1 -1
  263. data/spec/spec_tests/data/auth/connection-string.yml +13 -0
  264. data/spec/spec_tests/data/client_side_encryption/aggregate.yml +134 -0
  265. data/spec/spec_tests/data/client_side_encryption/badQueries.yml +526 -0
  266. data/spec/spec_tests/data/client_side_encryption/badSchema.yml +73 -0
  267. data/spec/spec_tests/data/client_side_encryption/basic.yml +116 -0
  268. data/spec/spec_tests/data/client_side_encryption/bulk.yml +88 -0
  269. data/spec/spec_tests/data/client_side_encryption/bypassAutoEncryption.yml +100 -0
  270. data/spec/spec_tests/data/client_side_encryption/bypassedCommand.yml +42 -0
  271. data/spec/spec_tests/data/client_side_encryption/count.yml +61 -0
  272. data/spec/spec_tests/data/client_side_encryption/countDocuments.yml +59 -0
  273. data/spec/spec_tests/data/client_side_encryption/delete.yml +105 -0
  274. data/spec/spec_tests/data/client_side_encryption/distinct.yml +73 -0
  275. data/spec/spec_tests/data/client_side_encryption/explain.yml +64 -0
  276. data/spec/spec_tests/data/client_side_encryption/find.yml +119 -0
  277. data/spec/spec_tests/data/client_side_encryption/findOneAndDelete.yml +57 -0
  278. data/spec/spec_tests/data/client_side_encryption/findOneAndReplace.yml +57 -0
  279. data/spec/spec_tests/data/client_side_encryption/findOneAndUpdate.yml +57 -0
  280. data/spec/spec_tests/data/client_side_encryption/getMore.yml +68 -0
  281. data/spec/spec_tests/data/client_side_encryption/insert.yml +102 -0
  282. data/spec/spec_tests/data/client_side_encryption/keyAltName.yml +71 -0
  283. data/spec/spec_tests/data/client_side_encryption/localKMS.yml +54 -0
  284. data/spec/spec_tests/data/client_side_encryption/localSchema.yml +72 -0
  285. data/spec/spec_tests/data/client_side_encryption/malformedCiphertext.yml +69 -0
  286. data/spec/spec_tests/data/client_side_encryption/maxWireVersion.yml +20 -0
  287. data/spec/spec_tests/data/client_side_encryption/missingKey.yml +49 -0
  288. data/spec/spec_tests/data/client_side_encryption/replaceOne.yml +64 -0
  289. data/spec/spec_tests/data/client_side_encryption/types.yml +527 -0
  290. data/spec/spec_tests/data/client_side_encryption/unsupportedCommand.yml +25 -0
  291. data/spec/spec_tests/data/client_side_encryption/updateMany.yml +77 -0
  292. data/spec/spec_tests/data/client_side_encryption/updateOne.yml +171 -0
  293. data/spec/spec_tests/data/read_write_concern/connection-string/write-concern.yml +1 -4
  294. data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +21 -0
  295. data/spec/spec_tests/data/sdam/rs/incompatible_ghost.yml +2 -4
  296. data/spec/spec_tests/data/sdam/rs/incompatible_other.yml +1 -1
  297. data/spec/spec_tests/data/sdam/rs/primary_mismatched_me_not_removed.yml +73 -0
  298. data/spec/spec_tests/data/sdam/rs/primary_to_no_primary_mismatched_me.yml +1 -2
  299. data/spec/spec_tests/data/sdam/rs/repeated.yml +101 -0
  300. data/spec/spec_tests/data/sdam/rs/{primary_address_change.yml → ruby_primary_address_change.yml} +2 -0
  301. 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
  302. data/spec/spec_tests/data/sdam/sharded/ruby_discovered_single_mongos.yml +27 -0
  303. data/spec/spec_tests/data/sdam/sharded/{primary_address_change.yml → ruby_primary_different_address.yml} +1 -1
  304. data/spec/spec_tests/data/sdam/sharded/{primary_mismatched_me.yml → ruby_primary_mismatched_me.yml} +1 -1
  305. data/spec/spec_tests/data/sdam/single/{primary_address_change.yml → ruby_primary_different_address.yml} +1 -1
  306. data/spec/spec_tests/data/sdam/single/{primary_mismatched_me.yml → ruby_primary_mismatched_me.yml} +1 -1
  307. data/spec/spec_tests/data/sdam_monitoring/{replica_set_with_primary_change.yml → replica_set_primary_address_change.yml} +27 -5
  308. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_me_mismatch.yml +26 -74
  309. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_removal.yml +20 -16
  310. data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +73 -0
  311. data/spec/spec_tests/data/transactions/pin-mongos.yml +2 -3
  312. data/spec/spec_tests/data/uri_options/auth-options.yml +10 -0
  313. data/spec/spec_tests/data/uri_options/tls-options.yml +75 -4
  314. data/spec/spec_tests/read_write_concern_connection_string_spec.rb +1 -1
  315. data/spec/spec_tests/uri_options_spec.rb +6 -8
  316. data/spec/stress/connection_pool_timing_spec.rb +6 -3
  317. data/spec/support/certificates/README.md +4 -0
  318. data/spec/support/certificates/server-second-level-bundle.pem +77 -77
  319. data/spec/support/certificates/server-second-level.crt +52 -52
  320. data/spec/support/certificates/server-second-level.key +25 -25
  321. data/spec/support/certificates/server-second-level.pem +77 -77
  322. data/spec/support/client_registry.rb +19 -3
  323. data/spec/support/cluster_config.rb +9 -1
  324. data/spec/support/cluster_tools.rb +6 -1
  325. data/spec/support/common_shortcuts.rb +12 -0
  326. data/spec/support/constraints.rb +16 -0
  327. data/spec/support/crypt.rb +154 -0
  328. data/spec/support/crypt/corpus/corpus-key-aws.json +33 -0
  329. data/spec/support/crypt/corpus/corpus-key-local.json +31 -0
  330. data/spec/support/crypt/corpus/corpus-schema.json +2057 -0
  331. data/spec/support/crypt/corpus/corpus.json +3657 -0
  332. data/spec/support/crypt/corpus/corpus_encrypted.json +4152 -0
  333. data/spec/support/crypt/data_keys/key_document_aws.json +34 -0
  334. data/spec/support/crypt/data_keys/key_document_local.json +31 -0
  335. data/spec/support/crypt/external/external-key.json +31 -0
  336. data/spec/support/crypt/external/external-schema.json +19 -0
  337. data/spec/support/crypt/limits/limits-doc.json +102 -0
  338. data/spec/support/crypt/limits/limits-key.json +31 -0
  339. data/spec/support/crypt/limits/limits-schema.json +1405 -0
  340. data/spec/support/crypt/schema_maps/schema_map_aws.json +17 -0
  341. data/spec/support/crypt/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  342. data/spec/support/crypt/schema_maps/schema_map_local.json +18 -0
  343. data/spec/support/crypt/schema_maps/schema_map_local_key_alt_names.json +12 -0
  344. data/spec/support/lite_constraints.rb +19 -1
  345. data/spec/support/matchers.rb +19 -0
  346. data/spec/support/shared/protocol.rb +2 -0
  347. data/spec/support/spec_config.rb +53 -13
  348. data/spec/support/utils.rb +140 -10
  349. metadata +894 -687
  350. metadata.gz.sig +0 -0
  351. data/lib/mongo/cluster/srv_monitor.rb +0 -127
  352. data/lib/mongo/srv/warning_result.rb +0 -35
  353. data/spec/enterprise_auth/kerberos_spec.rb +0 -58
  354. data/spec/mongo/cluster/srv_monitor_spec.rb +0 -214
  355. data/spec/mongo/operation/read_preference_spec.rb +0 -245
  356. data/spec/spec_tests/data/sdam/sharded/single_mongos.yml +0 -33
  357. 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