mongo 2.12.4 → 2.13.0.beta1

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 (817) 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 +8 -36
  5. data/LICENSE +1 -1
  6. data/README.md +54 -54
  7. data/Rakefile +1 -1
  8. data/lib/mongo.rb +4 -1
  9. data/lib/mongo/active_support.rb +1 -1
  10. data/lib/mongo/address.rb +40 -13
  11. data/lib/mongo/address/ipv4.rb +32 -5
  12. data/lib/mongo/address/ipv6.rb +32 -5
  13. data/lib/mongo/address/unix.rb +3 -3
  14. data/lib/mongo/address/validator.rb +1 -1
  15. data/lib/mongo/auth.rb +36 -13
  16. data/lib/mongo/auth/aws.rb +37 -0
  17. data/lib/mongo/auth/aws/conversation.rb +128 -0
  18. data/lib/mongo/auth/aws/credentials_retriever.rb +219 -0
  19. data/lib/mongo/auth/aws/request.rb +257 -0
  20. data/lib/mongo/auth/base.rb +129 -0
  21. data/lib/mongo/auth/conversation_base.rb +52 -0
  22. data/lib/mongo/auth/cr.rb +9 -36
  23. data/lib/mongo/auth/cr/conversation.rb +24 -69
  24. data/lib/mongo/auth/credential_cache.rb +1 -1
  25. data/lib/mongo/auth/gssapi.rb +38 -0
  26. data/lib/mongo/auth/gssapi/conversation.rb +108 -0
  27. data/lib/mongo/auth/ldap.rb +9 -34
  28. data/lib/mongo/auth/ldap/conversation.rb +3 -43
  29. data/lib/mongo/auth/roles.rb +1 -1
  30. data/lib/mongo/auth/sasl_conversation_base.rb +111 -0
  31. data/lib/mongo/auth/scram.rb +39 -51
  32. data/lib/mongo/auth/scram/conversation.rb +12 -506
  33. data/lib/mongo/auth/scram256.rb +31 -0
  34. data/lib/mongo/auth/scram256/conversation.rb +63 -0
  35. data/lib/mongo/auth/scram_conversation_base.rb +402 -0
  36. data/lib/mongo/auth/stringprep.rb +5 -4
  37. data/lib/mongo/auth/stringprep/profiles/sasl.rb +2 -1
  38. data/lib/mongo/auth/stringprep/tables.rb +2 -1
  39. data/lib/mongo/auth/stringprep/unicode_normalize/normalize.rb +1 -0
  40. data/lib/mongo/auth/stringprep/unicode_normalize/tables.rb +1 -0
  41. data/lib/mongo/auth/user.rb +2 -2
  42. data/lib/mongo/auth/user/view.rb +1 -1
  43. data/lib/mongo/auth/x509.rb +14 -32
  44. data/lib/mongo/auth/x509/conversation.rb +15 -42
  45. data/lib/mongo/background_thread.rb +11 -2
  46. data/lib/mongo/bson.rb +1 -1
  47. data/lib/mongo/bulk_write.rb +61 -26
  48. data/lib/mongo/bulk_write/combineable.rb +20 -8
  49. data/lib/mongo/bulk_write/ordered_combiner.rb +1 -1
  50. data/lib/mongo/bulk_write/result.rb +1 -1
  51. data/lib/mongo/bulk_write/result_combiner.rb +1 -1
  52. data/lib/mongo/bulk_write/transformable.rb +9 -10
  53. data/lib/mongo/bulk_write/unordered_combiner.rb +1 -1
  54. data/lib/mongo/bulk_write/validatable.rb +5 -1
  55. data/lib/mongo/client.rb +38 -23
  56. data/lib/mongo/client_encryption.rb +1 -1
  57. data/lib/mongo/cluster.rb +126 -54
  58. data/lib/mongo/cluster/periodic_executor.rb +1 -1
  59. data/lib/mongo/cluster/reapers/cursor_reaper.rb +1 -1
  60. data/lib/mongo/cluster/reapers/socket_reaper.rb +1 -1
  61. data/lib/mongo/cluster/sdam_flow.rb +23 -7
  62. data/lib/mongo/cluster/topology.rb +19 -2
  63. data/lib/mongo/cluster/topology/base.rb +1 -1
  64. data/lib/mongo/cluster/topology/no_replica_set_options.rb +1 -1
  65. data/lib/mongo/cluster/topology/replica_set_no_primary.rb +1 -1
  66. data/lib/mongo/cluster/topology/replica_set_with_primary.rb +1 -1
  67. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  68. data/lib/mongo/cluster/topology/single.rb +1 -1
  69. data/lib/mongo/cluster/topology/unknown.rb +1 -1
  70. data/lib/mongo/cluster_time.rb +1 -1
  71. data/lib/mongo/collection.rb +24 -8
  72. data/lib/mongo/collection/view.rb +6 -2
  73. data/lib/mongo/collection/view/aggregation.rb +6 -3
  74. data/lib/mongo/collection/view/builder.rb +1 -1
  75. data/lib/mongo/collection/view/builder/aggregation.rb +1 -1
  76. data/lib/mongo/collection/view/builder/find_command.rb +9 -1
  77. data/lib/mongo/collection/view/builder/flags.rb +1 -1
  78. data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
  79. data/lib/mongo/collection/view/builder/modifiers.rb +1 -1
  80. data/lib/mongo/collection/view/builder/op_query.rb +1 -1
  81. data/lib/mongo/collection/view/change_stream.rb +3 -6
  82. data/lib/mongo/collection/view/change_stream/retryable.rb +1 -1
  83. data/lib/mongo/collection/view/explainable.rb +1 -1
  84. data/lib/mongo/collection/view/immutable.rb +1 -1
  85. data/lib/mongo/collection/view/iterable.rb +8 -2
  86. data/lib/mongo/collection/view/map_reduce.rb +7 -4
  87. data/lib/mongo/collection/view/readable.rb +11 -5
  88. data/lib/mongo/collection/view/writable.rb +52 -8
  89. data/lib/mongo/crypt.rb +1 -1
  90. data/lib/mongo/crypt/auto_decryption_context.rb +1 -1
  91. data/lib/mongo/crypt/auto_encrypter.rb +1 -1
  92. data/lib/mongo/crypt/auto_encryption_context.rb +1 -1
  93. data/lib/mongo/crypt/binary.rb +1 -1
  94. data/lib/mongo/crypt/binding.rb +1 -1
  95. data/lib/mongo/crypt/context.rb +1 -1
  96. data/lib/mongo/crypt/data_key_context.rb +1 -1
  97. data/lib/mongo/crypt/encryption_io.rb +41 -24
  98. data/lib/mongo/crypt/explicit_decryption_context.rb +1 -1
  99. data/lib/mongo/crypt/explicit_encrypter.rb +1 -1
  100. data/lib/mongo/crypt/explicit_encryption_context.rb +1 -1
  101. data/lib/mongo/crypt/handle.rb +1 -1
  102. data/lib/mongo/crypt/hooks.rb +1 -1
  103. data/lib/mongo/crypt/kms_context.rb +1 -1
  104. data/lib/mongo/crypt/status.rb +1 -1
  105. data/lib/mongo/cursor.rb +3 -3
  106. data/lib/mongo/cursor/builder.rb +1 -1
  107. data/lib/mongo/cursor/builder/get_more_command.rb +1 -1
  108. data/lib/mongo/cursor/builder/kill_cursors_command.rb +1 -1
  109. data/lib/mongo/cursor/builder/op_get_more.rb +1 -1
  110. data/lib/mongo/cursor/builder/op_kill_cursors.rb +1 -1
  111. data/lib/mongo/database.rb +4 -1
  112. data/lib/mongo/database/view.rb +2 -2
  113. data/lib/mongo/dbref.rb +1 -1
  114. data/lib/mongo/error.rb +25 -2
  115. data/lib/mongo/error/auth_error.rb +1 -1
  116. data/lib/mongo/error/bulk_write_error.rb +1 -1
  117. data/lib/mongo/error/change_stream_resumable.rb +1 -1
  118. data/lib/mongo/error/closed_stream.rb +1 -1
  119. data/lib/mongo/error/connection_check_out_timeout.rb +1 -1
  120. data/lib/mongo/error/connection_perished.rb +23 -0
  121. data/lib/mongo/error/credential_check_error.rb +26 -0
  122. data/lib/mongo/error/extra_file_chunk.rb +1 -1
  123. data/lib/mongo/error/file_not_found.rb +1 -1
  124. data/lib/mongo/error/handshake_error.rb +1 -1
  125. data/lib/mongo/error/insufficient_iteration_count.rb +1 -1
  126. data/lib/mongo/error/invalid_address.rb +1 -1
  127. data/lib/mongo/error/invalid_application_name.rb +1 -1
  128. data/lib/mongo/error/invalid_bulk_operation.rb +1 -1
  129. data/lib/mongo/error/invalid_bulk_operation_type.rb +1 -1
  130. data/lib/mongo/error/invalid_collection_name.rb +1 -1
  131. data/lib/mongo/error/invalid_cursor_operation.rb +1 -1
  132. data/lib/mongo/error/invalid_database_name.rb +1 -1
  133. data/lib/mongo/error/invalid_document.rb +1 -1
  134. data/lib/mongo/error/invalid_file.rb +1 -1
  135. data/lib/mongo/error/invalid_file_revision.rb +1 -1
  136. data/lib/mongo/error/invalid_min_pool_size.rb +1 -1
  137. data/lib/mongo/error/invalid_nonce.rb +2 -2
  138. data/lib/mongo/error/invalid_read_option.rb +1 -1
  139. data/lib/mongo/error/invalid_replacement_document.rb +1 -1
  140. data/lib/mongo/error/invalid_server_auth_response.rb +23 -0
  141. data/lib/mongo/error/invalid_server_preference.rb +6 -1
  142. data/lib/mongo/error/invalid_session.rb +1 -1
  143. data/lib/mongo/error/invalid_signature.rb +1 -1
  144. data/lib/mongo/error/invalid_transaction_operation.rb +1 -1
  145. data/lib/mongo/error/invalid_txt_record.rb +1 -1
  146. data/lib/mongo/error/invalid_update_document.rb +1 -1
  147. data/lib/mongo/error/invalid_uri.rb +1 -1
  148. data/lib/mongo/error/invalid_write_concern.rb +1 -1
  149. data/lib/mongo/error/lint_error.rb +1 -1
  150. data/lib/mongo/error/max_bson_size.rb +1 -1
  151. data/lib/mongo/error/max_message_size.rb +1 -1
  152. data/lib/mongo/error/mismatched_domain.rb +1 -1
  153. data/lib/mongo/error/missing_file_chunk.rb +1 -1
  154. data/lib/mongo/error/missing_password.rb +1 -1
  155. data/lib/mongo/error/missing_resume_token.rb +1 -1
  156. data/lib/mongo/error/missing_scram_server_signature.rb +27 -0
  157. data/lib/mongo/error/multi_index_drop.rb +1 -1
  158. data/lib/mongo/error/need_primary_server.rb +1 -1
  159. data/lib/mongo/error/no_server_available.rb +1 -1
  160. data/lib/mongo/error/no_srv_records.rb +1 -1
  161. data/lib/mongo/error/notable.rb +18 -3
  162. data/lib/mongo/error/operation_failure.rb +62 -49
  163. data/lib/mongo/error/parser.rb +16 -5
  164. data/lib/mongo/error/pool_closed_error.rb +1 -1
  165. data/lib/mongo/error/raise_original_error.rb +29 -0
  166. data/lib/mongo/error/session_ended.rb +1 -1
  167. data/lib/mongo/error/socket_error.rb +1 -1
  168. data/lib/mongo/error/socket_timeout_error.rb +1 -1
  169. data/lib/mongo/error/unchangeable_collection_option.rb +1 -1
  170. data/lib/mongo/error/unexpected_chunk_length.rb +1 -1
  171. data/lib/mongo/error/unexpected_response.rb +1 -1
  172. data/lib/mongo/error/unknown_payload_type.rb +1 -1
  173. data/lib/mongo/error/unsupported_array_filters.rb +7 -2
  174. data/lib/mongo/error/unsupported_collation.rb +7 -2
  175. data/lib/mongo/error/unsupported_features.rb +1 -1
  176. data/lib/mongo/error/unsupported_message_type.rb +1 -1
  177. data/lib/mongo/error/unsupported_option.rb +99 -0
  178. data/lib/mongo/error/write_retryable.rb +1 -1
  179. data/lib/mongo/event.rb +1 -1
  180. data/lib/mongo/event/base.rb +1 -1
  181. data/lib/mongo/event/listeners.rb +1 -1
  182. data/lib/mongo/event/publisher.rb +1 -1
  183. data/lib/mongo/event/subscriber.rb +1 -1
  184. data/lib/mongo/grid.rb +1 -1
  185. data/lib/mongo/grid/file.rb +1 -6
  186. data/lib/mongo/grid/file/chunk.rb +1 -3
  187. data/lib/mongo/grid/file/info.rb +1 -1
  188. data/lib/mongo/grid/fs_bucket.rb +20 -17
  189. data/lib/mongo/grid/stream.rb +1 -1
  190. data/lib/mongo/grid/stream/read.rb +1 -1
  191. data/lib/mongo/grid/stream/write.rb +4 -10
  192. data/lib/mongo/id.rb +1 -1
  193. data/lib/mongo/index.rb +2 -1
  194. data/lib/mongo/index/view.rb +58 -11
  195. data/lib/mongo/lint.rb +10 -0
  196. data/lib/mongo/loggable.rb +1 -1
  197. data/lib/mongo/logger.rb +1 -1
  198. data/lib/mongo/monitoring.rb +1 -1
  199. data/lib/mongo/monitoring/cmap_log_subscriber.rb +1 -1
  200. data/lib/mongo/monitoring/command_log_subscriber.rb +12 -5
  201. data/lib/mongo/monitoring/event.rb +1 -1
  202. data/lib/mongo/monitoring/event/cmap.rb +1 -1
  203. data/lib/mongo/monitoring/event/cmap/base.rb +1 -1
  204. data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +1 -1
  205. data/lib/mongo/monitoring/event/cmap/connection_check_out_started.rb +1 -1
  206. data/lib/mongo/monitoring/event/cmap/connection_checked_in.rb +1 -1
  207. data/lib/mongo/monitoring/event/cmap/connection_checked_out.rb +1 -1
  208. data/lib/mongo/monitoring/event/cmap/connection_closed.rb +1 -1
  209. data/lib/mongo/monitoring/event/cmap/connection_created.rb +1 -1
  210. data/lib/mongo/monitoring/event/cmap/connection_ready.rb +1 -1
  211. data/lib/mongo/monitoring/event/cmap/pool_cleared.rb +1 -1
  212. data/lib/mongo/monitoring/event/cmap/pool_closed.rb +1 -1
  213. data/lib/mongo/monitoring/event/cmap/pool_created.rb +1 -1
  214. data/lib/mongo/monitoring/event/command_failed.rb +1 -1
  215. data/lib/mongo/monitoring/event/command_started.rb +9 -3
  216. data/lib/mongo/monitoring/event/command_succeeded.rb +1 -1
  217. data/lib/mongo/monitoring/event/secure.rb +8 -2
  218. data/lib/mongo/monitoring/event/server_closed.rb +1 -1
  219. data/lib/mongo/monitoring/event/server_description_changed.rb +1 -1
  220. data/lib/mongo/monitoring/event/server_heartbeat_failed.rb +1 -1
  221. data/lib/mongo/monitoring/event/server_heartbeat_started.rb +1 -1
  222. data/lib/mongo/monitoring/event/server_heartbeat_succeeded.rb +1 -1
  223. data/lib/mongo/monitoring/event/server_opening.rb +1 -1
  224. data/lib/mongo/monitoring/event/topology_changed.rb +1 -1
  225. data/lib/mongo/monitoring/event/topology_closed.rb +1 -1
  226. data/lib/mongo/monitoring/event/topology_opening.rb +1 -1
  227. data/lib/mongo/monitoring/publishable.rb +5 -8
  228. data/lib/mongo/monitoring/sdam_log_subscriber.rb +1 -1
  229. data/lib/mongo/monitoring/server_closed_log_subscriber.rb +1 -1
  230. data/lib/mongo/monitoring/server_description_changed_log_subscriber.rb +1 -1
  231. data/lib/mongo/monitoring/server_opening_log_subscriber.rb +1 -1
  232. data/lib/mongo/monitoring/topology_changed_log_subscriber.rb +1 -1
  233. data/lib/mongo/monitoring/topology_closed_log_subscriber.rb +1 -1
  234. data/lib/mongo/monitoring/topology_opening_log_subscriber.rb +1 -1
  235. data/lib/mongo/monitoring/unified_sdam_log_subscriber.rb +1 -1
  236. data/lib/mongo/operation.rb +1 -0
  237. data/lib/mongo/operation/aggregate.rb +1 -1
  238. data/lib/mongo/operation/aggregate/command.rb +5 -5
  239. data/lib/mongo/operation/aggregate/op_msg.rb +1 -1
  240. data/lib/mongo/operation/aggregate/result.rb +1 -1
  241. data/lib/mongo/operation/collections_info.rb +3 -36
  242. data/lib/mongo/operation/collections_info/command.rb +40 -0
  243. data/lib/mongo/operation/collections_info/result.rb +1 -1
  244. data/lib/mongo/operation/command.rb +1 -1
  245. data/lib/mongo/operation/command/command.rb +3 -3
  246. data/lib/mongo/operation/command/op_msg.rb +1 -1
  247. data/lib/mongo/operation/count.rb +1 -1
  248. data/lib/mongo/operation/count/command.rb +3 -3
  249. data/lib/mongo/operation/count/op_msg.rb +1 -1
  250. data/lib/mongo/operation/create.rb +1 -1
  251. data/lib/mongo/operation/create/command.rb +3 -3
  252. data/lib/mongo/operation/create/op_msg.rb +1 -1
  253. data/lib/mongo/operation/create_index.rb +1 -1
  254. data/lib/mongo/operation/create_index/command.rb +4 -4
  255. data/lib/mongo/operation/create_index/op_msg.rb +6 -3
  256. data/lib/mongo/operation/create_user.rb +1 -1
  257. data/lib/mongo/operation/create_user/command.rb +4 -4
  258. data/lib/mongo/operation/create_user/op_msg.rb +2 -2
  259. data/lib/mongo/operation/delete.rb +1 -1
  260. data/lib/mongo/operation/delete/bulk_result.rb +1 -1
  261. data/lib/mongo/operation/delete/command.rb +4 -4
  262. data/lib/mongo/operation/delete/legacy.rb +2 -2
  263. data/lib/mongo/operation/delete/op_msg.rb +4 -4
  264. data/lib/mongo/operation/delete/result.rb +2 -2
  265. data/lib/mongo/operation/distinct.rb +1 -1
  266. data/lib/mongo/operation/distinct/command.rb +3 -3
  267. data/lib/mongo/operation/distinct/op_msg.rb +1 -1
  268. data/lib/mongo/operation/drop.rb +1 -1
  269. data/lib/mongo/operation/drop/command.rb +3 -3
  270. data/lib/mongo/operation/drop/op_msg.rb +1 -1
  271. data/lib/mongo/operation/drop_database.rb +1 -1
  272. data/lib/mongo/operation/drop_database/command.rb +3 -3
  273. data/lib/mongo/operation/drop_database/op_msg.rb +1 -1
  274. data/lib/mongo/operation/drop_index.rb +1 -1
  275. data/lib/mongo/operation/drop_index/command.rb +4 -4
  276. data/lib/mongo/operation/drop_index/op_msg.rb +2 -2
  277. data/lib/mongo/operation/explain.rb +1 -1
  278. data/lib/mongo/operation/explain/command.rb +3 -3
  279. data/lib/mongo/operation/explain/legacy.rb +3 -3
  280. data/lib/mongo/operation/explain/op_msg.rb +1 -1
  281. data/lib/mongo/operation/explain/result.rb +1 -1
  282. data/lib/mongo/operation/find.rb +1 -1
  283. data/lib/mongo/operation/find/command.rb +3 -3
  284. data/lib/mongo/operation/find/legacy.rb +3 -3
  285. data/lib/mongo/operation/find/legacy/result.rb +1 -1
  286. data/lib/mongo/operation/find/op_msg.rb +2 -12
  287. data/lib/mongo/operation/find/result.rb +1 -1
  288. data/lib/mongo/operation/get_more.rb +1 -1
  289. data/lib/mongo/operation/get_more/command.rb +3 -3
  290. data/lib/mongo/operation/get_more/legacy.rb +2 -2
  291. data/lib/mongo/operation/get_more/op_msg.rb +2 -12
  292. data/lib/mongo/operation/get_more/result.rb +1 -1
  293. data/lib/mongo/operation/indexes.rb +1 -1
  294. data/lib/mongo/operation/indexes/command.rb +3 -3
  295. data/lib/mongo/operation/indexes/legacy.rb +4 -4
  296. data/lib/mongo/operation/indexes/op_msg.rb +1 -1
  297. data/lib/mongo/operation/indexes/result.rb +1 -1
  298. data/lib/mongo/operation/insert.rb +3 -2
  299. data/lib/mongo/operation/insert/bulk_result.rb +6 -2
  300. data/lib/mongo/operation/insert/command.rb +7 -7
  301. data/lib/mongo/operation/insert/legacy.rb +9 -5
  302. data/lib/mongo/operation/insert/op_msg.rb +6 -6
  303. data/lib/mongo/operation/insert/result.rb +7 -4
  304. data/lib/mongo/operation/kill_cursors.rb +1 -1
  305. data/lib/mongo/operation/kill_cursors/command.rb +3 -3
  306. data/lib/mongo/operation/kill_cursors/legacy.rb +2 -2
  307. data/lib/mongo/operation/kill_cursors/op_msg.rb +1 -1
  308. data/lib/mongo/operation/list_collections.rb +1 -1
  309. data/lib/mongo/operation/list_collections/command.rb +4 -4
  310. data/lib/mongo/operation/list_collections/op_msg.rb +2 -2
  311. data/lib/mongo/operation/list_collections/result.rb +1 -1
  312. data/lib/mongo/operation/map_reduce.rb +1 -1
  313. data/lib/mongo/operation/map_reduce/command.rb +3 -3
  314. data/lib/mongo/operation/map_reduce/op_msg.rb +1 -1
  315. data/lib/mongo/operation/map_reduce/result.rb +1 -1
  316. data/lib/mongo/operation/op_msg_base.rb +3 -3
  317. data/lib/mongo/operation/parallel_scan.rb +1 -1
  318. data/lib/mongo/operation/parallel_scan/command.rb +5 -5
  319. data/lib/mongo/operation/parallel_scan/op_msg.rb +2 -2
  320. data/lib/mongo/operation/parallel_scan/result.rb +1 -1
  321. data/lib/mongo/operation/remove_user.rb +1 -1
  322. data/lib/mongo/operation/remove_user/command.rb +4 -4
  323. data/lib/mongo/operation/remove_user/op_msg.rb +2 -2
  324. data/lib/mongo/operation/result.rb +28 -4
  325. data/lib/mongo/operation/shared/bypass_document_validation.rb +10 -4
  326. data/lib/mongo/operation/shared/causal_consistency_supported.rb +3 -3
  327. data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +56 -0
  328. data/lib/mongo/operation/shared/executable.rb +46 -28
  329. data/lib/mongo/operation/shared/executable_no_validate.rb +3 -3
  330. data/lib/mongo/operation/shared/executable_transaction_label.rb +1 -1
  331. data/lib/mongo/operation/shared/idable.rb +1 -1
  332. data/lib/mongo/operation/shared/limited.rb +10 -2
  333. data/lib/mongo/operation/shared/object_id_generator.rb +1 -1
  334. data/lib/mongo/operation/shared/op_msg_or_command.rb +7 -5
  335. data/lib/mongo/operation/shared/op_msg_or_find_command.rb +8 -6
  336. data/lib/mongo/operation/shared/op_msg_or_list_indexes_command.rb +8 -6
  337. data/lib/mongo/operation/shared/polymorphic_lookup.rb +1 -1
  338. data/lib/mongo/operation/shared/polymorphic_result.rb +1 -1
  339. data/lib/mongo/operation/shared/read_preference_supported.rb +19 -16
  340. data/lib/mongo/operation/shared/response_handling.rb +83 -8
  341. data/lib/mongo/operation/shared/result/aggregatable.rb +1 -1
  342. data/lib/mongo/operation/shared/result/use_legacy_error_parser.rb +1 -1
  343. data/lib/mongo/operation/shared/sessions_supported.rb +50 -27
  344. data/lib/mongo/operation/shared/specifiable.rb +32 -20
  345. data/lib/mongo/operation/shared/write.rb +25 -19
  346. data/lib/mongo/operation/shared/write_concern_supported.rb +6 -6
  347. data/lib/mongo/operation/update.rb +1 -1
  348. data/lib/mongo/operation/update/bulk_result.rb +1 -1
  349. data/lib/mongo/operation/update/command.rb +4 -4
  350. data/lib/mongo/operation/update/legacy.rb +2 -2
  351. data/lib/mongo/operation/update/legacy/result.rb +1 -1
  352. data/lib/mongo/operation/update/op_msg.rb +4 -4
  353. data/lib/mongo/operation/update/result.rb +2 -2
  354. data/lib/mongo/operation/update_user.rb +1 -1
  355. data/lib/mongo/operation/update_user/command.rb +4 -4
  356. data/lib/mongo/operation/update_user/op_msg.rb +2 -2
  357. data/lib/mongo/operation/users_info.rb +1 -1
  358. data/lib/mongo/operation/users_info/command.rb +4 -4
  359. data/lib/mongo/operation/users_info/op_msg.rb +2 -2
  360. data/lib/mongo/operation/users_info/result.rb +1 -1
  361. data/lib/mongo/options.rb +1 -1
  362. data/lib/mongo/options/mapper.rb +1 -1
  363. data/lib/mongo/options/redacted.rb +1 -1
  364. data/lib/mongo/protocol/bit_vector.rb +1 -1
  365. data/lib/mongo/protocol/compressed.rb +1 -1
  366. data/lib/mongo/protocol/delete.rb +1 -1
  367. data/lib/mongo/protocol/get_more.rb +1 -1
  368. data/lib/mongo/protocol/insert.rb +1 -1
  369. data/lib/mongo/protocol/kill_cursors.rb +1 -1
  370. data/lib/mongo/protocol/message.rb +5 -14
  371. data/lib/mongo/protocol/msg.rb +5 -24
  372. data/lib/mongo/protocol/query.rb +1 -37
  373. data/lib/mongo/protocol/registry.rb +1 -1
  374. data/lib/mongo/protocol/reply.rb +1 -1
  375. data/lib/mongo/protocol/serializers.rb +3 -6
  376. data/lib/mongo/protocol/update.rb +1 -1
  377. data/lib/mongo/retryable.rb +23 -10
  378. data/lib/mongo/semaphore.rb +1 -1
  379. data/lib/mongo/server.rb +32 -7
  380. data/lib/mongo/server/app_metadata.rb +17 -4
  381. data/lib/mongo/server/connection.rb +35 -131
  382. data/lib/mongo/server/connection_base.rb +31 -42
  383. data/lib/mongo/server/connection_common.rb +75 -1
  384. data/lib/mongo/server/connection_pool.rb +20 -1
  385. data/lib/mongo/server/connection_pool/populator.rb +1 -1
  386. data/lib/mongo/server/context.rb +1 -1
  387. data/lib/mongo/server/description.rb +44 -2
  388. data/lib/mongo/server/description/features.rb +12 -3
  389. data/lib/mongo/server/monitor.rb +116 -72
  390. data/lib/mongo/server/monitor/app_metadata.rb +1 -1
  391. data/lib/mongo/server/monitor/connection.rb +62 -80
  392. data/lib/mongo/server/pending_connection.rb +205 -3
  393. data/lib/mongo/server/round_trip_time_averager.rb +12 -3
  394. data/lib/mongo/server_selector.rb +2 -1
  395. data/lib/mongo/server_selector/base.rb +40 -0
  396. data/lib/mongo/server_selector/nearest.rb +25 -15
  397. data/lib/mongo/server_selector/primary.rb +23 -22
  398. data/lib/mongo/server_selector/primary_preferred.rb +25 -15
  399. data/lib/mongo/server_selector/secondary.rb +25 -15
  400. data/lib/mongo/server_selector/secondary_preferred.rb +28 -27
  401. data/lib/mongo/server_selector/selectable.rb +30 -15
  402. data/lib/mongo/session.rb +12 -1
  403. data/lib/mongo/session/server_session.rb +1 -1
  404. data/lib/mongo/session/session_pool.rb +1 -1
  405. data/lib/mongo/socket.rb +103 -35
  406. data/lib/mongo/socket/ssl.rb +97 -34
  407. data/lib/mongo/socket/tcp.rb +39 -31
  408. data/lib/mongo/socket/unix.rb +14 -6
  409. data/lib/mongo/srv.rb +1 -1
  410. data/lib/mongo/srv/monitor.rb +1 -1
  411. data/lib/mongo/srv/resolver.rb +1 -1
  412. data/lib/mongo/srv/result.rb +1 -1
  413. data/lib/mongo/timeout.rb +9 -9
  414. data/lib/mongo/topology_version.rb +80 -0
  415. data/lib/mongo/uri.rb +61 -47
  416. data/lib/mongo/uri/srv_protocol.rb +9 -1
  417. data/lib/mongo/version.rb +2 -2
  418. data/lib/mongo/write_concern.rb +1 -1
  419. data/lib/mongo/write_concern/acknowledged.rb +1 -1
  420. data/lib/mongo/write_concern/base.rb +1 -1
  421. data/lib/mongo/write_concern/unacknowledged.rb +1 -1
  422. data/mongo.gemspec +1 -1
  423. data/spec/NOTES.aws-auth.md +291 -0
  424. data/spec/README.aws-auth.md +318 -0
  425. data/spec/README.md +64 -17
  426. data/spec/integration/auth_spec.rb +29 -9
  427. data/spec/integration/aws_auth_request_spec.rb +74 -0
  428. data/spec/integration/aws_credentials_retriever_spec.rb +103 -0
  429. data/spec/integration/change_stream_spec.rb +123 -51
  430. data/spec/integration/client_authentication_options_spec.rb +0 -37
  431. data/spec/integration/client_construction_aws_auth_spec.rb +191 -0
  432. data/spec/integration/client_construction_spec.rb +1 -1
  433. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +5 -9
  434. data/spec/integration/collection_indexes_prose_spec.rb +55 -0
  435. data/spec/integration/command_monitoring_spec.rb +30 -6
  436. data/spec/integration/command_spec.rb +11 -9
  437. data/spec/integration/connect_single_rs_name_spec.rb +5 -3
  438. data/spec/integration/connection_spec.rb +1 -0
  439. data/spec/integration/crud_spec.rb +28 -0
  440. data/spec/integration/cursor_reaping_spec.rb +14 -10
  441. data/spec/integration/fork_reconnect_spec.rb +143 -0
  442. data/spec/integration/get_more_spec.rb +10 -3
  443. data/spec/integration/heartbeat_events_spec.rb +1 -1
  444. data/spec/integration/read_preference_spec.rb +41 -11
  445. data/spec/integration/reconnect_spec.rb +2 -3
  446. data/spec/integration/retryable_errors_spec.rb +33 -14
  447. data/spec/integration/{retryable_writes_spec.rb → retryable_writes/retryable_writes_36_and_older_spec.rb} +55 -51
  448. data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +401 -0
  449. data/spec/integration/retryable_writes/shared/adds_diagnostics.rb +15 -0
  450. data/spec/integration/retryable_writes/shared/does_not_support_retries.rb +24 -0
  451. data/spec/integration/retryable_writes/shared/only_supports_legacy_retries.rb +25 -0
  452. data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +215 -0
  453. data/spec/integration/retryable_writes/shared/performs_modern_retries.rb +232 -0
  454. data/spec/integration/retryable_writes/shared/performs_no_retries.rb +110 -0
  455. data/spec/integration/retryable_writes/shared/supports_legacy_retries.rb +19 -0
  456. data/spec/integration/retryable_writes/shared/supports_modern_retries.rb +25 -0
  457. data/spec/integration/retryable_writes/shared/supports_retries.rb +16 -0
  458. data/spec/integration/sdam_error_handling_spec.rb +116 -18
  459. data/spec/integration/sdam_events_spec.rb +1 -0
  460. data/spec/integration/server_spec.rb +42 -26
  461. data/spec/integration/size_limit_spec.rb +2 -20
  462. data/spec/integration/step_down_spec.rb +15 -15
  463. data/spec/integration/transactions_api_examples_spec.rb +59 -0
  464. data/spec/integration/transactions_examples_spec.rb +5 -2
  465. data/spec/integration/x509_auth_spec.rb +109 -0
  466. data/spec/kerberos/kerberos_spec.rb +10 -6
  467. data/spec/lite_spec_helper.rb +21 -19
  468. data/spec/mongo/address/ipv4_spec.rb +1 -1
  469. data/spec/mongo/address_spec.rb +2 -2
  470. data/spec/mongo/auth/cr_spec.rb +7 -7
  471. data/spec/mongo/auth/gssapi/conversation_spec.rb +121 -0
  472. data/spec/mongo/auth/invalid_mechanism_spec.rb +1 -1
  473. data/spec/mongo/auth/ldap/conversation_spec.rb +1 -1
  474. data/spec/mongo/auth/ldap_spec.rb +3 -3
  475. data/spec/mongo/auth/scram/conversation_spec.rb +119 -334
  476. data/spec/mongo/auth/scram256/conversation_spec.rb +171 -0
  477. data/spec/mongo/auth/{scram/negotiation_spec.rb → scram_negotiation_spec.rb} +13 -8
  478. data/spec/mongo/auth/scram_spec.rb +28 -68
  479. data/spec/mongo/auth/user_spec.rb +1 -1
  480. data/spec/mongo/auth/x509/conversation_spec.rb +1 -1
  481. data/spec/mongo/auth/x509_spec.rb +8 -8
  482. data/spec/mongo/auth_spec.rb +4 -4
  483. data/spec/mongo/bulk_write_spec.rb +206 -2
  484. data/spec/mongo/client_construction_spec.rb +290 -86
  485. data/spec/mongo/client_spec.rb +21 -2
  486. data/spec/mongo/cluster_spec.rb +4 -2
  487. data/spec/mongo/collection/view/aggregation_spec.rb +6 -2
  488. data/spec/mongo/collection/view/builder/find_command_spec.rb +17 -6
  489. data/spec/mongo/collection/view/change_stream_resume_spec.rb +392 -0
  490. data/spec/mongo/collection/view/change_stream_spec.rb +0 -318
  491. data/spec/mongo/collection/view/iterable_spec.rb +38 -0
  492. data/spec/mongo/collection/view/map_reduce_spec.rb +6 -2
  493. data/spec/mongo/collection/view/readable_spec.rb +15 -1
  494. data/spec/mongo/collection/view/writable_spec.rb +208 -1
  495. data/spec/mongo/collection_spec.rb +31 -67
  496. data/spec/mongo/cursor/builder/get_more_command_spec.rb +6 -1
  497. data/spec/mongo/cursor/builder/op_get_more_spec.rb +6 -1
  498. data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +6 -1
  499. data/spec/mongo/cursor_spec.rb +9 -1
  500. data/spec/mongo/database_spec.rb +6 -2
  501. data/spec/mongo/error/operation_failure_heavy_spec.rb +58 -0
  502. data/spec/mongo/error/operation_failure_spec.rb +130 -72
  503. data/spec/mongo/error/unsupported_option_spec.rb +54 -0
  504. data/spec/mongo/grid/fs_bucket_spec.rb +18 -0
  505. data/spec/mongo/grid/stream/write_spec.rb +32 -0
  506. data/spec/mongo/index/view_spec.rb +166 -0
  507. data/spec/mongo/operation/aggregate/result_spec.rb +6 -1
  508. data/spec/mongo/operation/delete/bulk_spec.rb +18 -6
  509. data/spec/mongo/operation/delete/op_msg_spec.rb +22 -14
  510. data/spec/mongo/operation/find/legacy_spec.rb +27 -7
  511. data/spec/mongo/operation/get_more_spec.rb +6 -1
  512. data/spec/mongo/operation/insert/bulk_spec.rb +21 -7
  513. data/spec/mongo/operation/insert/command_spec.rb +4 -0
  514. data/spec/mongo/operation/insert/op_msg_spec.rb +22 -14
  515. data/spec/mongo/operation/limited_spec.rb +5 -3
  516. data/spec/mongo/operation/read_preference_legacy_spec.rb +16 -4
  517. data/spec/mongo/operation/read_preference_op_msg_spec.rb +115 -5
  518. data/spec/mongo/operation/result_spec.rb +6 -1
  519. data/spec/mongo/operation/update/bulk_spec.rb +18 -6
  520. data/spec/mongo/operation/update/command_spec.rb +4 -0
  521. data/spec/mongo/operation/update/op_msg_spec.rb +22 -14
  522. data/spec/mongo/retryable_spec.rb +71 -70
  523. data/spec/mongo/server/app_metadata_shared.rb +56 -0
  524. data/spec/mongo/server/app_metadata_spec.rb +8 -1
  525. data/spec/mongo/server/connection_auth_spec.rb +31 -12
  526. data/spec/mongo/server/connection_pool_spec.rb +0 -31
  527. data/spec/mongo/server/connection_spec.rb +118 -71
  528. data/spec/mongo/server/monitor/app_metadata_spec.rb +8 -1
  529. data/spec/mongo/server/monitor/connection_spec.rb +1 -82
  530. data/spec/mongo/server/monitor_spec.rb +76 -17
  531. data/spec/mongo/server/round_trip_time_averager_spec.rb +5 -3
  532. data/spec/mongo/server_selector/nearest_spec.rb +1 -0
  533. data/spec/mongo/server_selector/primary_preferred_spec.rb +1 -0
  534. data/spec/mongo/server_selector/primary_spec.rb +18 -0
  535. data/spec/mongo/server_selector/secondary_preferred_spec.rb +18 -1
  536. data/spec/mongo/server_selector/secondary_spec.rb +1 -0
  537. data/spec/mongo/server_selector_spec.rb +0 -1
  538. data/spec/mongo/session/session_pool_spec.rb +7 -3
  539. data/spec/mongo/socket/ssl_spec.rb +2 -2
  540. data/spec/mongo/socket/tcp_spec.rb +2 -2
  541. data/spec/mongo/socket/unix_spec.rb +2 -2
  542. data/spec/mongo/socket_spec.rb +9 -9
  543. data/spec/mongo/timeout_spec.rb +22 -68
  544. data/spec/mongo/uri_spec.rb +21 -6
  545. data/spec/runners/auth.rb +5 -6
  546. data/spec/runners/change_streams/outcome.rb +42 -0
  547. data/spec/runners/change_streams/spec.rb +57 -0
  548. data/spec/runners/change_streams/test.rb +229 -0
  549. data/spec/runners/cmap/verifier.rb +1 -1
  550. data/spec/runners/command_monitoring.rb +1 -1
  551. data/spec/runners/connection_string.rb +3 -2
  552. data/spec/runners/crud.rb +2 -2
  553. data/spec/runners/crud/context.rb +1 -1
  554. data/spec/runners/crud/operation.rb +120 -30
  555. data/spec/runners/crud/outcome.rb +1 -1
  556. data/spec/runners/crud/spec.rb +1 -0
  557. data/spec/runners/crud/test.rb +8 -26
  558. data/spec/runners/crud/test_base.rb +47 -0
  559. data/spec/runners/crud/verifier.rb +21 -3
  560. data/spec/runners/gridfs.rb +1 -1
  561. data/spec/runners/{server_discovery_and_monitoring.rb → sdam.rb} +41 -22
  562. data/spec/runners/sdam/verifier.rb +26 -8
  563. data/spec/runners/sdam_monitoring.rb +1 -1
  564. data/spec/runners/transactions.rb +1 -2
  565. data/spec/runners/transactions/context.rb +1 -1
  566. data/spec/runners/transactions/operation.rb +5 -1
  567. data/spec/runners/transactions/spec.rb +1 -1
  568. data/spec/runners/transactions/test.rb +48 -54
  569. data/spec/spec_tests/auth_spec.rb +2 -0
  570. data/spec/spec_tests/change_streams_spec.rb +39 -4
  571. data/spec/spec_tests/client_side_encryption_spec.rb +3 -0
  572. data/spec/spec_tests/cmap_spec.rb +5 -0
  573. data/spec/spec_tests/command_monitoring_spec.rb +3 -0
  574. data/spec/spec_tests/connection_string_spec.rb +2 -0
  575. data/spec/spec_tests/crud_spec.rb +2 -0
  576. data/spec/spec_tests/data/auth/connection-string.yml +57 -1
  577. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +30 -0
  578. data/spec/spec_tests/data/change_streams/change-streams-resume-errorLabels.yml +1105 -0
  579. data/spec/spec_tests/data/change_streams/change-streams-resume-whitelist.yml +1107 -0
  580. data/spec/spec_tests/data/change_streams/change-streams.yml +5 -4
  581. data/spec/spec_tests/data/crud_v2/aggregate-merge.yml +1 -1
  582. data/spec/spec_tests/data/crud_v2/bulkWrite-arrayFilters.yml +33 -11
  583. data/spec/spec_tests/data/crud_v2/bulkWrite-delete-hint-clientError.yml +63 -0
  584. data/spec/spec_tests/data/crud_v2/bulkWrite-delete-hint-serverError.yml +92 -0
  585. data/spec/spec_tests/data/crud_v2/bulkWrite-delete-hint.yml +103 -0
  586. data/spec/spec_tests/data/crud_v2/bulkWrite-update-hint-clientError.yml +90 -0
  587. data/spec/spec_tests/data/crud_v2/bulkWrite-update-hint-serverError.yml +147 -0
  588. data/spec/spec_tests/data/crud_v2/bulkWrite-update-hint.yml +164 -0
  589. data/spec/spec_tests/data/crud_v2/deleteMany-hint-clientError.yml +43 -0
  590. data/spec/spec_tests/data/crud_v2/deleteMany-hint-serverError.yml +62 -0
  591. data/spec/spec_tests/data/crud_v2/deleteMany-hint.yml +58 -0
  592. data/spec/spec_tests/data/crud_v2/deleteOne-hint-clientError.yml +41 -0
  593. data/spec/spec_tests/data/crud_v2/deleteOne-hint-serverError.yml +60 -0
  594. data/spec/spec_tests/data/crud_v2/deleteOne-hint.yml +57 -0
  595. data/spec/spec_tests/data/crud_v2/find-allowdiskuse-clientError.yml +28 -0
  596. data/spec/spec_tests/data/crud_v2/find-allowdiskuse-serverError.yml +44 -0
  597. data/spec/spec_tests/data/crud_v2/find-allowdiskuse.yml +50 -0
  598. data/spec/spec_tests/data/crud_v2/findOneAndDelete-hint-clientError.yml +45 -0
  599. data/spec/spec_tests/data/crud_v2/findOneAndDelete-hint-serverError.yml +60 -0
  600. data/spec/spec_tests/data/crud_v2/findOneAndDelete-hint.yml +56 -0
  601. data/spec/spec_tests/data/crud_v2/findOneAndReplace-hint-clientError.yml +40 -0
  602. data/spec/spec_tests/data/crud_v2/findOneAndReplace-hint-serverError.yml +59 -0
  603. data/spec/spec_tests/data/crud_v2/findOneAndReplace-hint.yml +55 -0
  604. data/spec/spec_tests/data/crud_v2/findOneAndUpdate-hint-clientError.yml +40 -0
  605. data/spec/spec_tests/data/crud_v2/findOneAndUpdate-hint-serverError.yml +58 -0
  606. data/spec/spec_tests/data/crud_v2/findOneAndUpdate-hint.yml +55 -0
  607. data/spec/spec_tests/data/crud_v2/replaceOne-hint.yml +61 -0
  608. data/spec/spec_tests/data/crud_v2/unacknowledged-bulkWrite-delete-hint-clientError.yml +60 -0
  609. data/spec/spec_tests/data/crud_v2/unacknowledged-bulkWrite-update-hint-clientError.yml +88 -0
  610. data/spec/spec_tests/data/crud_v2/unacknowledged-deleteMany-hint-clientError.yml +40 -0
  611. data/spec/spec_tests/data/crud_v2/unacknowledged-deleteOne-hint-clientError.yml +38 -0
  612. data/spec/spec_tests/data/crud_v2/unacknowledged-findOneAndDelete-hint-clientError.yml +42 -0
  613. data/spec/spec_tests/data/crud_v2/unacknowledged-findOneAndReplace-hint-clientError.yml +40 -0
  614. data/spec/spec_tests/data/crud_v2/unacknowledged-findOneAndUpdate-hint-clientError.yml +40 -0
  615. data/spec/spec_tests/data/crud_v2/unacknowledged-replaceOne-hint-clientError.yml +40 -0
  616. data/spec/spec_tests/data/crud_v2/unacknowledged-updateMany-hint-clientError.yml +43 -0
  617. data/spec/spec_tests/data/crud_v2/unacknowledged-updateOne-hint-clientError.yml +40 -0
  618. data/spec/spec_tests/data/crud_v2/updateMany-hint-clientError.yml +45 -0
  619. data/spec/spec_tests/data/crud_v2/updateMany-hint-serverError.yml +66 -0
  620. data/spec/spec_tests/data/crud_v2/updateMany-hint.yml +65 -0
  621. data/spec/spec_tests/data/crud_v2/updateOne-hint-clientError.yml +43 -0
  622. data/spec/spec_tests/data/crud_v2/updateOne-hint-serverError.yml +62 -0
  623. data/spec/spec_tests/data/crud_v2/updateOne-hint.yml +61 -0
  624. data/spec/spec_tests/data/crud_v2/updateWithPipelines.yml +65 -0
  625. data/spec/spec_tests/data/dns_seedlist_discovery/direct-connection-false.yml +10 -0
  626. data/spec/spec_tests/data/dns_seedlist_discovery/direct-connection-true.yml +5 -0
  627. data/spec/spec_tests/data/read_write_concern/operation/default-write-concern-2.6.yml +215 -0
  628. data/spec/spec_tests/data/read_write_concern/operation/default-write-concern-3.2.yml +58 -0
  629. data/spec/spec_tests/data/read_write_concern/operation/default-write-concern-3.4.yml +95 -0
  630. data/spec/spec_tests/data/read_write_concern/operation/default-write-concern-4.2.yml +36 -0
  631. data/spec/spec_tests/data/retryable_writes/bulkWrite-errorLabels.yml +77 -0
  632. data/spec/spec_tests/data/retryable_writes/bulkWrite-serverErrors.yml +37 -0
  633. data/spec/spec_tests/data/retryable_writes/deleteOne-errorLabels.yml +48 -0
  634. data/spec/spec_tests/data/retryable_writes/deleteOne-serverErrors.yml +22 -0
  635. data/spec/spec_tests/data/retryable_writes/findOneAndDelete-errorLabels.yml +49 -0
  636. data/spec/spec_tests/data/retryable_writes/findOneAndDelete-serverErrors.yml +23 -0
  637. data/spec/spec_tests/data/retryable_writes/findOneAndReplace-errorLabels.yml +52 -0
  638. data/spec/spec_tests/data/retryable_writes/findOneAndReplace-serverErrors.yml +25 -0
  639. data/spec/spec_tests/data/retryable_writes/findOneAndUpdate-errorLabels.yml +52 -0
  640. data/spec/spec_tests/data/retryable_writes/findOneAndUpdate-serverErrors.yml +24 -0
  641. data/spec/spec_tests/data/retryable_writes/insertMany-errorLabels.yml +54 -0
  642. data/spec/spec_tests/data/retryable_writes/insertMany-serverErrors.yml +24 -0
  643. data/spec/spec_tests/data/retryable_writes/insertOne-errorLabels.yml +44 -0
  644. data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +69 -0
  645. data/spec/spec_tests/data/retryable_writes/replaceOne-errorLabels.yml +53 -0
  646. data/spec/spec_tests/data/retryable_writes/replaceOne-serverErrors.yml +23 -0
  647. data/spec/spec_tests/data/retryable_writes/updateOne-errorLabels.yml +53 -0
  648. data/spec/spec_tests/data/retryable_writes/updateOne-serverErrors.yml +23 -0
  649. data/spec/spec_tests/data/sdam/errors/error_handling_handshake.yml +54 -0
  650. data/spec/spec_tests/data/sdam/errors/non-stale-network-error.yml +46 -0
  651. data/spec/spec_tests/data/sdam/errors/non-stale-network-timeout-error.yml +37 -0
  652. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-InterruptedAtShutdown.yml +60 -0
  653. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-InterruptedDueToReplStateChange.yml +60 -0
  654. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-NotMaster.yml +60 -0
  655. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-NotMasterNoSlaveOk.yml +60 -0
  656. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-NotMasterOrSecondary.yml +60 -0
  657. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-PrimarySteppedDown.yml +60 -0
  658. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-greater-ShutdownInProgress.yml +60 -0
  659. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-InterruptedAtShutdown.yml +51 -0
  660. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-InterruptedDueToReplStateChange.yml +51 -0
  661. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-NotMaster.yml +51 -0
  662. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-NotMasterNoSlaveOk.yml +51 -0
  663. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-NotMasterOrSecondary.yml +51 -0
  664. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-PrimarySteppedDown.yml +51 -0
  665. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-missing-ShutdownInProgress.yml +51 -0
  666. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-InterruptedAtShutdown.yml +60 -0
  667. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-InterruptedDueToReplStateChange.yml +60 -0
  668. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-NotMaster.yml +60 -0
  669. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-NotMasterNoSlaveOk.yml +60 -0
  670. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-NotMasterOrSecondary.yml +60 -0
  671. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-PrimarySteppedDown.yml +60 -0
  672. data/spec/spec_tests/data/sdam/errors/non-stale-topologyVersion-proccessId-changed-ShutdownInProgress.yml +60 -0
  673. data/spec/spec_tests/data/sdam/errors/post-42-InterruptedAtShutdown.yml +46 -0
  674. data/spec/spec_tests/data/sdam/errors/post-42-InterruptedDueToReplStateChange.yml +46 -0
  675. data/spec/spec_tests/data/sdam/errors/post-42-NotMaster.yml +46 -0
  676. data/spec/spec_tests/data/sdam/errors/post-42-NotMasterNoSlaveOk.yml +46 -0
  677. data/spec/spec_tests/data/sdam/errors/post-42-NotMasterOrSecondary.yml +46 -0
  678. data/spec/spec_tests/data/sdam/errors/post-42-PrimarySteppedDown.yml +46 -0
  679. data/spec/spec_tests/data/sdam/errors/post-42-ShutdownInProgress.yml +46 -0
  680. data/spec/spec_tests/data/sdam/errors/pre-42-InterruptedAtShutdown.yml +46 -0
  681. data/spec/spec_tests/data/sdam/errors/pre-42-InterruptedDueToReplStateChange.yml +46 -0
  682. data/spec/spec_tests/data/sdam/errors/pre-42-NotMaster.yml +46 -0
  683. data/spec/spec_tests/data/sdam/errors/pre-42-NotMasterNoSlaveOk.yml +46 -0
  684. data/spec/spec_tests/data/sdam/errors/pre-42-NotMasterOrSecondary.yml +46 -0
  685. data/spec/spec_tests/data/sdam/errors/pre-42-PrimarySteppedDown.yml +46 -0
  686. data/spec/spec_tests/data/sdam/errors/pre-42-ShutdownInProgress.yml +46 -0
  687. data/spec/spec_tests/data/sdam/errors/stale-generation-InterruptedAtShutdown.yml +89 -0
  688. data/spec/spec_tests/data/sdam/errors/stale-generation-InterruptedDueToReplStateChange.yml +89 -0
  689. data/spec/spec_tests/data/sdam/errors/stale-generation-NotMaster.yml +89 -0
  690. data/spec/spec_tests/data/sdam/errors/stale-generation-NotMasterNoSlaveOk.yml +89 -0
  691. data/spec/spec_tests/data/sdam/errors/stale-generation-NotMasterOrSecondary.yml +89 -0
  692. data/spec/spec_tests/data/sdam/errors/stale-generation-PrimarySteppedDown.yml +89 -0
  693. data/spec/spec_tests/data/sdam/errors/stale-generation-ShutdownInProgress.yml +89 -0
  694. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-InterruptedAtShutdown.yml +89 -0
  695. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-InterruptedDueToReplStateChange.yml +89 -0
  696. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-NotMaster.yml +89 -0
  697. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-NotMasterNoSlaveOk.yml +89 -0
  698. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-NotMasterOrSecondary.yml +89 -0
  699. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-PrimarySteppedDown.yml +89 -0
  700. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-ShutdownInProgress.yml +89 -0
  701. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-network.yml +80 -0
  702. data/spec/spec_tests/data/sdam/errors/stale-generation-afterHandshakeCompletes-timeout.yml +80 -0
  703. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-InterruptedAtShutdown.yml +89 -0
  704. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-InterruptedDueToReplStateChange.yml +89 -0
  705. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-NotMaster.yml +89 -0
  706. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-NotMasterNoSlaveOk.yml +89 -0
  707. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-NotMasterOrSecondary.yml +89 -0
  708. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-PrimarySteppedDown.yml +89 -0
  709. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-ShutdownInProgress.yml +89 -0
  710. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-network.yml +80 -0
  711. data/spec/spec_tests/data/sdam/errors/stale-generation-beforeHandshakeCompletes-timeout.yml +80 -0
  712. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-InterruptedAtShutdown.yml +64 -0
  713. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-InterruptedDueToReplStateChange.yml +64 -0
  714. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-NotMaster.yml +64 -0
  715. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-NotMasterNoSlaveOk.yml +64 -0
  716. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-NotMasterOrSecondary.yml +64 -0
  717. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-PrimarySteppedDown.yml +64 -0
  718. data/spec/spec_tests/data/sdam/errors/stale-topologyVersion-ShutdownInProgress.yml +64 -0
  719. data/spec/spec_tests/data/sdam/rs/compatible.yml +2 -0
  720. data/spec/spec_tests/data/sdam/rs/compatible_unknown.yml +2 -0
  721. data/spec/spec_tests/data/sdam/rs/discover_arbiters.yml +2 -2
  722. data/spec/spec_tests/data/sdam/rs/discover_arbiters_replicaset.yml +43 -0
  723. data/spec/spec_tests/data/sdam/rs/discover_ghost.yml +35 -0
  724. data/spec/spec_tests/data/sdam/rs/{ghost_discovered.yml → discover_ghost_replicaset.yml} +1 -1
  725. data/spec/spec_tests/data/sdam/rs/discover_hidden.yml +50 -0
  726. data/spec/spec_tests/data/sdam/rs/discover_hidden_replicaset.yml +50 -0
  727. data/spec/spec_tests/data/sdam/rs/discover_passives.yml +2 -2
  728. data/spec/spec_tests/data/sdam/rs/discover_passives_replicaset.yml +81 -0
  729. data/spec/spec_tests/data/sdam/rs/discover_primary.yml +2 -2
  730. data/spec/spec_tests/data/sdam/rs/discover_primary_replicaset.yml +42 -0
  731. data/spec/spec_tests/data/sdam/rs/discover_rsother.yml +49 -0
  732. data/spec/spec_tests/data/sdam/rs/{rsother_discovered.yml → discover_rsother_replicaset.yml} +1 -1
  733. data/spec/spec_tests/data/sdam/rs/discover_secondary.yml +2 -2
  734. data/spec/spec_tests/data/sdam/rs/discover_secondary_replicaset.yml +43 -0
  735. data/spec/spec_tests/data/sdam/rs/incompatible_arbiter.yml +2 -0
  736. data/spec/spec_tests/data/sdam/rs/incompatible_ghost.yml +2 -0
  737. data/spec/spec_tests/data/sdam/rs/incompatible_other.yml +2 -0
  738. data/spec/spec_tests/data/sdam/rs/primary_mismatched_me.yml +23 -27
  739. data/spec/spec_tests/data/sdam/rs/primary_to_no_primary_mismatched_me.yml +79 -55
  740. data/spec/spec_tests/data/sdam/rs/replicaset_rsnp.yml +20 -0
  741. data/spec/spec_tests/data/sdam/rs/secondary_mismatched_me.yml +3 -2
  742. data/spec/spec_tests/data/sdam/rs/too_new.yml +2 -0
  743. data/spec/spec_tests/data/sdam/rs/topology_version_equal.yml +66 -0
  744. data/spec/spec_tests/data/sdam/rs/topology_version_greater.yml +189 -0
  745. data/spec/spec_tests/data/sdam/rs/topology_version_less.yml +62 -0
  746. data/spec/spec_tests/data/sdam/sharded/discover_single_mongos.yml +23 -0
  747. data/spec/spec_tests/data/sdam/single/direct_connection_external_ip.yml +1 -1
  748. data/spec/spec_tests/data/sdam/single/direct_connection_mongos.yml +2 -2
  749. data/spec/spec_tests/data/sdam/single/direct_connection_replicaset.yml +22 -0
  750. data/spec/spec_tests/data/sdam/single/direct_connection_rsarbiter.yml +2 -2
  751. data/spec/spec_tests/data/sdam/single/direct_connection_rsprimary.yml +2 -2
  752. data/spec/spec_tests/data/sdam/single/direct_connection_rssecondary.yml +2 -2
  753. data/spec/spec_tests/data/sdam/single/direct_connection_slave.yml +1 -1
  754. data/spec/spec_tests/data/sdam/single/direct_connection_standalone.yml +2 -2
  755. data/spec/spec_tests/data/sdam/single/{unavailable_seed.yml → direct_connection_unavailable_seed.yml} +2 -2
  756. data/spec/spec_tests/data/sdam/single/direct_connection_wrong_set_name.yml +38 -0
  757. data/spec/spec_tests/data/sdam/single/discover_standalone.yml +34 -0
  758. data/spec/spec_tests/data/sdam/single/discover_unavailable_seed.yml +28 -0
  759. data/spec/spec_tests/data/sdam/single/too_old_then_upgraded.yml +46 -0
  760. data/spec/spec_tests/data/transactions/create-collection.yml +131 -0
  761. data/spec/spec_tests/data/transactions/create-index.yml +152 -0
  762. data/spec/spec_tests/data/transactions/error-labels.yml +87 -21
  763. data/spec/spec_tests/data/transactions/mongos-recovery-token.yml +1 -0
  764. data/spec/spec_tests/data/transactions/retryable-abort-errorLabels.yml +124 -0
  765. data/spec/spec_tests/data/transactions/retryable-abort.yml +17 -2
  766. data/spec/spec_tests/data/transactions/retryable-commit-errorLabels.yml +132 -0
  767. data/spec/spec_tests/data/transactions/retryable-commit.yml +24 -9
  768. data/spec/spec_tests/data/uri_options/connection-options.yml +43 -0
  769. data/spec/spec_tests/data/uri_options/ruby-auth-options.yml +12 -0
  770. data/spec/spec_tests/data/uri_options/ruby-connection-options.yml +57 -0
  771. data/spec/spec_tests/dns_seedlist_discovery_spec.rb +3 -1
  772. data/spec/spec_tests/gridfs_spec.rb +2 -0
  773. data/spec/spec_tests/max_staleness_spec.rb +3 -1
  774. data/spec/spec_tests/read_write_concern_connection_string_spec.rb +2 -0
  775. data/spec/spec_tests/read_write_concern_operaton_spec.rb +10 -0
  776. data/spec/spec_tests/retryable_reads_spec.rb +2 -0
  777. data/spec/spec_tests/retryable_writes_spec.rb +8 -1
  778. data/spec/spec_tests/sdam_monitoring_spec.rb +3 -1
  779. data/spec/spec_tests/sdam_spec.rb +70 -1
  780. data/spec/spec_tests/server_selection_rtt_spec.rb +2 -0
  781. data/spec/spec_tests/server_selection_spec.rb +2 -0
  782. data/spec/spec_tests/transactions_api_spec.rb +5 -0
  783. data/spec/spec_tests/transactions_spec.rb +5 -0
  784. data/spec/spec_tests/uri_options_spec.rb +2 -0
  785. data/spec/stress/cleanup_spec.rb +43 -0
  786. data/spec/stress/connection_pool_stress_spec.rb +1 -5
  787. data/spec/stress/connection_pool_timing_spec.rb +3 -6
  788. data/spec/stress/fork_reconnect_stress_spec.rb +109 -0
  789. data/spec/support/authorization.rb +1 -11
  790. data/spec/support/aws_utils.rb +62 -0
  791. data/spec/support/aws_utils/base.rb +134 -0
  792. data/spec/support/aws_utils/inspector.rb +224 -0
  793. data/spec/support/aws_utils/orchestrator.rb +370 -0
  794. data/spec/support/aws_utils/provisioner.rb +360 -0
  795. data/spec/support/background_thread_registry.rb +6 -2
  796. data/spec/support/client_registry.rb +5 -24
  797. data/spec/support/cluster_config.rb +1 -0
  798. data/spec/support/common_shortcuts.rb +43 -0
  799. data/spec/support/constraints.rb +27 -7
  800. data/spec/support/crypt.rb +1 -1
  801. data/spec/support/event_subscriber.rb +94 -84
  802. data/spec/support/lite_constraints.rb +47 -0
  803. data/spec/support/shared/scram_conversation.rb +100 -0
  804. data/spec/support/shared/server_selector.rb +81 -1
  805. data/spec/support/shared/session.rb +29 -21
  806. data/spec/support/spec_config.rb +39 -9
  807. data/spec/support/spec_setup.rb +8 -4
  808. data/spec/support/utils.rb +115 -24
  809. metadata +1134 -744
  810. metadata.gz.sig +0 -0
  811. data/lib/mongo/server/connectable.rb +0 -107
  812. data/spec/integration/bulk_write_spec.rb +0 -19
  813. data/spec/integration/grid_fs_bucket_spec.rb +0 -48
  814. data/spec/integration/zlib_compression_spec.rb +0 -25
  815. data/spec/runners/change_streams.rb +0 -262
  816. data/spec/runners/change_streams/operation.rb +0 -89
  817. data/spec/spec_tests/data/sdam/sharded/ruby_discovered_single_mongos.yml +0 -27
@@ -0,0 +1,111 @@
1
+ # Copyright (C) 2020 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 Auth
17
+
18
+ # Defines common behavior around SASL conversations between
19
+ # the client and the server.
20
+ #
21
+ # @api private
22
+ class SaslConversationBase < ConversationBase
23
+
24
+ # The base client first message.
25
+ CLIENT_FIRST_MESSAGE = { saslStart: 1, autoAuthorize: 1 }.freeze
26
+
27
+ # The base client continue message.
28
+ CLIENT_CONTINUE_MESSAGE = { saslContinue: 1 }.freeze
29
+
30
+ # Start the SASL conversation. This returns the first message that
31
+ # needs to be sent to the server.
32
+ #
33
+ # @param [ Server::Connection ] connection The connection being authenticated.
34
+ #
35
+ # @return [ Protocol::Message ] The first SASL conversation message.
36
+ def start(connection)
37
+ selector = client_first_document
38
+ if connection && connection.features.op_msg_enabled?
39
+ selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
40
+ cluster_time = connection.mongos? && connection.cluster_time
41
+ selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
42
+ Protocol::Msg.new([], {}, selector)
43
+ else
44
+ Protocol::Query.new(
45
+ user.auth_source,
46
+ Database::COMMAND,
47
+ selector,
48
+ limit: -1,
49
+ )
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ # Gets the auth mechanism name for the conversation class.
56
+ #
57
+ # Example return: SCRAM-SHA-1.
58
+ #
59
+ # @return [ String ] Auth mechanism name.
60
+ def auth_mechanism_name
61
+ # self.class.name is e.g. Mongo::Auth::Scram256::Mechanism.
62
+ # We need Mongo::Auth::Scram::MECHANISM.
63
+ # Pull out the Scram256 part, get that class off of Auth,
64
+ # then get the value of MECHANISM constant in Scram256.
65
+ # With ActiveSupport, this method would be:
66
+ # self.class.module_parent.const_get(:MECHANISM)
67
+ parts = self.class.name.split('::')
68
+ parts.pop
69
+ Auth.const_get(parts.last).const_get(:MECHANISM)
70
+ end
71
+
72
+ def client_first_message_options
73
+ nil
74
+ end
75
+
76
+ def client_first_document
77
+ payload = client_first_payload
78
+ if Lint.enabled?
79
+ unless payload.is_a?(String)
80
+ raise Error::LintError, "Payload must be a string but is a #{payload.class}: #{payload}"
81
+ end
82
+ end
83
+ doc = CLIENT_FIRST_MESSAGE.merge(
84
+ mechanism: auth_mechanism_name,
85
+ payload: BSON::Binary.new(payload),
86
+ )
87
+ if options = client_first_message_options
88
+ # Short SCRAM conversation,
89
+ # https://jira.mongodb.org/browse/DRIVERS-707
90
+ doc[:options] = options
91
+ end
92
+ doc
93
+ end
94
+
95
+ # Helper method to validate that server nonce starts with the client
96
+ # nonce.
97
+ #
98
+ # Note that this class does not define the client_nonce or server_nonce
99
+ # attributes - derived classes must do so.
100
+ def validate_server_nonce!
101
+ if client_nonce.nil? || client_nonce.empty?
102
+ raise ArgumentError, 'Cannot validate server nonce when client nonce is nil or empty'
103
+ end
104
+
105
+ unless server_nonce.start_with?(client_nonce)
106
+ raise Error::InvalidNonce.new(client_nonce, server_nonce)
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2019 MongoDB Inc.
1
+ # Copyright (C) 2014-2020 MongoDB Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -12,73 +12,61 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require 'mongo/auth/scram/conversation'
16
-
17
15
  module Mongo
18
16
  module Auth
19
17
 
20
18
  # Defines behavior for SCRAM authentication.
21
19
  #
22
- # @since 2.0.0
23
20
  # @api private
24
- class SCRAM
21
+ class Scram < Base
25
22
 
26
- # The authentication mechanism string for SCRAM-SHA-1.
27
- #
28
- # @since 2.6.0
29
- SCRAM_SHA_1_MECHANISM = 'SCRAM-SHA-1'.freeze
23
+ # The authentication mechanism string.
24
+ MECHANISM = 'SCRAM-SHA-1'.freeze
30
25
 
31
- # The authentication mechanism string for SCRAM-SHA-256.
26
+ # Initializes the Scram authenticator.
32
27
  #
33
- # @since 2.6.0
34
- SCRAM_SHA_256_MECHANISM = 'SCRAM-SHA-256'.freeze
35
-
36
- # Map the user-specified authentication mechanism to the proper names of the mechanisms.
28
+ # @param [ Auth::User ] user The user to authenticate.
29
+ # @param [ Mongo::Connection ] connection The connection to authenticate over.
37
30
  #
38
- # @since 2.6.0
39
- MECHANISMS = {
40
- scram: SCRAM_SHA_1_MECHANISM,
41
- scram256: SCRAM_SHA_256_MECHANISM
42
- }.freeze
31
+ # @option opts [ String | nil ] speculative_auth_client_nonce The client
32
+ # nonce used in speculative auth on the specified connection that
33
+ # produced the specified speculative auth result.
34
+ # @option opts [ BSON::Document | nil ] speculative_auth_result The
35
+ # value of speculativeAuthenticate field of ismaster response of
36
+ # the handshake on the specified connection.
37
+ def initialize(user, connection, **opts)
38
+ super
39
+ @speculative_auth_client_nonce = opts[:speculative_auth_client_nonce]
40
+ @speculative_auth_result = opts[:speculative_auth_result]
41
+ end
43
42
 
44
- # @return [ Mongo::Auth::User ] The user to authenticate.
45
- attr_reader :user
43
+ # @return [ String | nil ] The client nonce used in speculative auth on
44
+ # the current connection.
45
+ attr_reader :speculative_auth_client_nonce
46
46
 
47
- # Instantiate a new authenticator.
48
- #
49
- # @example Create the authenticator.
50
- # Mongo::Auth::SCRAM.new(user)
51
- #
52
- # @param [ Mongo::Auth::User ] user The user to authenticate.
53
- #
54
- # @since 2.0.0
55
- def initialize(user)
56
- @user = user
47
+ # @return [ BSON::Document | nil ] The value of speculativeAuthenticate
48
+ # field of ismaster response of the handshake on the current connection.
49
+ attr_reader :speculative_auth_result
50
+
51
+ def conversation
52
+ @conversation ||= self.class.const_get(:Conversation).new(
53
+ user, connection, client_nonce: speculative_auth_client_nonce)
57
54
  end
58
55
 
59
- # Log the user in on the given connection.
60
- #
61
- # @example Log the user in.
62
- # user.login(connection)
63
- #
64
- # @param [ Mongo::Connection ] connection The connection to log into.
56
+ # Log the user in on the current connection.
65
57
  #
66
- # @return [ Protocol::Message ] The authentication response.
67
- #
68
- # @since 2.0.0
69
- def login(connection)
70
- mechanism = user.mechanism || :scram
71
- conversation = Conversation.new(user, mechanism)
72
- reply = connection.dispatch([ conversation.start(connection) ])
73
- connection.update_cluster_time(Operation::Result.new(reply))
74
- reply = connection.dispatch([ conversation.continue(reply, connection) ])
75
- connection.update_cluster_time(Operation::Result.new(reply))
76
- until reply.documents[0][Conversation::DONE]
77
- reply = connection.dispatch([ conversation.finalize(reply, connection) ])
78
- connection.update_cluster_time(Operation::Result.new(reply))
58
+ # @return [ BSON::Document ] The document of the authentication response.
59
+ def login
60
+ converse_multi_step(connection, conversation,
61
+ speculative_auth_result: speculative_auth_result,
62
+ ).tap do
63
+ unless conversation.server_verified?
64
+ raise Error::MissingScramServerSignature
65
+ end
79
66
  end
80
- reply
81
67
  end
82
68
  end
83
69
  end
84
70
  end
71
+
72
+ require 'mongo/auth/scram/conversation'
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2019 MongoDB Inc.
1
+ # Copyright (C) 2014-2020 MongoDB Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -14,337 +14,16 @@
14
14
 
15
15
  module Mongo
16
16
  module Auth
17
- class SCRAM
17
+ class Scram
18
18
 
19
- # Defines behavior around a single SCRAM-SHA-1/256 conversation between
19
+ # Defines behavior around a single SCRAM-SHA-1 conversation between
20
20
  # the client and server.
21
21
  #
22
- # @since 2.0.0
23
22
  # @api private
24
- class Conversation
25
-
26
- # The base client continue message.
27
- #
28
- # @since 2.0.0
29
- CLIENT_CONTINUE_MESSAGE = { saslContinue: 1 }.freeze
30
-
31
- # The base client first message.
32
- #
33
- # @since 2.0.0
34
- CLIENT_FIRST_MESSAGE = { saslStart: 1, autoAuthorize: 1 }.freeze
35
-
36
- # The client key string.
37
- #
38
- # @since 2.0.0
39
- # @deprecated
40
- CLIENT_KEY = 'Client Key'.freeze
41
-
42
- # The key for the done field in the responses.
43
- #
44
- # @since 2.0.0
45
- DONE = 'done'.freeze
46
-
47
- # The conversation id field.
48
- #
49
- # @since 2.0.0
50
- ID = 'conversationId'.freeze
51
-
52
- # The iterations key in the responses.
53
- #
54
- # @since 2.0.0
55
- ITERATIONS = /i=(\d+)/.freeze
56
-
57
- # The minimum iteration count for SCRAM-SHA-256.
58
- #
59
- # @api private
60
- #
61
- # @since 2.6.0
62
- MIN_ITER_COUNT = 4096
63
-
64
- # The payload field.
65
- #
66
- # @since 2.0.0
67
- PAYLOAD = 'payload'.freeze
68
-
69
- # The rnonce key in the responses.
70
- #
71
- # @since 2.0.0
72
- RNONCE = /r=([^,]*)/.freeze
73
-
74
- # The salt key in the responses.
75
- #
76
- # @since 2.0.0
77
- SALT = /s=([^,]*)/.freeze
78
-
79
- # The server key string.
80
- #
81
- # @since 2.0.0
82
- # @deprecated
83
- SERVER_KEY = 'Server Key'.freeze
84
-
85
- # The server signature verifier in the response.
86
- #
87
- # @since 2.0.0
88
- VERIFIER = /v=([^,]*)/.freeze
89
-
90
- # @return [ String ] nonce The initial user nonce.
91
- attr_reader :nonce
92
-
93
- # @return [ Protocol::Message ] reply The current reply in the
94
- # conversation.
95
- attr_reader :reply
96
-
97
- # @return [ User ] user The user for the conversation.
98
- attr_reader :user
99
-
100
- # Continue the SCRAM conversation. This sends the client final message
101
- # to the server after setting the reply from the previous server
102
- # communication.
103
- #
104
- # @example Continue the conversation.
105
- # conversation.continue(reply)
106
- #
107
- # @param [ Protocol::Message ] reply The reply of the previous
108
- # message.
109
- # @param [ Server::Connection ] connection The connection being
110
- # authenticated.
111
- #
112
- # @return [ Protocol::Message ] The next message to send.
113
- #
114
- # @since 2.0.0
115
- def continue(reply, connection)
116
- validate_first_message!(reply, connection.server)
117
-
118
- if connection && connection.features.op_msg_enabled?
119
- selector = CLIENT_CONTINUE_MESSAGE.merge(
120
- payload: client_final_message,
121
- conversationId: id,
122
- )
123
- selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
124
- cluster_time = connection.mongos? && connection.cluster_time
125
- selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
126
- Protocol::Msg.new([], {}, selector)
127
- else
128
- Protocol::Query.new(
129
- user.auth_source,
130
- Database::COMMAND,
131
- CLIENT_CONTINUE_MESSAGE.merge(
132
- payload: client_final_message,
133
- conversationId: id,
134
- ),
135
- limit: -1,
136
- )
137
- end
138
- end
139
-
140
- # Finalize the SCRAM conversation. This is meant to be iterated until
141
- # the provided reply indicates the conversation is finished.
142
- #
143
- # @param [ Protocol::Message ] reply The reply of the previous
144
- # message.
145
- # @param [ Server::Connection ] connection The connection being authenticated.
146
- #
147
- # @return [ Protocol::Query ] The next message to send.
148
- #
149
- # @since 2.0.0
150
- def finalize(reply, connection)
151
- validate_final_message!(reply, connection.server)
152
- if connection && connection.features.op_msg_enabled?
153
- selector = CLIENT_CONTINUE_MESSAGE.merge(
154
- payload: client_empty_message,
155
- conversationId: id,
156
- )
157
- selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
158
- cluster_time = connection.mongos? && connection.cluster_time
159
- selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
160
- Protocol::Msg.new([], {}, selector)
161
- else
162
- Protocol::Query.new(
163
- user.auth_source,
164
- Database::COMMAND,
165
- CLIENT_CONTINUE_MESSAGE.merge(
166
- payload: client_empty_message,
167
- conversationId: id,
168
- ),
169
- limit: -1,
170
- )
171
- end
172
- end
173
-
174
- # Start the SCRAM conversation. This returns the first message that
175
- # needs to be sent to the server.
176
- #
177
- # @param [ Server::Connection ] connection The connection being authenticated.
178
- #
179
- # @return [ Protocol::Query ] The first SCRAM conversation message.
180
- #
181
- # @since 2.0.0
182
- def start(connection)
183
- if connection && connection.features.op_msg_enabled?
184
- selector = CLIENT_FIRST_MESSAGE.merge(
185
- payload: client_first_message, mechanism: full_mechanism)
186
- selector[Protocol::Msg::DATABASE_IDENTIFIER] = user.auth_source
187
- cluster_time = connection.mongos? && connection.cluster_time
188
- selector[Operation::CLUSTER_TIME] = cluster_time if cluster_time
189
- Protocol::Msg.new([], {}, selector)
190
- else
191
- Protocol::Query.new(
192
- user.auth_source,
193
- Database::COMMAND,
194
- CLIENT_FIRST_MESSAGE.merge(
195
- payload: client_first_message, mechanism: full_mechanism),
196
- limit: -1,
197
- )
198
- end
199
- end
200
-
201
- def full_mechanism
202
- MECHANISMS[@mechanism]
203
- end
204
-
205
- # Get the id of the conversation.
206
- #
207
- # @example Get the id of the conversation.
208
- # conversation.id
209
- #
210
- # @return [ Integer ] The conversation id.
211
- #
212
- # @since 2.0.0
213
- def id
214
- reply.documents[0][ID]
215
- end
216
-
217
- # Create the new conversation.
218
- #
219
- # @example Create the new conversation.
220
- # Conversation.new(user, mechanism)
221
- #
222
- # @param [ Auth::User ] user The user to converse about.
223
- # @param [ Symbol ] mechanism Authentication mechanism.
224
- #
225
- # @since 2.0.0
226
- def initialize(user, mechanism)
227
- unless [:scram, :scram256].include?(mechanism)
228
- raise InvalidMechanism.new(mechanism)
229
- end
230
-
231
- @user = user
232
- @nonce = SecureRandom.base64
233
- @mechanism = mechanism
234
- end
23
+ class Conversation < ScramConversationBase
235
24
 
236
25
  private
237
26
 
238
- # Auth message algorithm implementation.
239
- #
240
- # @api private
241
- #
242
- # @see http://tools.ietf.org/html/rfc5802#section-3
243
- #
244
- # @since 2.0.0
245
- def auth_message
246
- @auth_message ||= "#{first_bare},#{reply.documents[0][PAYLOAD].data},#{without_proof}"
247
- end
248
-
249
- # Get the empty client message.
250
- #
251
- # @api private
252
- #
253
- # @since 2.0.0
254
- def client_empty_message
255
- BSON::Binary.new('')
256
- end
257
-
258
- # Get the final client message.
259
- #
260
- # @api private
261
- #
262
- # @see http://tools.ietf.org/html/rfc5802#section-3
263
- #
264
- # @since 2.0.0
265
- def client_final_message
266
- BSON::Binary.new("#{without_proof},p=#{client_final}")
267
- end
268
-
269
- # Get the client first message
270
- #
271
- # @api private
272
- #
273
- # @see http://tools.ietf.org/html/rfc5802#section-3
274
- #
275
- # @since 2.0.0
276
- def client_first_message
277
- BSON::Binary.new("n,,#{first_bare}")
278
- end
279
-
280
- # Client final implementation.
281
- #
282
- # @api private
283
- #
284
- # @see http://tools.ietf.org/html/rfc5802#section-7
285
- #
286
- # @since 2.0.0
287
- def client_final
288
- @client_final ||= client_proof(client_key, client_signature(stored_key(client_key), auth_message))
289
- end
290
-
291
- # Client key algorithm implementation.
292
- #
293
- # @api private
294
- #
295
- # @see http://tools.ietf.org/html/rfc5802#section-3
296
- #
297
- # @since 2.0.0
298
- def client_key
299
- @client_key ||= CredentialCache.cache(cache_key(:client_key)) do
300
- hmac(salted_password, 'Client Key')
301
- end
302
- end
303
-
304
- # Client proof algorithm implementation.
305
- #
306
- # @api private
307
- #
308
- # @see http://tools.ietf.org/html/rfc5802#section-3
309
- #
310
- # @since 2.0.0
311
- def client_proof(key, signature)
312
- @client_proof ||= Base64.strict_encode64(xor(key, signature))
313
- end
314
-
315
- # Client signature algorithm implementation.
316
- #
317
- # @api private
318
- #
319
- # @see http://tools.ietf.org/html/rfc5802#section-3
320
- #
321
- # @since 2.0.0
322
- def client_signature(key, message)
323
- @client_signature ||= hmac(key, message)
324
- end
325
-
326
- # First bare implementation.
327
- #
328
- # @api private
329
- #
330
- # @see http://tools.ietf.org/html/rfc5802#section-7
331
- #
332
- # @since 2.0.0
333
- def first_bare
334
- @first_bare ||= "n=#{user.encoded_name},r=#{nonce}"
335
- end
336
-
337
- # H algorithm implementation.
338
- #
339
- # @api private
340
- #
341
- # @see http://tools.ietf.org/html/rfc5802#section-2.2
342
- #
343
- # @since 2.0.0
344
- def h(string)
345
- digest.digest(string)
346
- end
347
-
348
27
  # HI algorithm implementation.
349
28
  #
350
29
  # @api private
@@ -353,80 +32,12 @@ module Mongo
353
32
  #
354
33
  # @since 2.0.0
355
34
  def hi(data)
356
- case @mechanism
357
- when :scram256
358
- OpenSSL::PKCS5.pbkdf2_hmac(
359
- data,
360
- Base64.strict_decode64(salt),
361
- iterations,
362
- digest.size,
363
- digest
364
- )
365
- else
366
- OpenSSL::PKCS5.pbkdf2_hmac_sha1(
367
- data,
368
- Base64.strict_decode64(salt),
369
- iterations,
370
- digest.size
371
- )
372
- end
373
- end
374
-
375
- # HMAC algorithm implementation.
376
- #
377
- # @api private
378
- #
379
- # @see http://tools.ietf.org/html/rfc5802#section-2.2
380
- #
381
- # @since 2.0.0
382
- def hmac(data, key)
383
- OpenSSL::HMAC.digest(digest, data, key)
384
- end
385
-
386
- # Get the iterations from the server response.
387
- #
388
- # @api private
389
- #
390
- # @since 2.0.0
391
- def iterations
392
- @iterations ||= payload_data.match(ITERATIONS)[1].to_i.tap do |i|
393
- if i < MIN_ITER_COUNT
394
- raise Error::InsufficientIterationCount.new(
395
- Error::InsufficientIterationCount.message(MIN_ITER_COUNT, i))
396
- end
397
- end
398
- end
399
-
400
- # Get the data from the returned payload.
401
- #
402
- # @api private
403
- #
404
- # @since 2.0.0
405
- def payload_data
406
- reply.documents[0][PAYLOAD].data
407
- end
408
-
409
- # Get the server nonce from the payload.
410
- #
411
- # @api private
412
- #
413
- # @since 2.0.0
414
- def rnonce
415
- @rnonce ||= payload_data.match(RNONCE)[1]
416
- end
417
-
418
- # Gets the salt from the server response.
419
- #
420
- # @api private
421
- #
422
- # @since 2.0.0
423
- def salt
424
- @salt ||= payload_data.match(SALT)[1]
425
- end
426
-
427
- # @api private
428
- def cache_key(*extra)
429
- [user.password, salt, iterations, @mechanism] + extra
35
+ OpenSSL::PKCS5.pbkdf2_hmac_sha1(
36
+ data,
37
+ salt,
38
+ iterations,
39
+ digest.size,
40
+ )
430
41
  end
431
42
 
432
43
  # Salted password algorithm implementation.
@@ -438,117 +49,12 @@ module Mongo
438
49
  # @since 2.0.0
439
50
  def salted_password
440
51
  @salted_password ||= CredentialCache.cache(cache_key(:salted_password)) do
441
- case @mechanism
442
- when :scram256
443
- hi(user.sasl_prepped_password)
444
- else
445
- hi(user.hashed_password)
446
- end
447
- end
448
- end
449
-
450
- # Server key algorithm implementation.
451
- #
452
- # @api private
453
- #
454
- # @see http://tools.ietf.org/html/rfc5802#section-3
455
- #
456
- # @since 2.0.0
457
- def server_key
458
- @server_key ||= CredentialCache.cache(cache_key(:server_key)) do
459
- hmac(salted_password, 'Server Key')
460
- end
461
- end
462
-
463
- # Server signature algorithm implementation.
464
- #
465
- # @api private
466
- #
467
- # @see http://tools.ietf.org/html/rfc5802#section-3
468
- #
469
- # @since 2.0.0
470
- def server_signature
471
- @server_signature ||= Base64.strict_encode64(hmac(server_key, auth_message))
472
- end
473
-
474
- # Stored key algorithm implementation.
475
- #
476
- # @api private
477
- #
478
- # @see http://tools.ietf.org/html/rfc5802#section-3
479
- #
480
- # @since 2.0.0
481
- def stored_key(key)
482
- h(key)
483
- end
484
-
485
- # Get the verifier token from the server response.
486
- #
487
- # @api private
488
- #
489
- # @since 2.0.0
490
- def verifier
491
- @verifier ||= payload_data.match(VERIFIER)[1]
492
- end
493
-
494
- # Get the without proof message.
495
- #
496
- # @api private
497
- #
498
- # @see http://tools.ietf.org/html/rfc5802#section-7
499
- #
500
- # @since 2.0.0
501
- def without_proof
502
- @without_proof ||= "c=biws,r=#{rnonce}"
503
- end
504
-
505
- # XOR operation for two strings.
506
- #
507
- # @api private
508
- #
509
- # @since 2.0.0
510
- def xor(first, second)
511
- first.bytes.zip(second.bytes).map{ |(a,b)| (a ^ b).chr }.join('')
512
- end
513
-
514
- def compare_digest(a, b)
515
- check = a.bytesize ^ b.bytesize
516
- a.bytes.zip(b.bytes){ |x, y| check |= x ^ y.to_i }
517
- check == 0
518
- end
519
-
520
- def validate_final_message!(reply, server)
521
- validate!(reply, server)
522
- unless compare_digest(verifier, server_signature)
523
- raise Error::InvalidSignature.new(verifier, server_signature)
52
+ hi(user.hashed_password)
524
53
  end
525
54
  end
526
55
 
527
- def validate_first_message!(reply, server)
528
- validate!(reply, server)
529
- raise Error::InvalidNonce.new(nonce, rnonce) unless rnonce.start_with?(nonce)
530
- end
531
-
532
- def validate!(reply, server)
533
- if reply.documents[0][Operation::Result::OK] != 1
534
- raise Unauthorized.new(user,
535
- used_mechanism: full_mechanism,
536
- message: reply.documents[0]['errmsg'],
537
- server: server,
538
- )
539
- end
540
- @reply = reply
541
- end
542
-
543
- private
544
-
545
56
  def digest
546
- @digest ||= case @mechanism
547
- when :scram256
548
- OpenSSL::Digest::SHA256.new.freeze
549
- else
550
- OpenSSL::Digest::SHA1.new.freeze
551
- end
57
+ @digest ||= OpenSSL::Digest::SHA1.new.freeze
552
58
  end
553
59
  end
554
60
  end