mongo 2.11.6 → 2.12.0.rc0

Sign up to get free protection for your applications and to get access to all the features.
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