mongo 2.17.3 → 2.18.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 (622) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +21 -37
  4. data/lib/mongo/auth/base.rb +8 -1
  5. data/lib/mongo/auth.rb +12 -1
  6. data/lib/mongo/bulk_write/result.rb +10 -1
  7. data/lib/mongo/bulk_write/result_combiner.rb +2 -4
  8. data/lib/mongo/bulk_write.rb +108 -28
  9. data/lib/mongo/client.rb +114 -12
  10. data/lib/mongo/client_encryption.rb +30 -9
  11. data/lib/mongo/cluster/reapers/cursor_reaper.rb +11 -1
  12. data/lib/mongo/cluster.rb +20 -24
  13. data/lib/mongo/collection/helpers.rb +43 -0
  14. data/lib/mongo/collection/queryable_encryption.rb +122 -0
  15. data/lib/mongo/collection/view/aggregation.rb +19 -16
  16. data/lib/mongo/collection/view/change_stream.rb +56 -23
  17. data/lib/mongo/collection/view/explainable.rb +1 -1
  18. data/lib/mongo/collection/view/iterable.rb +2 -3
  19. data/lib/mongo/collection/view/map_reduce.rb +18 -9
  20. data/lib/mongo/collection/view/readable.rb +19 -23
  21. data/lib/mongo/collection/view/writable.rb +133 -40
  22. data/lib/mongo/collection.rb +108 -48
  23. data/lib/mongo/config/options.rb +62 -0
  24. data/lib/mongo/config/validators/option.rb +26 -0
  25. data/lib/mongo/config.rb +31 -0
  26. data/lib/mongo/crypt/auto_encrypter.rb +79 -6
  27. data/lib/mongo/crypt/binding.rb +395 -143
  28. data/lib/mongo/crypt/context.rb +5 -2
  29. data/lib/mongo/crypt/data_key_context.rb +7 -104
  30. data/lib/mongo/crypt/encryption_io.rb +28 -60
  31. data/lib/mongo/crypt/explicit_encrypter.rb +27 -25
  32. data/lib/mongo/crypt/explicit_encryption_context.rb +31 -3
  33. data/lib/mongo/crypt/handle.rb +102 -79
  34. data/lib/mongo/crypt/hooks.rb +25 -2
  35. data/lib/mongo/crypt/kms/aws.rb +128 -0
  36. data/lib/mongo/crypt/kms/azure.rb +136 -0
  37. data/lib/mongo/crypt/kms/credentials.rb +81 -0
  38. data/lib/mongo/crypt/kms/gcp.rb +182 -0
  39. data/lib/mongo/crypt/kms/kmip.rb +110 -0
  40. data/lib/mongo/crypt/kms/local.rb +74 -0
  41. data/lib/mongo/crypt/kms/master_key_document.rb +65 -0
  42. data/lib/mongo/crypt/kms.rb +117 -0
  43. data/lib/mongo/crypt.rb +1 -0
  44. data/lib/mongo/cursor/kill_spec.rb +27 -6
  45. data/lib/mongo/cursor.rb +21 -16
  46. data/lib/mongo/database/view.rb +6 -3
  47. data/lib/mongo/database.rb +73 -12
  48. data/lib/mongo/dbref.rb +1 -105
  49. data/lib/mongo/error/bulk_write_error.rb +31 -4
  50. data/lib/mongo/error/invalid_config_option.rb +20 -0
  51. data/lib/mongo/error/invalid_replacement_document.rb +27 -9
  52. data/lib/mongo/error/invalid_update_document.rb +27 -7
  53. data/lib/mongo/error/labelable.rb +72 -0
  54. data/lib/mongo/error/missing_connection.rb +25 -0
  55. data/lib/mongo/error/notable.rb +7 -0
  56. data/lib/mongo/error/operation_failure.rb +34 -86
  57. data/lib/mongo/error/read_write_retryable.rb +108 -0
  58. data/lib/mongo/{operation/kill_cursors/legacy.rb → error/session_not_materialized.rb} +7 -19
  59. data/lib/mongo/error.rb +5 -37
  60. data/lib/mongo/index/view.rb +22 -7
  61. data/lib/mongo/monitoring/event/command_failed.rb +8 -2
  62. data/lib/mongo/monitoring/event/command_started.rb +1 -1
  63. data/lib/mongo/monitoring/event/command_succeeded.rb +9 -2
  64. data/lib/mongo/monitoring/publishable.rb +9 -5
  65. data/lib/mongo/operation/collections_info/result.rb +5 -2
  66. data/lib/mongo/operation/command/op_msg.rb +6 -0
  67. data/lib/mongo/operation/context.rb +24 -6
  68. data/lib/mongo/operation/count/op_msg.rb +4 -1
  69. data/lib/mongo/operation/create/op_msg.rb +16 -1
  70. data/lib/mongo/operation/create_index/op_msg.rb +2 -1
  71. data/lib/mongo/operation/delete/op_msg.rb +1 -0
  72. data/lib/mongo/operation/delete.rb +0 -1
  73. data/lib/mongo/operation/drop_index/op_msg.rb +5 -1
  74. data/lib/mongo/operation/get_more/command_builder.rb +5 -1
  75. data/lib/mongo/operation/insert/bulk_result.rb +5 -1
  76. data/lib/mongo/operation/insert/command.rb +0 -4
  77. data/lib/mongo/operation/insert/op_msg.rb +6 -3
  78. data/lib/mongo/operation/insert/result.rb +6 -3
  79. data/lib/mongo/operation/insert.rb +0 -1
  80. data/lib/mongo/operation/kill_cursors.rb +0 -1
  81. data/lib/mongo/operation/list_collections/op_msg.rb +4 -1
  82. data/lib/mongo/operation/map_reduce/result.rb +16 -0
  83. data/lib/mongo/operation/result.rb +21 -5
  84. data/lib/mongo/operation/shared/executable.rb +21 -6
  85. data/lib/mongo/operation/shared/polymorphic_operation.rb +15 -3
  86. data/lib/mongo/operation/shared/response_handling.rb +6 -5
  87. data/lib/mongo/operation/shared/sessions_supported.rb +3 -7
  88. data/lib/mongo/operation/shared/write.rb +18 -12
  89. data/lib/mongo/operation/update/op_msg.rb +2 -1
  90. data/lib/mongo/operation/update.rb +0 -1
  91. data/lib/mongo/protocol/caching_hash.rb +69 -0
  92. data/lib/mongo/protocol/msg.rb +37 -1
  93. data/lib/mongo/protocol.rb +1 -0
  94. data/lib/mongo/query_cache.rb +15 -0
  95. data/lib/mongo/retryable.rb +78 -30
  96. data/lib/mongo/server/connection.rb +33 -0
  97. data/lib/mongo/server/connection_base.rb +2 -0
  98. data/lib/mongo/server/connection_common.rb +4 -1
  99. data/lib/mongo/server/connection_pool.rb +69 -42
  100. data/lib/mongo/server/description/features.rb +3 -1
  101. data/lib/mongo/server/description.rb +7 -2
  102. data/lib/mongo/server/monitor/connection.rb +5 -10
  103. data/lib/mongo/server/monitor.rb +21 -13
  104. data/lib/mongo/server/push_monitor.rb +9 -3
  105. data/lib/mongo/server.rb +9 -5
  106. data/lib/mongo/session/session_pool.rb +8 -0
  107. data/lib/mongo/session.rb +111 -35
  108. data/lib/mongo/socket/ocsp_verifier.rb +4 -5
  109. data/lib/mongo/socket/tcp.rb +3 -0
  110. data/lib/mongo/srv/resolver.rb +24 -3
  111. data/lib/mongo/uri/options_mapper.rb +2 -0
  112. data/lib/mongo/uri/srv_protocol.rb +1 -1
  113. data/lib/mongo/uri.rb +20 -0
  114. data/lib/mongo/version.rb +1 -1
  115. data/lib/mongo.rb +20 -0
  116. data/mongo.gemspec +10 -4
  117. data/spec/README.md +5 -5
  118. data/spec/integration/aws_lambda_examples_spec.rb +68 -0
  119. data/spec/integration/bulk_write_error_message_spec.rb +32 -0
  120. data/spec/integration/bulk_write_spec.rb +0 -16
  121. data/spec/integration/change_stream_spec.rb +6 -5
  122. data/spec/integration/client_construction_spec.rb +1 -1
  123. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +9 -9
  124. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +18 -19
  125. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +0 -1
  126. data/spec/integration/client_side_encryption/auto_encryption_reconnect_spec.rb +31 -0
  127. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +108 -1
  128. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +2 -2
  129. data/spec/integration/client_side_encryption/bypass_mongocryptd_spawn_spec.rb +2 -2
  130. data/spec/integration/client_side_encryption/client_close_spec.rb +1 -1
  131. data/spec/integration/client_side_encryption/corpus_spec.rb +64 -35
  132. data/spec/integration/client_side_encryption/custom_endpoint_spec.rb +39 -42
  133. data/spec/integration/client_side_encryption/data_key_spec.rb +97 -7
  134. data/spec/integration/client_side_encryption/explicit_encryption_spec.rb +59 -0
  135. data/spec/integration/client_side_encryption/explicit_queryable_encryption_spec.rb +147 -0
  136. data/spec/integration/client_side_encryption/external_key_vault_spec.rb +6 -6
  137. data/spec/integration/client_side_encryption/kms_tls_options_spec.rb +394 -0
  138. data/spec/integration/client_side_encryption/kms_tls_spec.rb +92 -0
  139. data/spec/integration/client_side_encryption/queryable_encryption_examples_spec.rb +111 -0
  140. data/spec/integration/client_side_encryption/views_spec.rb +1 -1
  141. data/spec/integration/client_update_spec.rb +2 -2
  142. data/spec/integration/crud_spec.rb +12 -0
  143. data/spec/integration/cursor_pinning_spec.rb +3 -3
  144. data/spec/integration/fork_reconnect_spec.rb +15 -8
  145. data/spec/integration/grid_fs_bucket_spec.rb +3 -3
  146. data/spec/integration/ocsp_verifier_spec.rb +1 -0
  147. data/spec/integration/query_cache_spec.rb +34 -30
  148. data/spec/integration/retryable_writes/retryable_writes_36_and_older_spec.rb +1 -1
  149. data/spec/integration/sdam_events_spec.rb +0 -40
  150. data/spec/integration/server_monitor_spec.rb +2 -1
  151. data/spec/integration/size_limit_spec.rb +4 -1
  152. data/spec/integration/snapshot_query_examples_spec.rb +127 -0
  153. data/spec/integration/srv_monitoring_spec.rb +37 -0
  154. data/spec/integration/step_down_spec.rb +20 -4
  155. data/spec/integration/transaction_pinning_spec.rb +2 -2
  156. data/spec/integration/versioned_api_examples_spec.rb +37 -31
  157. data/spec/lite_spec_helper.rb +14 -5
  158. data/spec/mongo/address/ipv6_spec.rb +7 -0
  159. data/spec/mongo/address_spec.rb +7 -0
  160. data/spec/mongo/auth/scram/conversation_spec.rb +23 -23
  161. data/spec/mongo/auth/scram256/conversation_spec.rb +20 -20
  162. data/spec/mongo/auth/scram_negotiation_spec.rb +1 -0
  163. data/spec/mongo/bulk_write/result_spec.rb +15 -1
  164. data/spec/mongo/bulk_write_spec.rb +128 -20
  165. data/spec/mongo/client_construction_spec.rb +141 -7
  166. data/spec/mongo/client_encryption_spec.rb +11 -11
  167. data/spec/mongo/client_spec.rb +297 -1
  168. data/spec/mongo/cluster/cursor_reaper_spec.rb +21 -3
  169. data/spec/mongo/cluster_spec.rb +0 -44
  170. data/spec/mongo/collection/view/aggregation_spec.rb +2 -2
  171. data/spec/mongo/collection/view/change_stream_spec.rb +2 -2
  172. data/spec/mongo/collection/view/readable_spec.rb +35 -56
  173. data/spec/mongo/collection/view/writable_spec.rb +144 -32
  174. data/spec/mongo/collection_crud_spec.rb +63 -13
  175. data/spec/mongo/config/options_spec.rb +75 -0
  176. data/spec/mongo/config_spec.rb +73 -0
  177. data/spec/mongo/crypt/auto_decryption_context_spec.rb +17 -1
  178. data/spec/mongo/crypt/auto_encrypter_spec.rb +106 -0
  179. data/spec/mongo/crypt/auto_encryption_context_spec.rb +17 -1
  180. data/spec/mongo/crypt/binding/context_spec.rb +99 -17
  181. data/spec/mongo/crypt/binding/mongocrypt_spec.rb +17 -46
  182. data/spec/mongo/crypt/binding/version_spec.rb +25 -0
  183. data/spec/mongo/crypt/binding_unloaded_spec.rb +14 -0
  184. data/spec/mongo/crypt/data_key_context_spec.rb +42 -114
  185. data/spec/mongo/crypt/encryption_io_spec.rb +2 -0
  186. data/spec/mongo/crypt/explicit_decryption_context_spec.rb +32 -1
  187. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +89 -1
  188. data/spec/mongo/crypt/handle_spec.rb +47 -169
  189. data/spec/mongo/crypt/hooks_spec.rb +30 -0
  190. data/spec/mongo/crypt/kms/credentials_spec.rb +404 -0
  191. data/spec/mongo/crypt/kms_spec.rb +59 -0
  192. data/spec/mongo/cursor_spec.rb +37 -51
  193. data/spec/mongo/database_spec.rb +66 -1
  194. data/spec/mongo/error/operation_failure_heavy_spec.rb +49 -0
  195. data/spec/mongo/index/view_spec.rb +69 -0
  196. data/spec/mongo/operation/create/op_msg_spec.rb +286 -0
  197. data/spec/mongo/operation/delete/op_msg_spec.rb +13 -4
  198. data/spec/mongo/operation/delete_spec.rb +0 -30
  199. data/spec/mongo/operation/insert/op_msg_spec.rb +18 -10
  200. data/spec/mongo/operation/insert_spec.rb +0 -32
  201. data/spec/mongo/operation/result_spec.rb +20 -0
  202. data/spec/mongo/operation/update/op_msg_spec.rb +13 -4
  203. data/spec/mongo/operation/update_spec.rb +0 -29
  204. data/spec/mongo/protocol/caching_hash_spec.rb +82 -0
  205. data/spec/mongo/protocol/msg_spec.rb +41 -0
  206. data/spec/mongo/query_cache_spec.rb +1 -0
  207. data/spec/mongo/retryable_spec.rb +32 -3
  208. data/spec/mongo/server/connection_auth_spec.rb +3 -1
  209. data/spec/mongo/server/connection_common_spec.rb +13 -1
  210. data/spec/mongo/server/connection_pool_spec.rb +94 -49
  211. data/spec/mongo/server/connection_spec.rb +50 -159
  212. data/spec/mongo/server/description/features_spec.rb +24 -0
  213. data/spec/mongo/server/push_monitor_spec.rb +2 -8
  214. data/spec/mongo/session_spec.rb +26 -6
  215. data/spec/mongo/session_transaction_spec.rb +2 -1
  216. data/spec/mongo/socket/ssl_spec.rb +15 -4
  217. data/spec/mongo/uri/srv_protocol_spec.rb +101 -2
  218. data/spec/mongo/uri_spec.rb +25 -0
  219. data/spec/runners/connection_string.rb +8 -0
  220. data/spec/runners/crud/operation.rb +12 -3
  221. data/spec/runners/crud/requirement.rb +3 -3
  222. data/spec/runners/crud/spec.rb +5 -0
  223. data/spec/runners/crud/verifier.rb +6 -0
  224. data/spec/runners/transactions/test.rb +33 -14
  225. data/spec/runners/transactions.rb +9 -6
  226. data/spec/runners/unified/assertions.rb +59 -10
  227. data/spec/runners/unified/change_stream_operations.rb +9 -0
  228. data/spec/runners/unified/crud_operations.rb +50 -2
  229. data/spec/runners/unified/ddl_operations.rb +20 -0
  230. data/spec/runners/unified/error.rb +2 -1
  231. data/spec/runners/unified/support_operations.rb +5 -2
  232. data/spec/runners/unified/test.rb +19 -4
  233. data/spec/runners/unified.rb +9 -2
  234. data/spec/shared/lib/mrss/constraints.rb +10 -17
  235. data/spec/shared/lib/mrss/docker_runner.rb +21 -3
  236. data/spec/shared/lib/mrss/lite_constraints.rb +32 -1
  237. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  238. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  239. data/spec/shared/share/Dockerfile.erb +56 -54
  240. data/spec/shared/shlib/config.sh +27 -0
  241. data/spec/shared/shlib/distro.sh +2 -1
  242. data/spec/shared/shlib/server.sh +46 -21
  243. data/spec/shared/shlib/set_env.sh +40 -5
  244. data/spec/spec_helper.rb +0 -1
  245. data/spec/spec_tests/crud_spec.rb +0 -10
  246. data/spec/spec_tests/data/change_streams_unified/change-streams-errors.yml +124 -0
  247. data/spec/spec_tests/data/change_streams_unified/change-streams-pre_and_post_images.yml +351 -0
  248. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-allowlist.yml +1171 -0
  249. data/spec/spec_tests/data/change_streams_unified/change-streams-resume-errorLabels.yml +1068 -0
  250. data/spec/spec_tests/data/change_streams_unified/change-streams.yml +859 -4
  251. data/spec/spec_tests/data/client_side_encryption/aggregate.yml +3 -17
  252. data/spec/spec_tests/data/client_side_encryption/azureKMS.yml +46 -0
  253. data/spec/spec_tests/data/client_side_encryption/badQueries.yml +12 -2
  254. data/spec/spec_tests/data/client_side_encryption/basic.yml +3 -17
  255. data/spec/spec_tests/data/client_side_encryption/bulk.yml +1 -8
  256. data/spec/spec_tests/data/client_side_encryption/bypassAutoEncryption.yml +2 -2
  257. data/spec/spec_tests/data/client_side_encryption/count.yml +1 -8
  258. data/spec/spec_tests/data/client_side_encryption/countDocuments.yml +1 -8
  259. data/spec/spec_tests/data/client_side_encryption/delete.yml +2 -16
  260. data/spec/spec_tests/data/client_side_encryption/distinct.yml +1 -8
  261. data/spec/spec_tests/data/client_side_encryption/explain.yml +1 -8
  262. data/spec/spec_tests/data/client_side_encryption/find.yml +2 -16
  263. data/spec/spec_tests/data/client_side_encryption/findOneAndDelete.yml +1 -8
  264. data/spec/spec_tests/data/client_side_encryption/findOneAndReplace.yml +1 -8
  265. data/spec/spec_tests/data/client_side_encryption/findOneAndUpdate.yml +1 -8
  266. data/spec/spec_tests/data/client_side_encryption/fle2-BypassQueryAnalysis.yml +101 -0
  267. data/spec/spec_tests/data/client_side_encryption/fle2-Compact.yml +80 -0
  268. data/spec/spec_tests/data/client_side_encryption/fle2-CreateCollection.yml +1263 -0
  269. data/spec/spec_tests/data/client_side_encryption/fle2-DecryptExistingData.yml +64 -0
  270. data/spec/spec_tests/data/client_side_encryption/fle2-Delete.yml +107 -0
  271. data/spec/spec_tests/data/client_side_encryption/fle2-EncryptedFields-vs-EncryptedFieldsMap.yml +80 -0
  272. data/spec/spec_tests/data/client_side_encryption/fle2-EncryptedFields-vs-jsonSchema.yml +90 -0
  273. data/spec/spec_tests/data/client_side_encryption/fle2-EncryptedFieldsMap-defaults.yml +57 -0
  274. data/spec/spec_tests/data/client_side_encryption/fle2-FindOneAndUpdate.yml +213 -0
  275. data/spec/spec_tests/data/client_side_encryption/fle2-InsertFind-Indexed.yml +86 -0
  276. data/spec/spec_tests/data/client_side_encryption/fle2-InsertFind-Unindexed.yml +83 -0
  277. data/spec/spec_tests/data/client_side_encryption/fle2-MissingKey.yml +41 -0
  278. data/spec/spec_tests/data/client_side_encryption/fle2-NoEncryption.yml +42 -0
  279. data/spec/spec_tests/data/client_side_encryption/fle2-Update.yml +221 -0
  280. data/spec/spec_tests/data/client_side_encryption/fle2-validatorAndPartialFieldExpression.yml +168 -0
  281. data/spec/spec_tests/data/client_side_encryption/gcpKMS.yml +46 -0
  282. data/spec/spec_tests/data/client_side_encryption/getMore.yml +1 -8
  283. data/spec/spec_tests/data/client_side_encryption/insert.yml +2 -16
  284. data/spec/spec_tests/data/client_side_encryption/keyAltName.yml +1 -8
  285. data/spec/spec_tests/data/client_side_encryption/localKMS.yml +1 -8
  286. data/spec/spec_tests/data/client_side_encryption/localSchema.yml +1 -8
  287. data/spec/spec_tests/data/client_side_encryption/maxWireVersion.yml +2 -0
  288. data/spec/spec_tests/data/client_side_encryption/missingKey.yml +2 -9
  289. data/spec/spec_tests/data/client_side_encryption/noSchema.yml +39 -0
  290. data/spec/spec_tests/data/client_side_encryption/replaceOne.yml +1 -8
  291. data/spec/spec_tests/data/client_side_encryption/types.yml +44 -70
  292. data/spec/spec_tests/data/client_side_encryption/updateMany.yml +1 -8
  293. data/spec/spec_tests/data/client_side_encryption/updateOne.yml +1 -8
  294. data/spec/spec_tests/data/collection_management/clustered-indexes.yml +135 -0
  295. data/spec/spec_tests/data/collection_management/createCollection-pre_and_post_images.yml +50 -0
  296. data/spec/spec_tests/data/collection_management/modifyCollection-pre_and_post_images.yml +58 -0
  297. data/spec/spec_tests/data/command_monitoring_unified/pre-42-server-connection-id.yml +56 -0
  298. data/spec/spec_tests/data/command_monitoring_unified/server-connection-id.yml +56 -0
  299. data/spec/spec_tests/data/crud/read/aggregate-collation.yml +1 -1
  300. data/spec/spec_tests/data/crud/read/count-collation.yml +1 -1
  301. data/spec/spec_tests/data/crud/read/distinct-collation.yml +1 -1
  302. data/spec/spec_tests/data/crud/read/find-collation.yml +1 -1
  303. data/spec/spec_tests/data/crud/write/bulkWrite-collation.yml +1 -1
  304. data/spec/spec_tests/data/crud/write/deleteMany-collation.yml +1 -1
  305. data/spec/spec_tests/data/crud/write/deleteOne-collation.yml +1 -1
  306. data/spec/spec_tests/data/crud/write/findOneAndDelete-collation.yml +1 -1
  307. data/spec/spec_tests/data/crud/write/findOneAndReplace-collation.yml +1 -1
  308. data/spec/spec_tests/data/crud/write/findOneAndUpdate-collation.yml +1 -1
  309. data/spec/spec_tests/data/crud/write/replaceOne-collation.yml +1 -1
  310. data/spec/spec_tests/data/crud/write/updateMany-collation.yml +1 -1
  311. data/spec/spec_tests/data/crud/write/updateOne-collation.yml +1 -1
  312. data/spec/spec_tests/data/crud_unified/aggregate-allowdiskuse.yml +75 -0
  313. data/spec/spec_tests/data/crud_unified/aggregate-merge.yml +185 -0
  314. data/spec/spec_tests/data/crud_unified/aggregate-out-readConcern.yml +171 -0
  315. data/spec/spec_tests/data/crud_unified/aggregate.yml +215 -0
  316. data/spec/spec_tests/data/crud_unified/bulkWrite-arrayFilters-clientError.yml +98 -0
  317. data/spec/spec_tests/data/crud_unified/bulkWrite-arrayFilters.yml +174 -0
  318. data/spec/spec_tests/data/crud_unified/bulkWrite-comment.yml +189 -0
  319. data/spec/spec_tests/data/crud_unified/bulkWrite-delete-hint-clientError.yml +113 -0
  320. data/spec/spec_tests/data/crud_unified/bulkWrite-delete-hint-serverError.yml +142 -0
  321. data/spec/spec_tests/data/crud_unified/bulkWrite-delete-hint.yml +154 -0
  322. data/spec/spec_tests/data/crud_unified/bulkWrite-deleteMany-hint-unacknowledged.yml +98 -0
  323. data/spec/spec_tests/data/crud_unified/bulkWrite-deleteMany-let.yml +86 -0
  324. data/spec/spec_tests/data/crud_unified/bulkWrite-deleteOne-hint-unacknowledged.yml +97 -0
  325. data/spec/spec_tests/data/crud_unified/bulkWrite-deleteOne-let.yml +86 -0
  326. data/spec/spec_tests/data/crud_unified/bulkWrite-insertOne-dots_and_dollars.yml +138 -0
  327. data/spec/spec_tests/data/crud_unified/bulkWrite-replaceOne-dots_and_dollars.yml +165 -0
  328. data/spec/spec_tests/data/crud_unified/bulkWrite-replaceOne-hint-unacknowledged.yml +103 -0
  329. data/spec/spec_tests/data/crud_unified/bulkWrite-replaceOne-let.yml +93 -0
  330. data/spec/spec_tests/data/crud_unified/bulkWrite-update-hint-clientError.yml +148 -0
  331. data/spec/spec_tests/data/crud_unified/bulkWrite-update-hint-serverError.yml +239 -0
  332. data/spec/spec_tests/data/crud_unified/bulkWrite-update-hint.yml +256 -0
  333. data/spec/spec_tests/data/crud_unified/bulkWrite-update-validation.yml +73 -0
  334. data/spec/spec_tests/data/crud_unified/bulkWrite-updateMany-dots_and_dollars.yml +150 -0
  335. data/spec/spec_tests/data/crud_unified/bulkWrite-updateMany-hint-unacknowledged.yml +104 -0
  336. data/spec/spec_tests/data/crud_unified/bulkWrite-updateMany-let.yml +96 -0
  337. data/spec/spec_tests/data/crud_unified/bulkWrite-updateOne-dots_and_dollars.yml +150 -0
  338. data/spec/spec_tests/data/crud_unified/bulkWrite-updateOne-hint-unacknowledged.yml +103 -0
  339. data/spec/spec_tests/data/crud_unified/bulkWrite-updateOne-let.yml +95 -0
  340. data/spec/spec_tests/data/crud_unified/countDocuments-comment.yml +92 -0
  341. data/spec/spec_tests/data/crud_unified/db-aggregate.yml +73 -0
  342. data/spec/spec_tests/data/crud_unified/deleteMany-comment.yml +97 -0
  343. data/spec/spec_tests/data/crud_unified/deleteMany-hint-clientError.yml +87 -0
  344. data/spec/spec_tests/data/crud_unified/deleteMany-hint-serverError.yml +107 -0
  345. data/spec/spec_tests/data/crud_unified/deleteMany-hint-unacknowledged.yml +90 -0
  346. data/spec/spec_tests/data/crud_unified/deleteMany-hint.yml +99 -0
  347. data/spec/spec_tests/data/crud_unified/deleteMany-let.yml +2 -0
  348. data/spec/spec_tests/data/crud_unified/deleteOne-comment.yml +98 -0
  349. data/spec/spec_tests/data/crud_unified/deleteOne-hint-clientError.yml +80 -0
  350. data/spec/spec_tests/data/crud_unified/deleteOne-hint-serverError.yml +100 -0
  351. data/spec/spec_tests/data/crud_unified/deleteOne-hint-unacknowledged.yml +89 -0
  352. data/spec/spec_tests/data/crud_unified/deleteOne-hint.yml +95 -0
  353. data/spec/spec_tests/data/crud_unified/deleteOne-let.yml +2 -0
  354. data/spec/spec_tests/data/crud_unified/estimatedDocumentCount-comment.yml +95 -0
  355. data/spec/spec_tests/data/crud_unified/estimatedDocumentCount.yml +5 -135
  356. data/spec/spec_tests/data/crud_unified/find-allowdiskuse-clientError.yml +55 -0
  357. data/spec/spec_tests/data/crud_unified/find-allowdiskuse-serverError.yml +68 -0
  358. data/spec/spec_tests/data/crud_unified/find-allowdiskuse.yml +79 -0
  359. data/spec/spec_tests/data/crud_unified/find-comment.yml +166 -0
  360. data/spec/spec_tests/data/crud_unified/find.yml +68 -0
  361. data/spec/spec_tests/data/crud_unified/findOneAndDelete-comment.yml +96 -0
  362. data/spec/spec_tests/data/crud_unified/findOneAndDelete-hint-clientError.yml +91 -0
  363. data/spec/spec_tests/data/crud_unified/findOneAndDelete-hint-serverError.yml +107 -0
  364. data/spec/spec_tests/data/crud_unified/findOneAndDelete-hint-unacknowledged.yml +88 -0
  365. data/spec/spec_tests/data/crud_unified/findOneAndDelete-hint.yml +102 -0
  366. data/spec/spec_tests/data/crud_unified/findOneAndDelete-let.yml +2 -4
  367. data/spec/spec_tests/data/crud_unified/findOneAndReplace-comment.yml +101 -0
  368. data/spec/spec_tests/data/crud_unified/findOneAndReplace-dots_and_dollars.yml +140 -0
  369. data/spec/spec_tests/data/crud_unified/findOneAndReplace-hint-clientError.yml +83 -0
  370. data/spec/spec_tests/data/crud_unified/findOneAndReplace-hint-serverError.yml +99 -0
  371. data/spec/spec_tests/data/crud_unified/findOneAndReplace-hint-unacknowledged.yml +96 -0
  372. data/spec/spec_tests/data/crud_unified/findOneAndReplace-hint.yml +98 -0
  373. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-comment.yml +95 -0
  374. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-dots_and_dollars.yml +127 -0
  375. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-hint-clientError.yml +84 -0
  376. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-hint-serverError.yml +100 -0
  377. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-hint-unacknowledged.yml +92 -0
  378. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-hint.yml +99 -0
  379. data/spec/spec_tests/data/crud_unified/insertMany-comment.yml +93 -0
  380. data/spec/spec_tests/data/crud_unified/insertMany-dots_and_dollars.yml +128 -0
  381. data/spec/spec_tests/data/crud_unified/insertOne-comment.yml +91 -0
  382. data/spec/spec_tests/data/crud_unified/insertOne-dots_and_dollars.yml +238 -0
  383. data/spec/spec_tests/data/crud_unified/replaceOne-comment.yml +105 -0
  384. data/spec/spec_tests/data/crud_unified/replaceOne-dots_and_dollars.yml +180 -0
  385. data/spec/spec_tests/data/crud_unified/replaceOne-hint-unacknowledged.yml +95 -0
  386. data/spec/spec_tests/data/crud_unified/replaceOne-hint.yml +108 -0
  387. data/spec/spec_tests/data/crud_unified/replaceOne-let.yml +98 -0
  388. data/spec/spec_tests/data/crud_unified/replaceOne-validation.yml +37 -0
  389. data/spec/spec_tests/data/crud_unified/updateMany-comment.yml +104 -0
  390. data/spec/spec_tests/data/crud_unified/updateMany-dots_and_dollars.yml +138 -0
  391. data/spec/spec_tests/data/crud_unified/updateMany-hint-clientError.yml +91 -0
  392. data/spec/spec_tests/data/crud_unified/updateMany-hint-serverError.yml +115 -0
  393. data/spec/spec_tests/data/crud_unified/updateMany-hint-unacknowledged.yml +96 -0
  394. data/spec/spec_tests/data/crud_unified/updateMany-hint.yml +115 -0
  395. data/spec/spec_tests/data/crud_unified/updateMany-let.yml +5 -1
  396. data/spec/spec_tests/data/crud_unified/updateMany-validation.yml +39 -0
  397. data/spec/spec_tests/data/crud_unified/updateOne-comment.yml +104 -0
  398. data/spec/spec_tests/data/crud_unified/updateOne-dots_and_dollars.yml +138 -0
  399. data/spec/spec_tests/data/crud_unified/updateOne-hint-clientError.yml +85 -0
  400. data/spec/spec_tests/data/crud_unified/updateOne-hint-serverError.yml +109 -0
  401. data/spec/spec_tests/data/crud_unified/updateOne-hint-unacknowledged.yml +95 -0
  402. data/spec/spec_tests/data/crud_unified/updateOne-hint.yml +109 -0
  403. data/spec/spec_tests/data/crud_unified/updateOne-let.yml +5 -1
  404. data/spec/spec_tests/data/crud_unified/updateOne-validation.yml +37 -0
  405. data/spec/spec_tests/data/crud_unified/updateWithPipelines.yml +8 -14
  406. data/spec/spec_tests/data/retryable_reads/{aggregate-merge.yml → legacy/aggregate-merge.yml} +0 -0
  407. data/spec/spec_tests/data/retryable_reads/{aggregate-serverErrors.yml → legacy/aggregate-serverErrors.yml} +0 -0
  408. data/spec/spec_tests/data/retryable_reads/{aggregate.yml → legacy/aggregate.yml} +0 -0
  409. data/spec/spec_tests/data/retryable_reads/{changeStreams-client.watch-serverErrors.yml → legacy/changeStreams-client.watch-serverErrors.yml} +0 -0
  410. data/spec/spec_tests/data/retryable_reads/{changeStreams-client.watch.yml → legacy/changeStreams-client.watch.yml} +0 -0
  411. data/spec/spec_tests/data/retryable_reads/{changeStreams-db.coll.watch-serverErrors.yml → legacy/changeStreams-db.coll.watch-serverErrors.yml} +0 -0
  412. data/spec/spec_tests/data/retryable_reads/{changeStreams-db.coll.watch.yml → legacy/changeStreams-db.coll.watch.yml} +0 -0
  413. data/spec/spec_tests/data/retryable_reads/{changeStreams-db.watch-serverErrors.yml → legacy/changeStreams-db.watch-serverErrors.yml} +0 -0
  414. data/spec/spec_tests/data/retryable_reads/{changeStreams-db.watch.yml → legacy/changeStreams-db.watch.yml} +0 -0
  415. data/spec/spec_tests/data/retryable_reads/{count-serverErrors.yml → legacy/count-serverErrors.yml} +0 -0
  416. data/spec/spec_tests/data/retryable_reads/{count.yml → legacy/count.yml} +0 -0
  417. data/spec/spec_tests/data/retryable_reads/{countDocuments-serverErrors.yml → legacy/countDocuments-serverErrors.yml} +0 -0
  418. data/spec/spec_tests/data/retryable_reads/{countDocuments.yml → legacy/countDocuments.yml} +0 -0
  419. data/spec/spec_tests/data/retryable_reads/{distinct-serverErrors.yml → legacy/distinct-serverErrors.yml} +0 -0
  420. data/spec/spec_tests/data/retryable_reads/{distinct.yml → legacy/distinct.yml} +0 -0
  421. data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount-serverErrors-pre4.9.yml → legacy/estimatedDocumentCount-serverErrors.yml} +0 -2
  422. data/spec/spec_tests/data/retryable_reads/{estimatedDocumentCount-pre4.9.yml → legacy/estimatedDocumentCount.yml} +0 -2
  423. data/spec/spec_tests/data/retryable_reads/{find-serverErrors.yml → legacy/find-serverErrors.yml} +0 -0
  424. data/spec/spec_tests/data/retryable_reads/{find.yml → legacy/find.yml} +0 -0
  425. data/spec/spec_tests/data/retryable_reads/{findOne-serverErrors.yml → legacy/findOne-serverErrors.yml} +0 -0
  426. data/spec/spec_tests/data/retryable_reads/{findOne.yml → legacy/findOne.yml} +0 -0
  427. data/spec/spec_tests/data/retryable_reads/{gridfs-download-serverErrors.yml → legacy/gridfs-download-serverErrors.yml} +0 -0
  428. data/spec/spec_tests/data/retryable_reads/{gridfs-download.yml → legacy/gridfs-download.yml} +0 -0
  429. data/spec/spec_tests/data/retryable_reads/{gridfs-downloadByName-serverErrors.yml → legacy/gridfs-downloadByName-serverErrors.yml} +0 -0
  430. data/spec/spec_tests/data/retryable_reads/{gridfs-downloadByName.yml → legacy/gridfs-downloadByName.yml} +0 -0
  431. data/spec/spec_tests/data/retryable_reads/{listCollectionNames-serverErrors.yml → legacy/listCollectionNames-serverErrors.yml} +0 -0
  432. data/spec/spec_tests/data/retryable_reads/{listCollectionNames.yml → legacy/listCollectionNames.yml} +0 -0
  433. data/spec/spec_tests/data/retryable_reads/{listCollectionObjects-serverErrors.yml → legacy/listCollectionObjects-serverErrors.yml} +0 -0
  434. data/spec/spec_tests/data/retryable_reads/{listCollectionObjects.yml → legacy/listCollectionObjects.yml} +0 -0
  435. data/spec/spec_tests/data/retryable_reads/{listCollections-serverErrors.yml → legacy/listCollections-serverErrors.yml} +0 -0
  436. data/spec/spec_tests/data/retryable_reads/{listCollections.yml → legacy/listCollections.yml} +0 -0
  437. data/spec/spec_tests/data/retryable_reads/{listDatabaseNames-serverErrors.yml → legacy/listDatabaseNames-serverErrors.yml} +0 -0
  438. data/spec/spec_tests/data/retryable_reads/{listDatabaseNames.yml → legacy/listDatabaseNames.yml} +0 -0
  439. data/spec/spec_tests/data/retryable_reads/{listDatabaseObjects-serverErrors.yml → legacy/listDatabaseObjects-serverErrors.yml} +0 -0
  440. data/spec/spec_tests/data/retryable_reads/{listDatabaseObjects.yml → legacy/listDatabaseObjects.yml} +0 -0
  441. data/spec/spec_tests/data/retryable_reads/{listDatabases-serverErrors.yml → legacy/listDatabases-serverErrors.yml} +0 -0
  442. data/spec/spec_tests/data/retryable_reads/{listDatabases.yml → legacy/listDatabases.yml} +0 -0
  443. data/spec/spec_tests/data/retryable_reads/{listIndexNames-serverErrors.yml → legacy/listIndexNames-serverErrors.yml} +0 -0
  444. data/spec/spec_tests/data/retryable_reads/{listIndexNames.yml → legacy/listIndexNames.yml} +0 -0
  445. data/spec/spec_tests/data/retryable_reads/{listIndexes-serverErrors.yml → legacy/listIndexes-serverErrors.yml} +0 -0
  446. data/spec/spec_tests/data/retryable_reads/{listIndexes.yml → legacy/listIndexes.yml} +0 -0
  447. data/spec/spec_tests/data/retryable_reads/{mapReduce.yml → legacy/mapReduce.yml} +0 -0
  448. data/spec/spec_tests/data/retryable_reads/unified/handshakeError.yml +129 -0
  449. data/spec/spec_tests/data/retryable_writes/{bulkWrite-errorLabels.yml → legacy/bulkWrite-errorLabels.yml} +0 -0
  450. data/spec/spec_tests/data/retryable_writes/{bulkWrite-serverErrors.yml → legacy/bulkWrite-serverErrors.yml} +1 -1
  451. data/spec/spec_tests/data/retryable_writes/{bulkWrite.yml → legacy/bulkWrite.yml} +0 -0
  452. data/spec/spec_tests/data/retryable_writes/{deleteMany.yml → legacy/deleteMany.yml} +0 -0
  453. data/spec/spec_tests/data/retryable_writes/{deleteOne-errorLabels.yml → legacy/deleteOne-errorLabels.yml} +0 -0
  454. data/spec/spec_tests/data/retryable_writes/{deleteOne-serverErrors.yml → legacy/deleteOne-serverErrors.yml} +1 -1
  455. data/spec/spec_tests/data/retryable_writes/{deleteOne.yml → legacy/deleteOne.yml} +0 -0
  456. data/spec/spec_tests/data/retryable_writes/{findOneAndDelete-errorLabels.yml → legacy/findOneAndDelete-errorLabels.yml} +0 -0
  457. data/spec/spec_tests/data/retryable_writes/{findOneAndDelete-serverErrors.yml → legacy/findOneAndDelete-serverErrors.yml} +1 -1
  458. data/spec/spec_tests/data/retryable_writes/{findOneAndDelete.yml → legacy/findOneAndDelete.yml} +0 -0
  459. data/spec/spec_tests/data/retryable_writes/{findOneAndReplace-errorLabels.yml → legacy/findOneAndReplace-errorLabels.yml} +0 -0
  460. data/spec/spec_tests/data/retryable_writes/{findOneAndReplace-serverErrors.yml → legacy/findOneAndReplace-serverErrors.yml} +1 -1
  461. data/spec/spec_tests/data/retryable_writes/{findOneAndReplace.yml → legacy/findOneAndReplace.yml} +0 -0
  462. data/spec/spec_tests/data/retryable_writes/{findOneAndUpdate-errorLabels.yml → legacy/findOneAndUpdate-errorLabels.yml} +0 -0
  463. data/spec/spec_tests/data/retryable_writes/{findOneAndUpdate-serverErrors.yml → legacy/findOneAndUpdate-serverErrors.yml} +1 -1
  464. data/spec/spec_tests/data/retryable_writes/{findOneAndUpdate.yml → legacy/findOneAndUpdate.yml} +0 -0
  465. data/spec/spec_tests/data/retryable_writes/{insertMany-errorLabels.yml → legacy/insertMany-errorLabels.yml} +0 -0
  466. data/spec/spec_tests/data/retryable_writes/{insertMany-serverErrors.yml → legacy/insertMany-serverErrors.yml} +1 -1
  467. data/spec/spec_tests/data/retryable_writes/{insertMany.yml → legacy/insertMany.yml} +0 -0
  468. data/spec/spec_tests/data/retryable_writes/{insertOne-errorLabels.yml → legacy/insertOne-errorLabels.yml} +0 -0
  469. data/spec/spec_tests/data/retryable_writes/{insertOne-serverErrors.yml → legacy/insertOne-serverErrors.yml} +5 -5
  470. data/spec/spec_tests/data/retryable_writes/{insertOne.yml → legacy/insertOne.yml} +0 -0
  471. data/spec/spec_tests/data/retryable_writes/{replaceOne-errorLabels.yml → legacy/replaceOne-errorLabels.yml} +0 -0
  472. data/spec/spec_tests/data/retryable_writes/{replaceOne-serverErrors.yml → legacy/replaceOne-serverErrors.yml} +1 -1
  473. data/spec/spec_tests/data/retryable_writes/{replaceOne.yml → legacy/replaceOne.yml} +0 -0
  474. data/spec/spec_tests/data/retryable_writes/{updateMany.yml → legacy/updateMany.yml} +0 -0
  475. data/spec/spec_tests/data/retryable_writes/{updateOne-errorLabels.yml → legacy/updateOne-errorLabels.yml} +0 -0
  476. data/spec/spec_tests/data/retryable_writes/{updateOne-serverErrors.yml → legacy/updateOne-serverErrors.yml} +1 -1
  477. data/spec/spec_tests/data/retryable_writes/{updateOne.yml → legacy/updateOne.yml} +0 -0
  478. data/spec/spec_tests/data/retryable_writes/unified/bulkWrite-serverErrors.yml +96 -0
  479. data/spec/spec_tests/data/retryable_writes/unified/handshakeError.yml +137 -0
  480. data/spec/spec_tests/data/retryable_writes/unified/insertOne-serverErrors.yml +78 -0
  481. data/spec/spec_tests/data/sdam/errors/prefer-error-code.yml +2 -2
  482. data/spec/spec_tests/data/seed_list_discovery/load-balanced/loadBalanced-no-results.yml +5 -0
  483. data/spec/spec_tests/data/seed_list_discovery/load-balanced/srvMaxHosts-conflicts_with_loadBalanced-true-txt.yml +5 -0
  484. data/spec/spec_tests/data/seed_list_discovery/load-balanced/srvMaxHosts-conflicts_with_loadBalanced-true.yml +5 -0
  485. data/spec/spec_tests/data/seed_list_discovery/load-balanced/srvMaxHosts-zero-txt.yml +10 -0
  486. data/spec/spec_tests/data/seed_list_discovery/load-balanced/srvMaxHosts-zero.yml +10 -0
  487. data/spec/spec_tests/data/seed_list_discovery/replica-set/srv-service-name.yml +11 -0
  488. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-conflicts_with_replicaSet-txt.yml +5 -0
  489. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-conflicts_with_replicaSet.yml +5 -0
  490. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-equal_to_srv_records.yml +16 -0
  491. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-greater_than_srv_records.yml +15 -0
  492. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-less_than_srv_records.yml +15 -0
  493. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-zero-txt.yml +15 -0
  494. data/spec/spec_tests/data/seed_list_discovery/replica-set/srvMaxHosts-zero.yml +15 -0
  495. data/spec/spec_tests/data/seed_list_discovery/sharded/srvMaxHosts-equal_to_srv_records.yml +13 -0
  496. data/spec/spec_tests/data/seed_list_discovery/sharded/srvMaxHosts-greater_than_srv_records.yml +12 -0
  497. data/spec/spec_tests/data/seed_list_discovery/sharded/srvMaxHosts-less_than_srv_records.yml +10 -0
  498. data/spec/spec_tests/data/seed_list_discovery/sharded/srvMaxHosts-zero.yml +11 -0
  499. data/spec/spec_tests/data/server_selection/Unknown/read/ghost.yml +11 -0
  500. data/spec/spec_tests/data/server_selection/Unknown/write/ghost.yml +11 -0
  501. data/spec/spec_tests/data/sessions_unified/driver-sessions-server-support.yml +123 -0
  502. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-client-error.yml +9 -3
  503. data/spec/spec_tests/data/transactions/error-labels.yml +1 -1
  504. data/spec/spec_tests/data/transactions/errors-client.yml +8 -9
  505. data/spec/spec_tests/data/transactions/mongos-recovery-token.yml +1 -1
  506. data/spec/spec_tests/data/transactions/retryable-abort-errorLabels.yml +0 -2
  507. data/spec/spec_tests/data/transactions/retryable-abort.yml +7 -9
  508. data/spec/spec_tests/data/transactions/retryable-commit-errorLabels.yml +0 -2
  509. data/spec/spec_tests/data/transactions/retryable-commit.yml +7 -9
  510. data/spec/spec_tests/data/transactions/retryable-writes.yml +0 -2
  511. data/spec/spec_tests/data/unified/invalid/expectedEventsForClient-ignoreExtraEvents-type.yml +15 -0
  512. data/spec/spec_tests/data/unified/valid-fail/operation-unsupported.yml +13 -0
  513. data/spec/spec_tests/data/unified/valid-pass/expectedEventsForClient-ignoreExtraEvents.yml +78 -0
  514. data/spec/spec_tests/data/unified/valid-pass/poc-change-streams.yml +4 -1
  515. data/spec/spec_tests/data/unified/valid-pass/poc-command-monitoring.yml +3 -3
  516. data/spec/spec_tests/data/unified/valid-pass/poc-transactions.yml +3 -2
  517. data/spec/spec_tests/data/uri_options/srv-options.yml +96 -0
  518. data/spec/spec_tests/data/versioned_api/crud-api-version-1-strict.yml +6 -4
  519. data/spec/spec_tests/data/versioned_api/crud-api-version-1.yml +7 -5
  520. data/spec/spec_tests/retryable_reads_spec.rb +4 -1
  521. data/spec/spec_tests/retryable_reads_unified_spec.rb +22 -0
  522. data/spec/spec_tests/retryable_writes_spec.rb +4 -1
  523. data/spec/spec_tests/retryable_writes_unified_spec.rb +21 -0
  524. data/spec/spec_tests/seed_list_discovery_spec.rb +10 -1
  525. data/spec/spec_tests/unified_spec.rb +6 -1
  526. data/spec/stress/connection_pool_timing_spec.rb +2 -1
  527. data/spec/stress/fork_reconnect_stress_spec.rb +3 -2
  528. data/spec/support/authorization.rb +1 -1
  529. data/spec/support/certificates/atlas-ocsp-ca.crt +47 -40
  530. data/spec/support/certificates/atlas-ocsp.crt +106 -101
  531. data/spec/support/cluster_tools.rb +1 -1
  532. data/spec/support/common_shortcuts.rb +22 -0
  533. data/spec/support/crypt/corpus/corpus-encrypted.json +9515 -0
  534. data/spec/support/crypt/corpus/corpus-key-aws.json +32 -32
  535. data/spec/support/crypt/corpus/corpus-key-azure.json +33 -0
  536. data/spec/support/crypt/corpus/corpus-key-gcp.json +35 -0
  537. data/spec/support/crypt/corpus/corpus-key-kmip.json +32 -0
  538. data/spec/support/crypt/corpus/corpus-key-local.json +30 -30
  539. data/spec/support/crypt/corpus/corpus-schema.json +4399 -121
  540. data/spec/support/crypt/corpus/corpus.json +4999 -37
  541. data/spec/support/crypt/data_keys/key_document_azure.json +33 -0
  542. data/spec/support/crypt/data_keys/key_document_gcp.json +37 -0
  543. data/spec/support/crypt/data_keys/key_document_kmip.json +32 -0
  544. data/spec/support/crypt/encryptedFields.json +33 -0
  545. data/spec/support/crypt/keys/key1-document.json +30 -0
  546. data/spec/support/crypt/schema_maps/schema_map_azure.json +17 -0
  547. data/spec/support/crypt/schema_maps/schema_map_azure_key_alt_names.json +12 -0
  548. data/spec/support/crypt/schema_maps/schema_map_gcp.json +17 -0
  549. data/spec/support/crypt/schema_maps/schema_map_gcp_key_alt_names.json +12 -0
  550. data/spec/support/crypt/schema_maps/schema_map_kmip.json +17 -0
  551. data/spec/support/crypt/schema_maps/schema_map_kmip_key_alt_names.json +12 -0
  552. data/spec/support/crypt.rb +207 -6
  553. data/spec/support/macros.rb +18 -0
  554. data/spec/support/mongos_macros.rb +17 -0
  555. data/spec/support/shared/scram_conversation.rb +2 -1
  556. data/spec/support/shared/session.rb +13 -7
  557. data/spec/support/spec_config.rb +82 -1
  558. data/spec/support/utils.rb +25 -4
  559. data.tar.gz.sig +0 -0
  560. metadata +1468 -1214
  561. metadata.gz.sig +0 -0
  562. data/lib/mongo/operation/delete/legacy.rb +0 -64
  563. data/lib/mongo/operation/insert/legacy.rb +0 -68
  564. data/lib/mongo/operation/update/legacy/result.rb +0 -112
  565. data/lib/mongo/operation/update/legacy.rb +0 -76
  566. data/spec/mongo/dbref_spec.rb +0 -152
  567. data/spec/mongo/operation/kill_cursors_spec.rb +0 -47
  568. data/spec/spec_tests/change_streams_spec.rb +0 -93
  569. data/spec/spec_tests/data/change_streams/change-streams-errors.yml +0 -101
  570. data/spec/spec_tests/data/change_streams/change-streams-resume-allowlist.yml +0 -1173
  571. data/spec/spec_tests/data/change_streams/change-streams-resume-errorLabels.yml +0 -1105
  572. data/spec/spec_tests/data/change_streams/change-streams.yml +0 -535
  573. data/spec/spec_tests/data/crud_v2/aggregate-merge.yml +0 -103
  574. data/spec/spec_tests/data/crud_v2/aggregate-out-readConcern.yml +0 -111
  575. data/spec/spec_tests/data/crud_v2/bulkWrite-arrayFilters.yml +0 -103
  576. data/spec/spec_tests/data/crud_v2/bulkWrite-delete-hint-clientError.yml +0 -63
  577. data/spec/spec_tests/data/crud_v2/bulkWrite-delete-hint-serverError.yml +0 -92
  578. data/spec/spec_tests/data/crud_v2/bulkWrite-delete-hint.yml +0 -103
  579. data/spec/spec_tests/data/crud_v2/bulkWrite-update-hint-clientError.yml +0 -90
  580. data/spec/spec_tests/data/crud_v2/bulkWrite-update-hint-serverError.yml +0 -147
  581. data/spec/spec_tests/data/crud_v2/bulkWrite-update-hint.yml +0 -164
  582. data/spec/spec_tests/data/crud_v2/db-aggregate.yml +0 -39
  583. data/spec/spec_tests/data/crud_v2/deleteMany-hint-clientError.yml +0 -43
  584. data/spec/spec_tests/data/crud_v2/deleteMany-hint-serverError.yml +0 -62
  585. data/spec/spec_tests/data/crud_v2/deleteMany-hint.yml +0 -58
  586. data/spec/spec_tests/data/crud_v2/deleteOne-hint-clientError.yml +0 -41
  587. data/spec/spec_tests/data/crud_v2/deleteOne-hint-serverError.yml +0 -60
  588. data/spec/spec_tests/data/crud_v2/deleteOne-hint.yml +0 -57
  589. data/spec/spec_tests/data/crud_v2/find-allowdiskuse-clientError.yml +0 -28
  590. data/spec/spec_tests/data/crud_v2/find-allowdiskuse-serverError.yml +0 -44
  591. data/spec/spec_tests/data/crud_v2/find-allowdiskuse.yml +0 -50
  592. data/spec/spec_tests/data/crud_v2/findOneAndDelete-hint-clientError.yml +0 -45
  593. data/spec/spec_tests/data/crud_v2/findOneAndDelete-hint-serverError.yml +0 -60
  594. data/spec/spec_tests/data/crud_v2/findOneAndDelete-hint.yml +0 -56
  595. data/spec/spec_tests/data/crud_v2/findOneAndReplace-hint-clientError.yml +0 -40
  596. data/spec/spec_tests/data/crud_v2/findOneAndReplace-hint-serverError.yml +0 -59
  597. data/spec/spec_tests/data/crud_v2/findOneAndReplace-hint.yml +0 -55
  598. data/spec/spec_tests/data/crud_v2/findOneAndUpdate-hint-clientError.yml +0 -40
  599. data/spec/spec_tests/data/crud_v2/findOneAndUpdate-hint-serverError.yml +0 -58
  600. data/spec/spec_tests/data/crud_v2/findOneAndUpdate-hint.yml +0 -55
  601. data/spec/spec_tests/data/crud_v2/replaceOne-hint.yml +0 -61
  602. data/spec/spec_tests/data/crud_v2/unacknowledged-bulkWrite-delete-hint-clientError.yml +0 -60
  603. data/spec/spec_tests/data/crud_v2/unacknowledged-bulkWrite-update-hint-clientError.yml +0 -88
  604. data/spec/spec_tests/data/crud_v2/unacknowledged-deleteMany-hint-clientError.yml +0 -40
  605. data/spec/spec_tests/data/crud_v2/unacknowledged-deleteOne-hint-clientError.yml +0 -38
  606. data/spec/spec_tests/data/crud_v2/unacknowledged-findOneAndDelete-hint-clientError.yml +0 -42
  607. data/spec/spec_tests/data/crud_v2/unacknowledged-findOneAndReplace-hint-clientError.yml +0 -40
  608. data/spec/spec_tests/data/crud_v2/unacknowledged-findOneAndUpdate-hint-clientError.yml +0 -40
  609. data/spec/spec_tests/data/crud_v2/unacknowledged-replaceOne-hint-clientError.yml +0 -40
  610. data/spec/spec_tests/data/crud_v2/unacknowledged-updateMany-hint-clientError.yml +0 -43
  611. data/spec/spec_tests/data/crud_v2/unacknowledged-updateOne-hint-clientError.yml +0 -40
  612. data/spec/spec_tests/data/crud_v2/updateMany-hint-clientError.yml +0 -45
  613. data/spec/spec_tests/data/crud_v2/updateMany-hint-serverError.yml +0 -66
  614. data/spec/spec_tests/data/crud_v2/updateMany-hint.yml +0 -65
  615. data/spec/spec_tests/data/crud_v2/updateOne-hint-clientError.yml +0 -43
  616. data/spec/spec_tests/data/crud_v2/updateOne-hint-serverError.yml +0 -62
  617. data/spec/spec_tests/data/crud_v2/updateOne-hint.yml +0 -61
  618. data/spec/spec_tests/data/crud_v2/updateWithPipelines.yml +0 -157
  619. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-4.9.yml +0 -60
  620. data/spec/spec_tests/data/retryable_reads/estimatedDocumentCount-serverErrors-4.9.yml +0 -146
  621. data/spec/support/crypt/corpus/corpus_encrypted.json +0 -4152
  622. data/spec/support/session_registry.rb +0 -55
@@ -19,7 +19,7 @@ module Mongo
19
19
  module Crypt
20
20
 
21
21
  # A Context object initialized specifically for the purpose of creating
22
- # a data key in the key managemenet system.
22
+ # a data key in the key management system.
23
23
  #
24
24
  # @api private
25
25
  class DataKeyContext < Context
@@ -30,116 +30,19 @@ module Mongo
30
30
  # wraps a mongocrypt_t object used to create a new mongocrypt_ctx_t
31
31
  # @param [ Mongo::Crypt::EncryptionIO ] io An object that performs all
32
32
  # driver I/O on behalf of libmongocrypt
33
- # @param [ String ] kms_provider The KMS provider to use. Options are
34
- # "aws" and "local".
35
- # @param [ Hash ] options Data key creation options.
36
- #
37
- # @option options [ Hash ] :master_key A Hash of options related to the AWS
38
- # KMS provider option. Required if kms_provider is "aws".
39
- # - :region [ String ] The The AWS region of the master key (required).
40
- # - :key [ String ] The Amazon Resource Name (ARN) of the master key (required).
41
- # - :endpoint [ String ] An alternate host to send KMS requests to (optional).
42
- # @option options [ Array<String> ] :key_alt_names An optional array of strings specifying
33
+ # @param [ Mongo::Crypt::KMS::MasterKeyDocument ] master_key_document The master
34
+ # key document that contains master encryption key parameters.
35
+ # @param [ Array<String> | nil ] key_alt_names An optional array of strings specifying
43
36
  # alternate names for the new data key.
44
- def initialize(mongocrypt, io, kms_provider, options={})
37
+ def initialize(mongocrypt, io, master_key_document, key_alt_names = nil)
45
38
  super(mongocrypt, io)
46
-
47
- case kms_provider
48
- when 'local'
49
- Binding.ctx_setopt_master_key_local(self)
50
- when 'aws'
51
- unless options
52
- raise ArgumentError.new(
53
- 'When "aws" is specified as the KMS provider, options cannot be nil'
54
- )
55
- end
56
-
57
- unless options.key?(:master_key)
58
- raise ArgumentError.new(
59
- 'When "aws" is specified as the KMS provider, the options Hash ' +
60
- 'must contain a key named :master_key with a Hash value in the ' +
61
- '{ region: "AWS-REGION", key: "AWS-KEY-ARN" }'
62
- )
63
- end
64
-
65
- master_key_opts = options[:master_key]
66
-
67
- set_aws_master_key(master_key_opts)
68
- set_aws_endpoint(master_key_opts[:endpoint]) if master_key_opts[:endpoint]
69
- else
70
- raise ArgumentError.new(
71
- "#{kms_provider} is an invalid kms provider. " +
72
- "Valid options are 'aws' and 'local'"
73
- )
74
- end
75
-
76
- set_key_alt_names(options[:key_alt_names]) if options[:key_alt_names]
39
+ Binding.ctx_setopt_key_encryption_key(self, master_key_document.to_document)
40
+ set_key_alt_names(key_alt_names) if key_alt_names
77
41
  initialize_ctx
78
42
  end
79
43
 
80
44
  private
81
45
 
82
- # Configure the underlying mongocrypt_ctx_t object to accept AWS
83
- # KMS options
84
- def set_aws_master_key(master_key_opts)
85
- unless master_key_opts
86
- raise ArgumentError.new('The :master_key option cannot be nil')
87
- end
88
-
89
- unless master_key_opts.is_a?(Hash)
90
- raise ArgumentError.new(
91
- "#{master_key_opts} is an invalid :master_key option. " +
92
- "The :master_key option must be a Hash in the format " +
93
- "{ region: 'AWS-REGION', key: 'AWS-KEY-ARN' }"
94
- )
95
- end
96
-
97
- region = master_key_opts[:region]
98
- unless region
99
- raise ArgumentError.new(
100
- 'The value of :region option of the :master_key options hash cannot be nil'
101
- )
102
- end
103
-
104
- unless region.is_a?(String)
105
- raise ArgumentError.new(
106
- "#{master_key_opts[:region]} is an invalid AWS master_key region. " +
107
- "The value of :region option of the :master_key options hash must be a String"
108
- )
109
- end
110
-
111
- key = master_key_opts[:key]
112
- unless key
113
- raise ArgumentError.new(
114
- 'The value of :key option of the :master_key options hash cannot be nil'
115
- )
116
- end
117
-
118
- unless key.is_a?(String)
119
- raise ArgumentError.new(
120
- "#{master_key_opts[:key]} is an invalid AWS master_key key. " +
121
- "The value of :key option of the :master_key options hash must be a String"
122
- )
123
- end
124
-
125
- Binding.ctx_setopt_master_key_aws(
126
- self,
127
- region,
128
- key,
129
- )
130
- end
131
-
132
- def set_aws_endpoint(endpoint)
133
- unless endpoint.is_a?(String)
134
- raise ArgumentError.new(
135
- "#{endpoint} is an invalid AWS master_key endpoint. " +
136
- "The value of :endpoint option of the :master_key options hash must be a String"
137
- )
138
- end
139
-
140
- Binding.ctx_setopt_master_key_aws_endpoint(self, endpoint)
141
- end
142
-
143
46
  # Set the alt names option on the context
144
47
  def set_key_alt_names(key_alt_names)
145
48
  unless key_alt_names.is_a?(Array)
@@ -38,6 +38,8 @@ module Mongo
38
38
  # defaults to nil.
39
39
  # @param [ Mongo::Client ] key_vault_client The client connected to the
40
40
  # key vault collection.
41
+ # @param [ Mongo::Client | nil ] metadata_client The client to be used to
42
+ # obtain collection metadata.
41
43
  # @param [ String ] key_vault_namespace The key vault namespace in the format
42
44
  # db_name.collection_name.
43
45
  # @param [ Hash ] mongocryptd_options Options related to mongocryptd.
@@ -54,7 +56,7 @@ module Mongo
54
56
  # options are not nil and are in the correct format.
55
57
  def initialize(
56
58
  client: nil, mongocryptd_client: nil, key_vault_namespace:,
57
- key_vault_client:, mongocryptd_options: {}
59
+ key_vault_client:, metadata_client:, mongocryptd_options: {}
58
60
  )
59
61
  validate_key_vault_client!(key_vault_client)
60
62
  validate_key_vault_namespace!(key_vault_namespace)
@@ -63,6 +65,7 @@ module Mongo
63
65
  @mongocryptd_client = mongocryptd_client
64
66
  @key_vault_db_name, @key_vault_collection_name = key_vault_namespace.split('.')
65
67
  @key_vault_client = key_vault_client
68
+ @metadata_client = metadata_client
66
69
  @options = mongocryptd_options
67
70
  end
68
71
 
@@ -91,11 +94,11 @@ module Mongo
91
94
  #
92
95
  # @return [ Hash ] The collection information
93
96
  def collection_info(db_name, filter)
94
- unless @client
95
- raise ArgumentError, 'collection_info requires client to have been passed to the constructor, but it was not'
97
+ unless @metadata_client
98
+ raise ArgumentError, 'collection_info requires metadata_client to have been passed to the constructor, but it was not'
96
99
  end
97
100
 
98
- @client.use(db_name).database.list_collections(filter: filter).first
101
+ @metadata_client.use(db_name).database.list_collections(filter: filter).first
99
102
  end
100
103
 
101
104
  # Send the command to mongocryptd to be marked with intent-to-encrypt markings
@@ -124,16 +127,17 @@ module Mongo
124
127
  return response.first
125
128
  end
126
129
 
127
- # Get information about the AWS encryption key and feed it to the the
130
+ # Get information about the remote KMS encryption key and feed it to the the
128
131
  # KmsContext object
129
132
  #
130
133
  # @param [ Mongo::Crypt::KmsContext ] kms_context A KmsContext object
131
- # corresponding to one AWS KMS data key. Contains information about
134
+ # corresponding to one remote KMS data key. Contains information about
132
135
  # the endpoint at which to establish a TLS connection and the message
133
136
  # to send on that connection.
134
- def feed_kms(kms_context)
135
- with_ssl_socket(kms_context.endpoint) do |ssl_socket|
136
-
137
+ # @param [ Hash ] tls_options. TLS options to connect to KMS provider.
138
+ # The options are same as for Mongo::Client.
139
+ def feed_kms(kms_context, tls_options)
140
+ with_ssl_socket(kms_context.endpoint, tls_options) do |ssl_socket|
137
141
  Timeout.timeout(SOCKET_TIMEOUT, Error::SocketTimeoutError,
138
142
  'Socket write operation timed out'
139
143
  ) do
@@ -242,6 +246,8 @@ module Mongo
242
246
  # Provide a TLS socket to be used for KMS calls in a block API
243
247
  #
244
248
  # @param [ String ] endpoint The URI at which to connect the TLS socket.
249
+ # @param [ Hash ] tls_options. TLS options to connect to KMS provider.
250
+ # The options are same as for Mongo::Client.
245
251
  # @yieldparam [ OpenSSL::SSL::SSLSocket ] ssl_socket Yields a TLS socket
246
252
  # connected to the specified endpoint.
247
253
  #
@@ -250,59 +256,21 @@ module Mongo
250
256
  #
251
257
  # @note The socket is always closed when the provided block has finished
252
258
  # executing
253
- def with_ssl_socket(endpoint)
254
- host, port = endpoint.split(':')
255
- port ||= 443 # Default port for AWS KMS API
256
-
257
- # Create TCPSocket and set nodelay option
258
- tcp_socket = TCPSocket.open(host, port)
259
- begin
260
- tcp_socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
261
-
262
- ssl_socket = OpenSSL::SSL::SSLSocket.new(tcp_socket)
263
- begin
264
- # tcp_socket will be closed when ssl_socket is closed
265
- ssl_socket.sync_close = true
266
- # perform SNI
267
- ssl_socket.hostname = "#{host}:#{port}"
268
-
269
- Timeout.timeout(
270
- SOCKET_TIMEOUT,
271
- Error::SocketTimeoutError,
272
- "KMS socket connection timed out after #{SOCKET_TIMEOUT} seconds",
273
- ) do
274
- ssl_socket.connect
275
- end
276
-
277
- yield(ssl_socket)
278
- ensure
279
- begin
280
- Timeout.timeout(
281
- SOCKET_TIMEOUT,
282
- Error::SocketTimeoutError,
283
- 'KMS TLS socket close timed out'
284
- ) do
285
- ssl_socket.sysclose
286
- end
287
- rescue
288
- end
289
- end
290
- ensure
291
- # Still close tcp socket manually in case TLS socket creation
292
- # fails.
293
- begin
294
- Timeout.timeout(
295
- SOCKET_TIMEOUT,
296
- Error::SocketTimeoutError,
297
- 'KMS TCP socket close timed out'
298
- ) do
299
- tcp_socket.close
300
- end
301
- rescue
302
- end
259
+ def with_ssl_socket(endpoint, tls_options)
260
+ address = begin
261
+ host, port = endpoint.split(':')
262
+ port ||= 443 # All supported KMS APIs use this port by default.
263
+ Address.new([host, port].join(':'))
303
264
  end
265
+ mongo_socket = address.socket(
266
+ SOCKET_TIMEOUT,
267
+ tls_options.merge(ssl: true)
268
+ )
269
+ yield(mongo_socket.socket)
304
270
  rescue => e
305
- raise Error::KmsError, "Error decrypting data key: #{e.class}: #{e.message}"
271
+ raise Error::KmsError, "Error when connecting to KMS provider: #{e.class}: #{e.message}"
272
+ ensure
273
+ mongo_socket&.close
306
274
  end
307
275
  end
308
276
  end
@@ -29,14 +29,17 @@ module Mongo
29
29
  # to connect to the key vault collection.
30
30
  # @param [ String ] key_vault_namespace The namespace of the key vault
31
31
  # collection in the format "db_name.collection_name".
32
- # @option options [ Hash ] :kms_providers A hash of key management service
33
- # configuration information. Valid hash keys are :local or :aws. There
34
- # may be more than one KMS provider specified.
35
- def initialize(key_vault_client, key_vault_namespace, kms_providers)
36
- @crypt_handle = Handle.new(kms_providers)
37
-
32
+ # @param [ Crypt::KMS::Credentials ] kms_providers A hash of key management service
33
+ # configuration information.
34
+ # @param [ Hash ] kms_tls_options TLS options to connect to KMS
35
+ # providers. Keys of the hash should be KSM provider names; values
36
+ # should be hashes of TLS connection options. The options are equivalent
37
+ # to TLS connection options of Mongo::Client.
38
+ def initialize(key_vault_client, key_vault_namespace, kms_providers, kms_tls_options)
39
+ @crypt_handle = Handle.new(kms_providers, kms_tls_options)
38
40
  @encryption_io = EncryptionIO.new(
39
41
  key_vault_client: key_vault_client,
42
+ metadata_client: nil,
40
43
  key_vault_namespace: key_vault_namespace
41
44
  )
42
45
  end
@@ -45,30 +48,19 @@ module Mongo
45
48
  # that key in the KMS collection. The generated key is encrypted with
46
49
  # the KMS master key.
47
50
  #
48
- # @param [ String ] kms_provider The KMS provider to use. Valid values are
49
- # "aws" and "local".
50
- # @param [ Hash ] options
51
- #
52
- # @option options [ Hash ] :master_key Information about the AWS master key. Required
53
- # if kms_provider is "aws".
54
- # - :region [ String ] The The AWS region of the master key (required).
55
- # - :key [ String ] The Amazon Resource Name (ARN) of the master key (required).
56
- # - :endpoint [ String ] An alternate host to send KMS requests to (optional).
57
- # endpoint should be a host name with an optional port number separated
58
- # by a colon (e.g. "kms.us-east-1.amazonaws.com" or
59
- # "kms.us-east-1.amazonaws.com:443"). An endpoint in any other format
60
- # will not be properly parsed.
61
- # @option options [ Array<String> ] :key_alt_names An optional array of strings specifying
51
+ # @param [ Mongo::Crypt::KMS::MasterKeyDocument ] master_key_document The master
52
+ # key document that contains master encryption key parameters.
53
+ # @param [ Array<String> | nil ] key_alt_names An optional array of strings specifying
62
54
  # alternate names for the new data key.
63
55
  #
64
56
  # @return [ BSON::Binary ] The 16-byte UUID of the new data key as a
65
57
  # BSON::Binary object with type :uuid.
66
- def create_and_insert_data_key(kms_provider, options)
58
+ def create_and_insert_data_key(master_key_document, key_alt_names)
67
59
  data_key_document = Crypt::DataKeyContext.new(
68
60
  @crypt_handle,
69
61
  @encryption_io,
70
- kms_provider,
71
- options
62
+ master_key_document,
63
+ key_alt_names
72
64
  ).run_state_machine
73
65
 
74
66
  @encryption_io.insert_data_key(data_key_document).inserted_id
@@ -85,14 +77,24 @@ module Mongo
85
77
  # @option options [ String ] :key_alt_name The alternate name for the
86
78
  # encryption key.
87
79
  # @option options [ String ] :algorithm The algorithm used to encrypt the value.
88
- # Valid algorithms are "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
89
- # or "AEAD_AES_256_CBC_HMAC_SHA_512-Random".
80
+ # Valid algorithms are "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
81
+ # "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "Indexed", "Unindexed".
82
+ # @option options [ Integer | nil ] :contention_factor Contention factor
83
+ # to be applied if encryption algorithm is set to "Indexed". If not
84
+ # provided, it defaults to a value of 0. Contention factor should be set
85
+ # only if encryption algorithm is set to "Indexed".
86
+ # @option options [ Symbol ] query_type Query type to be applied
87
+ # if encryption algorithm is set to "Indexed". Query type should be set
88
+ # only if encryption algorithm is set to "Indexed". The only allowed
89
+ # value is :equality.
90
90
  #
91
91
  # @note The :key_id and :key_alt_name options are mutually exclusive. Only
92
92
  # one is required to perform explicit encryption.
93
93
  #
94
94
  # @return [ BSON::Binary ] A BSON Binary object of subtype 6 (ciphertext)
95
95
  # representing the encrypted value
96
+ # @raise [ ArgumentError ] if either contention_factor or query_type
97
+ # is set, and algorithm is not "Indexed".
96
98
  def encrypt(value, options)
97
99
  Crypt::ExplicitEncryptionContext.new(
98
100
  @crypt_handle,
@@ -38,8 +38,16 @@ module Mongo
38
38
  # @option options [ String ] :key_alt_name The alternate name of the data key
39
39
  # that will be used to encrypt the value.
40
40
  # @option options [ String ] :algorithm The algorithm used to encrypt the
41
- # value. Valid algorithms are "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
42
- # or "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
41
+ # value. Valid algorithms are "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
42
+ # "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "Indexed", "Unindexed".
43
+ # @option options [ Integer | nil ] :contention_factor Contention factor
44
+ # to be applied if encryption algorithm is set to "Indexed". If not
45
+ # provided, it defaults to a value of 0. Contention factor should be set
46
+ # only if encryption algorithm is set to "Indexed".
47
+ # @option options [ Symbol ] query_type Query type to be applied
48
+ # if encryption algorithm is set to "Indexed". Query type should be set
49
+ # only if encryption algorithm is set to "Indexed". The only allowed
50
+ # value is :equality.
43
51
  #
44
52
  # @raise [ ArgumentError|Mongo::Error::CryptError ] If invalid options are provided
45
53
  def initialize(mongocrypt, io, doc, options={})
@@ -81,7 +89,27 @@ module Mongo
81
89
 
82
90
  # Set the algorithm option on the mongocrypt_ctx_t object and raises
83
91
  # an exception if the algorithm is invalid.
84
- Binding.ctx_setopt_algorithm(self, options[:algorithm])
92
+ if options[:algorithm] == 'Indexed'
93
+ if options[:contention_factor]
94
+ Binding.ctx_setopt_contention_factor(self, options[:contention_factor])
95
+ end
96
+ if options[:query_type]
97
+ Binding.ctx_setopt_query_type(self, options[:query_type])
98
+ end
99
+ Binding.ctx_setopt_index_type(self, :equality)
100
+ else
101
+ if options[:contention_factor]
102
+ raise ArgumentError.new(':contention_factor is allowed only for "Indexed" algorithm')
103
+ end
104
+ if options[:query_type]
105
+ raise ArgumentError.new(':query_type is allowed only for "Indexed" algorithm')
106
+ end
107
+ if options[:algorithm] == 'Unindexed'
108
+ Binding.ctx_setopt_index_type(self, :none)
109
+ else
110
+ Binding.ctx_setopt_algorithm(self, options[:algorithm])
111
+ end
112
+ end
85
113
 
86
114
  # Initializes the mongocrypt_ctx_t object for explicit encryption and
87
115
  # passes in the value to be encrypted.
@@ -27,19 +27,28 @@ module Mongo
27
27
  #
28
28
  # @api private
29
29
  class Handle
30
+
30
31
  # Creates a new Handle object and initializes it with options
31
32
  #
32
- # @param [ Hash ] kms_providers A hash of KMS settings. The only supported
33
- # key is currently :local. Local KMS options must be passed in the
34
- # format { local: { key: <master key> } } where the master key is a
35
- # 96-byte, base64 encoded string.
36
- # @param [ Hash ] options A hash of options
33
+ # @param [ Crypt::KMS::Credentials ] kms_providers Credentials for KMS providers.
34
+ #
35
+ # @param [ Hash ] kms_tls_options TLS options to connect to KMS
36
+ # providers. Keys of the hash should be KSM provider names; values
37
+ # should be hashes of TLS connection options. The options are equivalent
38
+ # to TLS connection options of Mongo::Client.
37
39
  #
40
+ # @param [ Hash ] options A hash of options.
38
41
  # @option options [ Hash | nil ] :schema_map A hash representing the JSON schema
39
42
  # of the collection that stores auto encrypted documents.
43
+ # @option options [ Hash | nil ] :encrypted_fields_map maps a collection
44
+ # namespace to an encryptedFields.
45
+ # - Note: If a collection is present on both the encryptedFieldsMap
46
+ # and schemaMap, an error will be raised.
47
+ # @option options [ Boolean | nil ] :bypass_query_analysis When true
48
+ # disables automatic analysis of outgoing commands.
40
49
  # @option options [ Logger ] :logger A Logger object to which libmongocrypt logs
41
50
  # will be sent
42
- def initialize(kms_providers, options={})
51
+ def initialize(kms_providers, kms_tls_options, options={})
43
52
  # FFI::AutoPointer uses a custom release strategy to automatically free
44
53
  # the pointer once this object goes out of scope
45
54
  @mongocrypt = FFI::AutoPointer.new(
@@ -47,15 +56,23 @@ module Mongo
47
56
  Binding.method(:mongocrypt_destroy)
48
57
  )
49
58
 
59
+ @kms_tls_options = kms_tls_options
60
+
50
61
  @schema_map = options[:schema_map]
51
62
  set_schema_map if @schema_map
52
63
 
64
+ @encrypted_fields_map = options[:encrypted_fields_map]
65
+ set_encrypted_fields_map if @encrypted_fields_map
66
+
67
+ @bypass_query_analysis = options[:bypass_query_analysis]
68
+ set_bypass_query_analysis if @bypass_query_analysis
69
+
53
70
  @logger = options[:logger]
54
71
  set_logger_callback if @logger
55
72
 
56
73
  set_crypto_hooks
57
74
 
58
- set_kms_providers(kms_providers)
75
+ Binding.setopt_kms_providers(self, kms_providers.to_document)
59
76
  initialize_mongocrypt
60
77
  end
61
78
 
@@ -66,6 +83,16 @@ module Mongo
66
83
  @mongocrypt
67
84
  end
68
85
 
86
+ # Return TLS options for KMS provider. If there are no TLS options set,
87
+ # empty hash is returned.
88
+ #
89
+ # @param [ String ] provider KSM provider name.
90
+ #
91
+ # @return [ Hash ] TLS options to connect to KMS provider.
92
+ def kms_tls_options(provider)
93
+ @kms_tls_options.fetch(provider, {})
94
+ end
95
+
69
96
  private
70
97
 
71
98
  # Set the schema map option on the underlying mongocrypt_t object
@@ -79,6 +106,26 @@ module Mongo
79
106
  Binding.setopt_schema_map(self, @schema_map)
80
107
  end
81
108
 
109
+ def set_encrypted_fields_map
110
+ unless @encrypted_fields_map.is_a?(Hash)
111
+ raise ArgumentError.new(
112
+ "#{@encrypted_fields_map} is an invalid encrypted_fields_map: must be a Hash or nil"
113
+ )
114
+ end
115
+
116
+ Binding.setopt_encrypted_field_config_map(self, @encrypted_fields_map)
117
+ end
118
+
119
+ def set_bypass_query_analysis
120
+ unless [true, false].include?(@bypass_query_analysis)
121
+ raise ArgumentError.new(
122
+ "#{@bypass_query_analysis} is an invalid bypass_query_analysis value; must be a Boolean or nil"
123
+ )
124
+ end
125
+
126
+ Binding.setopt_bypass_query_analysis(self) if @bypass_query_analysis
127
+ end
128
+
82
129
  # Send the logs from libmongocrypt to the Mongo::Logger
83
130
  def set_logger_callback
84
131
  @log_callback = Proc.new do |level, msg|
@@ -136,13 +183,13 @@ module Mongo
136
183
  # Perform AES encryption or decryption and write the output to the
137
184
  # provided mongocrypt_binary_t object.
138
185
  def do_aes(key_binary_p, iv_binary_p, input_binary_p, output_binary_p,
139
- response_length_p, status_p, decrypt: false)
186
+ response_length_p, status_p, decrypt: false, mode: :CBC)
140
187
  key = Binary.from_pointer(key_binary_p).to_s
141
188
  iv = Binary.from_pointer(iv_binary_p).to_s
142
189
  input = Binary.from_pointer(input_binary_p).to_s
143
190
 
144
191
  write_binary_string_and_set_status(output_binary_p, status_p) do
145
- output = Hooks.aes(key, iv, input, decrypt: decrypt)
192
+ output = Hooks.aes(key, iv, input, decrypt: decrypt, mode: mode)
146
193
  response_length_p.write_int(output.bytesize)
147
194
 
148
195
  output
@@ -161,7 +208,19 @@ module Mongo
161
208
  end
162
209
  end
163
210
 
164
- # We are buildling libmongocrypt without crypto functions to remove the
211
+ # Perform signing using RSASSA-PKCS1-v1_5 with SHA256 hash and write
212
+ # the output to the provided mongocrypt_binary_t object.
213
+ def do_rsaes_pkcs_signature(key_binary_p, input_binary_p,
214
+ output_binary_p, status_p)
215
+ key = Binary.from_pointer(key_binary_p).to_s
216
+ input = Binary.from_pointer(input_binary_p).to_s
217
+
218
+ write_binary_string_and_set_status(output_binary_p, status_p) do
219
+ Hooks.rsaes_pkcs_signature(key, input)
220
+ end
221
+ end
222
+
223
+ # We are building libmongocrypt without crypto functions to remove the
165
224
  # external dependency on OpenSSL. This method binds native Ruby crypto
166
225
  # methods to the underlying mongocrypt_t object so that libmongocrypt can
167
226
  # still perform cryptography.
@@ -227,85 +286,49 @@ module Mongo
227
286
  @hmac_sha_256,
228
287
  @hmac_hash,
229
288
  )
230
- end
231
-
232
- # Validate the kms_providers option and use it to set the KMS provider
233
- # information on the underlying mongocrypt_t object
234
- def set_kms_providers(kms_providers)
235
- unless kms_providers
236
- raise ArgumentError.new("The kms_providers option must not be nil")
237
- end
238
-
239
- unless kms_providers.key?(:local) || kms_providers.key?(:aws)
240
- raise ArgumentError.new(
241
- 'The kms_providers option must have one of the following keys: ' +
242
- ':aws, :local'
243
- )
244
- end
245
-
246
- set_kms_providers_local(kms_providers) if kms_providers.key?(:local)
247
- set_kms_providers_aws(kms_providers) if kms_providers.key?(:aws)
248
- end
249
289
 
250
- # Validate and set the local KMS provider information on the underlying
251
- # mongocrypt_t object and raise an exception if the operation fails
252
- def set_kms_providers_local(kms_providers)
253
- unless kms_providers[:local][:key] && kms_providers[:local][:key].is_a?(String)
254
- raise ArgumentError.new(
255
- "The specified local kms_providers option is invalid: " +
256
- "#{kms_providers[:local]}. kms_providers with :local key must be " +
257
- "in the format: { local: { key: 'MASTER-KEY' } }"
290
+ @aes_ctr_encrypt = Proc.new do |_, key_binary_p, iv_binary_p, input_binary_p,
291
+ output_binary_p, response_length_p, status_p|
292
+ do_aes(
293
+ key_binary_p,
294
+ iv_binary_p,
295
+ input_binary_p,
296
+ output_binary_p,
297
+ response_length_p,
298
+ status_p,
299
+ mode: :CTR,
258
300
  )
259
301
  end
260
302
 
261
- master_key = kms_providers[:local][:key]
262
- Binding.setopt_kms_provider_local(self, master_key)
263
- end
264
-
265
- # Validate and set the aws KMS provider information on the underlying
266
- # mongocrypt_t object and raise an exception if the operation fails
267
- def set_kms_providers_aws(kms_providers)
268
- unless kms_providers[:aws]
269
- raise ArgumentError.new('The :aws KMS provider must not be nil')
270
- end
271
-
272
- access_key_id = kms_providers[:aws][:access_key_id]
273
- secret_access_key = kms_providers[:aws][:secret_access_key]
274
-
275
- unless kms_providers[:aws].key?(:access_key_id) &&
276
- kms_providers[:aws].key?(:secret_access_key)
277
- raise ArgumentError.new(
278
- "The specified aws kms_providers option is invalid: #{kms_providers[:aws]}. " +
279
- "kms_providers with :aws key must be in the format: " +
280
- "{ aws: { access_key_id: 'YOUR-ACCESS-KEY-ID', secret_access_key: 'SECRET-ACCESS-KEY' } }"
303
+ @aes_ctr_decrypt = Proc.new do |_, key_binary_p, iv_binary_p, input_binary_p,
304
+ output_binary_p, response_length_p, status_p|
305
+ do_aes(
306
+ key_binary_p,
307
+ iv_binary_p,
308
+ input_binary_p,
309
+ output_binary_p,
310
+ response_length_p,
311
+ status_p,
312
+ decrypt: true,
313
+ mode: :CTR,
281
314
  )
282
315
  end
283
316
 
284
- %i(access_key_id secret_access_key).each do |key|
285
- value = kms_providers[:aws][key]
286
- if value.nil?
287
- raise ArgumentError.new(
288
- "The aws #{key} option must be a String with at least one character; " \
289
- "currently have nil"
290
- )
291
- end
292
-
293
- unless value.is_a?(String)
294
- raise ArgumentError.new(
295
- "The aws #{key} option must be a String with at least one character; " \
296
- "currently have #{value}"
297
- )
298
- end
317
+ Binding.setopt_aes_256_ctr(
318
+ self,
319
+ @aes_ctr_encrypt,
320
+ @aes_ctr_decrypt,
321
+ )
299
322
 
300
- if value.empty?
301
- raise ArgumentError.new(
302
- "The aws #{key} option must be a String with at least one character; " \
303
- "it is currently an empty string"
304
- )
305
- end
323
+ @rsaes_pkcs_signature_cb = Proc.new do |_, key_binary_p, input_binary_p,
324
+ output_binary_p, status_p|
325
+ do_rsaes_pkcs_signature(key_binary_p, input_binary_p, output_binary_p, status_p)
306
326
  end
307
327
 
308
- Binding.setopt_kms_provider_aws(self, access_key_id, secret_access_key)
328
+ Binding.setopt_crypto_hook_sign_rsaes_pkcs1_v1_5(
329
+ self,
330
+ @rsaes_pkcs_signature_cb
331
+ )
309
332
  end
310
333
 
311
334
  # Initialize the underlying mongocrypt_t object and raise an error if the operation fails