mongo 2.11.6 → 2.12.0.rc0

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 (327) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -2
  3. data.tar.gz.sig +0 -0
  4. data/CONTRIBUTING.md +1 -1
  5. data/lib/mongo.rb +3 -0
  6. data/lib/mongo/address.rb +13 -2
  7. data/lib/mongo/auth.rb +1 -0
  8. data/lib/mongo/auth/credential_cache.rb +51 -0
  9. data/lib/mongo/auth/scram/conversation.rb +20 -16
  10. data/lib/mongo/auth/user.rb +0 -8
  11. data/lib/mongo/auth/user/view.rb +4 -4
  12. data/lib/mongo/background_thread.rb +1 -1
  13. data/lib/mongo/bulk_write.rb +5 -5
  14. data/lib/mongo/client.rb +126 -11
  15. data/lib/mongo/client_encryption.rb +103 -0
  16. data/lib/mongo/cluster.rb +2 -2
  17. data/lib/mongo/cluster/reapers/cursor_reaper.rb +18 -6
  18. data/lib/mongo/cluster/sdam_flow.rb +54 -58
  19. data/lib/mongo/cluster/srv_monitor.rb +1 -1
  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 +7 -9
  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 +42 -0
  30. data/lib/mongo/crypt/auto_encrypter.rb +169 -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 +1162 -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 +283 -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 +293 -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 +13 -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/crypt_error.rb +31 -0
  50. data/lib/mongo/error/{failed_stringprep_validation.rb → failed_string_prep_validation.rb} +0 -0
  51. data/lib/mongo/error/invalid_cursor_operation.rb +27 -0
  52. data/lib/mongo/error/kms_error.rb +22 -0
  53. data/lib/mongo/error/max_bson_size.rb +14 -3
  54. data/lib/mongo/error/mongocryptd_spawn_error.rb +22 -0
  55. data/lib/mongo/error/no_server_available.rb +8 -3
  56. data/lib/mongo/error/operation_failure.rb +1 -0
  57. data/lib/mongo/grid/file.rb +0 -5
  58. data/lib/mongo/grid/file/chunk.rb +0 -2
  59. data/lib/mongo/grid/file/info.rb +2 -1
  60. data/lib/mongo/grid/fs_bucket.rb +13 -15
  61. data/lib/mongo/grid/stream/write.rb +3 -9
  62. data/lib/mongo/index/view.rb +3 -3
  63. data/lib/mongo/monitoring/event/command_started.rb +6 -1
  64. data/lib/mongo/operation/collections_info.rb +6 -3
  65. data/lib/mongo/operation/delete/op_msg.rb +1 -1
  66. data/lib/mongo/operation/find/op_msg.rb +4 -1
  67. data/lib/mongo/operation/get_more/op_msg.rb +4 -1
  68. data/lib/mongo/operation/insert/command.rb +2 -2
  69. data/lib/mongo/operation/insert/legacy.rb +2 -2
  70. data/lib/mongo/operation/insert/op_msg.rb +3 -3
  71. data/lib/mongo/operation/result.rb +36 -27
  72. data/lib/mongo/operation/shared/executable.rb +10 -8
  73. data/lib/mongo/operation/shared/executable_no_validate.rb +2 -2
  74. data/lib/mongo/operation/shared/op_msg_or_command.rb +2 -2
  75. data/lib/mongo/operation/shared/op_msg_or_find_command.rb +2 -2
  76. data/lib/mongo/operation/shared/op_msg_or_list_indexes_command.rb +2 -2
  77. data/lib/mongo/operation/shared/write.rb +17 -10
  78. data/lib/mongo/operation/update/op_msg.rb +1 -1
  79. data/lib/mongo/protocol/compressed.rb +6 -5
  80. data/lib/mongo/protocol/insert.rb +3 -1
  81. data/lib/mongo/protocol/message.rb +72 -8
  82. data/lib/mongo/protocol/msg.rb +191 -37
  83. data/lib/mongo/protocol/query.rb +7 -9
  84. data/lib/mongo/protocol/serializers.rb +6 -2
  85. data/lib/mongo/server.rb +10 -4
  86. data/lib/mongo/server/connection.rb +20 -9
  87. data/lib/mongo/server/connection_base.rb +81 -12
  88. data/lib/mongo/server/connection_common.rb +61 -0
  89. data/lib/mongo/server/connection_pool.rb +37 -1
  90. data/lib/mongo/server/description.rb +9 -11
  91. data/lib/mongo/server/monitor.rb +2 -0
  92. data/lib/mongo/server/monitor/connection.rb +3 -18
  93. data/lib/mongo/server/pending_connection.rb +2 -1
  94. data/lib/mongo/session.rb +2 -2
  95. data/lib/mongo/session/session_pool.rb +8 -3
  96. data/lib/mongo/socket.rb +29 -16
  97. data/lib/mongo/socket/ssl.rb +23 -8
  98. data/lib/mongo/socket/tcp.rb +12 -3
  99. data/lib/mongo/timeout.rb +49 -0
  100. data/lib/mongo/uri.rb +30 -1
  101. data/lib/mongo/version.rb +1 -1
  102. data/mongo.gemspec +1 -1
  103. data/spec/README.md +134 -7
  104. data/spec/integration/auth_spec.rb +53 -0
  105. data/spec/integration/{client_options_spec.rb → client_authentication_options_spec.rb} +10 -10
  106. data/spec/integration/client_construction_spec.rb +76 -1
  107. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +351 -0
  108. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +301 -0
  109. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +71 -0
  110. data/spec/integration/client_side_encryption/auto_encryption_old_wire_version_spec.rb +76 -0
  111. data/spec/integration/client_side_encryption/auto_encryption_reconnect_spec.rb +216 -0
  112. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +600 -0
  113. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +183 -0
  114. data/spec/integration/client_side_encryption/bypass_mongocryptd_spawn_spec.rb +74 -0
  115. data/spec/integration/client_side_encryption/client_close_spec.rb +59 -0
  116. data/spec/integration/client_side_encryption/corpus_spec.rb +228 -0
  117. data/spec/integration/client_side_encryption/custom_endpoint_spec.rb +132 -0
  118. data/spec/integration/client_side_encryption/data_key_spec.rb +163 -0
  119. data/spec/integration/client_side_encryption/explicit_encryption_spec.rb +114 -0
  120. data/spec/integration/client_side_encryption/external_key_vault_spec.rb +137 -0
  121. data/spec/integration/client_side_encryption/views_spec.rb +42 -0
  122. data/spec/integration/client_update_spec.rb +120 -0
  123. data/spec/integration/command_monitoring_spec.rb +3 -1
  124. data/spec/integration/command_spec.rb +44 -10
  125. data/spec/integration/connection_spec.rb +57 -0
  126. data/spec/integration/reconnect_spec.rb +7 -6
  127. data/spec/integration/size_limit_spec.rb +94 -0
  128. data/spec/integration/srv_monitoring_spec.rb +14 -6
  129. data/spec/lite_spec_helper.rb +31 -22
  130. data/spec/mongo/auth/cr_spec.rb +8 -0
  131. data/spec/mongo/auth/ldap_spec.rb +5 -1
  132. data/spec/mongo/auth/scram/conversation_spec.rb +5 -6
  133. data/spec/mongo/auth/scram/negotiation_spec.rb +74 -75
  134. data/spec/mongo/auth/scram_spec.rb +45 -35
  135. data/spec/mongo/auth/x509_spec.rb +5 -1
  136. data/spec/mongo/client_construction_spec.rb +206 -3
  137. data/spec/mongo/client_encryption_spec.rb +408 -0
  138. data/spec/mongo/cluster/cursor_reaper_spec.rb +12 -8
  139. data/spec/mongo/cluster/socket_reaper_spec.rb +14 -3
  140. data/spec/mongo/collection/view/aggregation_spec.rb +0 -2
  141. data/spec/mongo/collection/view/change_stream_spec.rb +7 -7
  142. data/spec/mongo/collection/view/map_reduce_spec.rb +3 -3
  143. data/spec/mongo/collection/view_spec.rb +1 -1
  144. data/spec/mongo/collection_spec.rb +4 -33
  145. data/spec/mongo/crypt/auto_decryption_context_spec.rb +90 -0
  146. data/spec/mongo/crypt/auto_encrypter_spec.rb +182 -0
  147. data/spec/mongo/crypt/auto_encryption_context_spec.rb +107 -0
  148. data/spec/mongo/crypt/binary_spec.rb +115 -0
  149. data/spec/mongo/crypt/binding/binary_spec.rb +56 -0
  150. data/spec/mongo/crypt/binding/context_spec.rb +257 -0
  151. data/spec/mongo/crypt/binding/helpers_spec.rb +46 -0
  152. data/spec/mongo/crypt/binding/mongocrypt_spec.rb +144 -0
  153. data/spec/mongo/crypt/binding/status_spec.rb +99 -0
  154. data/spec/mongo/crypt/binding/version_spec.rb +22 -0
  155. data/spec/mongo/crypt/binding_unloaded_spec.rb +20 -0
  156. data/spec/mongo/crypt/data_key_context_spec.rb +213 -0
  157. data/spec/mongo/crypt/encryption_io_spec.rb +136 -0
  158. data/spec/mongo/crypt/explicit_decryption_context_spec.rb +72 -0
  159. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +170 -0
  160. data/spec/mongo/crypt/handle_spec.rb +198 -0
  161. data/spec/mongo/crypt/helpers/mongo_crypt_spec_helper.rb +108 -0
  162. data/spec/mongo/crypt/status_spec.rb +152 -0
  163. data/spec/mongo/cursor_spec.rb +24 -4
  164. data/spec/mongo/database_spec.rb +20 -0
  165. data/spec/mongo/error/crypt_error_spec.rb +26 -0
  166. data/spec/mongo/error/max_bson_size_spec.rb +35 -0
  167. data/spec/mongo/error/no_server_available_spec.rb +11 -1
  168. data/spec/mongo/error/operation_failure_spec.rb +6 -6
  169. data/spec/mongo/operation/aggregate_spec.rb +1 -1
  170. data/spec/mongo/operation/collections_info_spec.rb +1 -1
  171. data/spec/mongo/operation/command_spec.rb +3 -3
  172. data/spec/mongo/operation/create_index_spec.rb +3 -3
  173. data/spec/mongo/operation/create_user_spec.rb +3 -3
  174. data/spec/mongo/operation/delete/bulk_spec.rb +6 -6
  175. data/spec/mongo/operation/delete/op_msg_spec.rb +1 -6
  176. data/spec/mongo/operation/delete_spec.rb +7 -7
  177. data/spec/mongo/operation/drop_index_spec.rb +2 -2
  178. data/spec/mongo/operation/find/legacy_spec.rb +1 -1
  179. data/spec/mongo/operation/get_more_spec.rb +1 -1
  180. data/spec/mongo/operation/indexes_spec.rb +1 -1
  181. data/spec/mongo/operation/insert/bulk_spec.rb +7 -7
  182. data/spec/mongo/operation/insert/op_msg_spec.rb +3 -6
  183. data/spec/mongo/operation/insert_spec.rb +12 -12
  184. data/spec/mongo/operation/map_reduce_spec.rb +2 -2
  185. data/spec/mongo/operation/remove_user_spec.rb +3 -3
  186. data/spec/mongo/operation/update/bulk_spec.rb +6 -6
  187. data/spec/mongo/operation/update/op_msg_spec.rb +3 -6
  188. data/spec/mongo/operation/update_spec.rb +7 -7
  189. data/spec/mongo/operation/update_user_spec.rb +1 -1
  190. data/spec/mongo/protocol/compressed_spec.rb +2 -3
  191. data/spec/mongo/protocol/delete_spec.rb +9 -8
  192. data/spec/mongo/protocol/get_more_spec.rb +9 -8
  193. data/spec/mongo/protocol/insert_spec.rb +9 -8
  194. data/spec/mongo/protocol/kill_cursors_spec.rb +6 -5
  195. data/spec/mongo/protocol/msg_spec.rb +57 -53
  196. data/spec/mongo/protocol/query_spec.rb +12 -12
  197. data/spec/mongo/protocol/registry_spec.rb +1 -1
  198. data/spec/mongo/protocol/reply_spec.rb +1 -1
  199. data/spec/mongo/protocol/update_spec.rb +10 -9
  200. data/spec/mongo/server/connection_pool_spec.rb +1 -1
  201. data/spec/mongo/server/connection_spec.rb +28 -7
  202. data/spec/mongo/socket_spec.rb +1 -1
  203. data/spec/mongo/timeout_spec.rb +85 -0
  204. data/spec/mongo/uri/srv_protocol_spec.rb +2 -2
  205. data/spec/mongo/uri_spec.rb +52 -5
  206. data/spec/mongo/write_concern_spec.rb +13 -1
  207. data/spec/{support → runners}/auth.rb +14 -1
  208. data/spec/{support → runners}/change_streams.rb +1 -1
  209. data/spec/{support → runners}/change_streams/operation.rb +0 -0
  210. data/spec/{support → runners}/cmap.rb +1 -1
  211. data/spec/{support → runners}/cmap/verifier.rb +0 -0
  212. data/spec/{support → runners}/command_monitoring.rb +0 -0
  213. data/spec/runners/connection_string.rb +358 -4
  214. data/spec/{support → runners}/crud.rb +9 -9
  215. data/spec/{support → runners}/crud/context.rb +0 -0
  216. data/spec/{support → runners}/crud/operation.rb +7 -3
  217. data/spec/{support → runners}/crud/outcome.rb +0 -0
  218. data/spec/{support → runners}/crud/requirement.rb +1 -1
  219. data/spec/{support → runners}/crud/spec.rb +12 -1
  220. data/spec/{support → runners}/crud/test.rb +0 -0
  221. data/spec/{support → runners}/crud/test_base.rb +0 -0
  222. data/spec/{support → runners}/crud/verifier.rb +10 -12
  223. data/spec/{support → runners}/gridfs.rb +0 -0
  224. data/spec/{support → runners}/sdam_monitoring.rb +0 -0
  225. data/spec/{support → runners}/server_discovery_and_monitoring.rb +0 -0
  226. data/spec/{support → runners}/server_selection.rb +0 -0
  227. data/spec/{support → runners}/server_selection_rtt.rb +0 -0
  228. data/spec/{support → runners}/transactions.rb +4 -4
  229. data/spec/{support → runners}/transactions/context.rb +0 -0
  230. data/spec/{support → runners}/transactions/operation.rb +0 -0
  231. data/spec/{support → runners}/transactions/spec.rb +0 -0
  232. data/spec/{support → runners}/transactions/test.rb +37 -5
  233. data/spec/spec_helper.rb +0 -5
  234. data/spec/spec_tests/auth_spec.rb +3 -3
  235. data/spec/spec_tests/client_side_encryption_spec.rb +13 -0
  236. data/spec/spec_tests/connection_string_spec.rb +1 -1
  237. data/spec/spec_tests/data/auth/connection-string.yml +13 -0
  238. data/spec/spec_tests/data/client_side_encryption/aggregate.yml +134 -0
  239. data/spec/spec_tests/data/client_side_encryption/badQueries.yml +526 -0
  240. data/spec/spec_tests/data/client_side_encryption/badSchema.yml +73 -0
  241. data/spec/spec_tests/data/client_side_encryption/basic.yml +116 -0
  242. data/spec/spec_tests/data/client_side_encryption/bulk.yml +85 -0
  243. data/spec/spec_tests/data/client_side_encryption/bypassAutoEncryption.yml +100 -0
  244. data/spec/spec_tests/data/client_side_encryption/bypassedCommand.yml +42 -0
  245. data/spec/spec_tests/data/client_side_encryption/count.yml +61 -0
  246. data/spec/spec_tests/data/client_side_encryption/countDocuments.yml +59 -0
  247. data/spec/spec_tests/data/client_side_encryption/delete.yml +105 -0
  248. data/spec/spec_tests/data/client_side_encryption/distinct.yml +73 -0
  249. data/spec/spec_tests/data/client_side_encryption/explain.yml +64 -0
  250. data/spec/spec_tests/data/client_side_encryption/find.yml +119 -0
  251. data/spec/spec_tests/data/client_side_encryption/findOneAndDelete.yml +57 -0
  252. data/spec/spec_tests/data/client_side_encryption/findOneAndReplace.yml +57 -0
  253. data/spec/spec_tests/data/client_side_encryption/findOneAndUpdate.yml +57 -0
  254. data/spec/spec_tests/data/client_side_encryption/getMore.yml +68 -0
  255. data/spec/spec_tests/data/client_side_encryption/insert.yml +102 -0
  256. data/spec/spec_tests/data/client_side_encryption/keyAltName.yml +71 -0
  257. data/spec/spec_tests/data/client_side_encryption/localKMS.yml +54 -0
  258. data/spec/spec_tests/data/client_side_encryption/localSchema.yml +72 -0
  259. data/spec/spec_tests/data/client_side_encryption/malformedCiphertext.yml +69 -0
  260. data/spec/spec_tests/data/client_side_encryption/maxWireVersion.yml +20 -0
  261. data/spec/spec_tests/data/client_side_encryption/missingKey.yml +49 -0
  262. data/spec/spec_tests/data/client_side_encryption/replaceOne.yml +61 -0
  263. data/spec/spec_tests/data/client_side_encryption/types.yml +527 -0
  264. data/spec/spec_tests/data/client_side_encryption/unsupportedCommand.yml +25 -0
  265. data/spec/spec_tests/data/client_side_encryption/updateMany.yml +77 -0
  266. data/spec/spec_tests/data/client_side_encryption/updateOne.yml +168 -0
  267. data/spec/spec_tests/data/read_write_concern/connection-string/write-concern.yml +1 -4
  268. data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +21 -0
  269. data/spec/spec_tests/data/sdam/rs/incompatible_ghost.yml +2 -4
  270. data/spec/spec_tests/data/sdam/rs/incompatible_other.yml +1 -1
  271. data/spec/spec_tests/data/sdam/rs/primary_mismatched_me_not_removed.yml +73 -0
  272. data/spec/spec_tests/data/sdam/rs/primary_to_no_primary_mismatched_me.yml +1 -2
  273. data/spec/spec_tests/data/sdam/rs/repeated.yml +101 -0
  274. data/spec/spec_tests/data/sdam/rs/{primary_address_change.yml → ruby_primary_address_change.yml} +2 -0
  275. 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
  276. data/spec/spec_tests/data/sdam/sharded/ruby_discovered_single_mongos.yml +27 -0
  277. data/spec/spec_tests/data/sdam/sharded/{primary_address_change.yml → ruby_primary_different_address.yml} +1 -1
  278. data/spec/spec_tests/data/sdam/sharded/{primary_mismatched_me.yml → ruby_primary_mismatched_me.yml} +1 -1
  279. data/spec/spec_tests/data/sdam/single/{primary_address_change.yml → ruby_primary_different_address.yml} +1 -1
  280. data/spec/spec_tests/data/sdam/single/{primary_mismatched_me.yml → ruby_primary_mismatched_me.yml} +1 -1
  281. data/spec/spec_tests/data/sdam_monitoring/{replica_set_with_primary_change.yml → replica_set_primary_address_change.yml} +27 -5
  282. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_me_mismatch.yml +26 -74
  283. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_removal.yml +20 -16
  284. data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +73 -0
  285. data/spec/spec_tests/data/transactions/pin-mongos.yml +2 -3
  286. data/spec/spec_tests/data/uri_options/auth-options.yml +10 -0
  287. data/spec/spec_tests/data/uri_options/tls-options.yml +75 -4
  288. data/spec/spec_tests/read_write_concern_connection_string_spec.rb +1 -1
  289. data/spec/spec_tests/uri_options_spec.rb +6 -8
  290. data/spec/stress/connection_pool_timing_spec.rb +6 -3
  291. data/spec/support/certificates/README.md +4 -0
  292. data/spec/support/certificates/server-second-level-bundle.pem +77 -77
  293. data/spec/support/certificates/server-second-level.crt +52 -52
  294. data/spec/support/certificates/server-second-level.key +25 -25
  295. data/spec/support/certificates/server-second-level.pem +77 -77
  296. data/spec/support/client_registry.rb +19 -3
  297. data/spec/support/cluster_config.rb +9 -1
  298. data/spec/support/common_shortcuts.rb +12 -0
  299. data/spec/support/constraints.rb +16 -0
  300. data/spec/support/crypt.rb +140 -0
  301. data/spec/support/crypt/corpus/corpus-key-aws.json +33 -0
  302. data/spec/support/crypt/corpus/corpus-key-local.json +31 -0
  303. data/spec/support/crypt/corpus/corpus-schema.json +2057 -0
  304. data/spec/support/crypt/corpus/corpus.json +3657 -0
  305. data/spec/support/crypt/corpus/corpus_encrypted.json +4152 -0
  306. data/spec/support/crypt/data_keys/key_document_aws.json +34 -0
  307. data/spec/support/crypt/data_keys/key_document_local.json +31 -0
  308. data/spec/support/crypt/external/external-key.json +31 -0
  309. data/spec/support/crypt/external/external-schema.json +19 -0
  310. data/spec/support/crypt/limits/limits-doc.json +102 -0
  311. data/spec/support/crypt/limits/limits-key.json +31 -0
  312. data/spec/support/crypt/limits/limits-schema.json +1405 -0
  313. data/spec/support/crypt/schema_maps/schema_map_aws.json +17 -0
  314. data/spec/support/crypt/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  315. data/spec/support/crypt/schema_maps/schema_map_local.json +18 -0
  316. data/spec/support/crypt/schema_maps/schema_map_local_key_alt_names.json +12 -0
  317. data/spec/support/lite_constraints.rb +17 -1
  318. data/spec/support/matchers.rb +19 -0
  319. data/spec/support/shared/protocol.rb +2 -0
  320. data/spec/support/spec_config.rb +43 -13
  321. data/spec/support/utils.rb +132 -10
  322. metadata +277 -81
  323. metadata.gz.sig +0 -0
  324. data/spec/integration/grid_fs_bucket_spec.rb +0 -48
  325. data/spec/integration/zlib_compression_spec.rb +0 -25
  326. data/spec/spec_tests/data/sdam/sharded/single_mongos.yml +0 -33
  327. data/spec/support/connection_string.rb +0 -354
@@ -0,0 +1,135 @@
1
+ # Copyright (C) 2019 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module Crypt
17
+
18
+ # A wrapper around mongocrypt_ctx_t, which manages the
19
+ # state machine for encryption and decription.
20
+ #
21
+ # This class is a superclass that defines shared methods
22
+ # amongst contexts that are initialized for different purposes
23
+ # (e.g. data key creation, encryption, explicit encryption, etc.)
24
+ #
25
+ # @api private
26
+ class Context
27
+ # Create a new Context object
28
+ #
29
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_t object
30
+ # used to create a new mongocrypt_ctx_t
31
+ # @param [ ClientEncryption::IO ] A instance of the IO class
32
+ # that implements driver I/O methods required to run the
33
+ # state machine
34
+ def initialize(mongocrypt_handle, io)
35
+ # Ideally, this level of the API wouldn't be passing around pointer
36
+ # references between objects, so this method signature is subject to change.
37
+
38
+ # FFI::AutoPointer uses a custom release strategy to automatically free
39
+ # the pointer once this object goes out of scope
40
+ @ctx_p = FFI::AutoPointer.new(
41
+ Binding.mongocrypt_ctx_new(mongocrypt_handle.ref),
42
+ Binding.method(:mongocrypt_ctx_destroy)
43
+ )
44
+
45
+ @encryption_io = io
46
+ end
47
+
48
+ attr_reader :ctx_p
49
+
50
+ # Returns the state of the mongocrypt_ctx_t
51
+ #
52
+ # @return [ Symbol ] The context state
53
+ def state
54
+ Binding.mongocrypt_ctx_state(@ctx_p)
55
+ end
56
+
57
+ # Runs the mongocrypt_ctx_t state machine and handles
58
+ # all I/O on behalf of libmongocrypt
59
+ #
60
+ # @return [ BSON::Document ] A BSON document representing the outcome
61
+ # of the state machine. Contents can differ depending on how the
62
+ # context was initialized..
63
+ #
64
+ # @raise [ Error::CryptError ] If the state machine enters the
65
+ # :error state
66
+ #
67
+ # This method is not currently unit tested. It is integration tested
68
+ # in spec/integration/explicit_encryption_spec.rb
69
+ def run_state_machine
70
+ while true
71
+ case state
72
+ when :error
73
+ Binding.check_ctx_status(self)
74
+ when :ready
75
+ # Finalize the state machine and return the result as a BSON::Document
76
+ return Binding.ctx_finalize(self)
77
+ when :done
78
+ return nil
79
+ when :need_mongo_keys
80
+ filter = Binding.ctx_mongo_op(self)
81
+
82
+ @encryption_io.find_keys(filter).each do |key|
83
+ mongocrypt_feed(key) if key
84
+ end
85
+
86
+ mongocrypt_done
87
+ when :need_mongo_collinfo
88
+ filter = Binding.ctx_mongo_op(self)
89
+
90
+ result = @encryption_io.collection_info(@db_name, filter)
91
+ mongocrypt_feed(result) if result
92
+
93
+ mongocrypt_done
94
+ when :need_mongo_markings
95
+ cmd = Binding.ctx_mongo_op(self)
96
+
97
+ result = @encryption_io.mark_command(cmd)
98
+ mongocrypt_feed(result)
99
+
100
+ mongocrypt_done
101
+ when :need_kms
102
+ while kms_context = Binding.ctx_next_kms_ctx(self) do
103
+ @encryption_io.feed_kms(kms_context)
104
+ end
105
+
106
+ Binding.ctx_kms_done(self)
107
+ else
108
+ raise Error::CryptError.new(
109
+ # TODO: fix CryptError to improve this API -- the first argument
110
+ # in the initializer should not be optional
111
+ nil,
112
+ "State #{state} is not supported by Mongo::Crypt::Context"
113
+ )
114
+ end
115
+ end
116
+ end
117
+
118
+ private
119
+
120
+ # Indicate that state machine is done feeding I/O responses back to libmongocrypt
121
+ def mongocrypt_done
122
+ Binding.mongocrypt_ctx_mongo_done(ctx_p)
123
+ end
124
+
125
+ # Feeds the result of a Mongo operation back to libmongocrypt.
126
+ #
127
+ # @param [ Hash ] doc BSON document to feed.
128
+ #
129
+ # @return [ BSON::Document ] BSON document containing the result.
130
+ def mongocrypt_feed(doc)
131
+ Binding.ctx_mongo_feed(self, doc)
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,162 @@
1
+ # Copyright (C) 2019 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module Crypt
17
+
18
+ # A Context object initialized specifically for the purpose of creating
19
+ # a data key in the key managemenet system.
20
+ #
21
+ # @api private
22
+ class DataKeyContext < Context
23
+
24
+ # Create a new DataKeyContext object
25
+ #
26
+ # @param [ Mongo::Crypt::Handle ] mongocrypt a Handle that
27
+ # wraps a mongocrypt_t object used to create a new mongocrypt_ctx_t
28
+ # @param [ Mongo::Crypt::EncryptionIO ] io An object that performs all
29
+ # driver I/O on behalf of libmongocrypt
30
+ # @param [ String ] kms_provider The KMS provider to use. Options are
31
+ # "aws" and "local".
32
+ # @param [ Hash ] options Data key creation options.
33
+ #
34
+ # @option options [ Hash ] :master_key A Hash of options related to the AWS
35
+ # KMS provider option. Required if kms_provider is "aws".
36
+ # - :region [ String ] The The AWS region of the master key (required).
37
+ # - :key [ String ] The Amazon Resource Name (ARN) of the master key (required).
38
+ # - :endpoint [ String ] An alternate host to send KMS requests to (optional).
39
+ # @option options [ Array<String> ] :key_alt_names An optional array of strings specifying
40
+ # alternate names for the new data key.
41
+ def initialize(mongocrypt, io, kms_provider, options={})
42
+ super(mongocrypt, io)
43
+
44
+ case kms_provider
45
+ when 'local'
46
+ Binding.ctx_setopt_master_key_local(self)
47
+ when 'aws'
48
+ unless options
49
+ raise ArgumentError.new(
50
+ 'When "aws" is specified as the KMS provider, options cannot be nil'
51
+ )
52
+ end
53
+
54
+ unless options.key?(:master_key)
55
+ raise ArgumentError.new(
56
+ 'When "aws" is specified as the KMS provider, the options Hash ' +
57
+ 'must contain a key named :master_key with a Hash value in the ' +
58
+ '{ region: "AWS-REGION", key: "AWS-KEY-ARN" }'
59
+ )
60
+ end
61
+
62
+ master_key_opts = options[:master_key]
63
+
64
+ set_aws_master_key(master_key_opts)
65
+ set_aws_endpoint(master_key_opts[:endpoint]) if master_key_opts[:endpoint]
66
+ else
67
+ raise ArgumentError.new(
68
+ "#{kms_provider} is an invalid kms provider. " +
69
+ "Valid options are 'aws' and 'local'"
70
+ )
71
+ end
72
+
73
+ set_key_alt_names(options[:key_alt_names]) if options[:key_alt_names]
74
+ initialize_ctx
75
+ end
76
+
77
+ private
78
+
79
+ # Configure the underlying mongocrypt_ctx_t object to accept AWS
80
+ # KMS options
81
+ def set_aws_master_key(master_key_opts)
82
+ unless master_key_opts
83
+ raise ArgumentError.new('The :master_key option cannot be nil')
84
+ end
85
+
86
+ unless master_key_opts.is_a?(Hash)
87
+ raise ArgumentError.new(
88
+ "#{master_key_opts} is an invalid :master_key option. " +
89
+ "The :master_key option must be a Hash in the format " +
90
+ "{ region: 'AWS-REGION', key: 'AWS-KEY-ARN' }"
91
+ )
92
+ end
93
+
94
+ region = master_key_opts[:region]
95
+ unless region
96
+ raise ArgumentError.new(
97
+ 'The value of :region option of the :master_key options hash cannot be nil'
98
+ )
99
+ end
100
+
101
+ unless region.is_a?(String)
102
+ raise ArgumentError.new(
103
+ "#{master_key_opts[:region]} is an invalid AWS master_key region. " +
104
+ "The value of :region option of the :master_key options hash must be a String"
105
+ )
106
+ end
107
+
108
+ key = master_key_opts[:key]
109
+ unless key
110
+ raise ArgumentError.new(
111
+ 'The value of :key option of the :master_key options hash cannot be nil'
112
+ )
113
+ end
114
+
115
+ unless key.is_a?(String)
116
+ raise ArgumentError.new(
117
+ "#{master_key_opts[:key]} is an invalid AWS master_key key. " +
118
+ "The value of :key option of the :master_key options hash must be a String"
119
+ )
120
+ end
121
+
122
+ Binding.ctx_setopt_master_key_aws(
123
+ self,
124
+ region,
125
+ key,
126
+ )
127
+ end
128
+
129
+ def set_aws_endpoint(endpoint)
130
+ unless endpoint.is_a?(String)
131
+ raise ArgumentError.new(
132
+ "#{endpoint} is an invalid AWS master_key endpoint. " +
133
+ "The value of :endpoint option of the :master_key options hash must be a String"
134
+ )
135
+ end
136
+
137
+ Binding.ctx_setopt_master_key_aws_endpoint(self, endpoint)
138
+ end
139
+
140
+ # Set the alt names option on the context
141
+ def set_key_alt_names(key_alt_names)
142
+ unless key_alt_names.is_a?(Array)
143
+ raise ArgumentError.new, 'The :key_alt_names option must be an Array'
144
+ end
145
+
146
+ unless key_alt_names.all? { |key_alt_name| key_alt_name.is_a?(String) }
147
+ raise ArgumentError.new(
148
+ "#{key_alt_names} contains an invalid alternate key name. All " +
149
+ "values of the :key_alt_names option Array must be Strings"
150
+ )
151
+ end
152
+
153
+ Binding.ctx_setopt_key_alt_names(self, key_alt_names)
154
+ end
155
+
156
+ # Initializes the underlying mongocrypt_ctx_t object
157
+ def initialize_ctx
158
+ Binding.ctx_datakey_init(self)
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,283 @@
1
+ # Copyright (C) 2019 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Mongo
16
+ module Crypt
17
+
18
+ # A class that implements I/O methods between the driver and
19
+ # the MongoDB server or mongocryptd.
20
+ #
21
+ # @api private
22
+ class EncryptionIO
23
+
24
+ # Timeout used for SSL socket connection, reading, and writing.
25
+ # There is no specific timeout written in the spec. See SPEC-1394
26
+ # for a discussion and updates on what this timeout should be.
27
+ SOCKET_TIMEOUT = 10
28
+
29
+ # Creates a new EncryptionIO object with information about how to connect
30
+ # to the key vault.
31
+ #
32
+ # @param [ Mongo::Client ] client: The client used to connect to the collection
33
+ # that stores the encrypted documents, defaults to nil.
34
+ # @param [ Mongo::Client ] mongocryptd_client: The client connected to mongocryptd,
35
+ # defaults to nil.
36
+ # @param [ Mongo::Client ] key_vault_client: The client connected to the
37
+ # key vault collection.
38
+ # @param [ String ] key_vault_namespace: The key vault namespace in the format
39
+ # db_name.collection_name.
40
+ # @param [ Hash ] mongocryptd_options: Options related to mongocryptd.
41
+ #
42
+ # @option mongocryptd_options [ Boolean ] :mongocryptd_bypass_spawn
43
+ # @option mongocryptd_options [ String ] :mongocryptd_spawn_path
44
+ # @option mongocryptd_options [ Array<String> ] :mongocryptd_spawn_args
45
+ #
46
+ # @note When being used for auto encryption, all arguments are required.
47
+ # When being used for explicit encryption, only the key_vault_namespace
48
+ # and key_vault_client arguments are required.
49
+ #
50
+ # @note This class expects that the key_vault_client and key_vault_namespace
51
+ # options are not nil and are in the correct format.
52
+ def initialize(
53
+ client: nil, mongocryptd_client: nil, key_vault_namespace:,
54
+ key_vault_client:, mongocryptd_options: {}
55
+ )
56
+ validate_key_vault_client!(key_vault_client)
57
+ validate_key_vault_namespace!(key_vault_namespace)
58
+
59
+ @client = client
60
+ @mongocryptd_client = mongocryptd_client
61
+ @key_vault_db_name, @key_vault_collection_name = key_vault_namespace.split('.')
62
+ @key_vault_client = key_vault_client
63
+ @options = mongocryptd_options
64
+ end
65
+
66
+ # Query for keys in the key vault collection using the provided
67
+ # filter
68
+ #
69
+ # @param [ Hash ] filter
70
+ #
71
+ # @return [ Array<BSON::Document> ] The query results
72
+ def find_keys(filter)
73
+ key_vault_collection.find(filter).to_a
74
+ end
75
+
76
+ # Insert a document into the key vault collection
77
+ #
78
+ # @param [ Hash ] document
79
+ #
80
+ # @return [ Mongo::Operation::Insert::Result ] The insertion result
81
+ def insert_data_key(document)
82
+ key_vault_collection.insert_one(document)
83
+ end
84
+
85
+ # Get collection info for a collection matching the provided filter
86
+ #
87
+ # @param [ Hash ] filter
88
+ #
89
+ # @return [ Hash ] The collection information
90
+ def collection_info(db_name, filter)
91
+ unless @client
92
+ raise ArgumentError, 'collection_info requires client to have been passed to the constructor, but it was not'
93
+ end
94
+
95
+ @client.use(db_name).database.list_collections(filter: filter).first
96
+ end
97
+
98
+ # Send the command to mongocryptd to be marked with intent-to-encrypt markings
99
+ #
100
+ # @param [ Hash ] cmd
101
+ #
102
+ # @return [ Hash ] The marked command
103
+ def mark_command(cmd)
104
+ unless @mongocryptd_client
105
+ raise ArgumentError, 'mark_command requires mongocryptd_client to have been passed to the constructor, but it was not'
106
+ end
107
+
108
+ begin
109
+ response = @mongocryptd_client.database.command(cmd)
110
+ rescue Error::NoServerAvailable => e
111
+ raise e if @options[:mongocryptd_bypass_spawn]
112
+
113
+ spawn_mongocryptd
114
+ response = @mongocryptd_client.database.command(cmd)
115
+ end
116
+
117
+ return response.first
118
+ end
119
+
120
+ # Get information about the AWS encryption key and feed it to the the
121
+ # KmsContext object
122
+ #
123
+ # @param [ Mongo::Crypt::KmsContext ] kms_context A KmsContext object
124
+ # corresponding to one AWS KMS data key. Contains information about
125
+ # the endpoint at which to establish a TLS connection and the message
126
+ # to send on that connection.
127
+ def feed_kms(kms_context)
128
+ with_ssl_socket(kms_context.endpoint) do |ssl_socket|
129
+
130
+ Timeout.timeout(SOCKET_TIMEOUT, Error::SocketTimeoutError,
131
+ 'Socket write operation timed out'
132
+ ) do
133
+ ssl_socket.syswrite(kms_context.message)
134
+ end
135
+
136
+ bytes_needed = kms_context.bytes_needed
137
+ while bytes_needed > 0 do
138
+ bytes = Timeout.timeout(SOCKET_TIMEOUT, Error::SocketTimeoutError,
139
+ 'Socket read operation timed out'
140
+ ) do
141
+ ssl_socket.sysread(bytes_needed)
142
+ end
143
+
144
+ kms_context.feed(bytes)
145
+ bytes_needed = kms_context.bytes_needed
146
+ end
147
+ end
148
+ end
149
+
150
+ private
151
+
152
+ def validate_key_vault_client!(key_vault_client)
153
+ unless key_vault_client
154
+ raise ArgumentError.new('The :key_vault_client option cannot be nil')
155
+ end
156
+
157
+ unless key_vault_client.is_a?(Client)
158
+ raise ArgumentError.new(
159
+ 'The :key_vault_client option must be an instance of Mongo::Client'
160
+ )
161
+ end
162
+ end
163
+
164
+ def validate_key_vault_namespace!(key_vault_namespace)
165
+ unless key_vault_namespace
166
+ raise ArgumentError.new('The :key_vault_namespace option cannot be nil')
167
+ end
168
+
169
+ unless key_vault_namespace.split('.').length == 2
170
+ raise ArgumentError.new(
171
+ "#{key_vault_namespace} is an invalid key vault namespace." +
172
+ "The :key_vault_namespace option must be in the format database.collection"
173
+ )
174
+ end
175
+ end
176
+
177
+ # Use the provided key vault client and namespace to construct a
178
+ # Mongo::Collection object representing the key vault collection.
179
+ def key_vault_collection
180
+ @key_vault_collection ||= @key_vault_client.with(
181
+ database: @key_vault_db_name,
182
+ read_concern: { level: :majority }
183
+ )[@key_vault_collection_name]
184
+ end
185
+
186
+ # Spawn a new mongocryptd process using the mongocryptd_spawn_path
187
+ # and mongocryptd_spawn_args passed in through the extra auto
188
+ # encrypt options. Stdout and Stderr of this new process are written
189
+ # to /dev/null.
190
+ #
191
+ # @note To capture the mongocryptd logs, add "--logpath=/path/to/logs"
192
+ # to auto_encryption_options -> extra_options -> mongocrpytd_spawn_args
193
+ #
194
+ # @return [ Integer ] The process id of the spawned process
195
+ #
196
+ # @raise [ ArgumentError ] Raises an exception if no encryption options
197
+ # have been provided
198
+ def spawn_mongocryptd
199
+ mongocryptd_spawn_args = @options[:mongocryptd_spawn_args]
200
+ mongocryptd_spawn_path = @options[:mongocryptd_spawn_path]
201
+
202
+ unless mongocryptd_spawn_path
203
+ raise ArgumentError.new(
204
+ 'Cannot spawn mongocryptd process when no ' +
205
+ ':mongocryptd_spawn_path option is provided'
206
+ )
207
+ end
208
+
209
+ if mongocryptd_spawn_path.nil? ||
210
+ mongocryptd_spawn_args.nil? || mongocryptd_spawn_args.empty?
211
+ then
212
+ raise ArgumentError.new(
213
+ 'Cannot spawn mongocryptd process when no :mongocryptd_spawn_args ' +
214
+ 'option is provided. To start mongocryptd without arguments, pass ' +
215
+ '"--" for :mongocryptd_spawn_args'
216
+ )
217
+ end
218
+
219
+ begin
220
+ Process.spawn(
221
+ mongocryptd_spawn_path,
222
+ *mongocryptd_spawn_args,
223
+ [:out, :err]=>'/dev/null'
224
+ )
225
+ rescue Errno::ENOENT => e
226
+ raise Error::MongocryptdSpawnError.new(
227
+ "Failed to spawn mongocryptd at the path \"#{mongocryptd_spawn_path}\" " +
228
+ "with arguments #{mongocryptd_spawn_args}. Received error " +
229
+ "#{e.class}: \"#{e.message}\""
230
+ )
231
+ end
232
+ end
233
+
234
+ # Provide an SSL socket to be used for KMS calls in a block API
235
+ #
236
+ # @param [ String ] endpoint The URI at which to connect the SSL socket
237
+ # @param [ Proc ] block The block to execute
238
+ #
239
+ # @raise [ Mongo::Error::KmsError ] If the socket times out or raises
240
+ # an exception
241
+ #
242
+ # @note The socket is always closed when the provided block has finished
243
+ # executing
244
+ def with_ssl_socket(endpoint)
245
+ host, port = endpoint.split(':')
246
+ port ||= 443 # Default port for AWS KMS API
247
+
248
+ begin
249
+ # Create TCPSocket and set nodelay option
250
+ tcp_socket = TCPSocket.open(host, port)
251
+ tcp_socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
252
+
253
+ ssl_socket = OpenSSL::SSL::SSLSocket.new(tcp_socket)
254
+ ssl_socket.sync_close = true # tcp_socket will be closed when ssl_socket is closed
255
+ ssl_socket.hostname = "#{host}:#{port}" # perform SNI
256
+
257
+ Timeout.timeout(
258
+ SOCKET_TIMEOUT,
259
+ Error::SocketTimeoutError,
260
+ 'Socket connection timed out'
261
+ ) do
262
+ ssl_socket.connect
263
+ end
264
+
265
+ yield(ssl_socket)
266
+ rescue => e
267
+ raise Error::KmsError, "Error decrypting data key. #{e.class}: #{e.message}"
268
+ ensure
269
+ # If there is an error during socket creation, the
270
+ # ssl_socket object won't exist in this scope and this line will
271
+ # raise an exception
272
+ Timeout.timeout(
273
+ SOCKET_TIMEOUT,
274
+ Error::SocketTimeoutError,
275
+ 'Socket close timed out'
276
+ ) do
277
+ ssl_socket.sysclose rescue nil
278
+ end
279
+ end
280
+ end
281
+ end
282
+ end
283
+ end