mongo 2.11.6 → 2.12.0.rc0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -2
  3. data.tar.gz.sig +0 -0
  4. data/CONTRIBUTING.md +1 -1
  5. data/lib/mongo.rb +3 -0
  6. data/lib/mongo/address.rb +13 -2
  7. data/lib/mongo/auth.rb +1 -0
  8. data/lib/mongo/auth/credential_cache.rb +51 -0
  9. data/lib/mongo/auth/scram/conversation.rb +20 -16
  10. data/lib/mongo/auth/user.rb +0 -8
  11. data/lib/mongo/auth/user/view.rb +4 -4
  12. data/lib/mongo/background_thread.rb +1 -1
  13. data/lib/mongo/bulk_write.rb +5 -5
  14. data/lib/mongo/client.rb +126 -11
  15. data/lib/mongo/client_encryption.rb +103 -0
  16. data/lib/mongo/cluster.rb +2 -2
  17. data/lib/mongo/cluster/reapers/cursor_reaper.rb +18 -6
  18. data/lib/mongo/cluster/sdam_flow.rb +54 -58
  19. data/lib/mongo/cluster/srv_monitor.rb +1 -1
  20. data/lib/mongo/collection.rb +3 -3
  21. data/lib/mongo/collection/view.rb +1 -1
  22. data/lib/mongo/collection/view/aggregation.rb +1 -1
  23. data/lib/mongo/collection/view/change_stream.rb +12 -3
  24. data/lib/mongo/collection/view/iterable.rb +14 -5
  25. data/lib/mongo/collection/view/map_reduce.rb +2 -2
  26. data/lib/mongo/collection/view/readable.rb +7 -9
  27. data/lib/mongo/collection/view/writable.rb +7 -7
  28. data/lib/mongo/crypt.rb +33 -0
  29. data/lib/mongo/crypt/auto_decryption_context.rb +42 -0
  30. data/lib/mongo/crypt/auto_encrypter.rb +169 -0
  31. data/lib/mongo/crypt/auto_encryption_context.rb +44 -0
  32. data/lib/mongo/crypt/binary.rb +155 -0
  33. data/lib/mongo/crypt/binding.rb +1162 -0
  34. data/lib/mongo/crypt/context.rb +135 -0
  35. data/lib/mongo/crypt/data_key_context.rb +162 -0
  36. data/lib/mongo/crypt/encryption_io.rb +283 -0
  37. data/lib/mongo/crypt/explicit_decryption_context.rb +40 -0
  38. data/lib/mongo/crypt/explicit_encrypter.rb +117 -0
  39. data/lib/mongo/crypt/explicit_encryption_context.rb +89 -0
  40. data/lib/mongo/crypt/handle.rb +293 -0
  41. data/lib/mongo/crypt/hooks.rb +90 -0
  42. data/lib/mongo/crypt/kms_context.rb +67 -0
  43. data/lib/mongo/crypt/status.rb +131 -0
  44. data/lib/mongo/cursor.rb +64 -32
  45. data/lib/mongo/database.rb +13 -6
  46. data/lib/mongo/database/view.rb +13 -4
  47. data/lib/mongo/dbref.rb +9 -2
  48. data/lib/mongo/error.rb +5 -1
  49. data/lib/mongo/error/crypt_error.rb +31 -0
  50. data/lib/mongo/error/{failed_stringprep_validation.rb → failed_string_prep_validation.rb} +0 -0
  51. data/lib/mongo/error/invalid_cursor_operation.rb +27 -0
  52. data/lib/mongo/error/kms_error.rb +22 -0
  53. data/lib/mongo/error/max_bson_size.rb +14 -3
  54. data/lib/mongo/error/mongocryptd_spawn_error.rb +22 -0
  55. data/lib/mongo/error/no_server_available.rb +8 -3
  56. data/lib/mongo/error/operation_failure.rb +1 -0
  57. data/lib/mongo/grid/file.rb +0 -5
  58. data/lib/mongo/grid/file/chunk.rb +0 -2
  59. data/lib/mongo/grid/file/info.rb +2 -1
  60. data/lib/mongo/grid/fs_bucket.rb +13 -15
  61. data/lib/mongo/grid/stream/write.rb +3 -9
  62. data/lib/mongo/index/view.rb +3 -3
  63. data/lib/mongo/monitoring/event/command_started.rb +6 -1
  64. data/lib/mongo/operation/collections_info.rb +6 -3
  65. data/lib/mongo/operation/delete/op_msg.rb +1 -1
  66. data/lib/mongo/operation/find/op_msg.rb +4 -1
  67. data/lib/mongo/operation/get_more/op_msg.rb +4 -1
  68. data/lib/mongo/operation/insert/command.rb +2 -2
  69. data/lib/mongo/operation/insert/legacy.rb +2 -2
  70. data/lib/mongo/operation/insert/op_msg.rb +3 -3
  71. data/lib/mongo/operation/result.rb +36 -27
  72. data/lib/mongo/operation/shared/executable.rb +10 -8
  73. data/lib/mongo/operation/shared/executable_no_validate.rb +2 -2
  74. data/lib/mongo/operation/shared/op_msg_or_command.rb +2 -2
  75. data/lib/mongo/operation/shared/op_msg_or_find_command.rb +2 -2
  76. data/lib/mongo/operation/shared/op_msg_or_list_indexes_command.rb +2 -2
  77. data/lib/mongo/operation/shared/write.rb +17 -10
  78. data/lib/mongo/operation/update/op_msg.rb +1 -1
  79. data/lib/mongo/protocol/compressed.rb +6 -5
  80. data/lib/mongo/protocol/insert.rb +3 -1
  81. data/lib/mongo/protocol/message.rb +72 -8
  82. data/lib/mongo/protocol/msg.rb +191 -37
  83. data/lib/mongo/protocol/query.rb +7 -9
  84. data/lib/mongo/protocol/serializers.rb +6 -2
  85. data/lib/mongo/server.rb +10 -4
  86. data/lib/mongo/server/connection.rb +20 -9
  87. data/lib/mongo/server/connection_base.rb +81 -12
  88. data/lib/mongo/server/connection_common.rb +61 -0
  89. data/lib/mongo/server/connection_pool.rb +37 -1
  90. data/lib/mongo/server/description.rb +9 -11
  91. data/lib/mongo/server/monitor.rb +2 -0
  92. data/lib/mongo/server/monitor/connection.rb +3 -18
  93. data/lib/mongo/server/pending_connection.rb +2 -1
  94. data/lib/mongo/session.rb +2 -2
  95. data/lib/mongo/session/session_pool.rb +8 -3
  96. data/lib/mongo/socket.rb +29 -16
  97. data/lib/mongo/socket/ssl.rb +23 -8
  98. data/lib/mongo/socket/tcp.rb +12 -3
  99. data/lib/mongo/timeout.rb +49 -0
  100. data/lib/mongo/uri.rb +30 -1
  101. data/lib/mongo/version.rb +1 -1
  102. data/mongo.gemspec +1 -1
  103. data/spec/README.md +134 -7
  104. data/spec/integration/auth_spec.rb +53 -0
  105. data/spec/integration/{client_options_spec.rb → client_authentication_options_spec.rb} +10 -10
  106. data/spec/integration/client_construction_spec.rb +76 -1
  107. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +351 -0
  108. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +301 -0
  109. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +71 -0
  110. data/spec/integration/client_side_encryption/auto_encryption_old_wire_version_spec.rb +76 -0
  111. data/spec/integration/client_side_encryption/auto_encryption_reconnect_spec.rb +216 -0
  112. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +600 -0
  113. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +183 -0
  114. data/spec/integration/client_side_encryption/bypass_mongocryptd_spawn_spec.rb +74 -0
  115. data/spec/integration/client_side_encryption/client_close_spec.rb +59 -0
  116. data/spec/integration/client_side_encryption/corpus_spec.rb +228 -0
  117. data/spec/integration/client_side_encryption/custom_endpoint_spec.rb +132 -0
  118. data/spec/integration/client_side_encryption/data_key_spec.rb +163 -0
  119. data/spec/integration/client_side_encryption/explicit_encryption_spec.rb +114 -0
  120. data/spec/integration/client_side_encryption/external_key_vault_spec.rb +137 -0
  121. data/spec/integration/client_side_encryption/views_spec.rb +42 -0
  122. data/spec/integration/client_update_spec.rb +120 -0
  123. data/spec/integration/command_monitoring_spec.rb +3 -1
  124. data/spec/integration/command_spec.rb +44 -10
  125. data/spec/integration/connection_spec.rb +57 -0
  126. data/spec/integration/reconnect_spec.rb +7 -6
  127. data/spec/integration/size_limit_spec.rb +94 -0
  128. data/spec/integration/srv_monitoring_spec.rb +14 -6
  129. data/spec/lite_spec_helper.rb +31 -22
  130. data/spec/mongo/auth/cr_spec.rb +8 -0
  131. data/spec/mongo/auth/ldap_spec.rb +5 -1
  132. data/spec/mongo/auth/scram/conversation_spec.rb +5 -6
  133. data/spec/mongo/auth/scram/negotiation_spec.rb +74 -75
  134. data/spec/mongo/auth/scram_spec.rb +45 -35
  135. data/spec/mongo/auth/x509_spec.rb +5 -1
  136. data/spec/mongo/client_construction_spec.rb +206 -3
  137. data/spec/mongo/client_encryption_spec.rb +408 -0
  138. data/spec/mongo/cluster/cursor_reaper_spec.rb +12 -8
  139. data/spec/mongo/cluster/socket_reaper_spec.rb +14 -3
  140. data/spec/mongo/collection/view/aggregation_spec.rb +0 -2
  141. data/spec/mongo/collection/view/change_stream_spec.rb +7 -7
  142. data/spec/mongo/collection/view/map_reduce_spec.rb +3 -3
  143. data/spec/mongo/collection/view_spec.rb +1 -1
  144. data/spec/mongo/collection_spec.rb +4 -33
  145. data/spec/mongo/crypt/auto_decryption_context_spec.rb +90 -0
  146. data/spec/mongo/crypt/auto_encrypter_spec.rb +182 -0
  147. data/spec/mongo/crypt/auto_encryption_context_spec.rb +107 -0
  148. data/spec/mongo/crypt/binary_spec.rb +115 -0
  149. data/spec/mongo/crypt/binding/binary_spec.rb +56 -0
  150. data/spec/mongo/crypt/binding/context_spec.rb +257 -0
  151. data/spec/mongo/crypt/binding/helpers_spec.rb +46 -0
  152. data/spec/mongo/crypt/binding/mongocrypt_spec.rb +144 -0
  153. data/spec/mongo/crypt/binding/status_spec.rb +99 -0
  154. data/spec/mongo/crypt/binding/version_spec.rb +22 -0
  155. data/spec/mongo/crypt/binding_unloaded_spec.rb +20 -0
  156. data/spec/mongo/crypt/data_key_context_spec.rb +213 -0
  157. data/spec/mongo/crypt/encryption_io_spec.rb +136 -0
  158. data/spec/mongo/crypt/explicit_decryption_context_spec.rb +72 -0
  159. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +170 -0
  160. data/spec/mongo/crypt/handle_spec.rb +198 -0
  161. data/spec/mongo/crypt/helpers/mongo_crypt_spec_helper.rb +108 -0
  162. data/spec/mongo/crypt/status_spec.rb +152 -0
  163. data/spec/mongo/cursor_spec.rb +24 -4
  164. data/spec/mongo/database_spec.rb +20 -0
  165. data/spec/mongo/error/crypt_error_spec.rb +26 -0
  166. data/spec/mongo/error/max_bson_size_spec.rb +35 -0
  167. data/spec/mongo/error/no_server_available_spec.rb +11 -1
  168. data/spec/mongo/error/operation_failure_spec.rb +6 -6
  169. data/spec/mongo/operation/aggregate_spec.rb +1 -1
  170. data/spec/mongo/operation/collections_info_spec.rb +1 -1
  171. data/spec/mongo/operation/command_spec.rb +3 -3
  172. data/spec/mongo/operation/create_index_spec.rb +3 -3
  173. data/spec/mongo/operation/create_user_spec.rb +3 -3
  174. data/spec/mongo/operation/delete/bulk_spec.rb +6 -6
  175. data/spec/mongo/operation/delete/op_msg_spec.rb +1 -6
  176. data/spec/mongo/operation/delete_spec.rb +7 -7
  177. data/spec/mongo/operation/drop_index_spec.rb +2 -2
  178. data/spec/mongo/operation/find/legacy_spec.rb +1 -1
  179. data/spec/mongo/operation/get_more_spec.rb +1 -1
  180. data/spec/mongo/operation/indexes_spec.rb +1 -1
  181. data/spec/mongo/operation/insert/bulk_spec.rb +7 -7
  182. data/spec/mongo/operation/insert/op_msg_spec.rb +3 -6
  183. data/spec/mongo/operation/insert_spec.rb +12 -12
  184. data/spec/mongo/operation/map_reduce_spec.rb +2 -2
  185. data/spec/mongo/operation/remove_user_spec.rb +3 -3
  186. data/spec/mongo/operation/update/bulk_spec.rb +6 -6
  187. data/spec/mongo/operation/update/op_msg_spec.rb +3 -6
  188. data/spec/mongo/operation/update_spec.rb +7 -7
  189. data/spec/mongo/operation/update_user_spec.rb +1 -1
  190. data/spec/mongo/protocol/compressed_spec.rb +2 -3
  191. data/spec/mongo/protocol/delete_spec.rb +9 -8
  192. data/spec/mongo/protocol/get_more_spec.rb +9 -8
  193. data/spec/mongo/protocol/insert_spec.rb +9 -8
  194. data/spec/mongo/protocol/kill_cursors_spec.rb +6 -5
  195. data/spec/mongo/protocol/msg_spec.rb +57 -53
  196. data/spec/mongo/protocol/query_spec.rb +12 -12
  197. data/spec/mongo/protocol/registry_spec.rb +1 -1
  198. data/spec/mongo/protocol/reply_spec.rb +1 -1
  199. data/spec/mongo/protocol/update_spec.rb +10 -9
  200. data/spec/mongo/server/connection_pool_spec.rb +1 -1
  201. data/spec/mongo/server/connection_spec.rb +28 -7
  202. data/spec/mongo/socket_spec.rb +1 -1
  203. data/spec/mongo/timeout_spec.rb +85 -0
  204. data/spec/mongo/uri/srv_protocol_spec.rb +2 -2
  205. data/spec/mongo/uri_spec.rb +52 -5
  206. data/spec/mongo/write_concern_spec.rb +13 -1
  207. data/spec/{support → runners}/auth.rb +14 -1
  208. data/spec/{support → runners}/change_streams.rb +1 -1
  209. data/spec/{support → runners}/change_streams/operation.rb +0 -0
  210. data/spec/{support → runners}/cmap.rb +1 -1
  211. data/spec/{support → runners}/cmap/verifier.rb +0 -0
  212. data/spec/{support → runners}/command_monitoring.rb +0 -0
  213. data/spec/runners/connection_string.rb +358 -4
  214. data/spec/{support → runners}/crud.rb +9 -9
  215. data/spec/{support → runners}/crud/context.rb +0 -0
  216. data/spec/{support → runners}/crud/operation.rb +7 -3
  217. data/spec/{support → runners}/crud/outcome.rb +0 -0
  218. data/spec/{support → runners}/crud/requirement.rb +1 -1
  219. data/spec/{support → runners}/crud/spec.rb +12 -1
  220. data/spec/{support → runners}/crud/test.rb +0 -0
  221. data/spec/{support → runners}/crud/test_base.rb +0 -0
  222. data/spec/{support → runners}/crud/verifier.rb +10 -12
  223. data/spec/{support → runners}/gridfs.rb +0 -0
  224. data/spec/{support → runners}/sdam_monitoring.rb +0 -0
  225. data/spec/{support → runners}/server_discovery_and_monitoring.rb +0 -0
  226. data/spec/{support → runners}/server_selection.rb +0 -0
  227. data/spec/{support → runners}/server_selection_rtt.rb +0 -0
  228. data/spec/{support → runners}/transactions.rb +4 -4
  229. data/spec/{support → runners}/transactions/context.rb +0 -0
  230. data/spec/{support → runners}/transactions/operation.rb +0 -0
  231. data/spec/{support → runners}/transactions/spec.rb +0 -0
  232. data/spec/{support → runners}/transactions/test.rb +37 -5
  233. data/spec/spec_helper.rb +0 -5
  234. data/spec/spec_tests/auth_spec.rb +3 -3
  235. data/spec/spec_tests/client_side_encryption_spec.rb +13 -0
  236. data/spec/spec_tests/connection_string_spec.rb +1 -1
  237. data/spec/spec_tests/data/auth/connection-string.yml +13 -0
  238. data/spec/spec_tests/data/client_side_encryption/aggregate.yml +134 -0
  239. data/spec/spec_tests/data/client_side_encryption/badQueries.yml +526 -0
  240. data/spec/spec_tests/data/client_side_encryption/badSchema.yml +73 -0
  241. data/spec/spec_tests/data/client_side_encryption/basic.yml +116 -0
  242. data/spec/spec_tests/data/client_side_encryption/bulk.yml +85 -0
  243. data/spec/spec_tests/data/client_side_encryption/bypassAutoEncryption.yml +100 -0
  244. data/spec/spec_tests/data/client_side_encryption/bypassedCommand.yml +42 -0
  245. data/spec/spec_tests/data/client_side_encryption/count.yml +61 -0
  246. data/spec/spec_tests/data/client_side_encryption/countDocuments.yml +59 -0
  247. data/spec/spec_tests/data/client_side_encryption/delete.yml +105 -0
  248. data/spec/spec_tests/data/client_side_encryption/distinct.yml +73 -0
  249. data/spec/spec_tests/data/client_side_encryption/explain.yml +64 -0
  250. data/spec/spec_tests/data/client_side_encryption/find.yml +119 -0
  251. data/spec/spec_tests/data/client_side_encryption/findOneAndDelete.yml +57 -0
  252. data/spec/spec_tests/data/client_side_encryption/findOneAndReplace.yml +57 -0
  253. data/spec/spec_tests/data/client_side_encryption/findOneAndUpdate.yml +57 -0
  254. data/spec/spec_tests/data/client_side_encryption/getMore.yml +68 -0
  255. data/spec/spec_tests/data/client_side_encryption/insert.yml +102 -0
  256. data/spec/spec_tests/data/client_side_encryption/keyAltName.yml +71 -0
  257. data/spec/spec_tests/data/client_side_encryption/localKMS.yml +54 -0
  258. data/spec/spec_tests/data/client_side_encryption/localSchema.yml +72 -0
  259. data/spec/spec_tests/data/client_side_encryption/malformedCiphertext.yml +69 -0
  260. data/spec/spec_tests/data/client_side_encryption/maxWireVersion.yml +20 -0
  261. data/spec/spec_tests/data/client_side_encryption/missingKey.yml +49 -0
  262. data/spec/spec_tests/data/client_side_encryption/replaceOne.yml +61 -0
  263. data/spec/spec_tests/data/client_side_encryption/types.yml +527 -0
  264. data/spec/spec_tests/data/client_side_encryption/unsupportedCommand.yml +25 -0
  265. data/spec/spec_tests/data/client_side_encryption/updateMany.yml +77 -0
  266. data/spec/spec_tests/data/client_side_encryption/updateOne.yml +168 -0
  267. data/spec/spec_tests/data/read_write_concern/connection-string/write-concern.yml +1 -4
  268. data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +21 -0
  269. data/spec/spec_tests/data/sdam/rs/incompatible_ghost.yml +2 -4
  270. data/spec/spec_tests/data/sdam/rs/incompatible_other.yml +1 -1
  271. data/spec/spec_tests/data/sdam/rs/primary_mismatched_me_not_removed.yml +73 -0
  272. data/spec/spec_tests/data/sdam/rs/primary_to_no_primary_mismatched_me.yml +1 -2
  273. data/spec/spec_tests/data/sdam/rs/repeated.yml +101 -0
  274. data/spec/spec_tests/data/sdam/rs/{primary_address_change.yml → ruby_primary_address_change.yml} +2 -0
  275. data/spec/spec_tests/data/sdam/rs/{secondary_wrong_set_name_with_primary_second.yml → ruby_secondary_wrong_set_name_with_primary_second.yml} +0 -0
  276. data/spec/spec_tests/data/sdam/sharded/ruby_discovered_single_mongos.yml +27 -0
  277. data/spec/spec_tests/data/sdam/sharded/{primary_address_change.yml → ruby_primary_different_address.yml} +1 -1
  278. data/spec/spec_tests/data/sdam/sharded/{primary_mismatched_me.yml → ruby_primary_mismatched_me.yml} +1 -1
  279. data/spec/spec_tests/data/sdam/single/{primary_address_change.yml → ruby_primary_different_address.yml} +1 -1
  280. data/spec/spec_tests/data/sdam/single/{primary_mismatched_me.yml → ruby_primary_mismatched_me.yml} +1 -1
  281. data/spec/spec_tests/data/sdam_monitoring/{replica_set_with_primary_change.yml → replica_set_primary_address_change.yml} +27 -5
  282. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_me_mismatch.yml +26 -74
  283. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_removal.yml +20 -16
  284. data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +73 -0
  285. data/spec/spec_tests/data/transactions/pin-mongos.yml +2 -3
  286. data/spec/spec_tests/data/uri_options/auth-options.yml +10 -0
  287. data/spec/spec_tests/data/uri_options/tls-options.yml +75 -4
  288. data/spec/spec_tests/read_write_concern_connection_string_spec.rb +1 -1
  289. data/spec/spec_tests/uri_options_spec.rb +6 -8
  290. data/spec/stress/connection_pool_timing_spec.rb +6 -3
  291. data/spec/support/certificates/README.md +4 -0
  292. data/spec/support/certificates/server-second-level-bundle.pem +77 -77
  293. data/spec/support/certificates/server-second-level.crt +52 -52
  294. data/spec/support/certificates/server-second-level.key +25 -25
  295. data/spec/support/certificates/server-second-level.pem +77 -77
  296. data/spec/support/client_registry.rb +19 -3
  297. data/spec/support/cluster_config.rb +9 -1
  298. data/spec/support/common_shortcuts.rb +12 -0
  299. data/spec/support/constraints.rb +16 -0
  300. data/spec/support/crypt.rb +140 -0
  301. data/spec/support/crypt/corpus/corpus-key-aws.json +33 -0
  302. data/spec/support/crypt/corpus/corpus-key-local.json +31 -0
  303. data/spec/support/crypt/corpus/corpus-schema.json +2057 -0
  304. data/spec/support/crypt/corpus/corpus.json +3657 -0
  305. data/spec/support/crypt/corpus/corpus_encrypted.json +4152 -0
  306. data/spec/support/crypt/data_keys/key_document_aws.json +34 -0
  307. data/spec/support/crypt/data_keys/key_document_local.json +31 -0
  308. data/spec/support/crypt/external/external-key.json +31 -0
  309. data/spec/support/crypt/external/external-schema.json +19 -0
  310. data/spec/support/crypt/limits/limits-doc.json +102 -0
  311. data/spec/support/crypt/limits/limits-key.json +31 -0
  312. data/spec/support/crypt/limits/limits-schema.json +1405 -0
  313. data/spec/support/crypt/schema_maps/schema_map_aws.json +17 -0
  314. data/spec/support/crypt/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  315. data/spec/support/crypt/schema_maps/schema_map_local.json +18 -0
  316. data/spec/support/crypt/schema_maps/schema_map_local_key_alt_names.json +12 -0
  317. data/spec/support/lite_constraints.rb +17 -1
  318. data/spec/support/matchers.rb +19 -0
  319. data/spec/support/shared/protocol.rb +2 -0
  320. data/spec/support/spec_config.rb +43 -13
  321. data/spec/support/utils.rb +132 -10
  322. metadata +277 -81
  323. metadata.gz.sig +0 -0
  324. data/spec/integration/grid_fs_bucket_spec.rb +0 -48
  325. data/spec/integration/zlib_compression_spec.rb +0 -25
  326. data/spec/spec_tests/data/sdam/sharded/single_mongos.yml +0 -33
  327. data/spec/support/connection_string.rb +0 -354
@@ -0,0 +1,1162 @@
1
+ # Copyright (C) 2019 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ unless ENV['LIBMONGOCRYPT_PATH']
16
+ # It seems that MRI maintains autoload configuration for a module until
17
+ # that module is defined, but JRuby removes autoload configuration as soon
18
+ # as the referenced file is attempted to be loaded, even if the module
19
+ # never ends up being defined.
20
+ if BSON::Environment.jruby?
21
+ module Mongo
22
+ module Crypt
23
+ autoload :Binding, 'mongo/crypt/binding'
24
+ end
25
+ end
26
+ end
27
+
28
+ raise LoadError, "Cannot load Mongo::Crypt::Binding because there is no path " +
29
+ "to libmongocrypt specified in the LIBMONGOCRYPT_PATH environment variable."
30
+ end
31
+
32
+ require 'ffi'
33
+
34
+ module Mongo
35
+ module Crypt
36
+
37
+ # @api private
38
+ def reset_autoload
39
+ remove_const(:Binding)
40
+ autoload(:Binding, 'mongo/crypt/binding')
41
+ end
42
+ module_function :reset_autoload
43
+
44
+ # A Ruby binding for the libmongocrypt C library
45
+ #
46
+ # @api private
47
+ class Binding
48
+ extend FFI::Library
49
+
50
+ begin
51
+ ffi_lib ENV['LIBMONGOCRYPT_PATH']
52
+ rescue LoadError => e
53
+ Crypt.reset_autoload
54
+ raise LoadError, "Cannot load Mongo::Crypt::Binding because the path to " +
55
+ "libmongocrypt specified in the LIBMONGOCRYPT_PATH environment variable " +
56
+ "is invalid: #{ENV['LIBMONGOCRYPT_PATH']}\n\n#{e.class}: #{e.message}"
57
+ end
58
+
59
+ # Returns the version string of the libmongocrypt library
60
+ #
61
+ # @param [ FFI::Pointer | nil ] len (out param) An optional pointer to a
62
+ # uint8 that will reference the length of the returned string.
63
+ #
64
+ # @return [ String ] A version string for libmongocrypt
65
+ attach_function :mongocrypt_version, [:pointer], :string
66
+
67
+ # Create a new mongocrypt_binary_t object (a non-owning view of a byte
68
+ # array)
69
+ #
70
+ # @return [ FFI::Pointer ] A pointer to the newly-created
71
+ # mongocrypt_binary_t object
72
+ attach_function :mongocrypt_binary_new, [], :pointer
73
+
74
+ # Create a new mongocrypt_binary_t object that maintains a pointer to
75
+ # the specified byte array.
76
+ #
77
+ # @param [ FFI::Pointer ] data A pointer to an array of bytes; the data
78
+ # is not copied and must outlive the mongocrypt_binary_t object
79
+ # @param [ Integer ] len The length of the array argument
80
+ #
81
+ # @return [ FFI::Pointer ] A pointer to the newly-created
82
+ # mongocrypt_binary_t object
83
+ attach_function(
84
+ :mongocrypt_binary_new_from_data,
85
+ [:pointer, :int],
86
+ :pointer
87
+ )
88
+
89
+ # Get the pointer to the underlying data for the mongocrypt_binary_t
90
+ #
91
+ # @param [ FFI::Pointer ] binary A pointer to a mongocrypt_binary_t object
92
+ #
93
+ # @return [ FFI::Pointer ] A pointer to the data array
94
+ attach_function :mongocrypt_binary_data, [:pointer], :pointer
95
+
96
+ # Get the length of the underlying data array
97
+ #
98
+ # @param [ FFI::Pointer ] binary A pointer to a mongocrypt_binary_t object
99
+ #
100
+ # @return [ Integer ] The length of the data array
101
+ attach_function :mongocrypt_binary_len, [:pointer], :int
102
+
103
+ # Destroy the mongocrypt_binary_t object
104
+ #
105
+ # @param [ FFI::Pointer ] A pointer to a mongocrypt_binary_t object
106
+ #
107
+ # @return [ nil ] Always nil
108
+ attach_function :mongocrypt_binary_destroy, [:pointer], :void
109
+
110
+ # Enum labeling different status types
111
+ enum :status_type, [
112
+ :ok, 0,
113
+ :error_client, 1,
114
+ :error_kms, 2,
115
+ ]
116
+
117
+ # Create a new mongocrypt_status_t object
118
+ #
119
+ # @return [ FFI::Pointer ] A pointer to the new mongocrypt_status_ts
120
+ attach_function :mongocrypt_status_new, [], :pointer
121
+
122
+ # Set a message, type, and code on an existing status
123
+ #
124
+ # @param [ FFI::Pointer ] status A pointer to a mongocrypt_status_t
125
+ # @param [ Symbol ] type The status type; possible values are defined
126
+ # by the status_type enum
127
+ # @param [ Integer ] code The status code
128
+ # @param [ String ] message The status message
129
+ # @param [ Integer ] len The length of the message argument (or -1 for a
130
+ # null-terminated string)
131
+ #
132
+ # @return [ nil ] Always nil
133
+ attach_function(
134
+ :mongocrypt_status_set,
135
+ [:pointer, :status_type, :int, :string, :int],
136
+ :void
137
+ )
138
+
139
+ # Indicates the status type
140
+ #
141
+ # @param [ FFI::Pointer ] status A pointer to a mongocrypt_status_t
142
+ #
143
+ # @return [ Symbol ] The status type (as defined by the status_type enum)
144
+ attach_function :mongocrypt_status_type, [:pointer], :status_type
145
+
146
+ # Return the status error code
147
+ #
148
+ # @param [ FFI::Pointer ] status A pointer to a mongocrypt_status_t
149
+ #
150
+ # @return [ Integer ] The status code
151
+ attach_function :mongocrypt_status_code, [:pointer], :int
152
+
153
+ # Returns the status message
154
+ #
155
+ # @param [ FFI::Pointer ] status A pointer to a mongocrypt_status_t
156
+ # @param [ FFI::Pointer | nil ] len (out param) An optional pointer to a
157
+ # uint32, where the length of the retun string will be written
158
+ #
159
+ # @return [ String ] The status message
160
+ attach_function :mongocrypt_status_message, [:pointer, :pointer], :string
161
+
162
+ # Returns whether the status is ok or an error
163
+ #
164
+ # @param [ FFI::Pointer ] status A pointer to a mongocrypt_status_t
165
+ #
166
+ # @return [ Boolean ] Whether the status is ok
167
+ attach_function :mongocrypt_status_ok, [:pointer], :bool
168
+
169
+ # Destroys the reference to the mongocrypt_status_t object
170
+ #
171
+ # @param [ FFI::Pointer ] status A pointer to a mongocrypt_status_t
172
+ #
173
+ # @return [ nil ] Always nil
174
+ attach_function :mongocrypt_status_destroy, [:pointer], :void
175
+
176
+ # Enum labeling the various log levels
177
+ enum :log_level, [
178
+ :fatal, 0,
179
+ :error, 1,
180
+ :warn, 2,
181
+ :info, 3,
182
+ :debug, 4,
183
+ ]
184
+
185
+ # A callback to the mongocrypt log function
186
+ # Set a custom log callback with the mongocrypt_setopt_log_handler method
187
+ #
188
+ # @param [ Symbol ] level The log level; possible values defined by the
189
+ # log_level enum
190
+ # @param [ String ] message The log message
191
+ # @param [ Integer ] len The length of the message param, or -1 if the
192
+ # string is null terminated
193
+ # @param [ FFI::Pointer | nil ] ctx An optional pointer to a context
194
+ # object when this callback was set
195
+ #
196
+ # @return [ nil ] Always nil.
197
+ callback :mongocrypt_log_fn_t, [:log_level, :string, :int, :pointer], :void
198
+
199
+ # Creates a new mongocrypt_t object
200
+ #
201
+ # @return [ FFI::Pointer ] A pointer to a new mongocrypt_t object
202
+ attach_function :mongocrypt_new, [], :pointer
203
+
204
+ # Set the handler on the mongocrypt_t object to be called every time
205
+ # libmongocrypt logs a message
206
+ #
207
+ # @param [ FFI::Pointer ] crypt A pointer to a mongocrypt_t object
208
+ # @param [ Method ] log_fn A logging callback method
209
+ # @param [ FFI::Pointer | nil ] log_ctx An optional pointer to a context
210
+ # to be passed into the log callback on every invocation.
211
+ #
212
+ # @return [ Boolean ] Whether setting the callback was successful
213
+ attach_function(
214
+ :mongocrypt_setopt_log_handler,
215
+ [:pointer, :mongocrypt_log_fn_t, :pointer],
216
+ :bool
217
+ )
218
+
219
+ # Set the logger callback function on the Mongo::Crypt::Handle object
220
+ #
221
+ # @param [ Mongo::Crypt::Handle ] handle
222
+ # @param [ Method ] log_callback
223
+ #
224
+ # @raise [ Mongo::Error::CryptError ] If the callback is not set successfully
225
+ def self.setopt_log_handler(handle, log_callback)
226
+ check_status(handle) do
227
+ mongocrypt_setopt_log_handler(handle, log_callback, nil)
228
+ end
229
+ end
230
+
231
+ # Configure mongocrypt_t object with AWS KMS provider options
232
+ #
233
+ # @param [ FFI::Pointer ] crypt A pointer to a mongocrypt_t object
234
+ # @param [ String ] aws_access_key_id The AWS access key id
235
+ # @param [ Integer ] aws_access_key_id_len The length of the AWS access
236
+ # key string (or -1 for a null-terminated string)
237
+ # @param [ String ] aws_secret_access_key The AWS secret access key
238
+ # @param [ Integer ] aws_secret_access_key_len The length of the AWS
239
+ # secret access key (or -1 for a null-terminated string)
240
+ #
241
+ # @return [ Boolean ] Returns whether the option was set successfully
242
+ attach_function(
243
+ :mongocrypt_setopt_kms_provider_aws,
244
+ [:pointer, :string, :int, :string, :int],
245
+ :bool
246
+ )
247
+
248
+ # Configure the Handle object with AWS KMS provider options
249
+ #
250
+ # @param [ Mongo::Crypt::Handle ] handle
251
+ # @param [ String ] aws_access_key The AWS access key
252
+ # @param [ String ] aws_secret_access_key The AWS secret access key
253
+ #
254
+ # @raise [ Mongo::Error::CryptError ] If the option is not set successfully
255
+ def self.setopt_kms_provider_aws(handle,
256
+ aws_access_key, aws_secret_access_key
257
+ )
258
+ check_status(handle) do
259
+ mongocrypt_setopt_kms_provider_aws(
260
+ handle.ref,
261
+ aws_access_key,
262
+ -1,
263
+ aws_secret_access_key,
264
+ -1
265
+ )
266
+ end
267
+ end
268
+
269
+ # Configure mongocrypt_t object to take local KSM provider options
270
+ #
271
+ # @param [ FFI::Pointer ] crypt A pointer to a mongocrypt_t object
272
+ # @param [ FFI::Pointer ] key A pointer to a mongocrypt_binary_t object
273
+ # that references the 96-byte local master key
274
+ #
275
+ # @return [ Boolean ] Returns whether the option was set successfully
276
+ attach_function(
277
+ :mongocrypt_setopt_kms_provider_local,
278
+ [:pointer, :pointer],
279
+ :bool
280
+ )
281
+
282
+ # Set local KMS provider options on the Mongo::Crypt::Handle object
283
+ #
284
+ # @param [ Mongo::Crypt::Handle ] handle
285
+ # @param [ String ] master_key The 96-byte local KMS master key
286
+ #
287
+ # @raise [ Mongo::Error::CryptError ] If the option is not set successfully
288
+ def self.setopt_kms_provider_local(handle, master_key)
289
+ Binary.wrap_string(master_key) do |master_key_p|
290
+ check_status(handle) do
291
+ mongocrypt_setopt_kms_provider_local(handle.ref, master_key_p)
292
+ end
293
+ end
294
+ end
295
+
296
+ # Sets a local schema map for encryption
297
+ #
298
+ # @param [ FFI::Pointer ] crypt A pointer to a mongocrypt_t object
299
+ # @param [ FFI::Pointer ] schema_map A pointer to a mongocrypt_binary_t
300
+ # object that references the schema map as a BSON binary string
301
+ #
302
+ # @return [ Boolean ] Returns whether the option was set successfully
303
+ attach_function :mongocrypt_setopt_schema_map, [:pointer, :pointer], :bool
304
+
305
+ # Set schema map on the Mongo::Crypt::Handle object
306
+ #
307
+ # @param [ Mongo::Crypt::Handle ] handle
308
+ # @param [ BSON::Document ] schema_map_doc The schema map as a
309
+ # BSON::Document object
310
+ #
311
+ # @raise [ Mongo::Error::CryptError ] If the schema map is not set successfully
312
+ def self.setopt_schema_map(handle, schema_map_doc)
313
+ validate_document(schema_map_doc)
314
+ data = schema_map_doc.to_bson.to_s
315
+ Binary.wrap_string(data) do |data_p|
316
+ check_status(handle) do
317
+ mongocrypt_setopt_schema_map(handle.ref, data_p)
318
+ end
319
+ end
320
+ end
321
+
322
+ # Initialize the mongocrypt_t object
323
+ #
324
+ # @param [ FFI::Pointer ] crypt A pointer to a mongocrypt_t object
325
+ #
326
+ # @return [ Boolean ] Returns whether the crypt was initialized successfully
327
+ attach_function :mongocrypt_init, [:pointer], :bool
328
+
329
+ # Initialize the Mongo::Crypt::Handle object
330
+ #
331
+ # @param [ Mongo::Crypt::Handle ] handle
332
+ #
333
+ # @raise [ Mongo::Error::CryptError ] If initialization fails
334
+ def self.init(handle)
335
+ check_status(handle) do
336
+ mongocrypt_init(handle.ref)
337
+ end
338
+ end
339
+
340
+ # Set the status information from the mongocrypt_t object on the
341
+ # mongocrypt_status_t object
342
+ #
343
+ # @param [ FFI::Pointer ] crypt A pointer to a mongocrypt_t object
344
+ # @param [ FFI::Pointer ] status A pointer to a mongocrypt_status_t object
345
+ #
346
+ # @return [ Boolean ] Whether the status was successfully set
347
+ attach_function :mongocrypt_status, [:pointer, :pointer], :bool
348
+
349
+ # Destroy the reference the mongocrypt_t object
350
+ #
351
+ # @param [ FFI::Pointer ] crypt A pointer to a mongocrypt_t object
352
+ #
353
+ # @return [ nil ] Always nil
354
+ attach_function :mongocrypt_destroy, [:pointer], :void
355
+
356
+ # Create a new mongocrypt_ctx_t object (a wrapper for the libmongocrypt
357
+ # state machine)
358
+ #
359
+ # @param [ FFI::Pointer ] crypt A pointer to a mongocrypt_t object
360
+ #
361
+ # @return [ FFI::Pointer ] A new mongocrypt_ctx_t object
362
+ attach_function :mongocrypt_ctx_new, [:pointer], :pointer
363
+
364
+ # Set the status information from the mongocrypt_ctx_t object on the
365
+ # mongocrypt_status_t object
366
+ #
367
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
368
+ # @param [ FFI::Pointer ] status A pointer to a mongocrypt_status_t object
369
+ #
370
+ # @return [ Boolean ] Whether the status was successfully set
371
+ attach_function :mongocrypt_ctx_status, [:pointer, :pointer], :bool
372
+
373
+ # Set the key id used for explicit encryption
374
+ #
375
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
376
+ # @param [ FFI::Pointer ] key_id A pointer to a mongocrypt_binary_t object
377
+ # that references the 16-byte key-id
378
+ #
379
+ # @note Do not initialize ctx before calling this method
380
+ # @return [ Boolean ] Whether the option was successfully set
381
+ attach_function :mongocrypt_ctx_setopt_key_id, [:pointer, :pointer], :bool
382
+
383
+ # Sets the key id option on an explicit encryption context.
384
+ #
385
+ # @param [ Mongo::Crypt::Context ] context Explicit encryption context
386
+ # @param [ String ] key_id The key id
387
+ #
388
+ # @raise [ Mongo::Error::CryptError ] If the operation failed
389
+ def self.ctx_setopt_key_id(context, key_id)
390
+ Binary.wrap_string(key_id) do |key_id_p|
391
+ check_ctx_status(context) do
392
+ mongocrypt_ctx_setopt_key_id(context.ctx_p, key_id_p)
393
+ end
394
+ end
395
+ end
396
+
397
+ # When creating a data key, set an alternate name on that key. When
398
+ # performing explicit encryption, specifying which data key to use for
399
+ # encryption based on its keyAltName field.
400
+ #
401
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
402
+ # @param [ FFI::Pointer ] binary A pointer to a mongocrypt_binary_t
403
+ # object that references a BSON document in the format
404
+ # { "keyAltName": <BSON UTF8 value> }
405
+ #
406
+ # @return [ Boolean ] Whether the alternative name was successfully set
407
+ #
408
+ # @note Do not initialize ctx before calling this method
409
+ attach_function(
410
+ :mongocrypt_ctx_setopt_key_alt_name,
411
+ [:pointer, :pointer],
412
+ :bool
413
+ )
414
+
415
+ # Set multiple alternate key names on data key creation
416
+ #
417
+ # @param [ Mongo::Crypt::Context ] context A DataKeyContext
418
+ # @param [ Array ] key_alt_names An array of alternate key names as strings
419
+ #
420
+ # @raise [ Mongo::Error::CryptError ] If any of the alternate names are
421
+ # not valid UTF8 strings
422
+ def self.ctx_setopt_key_alt_names(context, key_alt_names)
423
+ key_alt_names.each do |key_alt_name|
424
+ key_alt_name_bson = { :keyAltName => key_alt_name }.to_bson.to_s
425
+
426
+ Binary.wrap_string(key_alt_name_bson) do |key_alt_name_p|
427
+ check_ctx_status(context) do
428
+ mongocrypt_ctx_setopt_key_alt_name(context.ctx_p, key_alt_name_p)
429
+ end
430
+ end
431
+ end
432
+ end
433
+
434
+ # Set the algorithm used for explicit encryption
435
+ #
436
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
437
+ # @param [ String ] algorithm The algorithm name. Valid values are:
438
+ # - "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
439
+ # - "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
440
+ # @param [ Integer ] len The length of the algorithm string
441
+ #
442
+ # @note Do not initialize ctx before calling this method
443
+ # @return [ Boolean ] Whether the option was successfully set
444
+ attach_function(
445
+ :mongocrypt_ctx_setopt_algorithm,
446
+ [:pointer, :string, :int],
447
+ :bool
448
+ )
449
+
450
+ # Set the algorithm on the context
451
+ #
452
+ # @param [ Mongo::Crypt::Context ] context
453
+ # @param [ String ] name The algorithm name. Valid values are:
454
+ # - "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
455
+ # - "AEAD_AES_256_CBC_HMAC_SHA_512-Random"
456
+ #
457
+ # @raise [ Mongo::Error::CryptError ] If the operation failed
458
+ def self.ctx_setopt_algorithm(context, name)
459
+ check_ctx_status(context) do
460
+ mongocrypt_ctx_setopt_algorithm(context.ctx_p, name, -1)
461
+ end
462
+ end
463
+
464
+ # Configure the ctx to take a master key from AWS
465
+ #
466
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_object
467
+ # @param [ String ] region The AWS region
468
+ # @param [ Integer ] region_len The length of the region string (or -1
469
+ # for a null-terminated string)
470
+ # @param [ String ] arn The Amazon Resource Name (ARN) of the mater key
471
+ # @param [ Integer ] arn_len The length of the ARN (or -1 for a
472
+ # null-terminated string)
473
+ #
474
+ # @return [ Boolean ] Returns whether the option was set successfully
475
+ attach_function(
476
+ :mongocrypt_ctx_setopt_masterkey_aws,
477
+ [:pointer, :string, :int, :string, :int],
478
+ :bool
479
+ )
480
+
481
+ # Configure the Context object to take a master key from AWS
482
+ #
483
+ # @param [ Mongo::Crypt::Context ] context
484
+ # @param [ String ] region The AWS region (e.g. "us-east-2")
485
+ # @param [ String ] arn The master key Amazon Resource Name
486
+ #
487
+ # @raise [ Mongo::Error::CryptError ] If the operation failed
488
+ def self.ctx_setopt_master_key_aws(context, region, arn)
489
+ check_ctx_status(context) do
490
+ mongocrypt_ctx_setopt_masterkey_aws(
491
+ context.ctx_p,
492
+ region,
493
+ -1,
494
+ arn,
495
+ -1
496
+ )
497
+ end
498
+ end
499
+
500
+ # Set a custom endpoint at which to fetch the AWS master key
501
+ #
502
+ # @param [ FFI::Pointer ] ctx
503
+ # @param [ String ] endpoint The custom endpoint
504
+ # @param [ Integer ] endpoint_len The length of the endpoint string (or
505
+ # -1 for a null-terminated string)
506
+ #
507
+ # @return [ Boolean ] Returns whether the option was set successfully
508
+ attach_function(
509
+ :mongocrypt_ctx_setopt_masterkey_aws_endpoint,
510
+ [:pointer, :string, :int],
511
+ :bool
512
+ )
513
+
514
+ # Configure the Context object to take a masterk ey from AWS
515
+ #
516
+ # @param [ Mongo::Crypt::Context ] context
517
+ # @param [ String ] endpoint The custom AWS master key endpoint
518
+ #
519
+ # @raise [ Mongo::Error::CryptError ] If the operation failed
520
+ def self.ctx_setopt_master_key_aws_endpoint(context, endpoint)
521
+ check_ctx_status(context) do
522
+ mongocrypt_ctx_setopt_masterkey_aws_endpoint(
523
+ context.ctx_p,
524
+ endpoint,
525
+ -1,
526
+ )
527
+ end
528
+ end
529
+
530
+ # Set the ctx to take a local master key
531
+ #
532
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
533
+ #
534
+ # @note Do not initialize ctx before calling this method
535
+ # @return [ Boolean ] Whether the option was successfully set
536
+ attach_function(
537
+ :mongocrypt_ctx_setopt_masterkey_local,
538
+ [:pointer],
539
+ :bool
540
+ )
541
+
542
+ # Tell the Context object to read the master key from local KMS options
543
+ #
544
+ # @param [ Mongo::Crypt::Context ] context
545
+ #
546
+ # @raise [ Mongo::Error::CryptError ] If the operation failed
547
+ def self.ctx_setopt_master_key_local(context)
548
+ check_ctx_status(context) do
549
+ mongocrypt_ctx_setopt_masterkey_local(context.ctx_p)
550
+ end
551
+ end
552
+
553
+ # Initializes the ctx to create a data key
554
+ #
555
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
556
+ #
557
+ # @note Before calling this method, master key options must be set.
558
+ # Set AWS master key by calling mongocrypt_ctx_setopt_masterkey_aws
559
+ # and mongocrypt_ctx_setopt_masterkey_aws_endpoint. Set local master
560
+ # key by calling mongocrypt_ctx_setopt_masterkey_local.
561
+ #
562
+ # @return [ Boolean ] Whether the initialization was successful
563
+ attach_function :mongocrypt_ctx_datakey_init, [:pointer], :bool
564
+
565
+ # Initialize the Context to create a data key
566
+ #
567
+ # @param [ Mongo::Crypt::Context ] context
568
+ #
569
+ # @raise [ Mongo::Error::CryptError ] If initialization fails
570
+ def self.ctx_datakey_init(context)
571
+ check_ctx_status(context) do
572
+ mongocrypt_ctx_datakey_init(context.ctx_p)
573
+ end
574
+ end
575
+
576
+ # Initializes the ctx for auto-encryption
577
+ #
578
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
579
+ # @param [ String ] db The database name
580
+ # @param [ Integer ] db_len The length of the database name argument (or
581
+ # -1 for a null-terminated string)
582
+ # @param [ FFI::Pointer ] cmd A pointer to a mongocrypt_binary_t object
583
+ # that references the database command as a binary string
584
+ #
585
+ # @note This method expects the passed-in BSON to be in the format:
586
+ # { "v": BSON value to decrypt }
587
+ #
588
+ # @return [ Boolean ] Whether the initialization was successful
589
+ attach_function(
590
+ :mongocrypt_ctx_encrypt_init,
591
+ [:pointer, :string, :int, :pointer],
592
+ :bool
593
+ )
594
+
595
+ # Initialize the Context for auto-encryption
596
+ #
597
+ # @param [ Mongo::Crypt::Context ] context
598
+ # @param [ String ] db_name The name of the database against which the
599
+ # encrypted command is being performed
600
+ # @param [ Hash ] command The command to be encrypted
601
+ #
602
+ # @raise [ Mongo::Error::CryptError ] If initialization fails
603
+ def self.ctx_encrypt_init(context, db_name, command)
604
+ validate_document(command)
605
+ data = command.to_bson.to_s
606
+ Binary.wrap_string(data) do |data_p|
607
+ check_ctx_status(context) do
608
+ mongocrypt_ctx_encrypt_init(context.ctx_p, db_name, -1, data_p)
609
+ end
610
+ end
611
+ end
612
+
613
+ # Initializes the ctx for explicit encryption
614
+ #
615
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
616
+ # @param [ FFI::Pointer ] msg A pointer to a mongocrypt_binary_t object
617
+ # that references the message to be encrypted as a binary string
618
+ #
619
+ # @note Before calling this method, set a key_id, key_alt_name (optional),
620
+ # and encryption algorithm using the following methods:
621
+ # mongocrypt_ctx_setopt_key_id, mongocrypt_ctx_setopt_key_alt_name,
622
+ # and mongocrypt_ctx_setopt_algorithm
623
+ #
624
+ # @return [ Boolean ] Whether the initialization was successful
625
+ attach_function(
626
+ :mongocrypt_ctx_explicit_encrypt_init,
627
+ [:pointer, :pointer],
628
+ :bool
629
+ )
630
+
631
+ # Initialize the Context for explicit encryption
632
+ #
633
+ # @param [ Mongo::Crypt::Context ] context
634
+ # @param [ Hash ] A BSON document to encrypt
635
+ #
636
+ # @raise [ Mongo::Error::CryptError ] If initialization fails
637
+ def self.ctx_explicit_encrypt_init(context, doc)
638
+ validate_document(doc)
639
+ data = doc.to_bson.to_s
640
+ Binary.wrap_string(data) do |data_p|
641
+ check_ctx_status(context) do
642
+ mongocrypt_ctx_explicit_encrypt_init(context.ctx_p, data_p)
643
+ end
644
+ end
645
+ end
646
+
647
+ # Initializes the ctx for auto-decryption
648
+ #
649
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
650
+ # @param [ FFI::Pointer ] doc A pointer to a mongocrypt_binary_t object
651
+ # that references the document to be decrypted as a BSON binary string
652
+ #
653
+ # @return [ Boolean ] Whether the initialization was successful
654
+ attach_function :mongocrypt_ctx_decrypt_init, [:pointer, :pointer], :bool
655
+
656
+ # Initialize the Context for auto-decryption
657
+ #
658
+ # @param [ Mongo::Crypt::Context ] context
659
+ # @param [ BSON::Document ] A BSON document to decrypt
660
+ #
661
+ # @raise [ Mongo::Error::CryptError ] If initialization fails
662
+ def self.ctx_decrypt_init(context, command)
663
+ validate_document(command)
664
+ data = command.to_bson.to_s
665
+ Binary.wrap_string(data) do |data_p|
666
+ check_ctx_status(context) do
667
+ mongocrypt_ctx_decrypt_init(context.ctx_p, data_p)
668
+ end
669
+ end
670
+ end
671
+
672
+ # Initializes the ctx for explicit decryption
673
+ #
674
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
675
+ # @param [ FFI::Pointer ] msg A pointer to a mongocrypt_binary_t object
676
+ # that references the message to be decrypted as a BSON binary string
677
+ #
678
+ # @return [ Boolean ] Whether the initialization was successful
679
+ attach_function(
680
+ :mongocrypt_ctx_explicit_decrypt_init,
681
+ [:pointer, :pointer],
682
+ :bool
683
+ )
684
+
685
+ # Initialize the Context for explicit decryption
686
+ #
687
+ # @param [ Mongo::Crypt::Context ] context
688
+ # @param [ Hash ] A BSON document to decrypt
689
+ #
690
+ # @raise [ Mongo::Error::CryptError ] If initialization fails
691
+ def self.ctx_explicit_decrypt_init(context, doc)
692
+ validate_document(doc)
693
+ data = doc.to_bson.to_s
694
+ Binary.wrap_string(data) do |data_p|
695
+ check_ctx_status(context) do
696
+ mongocrypt_ctx_explicit_decrypt_init(context.ctx_p, data_p)
697
+ end
698
+ end
699
+ end
700
+
701
+ # An enum labeling different libmognocrypt state machine states
702
+ enum :mongocrypt_ctx_state, [
703
+ :error, 0,
704
+ :need_mongo_collinfo, 1,
705
+ :need_mongo_markings, 2,
706
+ :need_mongo_keys, 3,
707
+ :need_kms, 4,
708
+ :ready, 5,
709
+ :done, 6,
710
+ ]
711
+
712
+ # Get the current state of the ctx
713
+ #
714
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
715
+ #
716
+ # @return [ Symbol ] The current state, will be one of the values defined
717
+ # by the mongocrypt_ctx_state enum
718
+ attach_function :mongocrypt_ctx_state, [:pointer], :mongocrypt_ctx_state
719
+
720
+ # Get a BSON operation for the driver to run against the MongoDB
721
+ # collection, the key vault database, or mongocryptd.
722
+ #
723
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
724
+ # @param [ FFI::Pointer ] op_bson (out param) A pointer to a
725
+ # mongocrypt_binary_t object that will have a reference to the
726
+ # BSON operation written to it by libmongocrypt
727
+ #
728
+ # @return [ Boolean ] A boolean indicating the success of the operation
729
+ attach_function :mongocrypt_ctx_mongo_op, [:pointer, :pointer], :bool
730
+
731
+ # Returns a BSON::Document representing an operation that the
732
+ # driver must perform on behalf of libmongocrypt to get the
733
+ # information it needs in order to continue with
734
+ # encryption/decryption (for example, a filter for a key vault query).
735
+ #
736
+ # @param [ Mongo::Crypt::Context ] context
737
+ #
738
+ # @raise [ Mongo::Crypt ] If there is an error getting the operation
739
+ # @return [ BSON::Document ] The operation that the driver must perform
740
+ def self.ctx_mongo_op(context)
741
+ binary = Binary.new
742
+
743
+ check_ctx_status(context) do
744
+ mongocrypt_ctx_mongo_op(context.ctx_p, binary.ref)
745
+ end
746
+
747
+ # TODO since the binary references a C pointer, and ByteBuffer is
748
+ # written in C in MRI, we could omit a copy of the data by making
749
+ # ByteBuffer reference the string that is owned by libmongocrypt.
750
+ BSON::Document.from_bson(BSON::ByteBuffer.new(binary.to_s), mode: :bson)
751
+ end
752
+
753
+ # Feed a BSON reply to libmongocrypt
754
+ #
755
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
756
+ # @param [ FFI::Pointer ] reply A mongocrypt_binary_t object that
757
+ # references the BSON reply to feed to libmongocrypt
758
+ #
759
+ # @return [ Boolean ] A boolean indicating the success of the operation
760
+ attach_function :mongocrypt_ctx_mongo_feed, [:pointer, :pointer], :bool
761
+
762
+ # Feed a response from the driver back to libmongocrypt
763
+ #
764
+ # @param [ Mongo::Crypt::Context ] context
765
+ # @param [ BSON::Document ] doc The document representing the response
766
+ #
767
+ # @raise [ Mongo::Error::CryptError ] If the response is not fed successfully
768
+ def self.ctx_mongo_feed(context, doc)
769
+ validate_document(doc)
770
+ data = doc.to_bson.to_s
771
+ Binary.wrap_string(data) do |data_p|
772
+ check_ctx_status(context) do
773
+ mongocrypt_ctx_mongo_feed(context.ctx_p, data_p)
774
+ end
775
+ end
776
+ end
777
+
778
+ # Indicate to libmongocrypt that the driver is done feeding replies
779
+ #
780
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
781
+ #
782
+ # @return [ Boolean ] A boolean indicating the success of the operation
783
+ attach_function :mongocrypt_ctx_mongo_done, [:pointer], :bool
784
+
785
+ # Return a pointer to a mongocrypt_kms_ctx_t object or NULL.
786
+ #
787
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
788
+ #
789
+ # @return [ FFI::Pointer ] A pointer to a mongocrypt_kms_ctx_t object
790
+ attach_function :mongocrypt_ctx_next_kms_ctx, [:pointer], :pointer
791
+
792
+ # Return a new KmsContext object needed by a Context object.
793
+ #
794
+ # @param [ Mongo::Crypt::Context ] context
795
+ #
796
+ # @return [ Mongo::Crypt::KmsContext | nil ] The KmsContext needed to
797
+ # fetch an AWS master key or nil, if no KmsContext is needed
798
+ def self.ctx_next_kms_ctx(context)
799
+ kms_ctx_p = mongocrypt_ctx_next_kms_ctx(context.ctx_p)
800
+
801
+ if kms_ctx_p.null?
802
+ nil
803
+ else
804
+ KmsContext.new(kms_ctx_p)
805
+ end
806
+ end
807
+
808
+ # Get the message needed to fetch the AWS KMS master key.
809
+ #
810
+ # @param [ FFI::Pointer ] kms Pointer to the mongocrypt_kms_ctx_t object
811
+ # @param [ FFI::Pointer ] msg (outparam) Pointer to a mongocrypt_binary_t
812
+ # object that will have the location of the message written to it by
813
+ # libmongocrypt
814
+ #
815
+ # @return [ Boolean ] Whether the operation is successful
816
+ attach_function :mongocrypt_kms_ctx_message, [:pointer, :pointer], :bool
817
+
818
+ # Get the HTTP message needed to fetch the AWS KMS master key from a
819
+ # KmsContext object.
820
+ #
821
+ # @param [ Mongo::Crypt::KmsContext ] kms_context
822
+ #
823
+ # @raise [ Mongo::Error::CryptError ] If the response is not fed successfully
824
+ #
825
+ # @return [ String ] The HTTP message
826
+ def self.kms_ctx_message(kms_context)
827
+ binary = Binary.new
828
+
829
+ check_kms_ctx_status(kms_context) do
830
+ mongocrypt_kms_ctx_message(kms_context.kms_ctx_p, binary.ref)
831
+ end
832
+
833
+ return binary.to_s
834
+ end
835
+
836
+ # Get the hostname with which to connect over TLS to get information about
837
+ # the AWS master key.
838
+ #
839
+ # @param [ FFI::Pointer ] kms A pointer to a mongocrypt_kms_ctx_t object
840
+ # @param [ FFI::Pointer ] endpoint (out param) A pointer to which the
841
+ # endpoint string will be written by libmongocrypt
842
+ #
843
+ # @return [ Boolean ] Whether the operation was successful
844
+ attach_function :mongocrypt_kms_ctx_endpoint, [:pointer, :pointer], :bool
845
+
846
+ # Get the hostname with which to connect over TLS to get information
847
+ # about the AWS master key.
848
+ #
849
+ # @param [ Mongo::Crypt::KmsContext ] kms_context
850
+ #
851
+ # @raise [ Mongo::Error::CryptError ] If the response is not fed successfully
852
+ #
853
+ # @return [ String | nil ] The hostname, or nil if none exists
854
+ def self.kms_ctx_endpoint(kms_context)
855
+ ptr = FFI::MemoryPointer.new(:pointer, 1)
856
+
857
+ check_kms_ctx_status(kms_context) do
858
+ mongocrypt_kms_ctx_endpoint(kms_context.kms_ctx_p, ptr)
859
+ end
860
+
861
+ str_ptr = ptr.read_pointer
862
+ str_ptr.null? ? nil : str_ptr.read_string.force_encoding('UTF-8')
863
+ end
864
+
865
+ # Get the number of bytes needed by the KMS context.
866
+ #
867
+ # @param [ FFI::Pointer ] kms The mongocrypt_kms_ctx_t object
868
+ #
869
+ # @return [ Integer ] The number of bytes needed
870
+ attach_function :mongocrypt_kms_ctx_bytes_needed, [:pointer], :int
871
+
872
+ # Get the number of bytes needed by the KmsContext.
873
+ #
874
+ # @param [ Mongo::Crypt::KmsContext ] kms_context
875
+ #
876
+ # @return [ Integer ] The number of bytes needed
877
+ def self.kms_ctx_bytes_needed(kms_context)
878
+ mongocrypt_kms_ctx_bytes_needed(kms_context.kms_ctx_p)
879
+ end
880
+
881
+ # Feed replies from the KMS back to libmongocrypt.
882
+ #
883
+ # @param [ FFI::Pointer ] kms A pointer to the mongocrypt_kms_ctx_t object
884
+ # @param [ FFI::Pointer ] bytes A pointer to a mongocrypt_binary_t
885
+ # object that references the response from the KMS
886
+ #
887
+ # @return [ Boolean ] Whether the operation was successful
888
+ attach_function :mongocrypt_kms_ctx_feed, [:pointer, :pointer], :bool
889
+
890
+ # Feed replies from the KMS back to libmongocrypt.
891
+ #
892
+ # @param [ Mongo::Crypt::KmsContext ] kms_context
893
+ # @oaram [ String ] data The data to feed to libmongocrypt
894
+ #
895
+ # @raise [ Mongo::Error::CryptError ] If the response is not fed successfully
896
+ def self.kms_ctx_feed(kms_context, bytes)
897
+ check_kms_ctx_status(kms_context) do
898
+ Binary.wrap_string(bytes) do |bytes_p|
899
+ mongocrypt_kms_ctx_feed(kms_context.kms_ctx_p, bytes_p)
900
+ end
901
+ end
902
+ end
903
+
904
+ # Write status information about the mongocrypt_kms_ctx_t object
905
+ # to the mongocrypt_status_t object.
906
+ #
907
+ # @param [ FFI::Pointer ] kms A pointer to the mongocrypt_kms_ctx_t object
908
+ # @param [ FFI::Pointer ] status A pointer to a mongocrypt_status_t object
909
+ #
910
+ # @return [ Boolean ] Whether the operation was successful
911
+ attach_function :mongocrypt_kms_ctx_status, [:pointer, :pointer], :bool
912
+
913
+ # If the provided block returns false, raise a CryptError with the
914
+ # status information from the provided KmsContext object.
915
+ #
916
+ # @param [ Mongo::Crypt::KmsContext ] kms_context
917
+ #
918
+ # @raise [ Mongo::Error::CryptError ] If the provided block returns false
919
+ def self.check_kms_ctx_status(kms_context)
920
+ unless yield
921
+ status = Status.new
922
+
923
+ mongocrypt_kms_ctx_status(kms_context.kms_ctx_p, status.ref)
924
+ status.raise_crypt_error
925
+ end
926
+ end
927
+
928
+ # Indicate to libmongocrypt that it will receive no more replies from
929
+ # mongocrypt_kms_ctx_t objects.
930
+ #
931
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
932
+ #
933
+ # @return [ Boolean ] Whether the operation was successful
934
+ attach_function :mongocrypt_ctx_kms_done, [:pointer], :bool
935
+
936
+ # Indicate to libmongocrypt that it will receive no more KMS replies.
937
+ #
938
+ # @param [ Mongo::Crypt::Context ] context
939
+ #
940
+ # @raise [ Mongo::Error::CryptError ] If the operation is unsuccessful
941
+ def self.ctx_kms_done(context)
942
+ check_ctx_status(context) do
943
+ mongocrypt_ctx_kms_done(context.ctx_p)
944
+ end
945
+ end
946
+
947
+ # Perform the final encryption or decryption and return a BSON document
948
+ #
949
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
950
+ # @param [ FFI::Pointer ] op_bson (out param) A pointer to a
951
+ # mongocrypt_binary_t object that will have a reference to the
952
+ # final encrypted BSON document
953
+ #
954
+ # @return [ Boolean ] A boolean indicating the success of the operation
955
+ attach_function :mongocrypt_ctx_finalize, [:pointer, :pointer], :void
956
+
957
+ # Finalize the state machine represented by the Context
958
+ #
959
+ # @param [ Mongo::Crypt::Context ] context
960
+ #
961
+ # @raise [ Mongo::Error::CryptError ] If the state machine is not successfully
962
+ # finalized
963
+ def self.ctx_finalize(context)
964
+ binary = Binary.new
965
+
966
+ check_ctx_status(context) do
967
+ mongocrypt_ctx_finalize(context.ctx_p, binary.ref)
968
+ end
969
+
970
+ # TODO since the binary references a C pointer, and ByteBuffer is
971
+ # written in C in MRI, we could omit a copy of the data by making
972
+ # ByteBuffer reference the string that is owned by libmongocrypt.
973
+ BSON::Document.from_bson(BSON::ByteBuffer.new(binary.to_s), mode: :bson)
974
+ end
975
+
976
+ # Destroy the reference to the mongocrypt_ctx_t object
977
+ #
978
+ # @param [ FFI::Pointer ] ctx A pointer to a mongocrypt_ctx_t object
979
+ #
980
+ # @return [ nil ] Always nil
981
+ attach_function :mongocrypt_ctx_destroy, [:pointer], :void
982
+
983
+ # A callback to a function that performs AES encryption or decryption
984
+ #
985
+ # @param [ FFI::Pointer | nil] ctx An optional pointer to a context object
986
+ # that may have been set when hooks were enabled.
987
+ # @param [ FFI::Pointer ] key A pointer to a mongocrypt_binary_t object
988
+ # that references the 32-byte AES encryption key
989
+ # @param [ FFI::Pointer ] iv A pointer to a mongocrypt_binary_t object
990
+ # that references the 16-byte AES IV
991
+ # @param [ FFI::Pointer ] in A pointer to a mongocrypt_binary_t object
992
+ # that references the value to be encrypted/decrypted
993
+ # @param [ FFI::Pointer ] out (out param) A pointer to a
994
+ # mongocrypt_binary_t object will have a reference to the encrypted/
995
+ # decrypted value written to it by libmongocrypt
996
+ # @param [ FFI::Pointer ] status A pointer to a mongocrypt_status_t
997
+ # object to which an error message will be written if encryption fails
998
+ #
999
+ # @return [ Bool ] Whether encryption/decryption was successful
1000
+ callback(
1001
+ :mongocrypt_crypto_fn,
1002
+ [:pointer, :pointer, :pointer, :pointer, :pointer, :pointer, :pointer],
1003
+ :bool
1004
+ )
1005
+
1006
+ # A callback to a function that performs HMAC SHA-512 or SHA-256
1007
+ #
1008
+ # @param [ FFI::Pointer | nil ] ctx An optional pointer to a context object
1009
+ # that may have been set when hooks were enabled.
1010
+ # @param [ FFI::Pointer ] key A pointer to a mongocrypt_binary_t object
1011
+ # that references the 32-byte HMAC SHA encryption key
1012
+ # @param [ FFI::Pointer ] in A pointer to a mongocrypt_binary_t object
1013
+ # that references the input value
1014
+ # @param [ FFI::Pointer ] out (out param) A pointer to a
1015
+ # mongocrypt_binary_t object will have a reference to the output value
1016
+ # written to it by libmongocrypt
1017
+ # @param [ FFI::Pointer ] status A pointer to a mongocrypt_status_t
1018
+ # object to which an error message will be written if encryption fails
1019
+ #
1020
+ # @return [ Bool ] Whether HMAC-SHA was successful
1021
+ callback(
1022
+ :mongocrypt_hmac_fn,
1023
+ [:pointer, :pointer, :pointer, :pointer, :pointer],
1024
+ :bool
1025
+ )
1026
+
1027
+ # A callback to a SHA-256 hash function
1028
+ #
1029
+ # @param [ FFI::Pointer | nil ] ctx An optional pointer to a context object
1030
+ # that may have been set when hooks were enabled.
1031
+ # @param [ FFI::Pointer ] in A pointer to a mongocrypt_binary_t object
1032
+ # that references the value to be hashed
1033
+ # @param [ FFI::Pointer ] out (out param) A pointer to a
1034
+ # mongocrypt_binary_t object will have a reference to the output value
1035
+ # written to it by libmongocrypt
1036
+ # @param [ FFI::Pointer ] status A pointer to a mongocrypt_status_t
1037
+ # object to which an error message will be written if encryption fails
1038
+ #
1039
+ # @return [ Bool ] Whether hashing was successful
1040
+ callback :mongocrypt_hash_fn, [:pointer, :pointer, :pointer, :pointer], :bool
1041
+
1042
+ # A callback to a crypto secure random function
1043
+ #
1044
+ # @param [ FFI::Pointer | nil ] ctx An optional pointer to a context object
1045
+ # that may have been set when hooks were enabled.
1046
+ # @param [ FFI::Pointer ] out (out param) A pointer to a
1047
+ # mongocrypt_binary_t object will have a reference to the output value
1048
+ # written to it by libmongocrypt
1049
+ # @param [ Integer ] count The number of random bytes to return
1050
+ # @param [ FFI::Pointer ] status A pointer to a mongocrypt_status_t
1051
+ # object to which an error message will be written if encryption fails
1052
+ #
1053
+ # @return [ Bool ] Whether hashing was successful
1054
+ callback :mongocrypt_random_fn, [:pointer, :pointer, :int, :pointer], :bool
1055
+
1056
+ # Set crypto hooks on the provided mongocrypt object
1057
+ #
1058
+ # @param [ FFI::Pointer ] crypt A pointer to a mongocrypt_t object
1059
+ # @param [ Proc ] An AES encryption method
1060
+ # @param [ Proc ] An AES decryption method
1061
+ # @param [ Proc ] A random method
1062
+ # @param [ Proc ] A HMAC SHA-512 method
1063
+ # @param [ Proc ] A HMAC SHA-256 method
1064
+ # @param [ Proc ] A SHA-256 hash method
1065
+ # @param [ FFI::Pointer | nil ] ctx An optional pointer to a context object
1066
+ # that may have been set when hooks were enabled.
1067
+ #
1068
+ # @return [ Boolean ] Whether setting this option succeeded
1069
+ attach_function(
1070
+ :mongocrypt_setopt_crypto_hooks,
1071
+ [
1072
+ :pointer,
1073
+ :mongocrypt_crypto_fn,
1074
+ :mongocrypt_crypto_fn,
1075
+ :mongocrypt_random_fn,
1076
+ :mongocrypt_hmac_fn,
1077
+ :mongocrypt_hmac_fn,
1078
+ :mongocrypt_hash_fn,
1079
+ :pointer
1080
+ ],
1081
+ :bool
1082
+ )
1083
+
1084
+ # Set crypto callbacks on the Handle
1085
+ #
1086
+ # @param [ Mongo::Crypt::Handle ] handle
1087
+ # @param [ Method ] aes_encrypt_cb An AES encryption method
1088
+ # @param [ Method ] aes_decrypt_cb A AES decryption method
1089
+ # @param [ Method ] random_cb A method that returns a string of random bytes
1090
+ # @param [ Method ] hmac_sha_512_cb A HMAC SHA-512 method
1091
+ # @param [ Method ] hmac_sha_256_cb A HMAC SHA-256 method
1092
+ # @param [ Method ] hmac_hash_cb A SHA-256 hash method
1093
+ #
1094
+ # @raise [ Mongo::Error::CryptError ] If the callbacks aren't set successfully
1095
+ def self.setopt_crypto_hooks(handle,
1096
+ aes_encrypt_cb, aes_decrypt_cb, random_cb,
1097
+ hmac_sha_512_cb, hmac_sha_256_cb, hmac_hash_cb
1098
+ )
1099
+ check_status(handle) do
1100
+ mongocrypt_setopt_crypto_hooks(handle.ref,
1101
+ aes_encrypt_cb, aes_decrypt_cb, random_cb,
1102
+ hmac_sha_512_cb, hmac_sha_256_cb, hmac_hash_cb, nil
1103
+ )
1104
+ end
1105
+ end
1106
+
1107
+ # Raise a Mongo::Error::CryptError based on the status of the underlying
1108
+ # mongocrypt_t object.
1109
+ #
1110
+ # @return [ nil ] Always nil.
1111
+ def self.check_status(handle)
1112
+ unless yield
1113
+ status = Status.new
1114
+
1115
+ mongocrypt_status(handle.ref, status.ref)
1116
+ status.raise_crypt_error
1117
+ end
1118
+ end
1119
+
1120
+ # Raise a Mongo::Error::CryptError based on the status of the underlying
1121
+ # mongocrypt_ctx_t object.
1122
+ #
1123
+ # @return [ nil ] Always nil.
1124
+ def self.check_ctx_status(context)
1125
+ if block_given?
1126
+ do_raise = !yield
1127
+ else
1128
+ do_raise = true
1129
+ end
1130
+
1131
+ if do_raise
1132
+ status = Status.new
1133
+
1134
+ mongocrypt_ctx_status(context.ctx_p, status.ref)
1135
+ status.raise_crypt_error
1136
+ end
1137
+ end
1138
+
1139
+ # Checks that the specified data is a Hash before serializing
1140
+ # it to BSON to prevent errors from libmongocrypt
1141
+ #
1142
+ # @note All BSON::Document instances are also Hash instances
1143
+ #
1144
+ # @param [ Object ] data The data to be passed to libmongocrypt
1145
+ #
1146
+ # @raise [ Mongo::Error::CryptError ] If the data is not a Hash
1147
+ def self.validate_document(data)
1148
+ return if data.is_a?(Hash)
1149
+
1150
+ if data.nil?
1151
+ message = "Attempted to pass nil data to libmongocrypt. " +
1152
+ "Data must be a Hash"
1153
+ else
1154
+ message = "Attempted to pass invalid data to libmongocrypt: #{data} " +
1155
+ "Data must be a Hash"
1156
+ end
1157
+
1158
+ raise Error::CryptError.new(message)
1159
+ end
1160
+ end
1161
+ end
1162
+ end