mongo 2.18.0.beta1 → 2.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/mongo/bulk_write.rb +8 -2
  4. data/lib/mongo/client.rb +19 -5
  5. data/lib/mongo/client_encryption.rb +86 -4
  6. data/lib/mongo/cluster.rb +6 -4
  7. data/lib/mongo/collection/view/aggregation.rb +3 -0
  8. data/lib/mongo/collection/view/change_stream.rb +9 -0
  9. data/lib/mongo/collection/view/iterable.rb +1 -0
  10. data/lib/mongo/collection/view/readable.rb +11 -3
  11. data/lib/mongo/collection.rb +9 -1
  12. data/lib/mongo/config.rb +11 -0
  13. data/lib/mongo/crypt/auto_encrypter.rb +49 -21
  14. data/lib/mongo/crypt/binding.rb +73 -48
  15. data/lib/mongo/crypt/data_key_context.rb +6 -1
  16. data/lib/mongo/crypt/encryption_io.rb +66 -0
  17. data/lib/mongo/crypt/explicit_encrypter.rb +116 -5
  18. data/lib/mongo/crypt/explicit_encryption_context.rb +3 -8
  19. data/lib/mongo/crypt/handle.rb +26 -8
  20. data/lib/mongo/crypt/kms/aws.rb +11 -3
  21. data/lib/mongo/crypt/kms/azure.rb +14 -6
  22. data/lib/mongo/crypt/kms/gcp.rb +12 -5
  23. data/lib/mongo/crypt/kms/kmip.rb +15 -9
  24. data/lib/mongo/crypt/kms/local.rb +9 -1
  25. data/lib/mongo/crypt/kms/master_key_document.rb +1 -1
  26. data/lib/mongo/crypt/rewrap_many_data_key_context.rb +46 -0
  27. data/lib/mongo/crypt/rewrap_many_data_key_result.rb +37 -0
  28. data/lib/mongo/crypt/status.rb +8 -2
  29. data/lib/mongo/crypt.rb +2 -0
  30. data/lib/mongo/database.rb +10 -27
  31. data/lib/mongo/error/missing_file_chunk.rb +8 -2
  32. data/lib/mongo/grid/stream/read.rb +6 -0
  33. data/lib/mongo/index/view.rb +1 -0
  34. data/lib/mongo/operation/create/op_msg.rb +1 -13
  35. data/lib/mongo/operation/distinct/op_msg.rb +4 -1
  36. data/lib/mongo/protocol/msg.rb +0 -16
  37. data/lib/mongo/server/connection_pool.rb +5 -4
  38. data/lib/mongo/server/monitor/connection.rb +10 -4
  39. data/lib/mongo/server/monitor.rb +4 -0
  40. data/lib/mongo/server/push_monitor.rb +4 -0
  41. data/lib/mongo/version.rb +1 -1
  42. data/lib/mongo.rb +2 -0
  43. data/spec/README.md +14 -0
  44. data/spec/integration/change_stream_spec.rb +1 -1
  45. data/spec/integration/client_construction_spec.rb +73 -7
  46. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +165 -164
  47. data/spec/integration/client_side_encryption/decryption_events_prose_spec.rb +158 -0
  48. data/spec/integration/client_side_encryption/explicit_queryable_encryption_spec.rb +5 -5
  49. data/spec/integration/client_side_encryption/kms_tls_options_spec.rb +50 -8
  50. data/spec/integration/client_side_encryption/unique_index_on_key_alt_names_prose_spec.rb +85 -0
  51. data/spec/integration/ocsp_verifier_spec.rb +1 -1
  52. data/spec/integration/reconnect_spec.rb +2 -0
  53. data/spec/integration/sdam_events_spec.rb +40 -0
  54. data/spec/integration/srv_monitoring_spec.rb +1 -0
  55. data/spec/integration/srv_spec.rb +1 -0
  56. data/spec/lite_spec_helper.rb +5 -4
  57. data/spec/mongo/bulk_write_spec.rb +13 -0
  58. data/spec/mongo/client_construction_spec.rb +45 -2
  59. data/spec/mongo/client_encryption_spec.rb +0 -12
  60. data/spec/mongo/client_spec.rb +1 -1
  61. data/spec/mongo/collection/view/aggregation_spec.rb +119 -0
  62. data/spec/mongo/collection/view/readable_spec.rb +630 -5
  63. data/spec/mongo/collection_spec.rb +32 -0
  64. data/spec/mongo/crypt/auto_encrypter_spec.rb +110 -0
  65. data/spec/mongo/crypt/binding/context_spec.rb +3 -35
  66. data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
  67. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +8 -3
  68. data/spec/mongo/crypt/handle_spec.rb +39 -3
  69. data/spec/mongo/crypt/kms/credentials_spec.rb +0 -47
  70. data/spec/mongo/index/view_spec.rb +56 -0
  71. data/spec/mongo/operation/create/op_msg_spec.rb +0 -42
  72. data/spec/mongo/server/connection_pool_spec.rb +26 -4
  73. data/spec/mongo/socket/ssl_spec.rb +3 -3
  74. data/spec/runners/crud/requirement.rb +6 -1
  75. data/spec/runners/crud/test.rb +1 -1
  76. data/spec/runners/transactions/spec.rb +2 -2
  77. data/spec/runners/transactions/test.rb +4 -20
  78. data/spec/runners/transactions.rb +2 -2
  79. data/spec/runners/unified/assertions.rb +32 -2
  80. data/spec/runners/unified/change_stream_operations.rb +3 -0
  81. data/spec/runners/unified/client_side_encryption_operations.rb +83 -0
  82. data/spec/runners/unified/crud_operations.rb +17 -2
  83. data/spec/runners/unified/ddl_operations.rb +27 -2
  84. data/spec/runners/unified/grid_fs_operations.rb +21 -0
  85. data/spec/runners/unified/test.rb +59 -1
  86. data/spec/shared/lib/mrss/docker_runner.rb +2 -0
  87. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  88. data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
  89. data/spec/shared/shlib/set_env.sh +3 -0
  90. data/spec/solo/clean_exit_spec.rb +5 -0
  91. data/spec/spec_tests/client_side_encryption_spec.rb +1 -1
  92. data/spec/spec_tests/client_side_encryption_unified_spec.rb +16 -0
  93. data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +298 -0
  94. data/spec/spec_tests/data/client_side_encryption/create-and-createIndexes.yml +58 -0
  95. data/spec/spec_tests/data/client_side_encryption/fle2-Delete.yml +1 -1
  96. data/spec/spec_tests/data/client_side_encryption/fle2-EncryptedFields-vs-jsonSchema.yml +1 -1
  97. data/spec/spec_tests/data/client_side_encryption/fle2-FindOneAndUpdate.yml +2 -2
  98. data/spec/spec_tests/data/client_side_encryption/fle2-InsertFind-Indexed.yml +1 -1
  99. data/spec/spec_tests/data/client_side_encryption/fle2-Update.yml +2 -2
  100. data/spec/spec_tests/data/client_side_encryption/unified/addKeyAltName.yml +194 -0
  101. data/spec/spec_tests/data/client_side_encryption/unified/createDataKey-kms_providers-invalid.yml +67 -0
  102. data/spec/spec_tests/data/client_side_encryption/unified/createDataKey.yml +309 -0
  103. data/spec/spec_tests/data/client_side_encryption/unified/deleteKey.yml +159 -0
  104. data/spec/spec_tests/data/client_side_encryption/unified/getKey.yml +105 -0
  105. data/spec/spec_tests/data/client_side_encryption/unified/getKeyByAltName.yml +104 -0
  106. data/spec/spec_tests/data/client_side_encryption/unified/getKeys.yml +122 -0
  107. data/spec/spec_tests/data/client_side_encryption/unified/removeKeyAltName.yml +157 -0
  108. data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-decrypt_failure.yml +69 -0
  109. data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-encrypt_failure.yml +122 -0
  110. data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey.yml +432 -0
  111. data/spec/spec_tests/data/client_side_encryption/validatorAndPartialFieldExpression.yml +166 -0
  112. data/spec/spec_tests/data/command_monitoring_unified/bulkWrite.yml +68 -0
  113. data/spec/spec_tests/data/command_monitoring_unified/command.yml +50 -0
  114. data/spec/spec_tests/data/command_monitoring_unified/deleteMany.yml +79 -0
  115. data/spec/spec_tests/data/command_monitoring_unified/deleteOne.yml +79 -0
  116. data/spec/spec_tests/data/command_monitoring_unified/find.yml +254 -0
  117. data/spec/spec_tests/data/command_monitoring_unified/insertMany.yml +79 -0
  118. data/spec/spec_tests/data/command_monitoring_unified/insertOne.yml +77 -0
  119. data/spec/spec_tests/data/command_monitoring_unified/unacknowledgedBulkWrite.yml +55 -0
  120. data/spec/spec_tests/data/command_monitoring_unified/updateMany.yml +87 -0
  121. data/spec/spec_tests/data/command_monitoring_unified/updateOne.yml +118 -0
  122. data/spec/spec_tests/data/crud_unified/distinct-comment.yml +98 -0
  123. data/spec/spec_tests/data/gridfs_unified/delete.yml +198 -0
  124. data/spec/spec_tests/data/gridfs_unified/download.yml +241 -0
  125. data/spec/spec_tests/data/gridfs_unified/downloadByName.yml +159 -0
  126. data/spec/spec_tests/data/gridfs_unified/upload-disableMD5.yml +92 -0
  127. data/spec/spec_tests/data/gridfs_unified/upload.yml +288 -0
  128. data/spec/spec_tests/gridfs_unified_spec.rb +13 -0
  129. data/spec/stress/connection_pool_timing_spec.rb +2 -2
  130. data/spec/support/background_thread_registry.rb +3 -13
  131. data/spec/support/certificates/atlas-ocsp-ca.crt +40 -47
  132. data/spec/support/certificates/atlas-ocsp.crt +101 -106
  133. data/spec/support/crypt.rb +57 -13
  134. data/spec/support/macros.rb +10 -0
  135. data/spec/support/spec_config.rb +4 -0
  136. data.tar.gz.sig +0 -0
  137. metadata +1271 -1219
  138. metadata.gz.sig +0 -0
  139. data/spec/spec_tests/command_monitoring_spec.rb +0 -71
  140. data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +0 -49
  141. data/spec/spec_tests/data/command_monitoring/command.yml +0 -61
  142. data/spec/spec_tests/data/command_monitoring/deleteMany.yml +0 -55
  143. data/spec/spec_tests/data/command_monitoring/deleteOne.yml +0 -55
  144. data/spec/spec_tests/data/command_monitoring/find.yml +0 -266
  145. data/spec/spec_tests/data/command_monitoring/insertMany.yml +0 -75
  146. data/spec/spec_tests/data/command_monitoring/insertOne.yml +0 -51
  147. data/spec/spec_tests/data/command_monitoring/unacknowledgedBulkWrite.yml +0 -34
  148. data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -65
  149. data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -90
@@ -32,7 +32,7 @@ describe 'Auto Encryption' do
32
32
  database: db_name
33
33
  ),
34
34
  ).tap do |client|
35
- client.encrypter.key_vault_client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
35
+ client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
36
36
  end
37
37
  end
38
38
 
@@ -41,19 +41,14 @@ describe 'Auto Encryption' do
41
41
  key_vault_collection.insert_one(data_key)
42
42
 
43
43
  encryption_client['users'].drop
44
- result = encryption_client['users'].insert_one(ssn: ssn, age: 23)
45
44
  end
46
45
 
47
46
  let(:started_event) do
48
- subscriber.started_events.find do |event|
49
- event.command_name == command_name && event.database_name == db_name
50
- end
47
+ subscriber.single_command_started_event(command_name, database_name: db_name)
51
48
  end
52
49
 
53
50
  let(:succeeded_event) do
54
- subscriber.succeeded_events.find do |event|
55
- event.command_name == command_name && event.database_name == db_name
56
- end
51
+ subscriber.single_command_succeeded_event(command_name, database_name: db_name)
57
52
  end
58
53
 
59
54
  let(:key_vault_list_collections_event) do
@@ -68,236 +63,242 @@ describe 'Auto Encryption' do
68
63
  end
69
64
  end
70
65
 
71
- describe '#aggregate' do
72
- let(:command_name) { 'aggregate' }
73
-
66
+ context 'when performing operations that need a document in the database' do
74
67
  before do
75
- encryption_client['users'].aggregate([{ '$match' => { 'ssn' => ssn } }]).first
68
+ result = encryption_client['users'].insert_one(ssn: ssn, age: 23)
76
69
  end
77
70
 
78
- it 'has encrypted data in command monitoring' do
79
- # Command started event occurs after ssn is encrypted
80
- expect(
81
- started_event.command["pipeline"].first["$match"]["ssn"]["$eq"]
82
- ).to be_ciphertext
71
+ describe '#aggregate' do
72
+ let(:command_name) { 'aggregate' }
83
73
 
84
- # Command succeeded event occurs before ssn is decrypted
85
- expect(succeeded_event.reply["cursor"]["firstBatch"].first["ssn"]).to be_ciphertext
86
- end
74
+ before do
75
+ encryption_client['users'].aggregate([{ '$match' => { 'ssn' => ssn } }]).first
76
+ end
87
77
 
88
- it_behaves_like 'it has a non-encrypted key_vault_client'
89
- end
78
+ it 'has encrypted data in command monitoring' do
79
+ # Command started event occurs after ssn is encrypted
80
+ expect(
81
+ started_event.command["pipeline"].first["$match"]["ssn"]["$eq"]
82
+ ).to be_ciphertext
90
83
 
91
- describe '#count' do
92
- let(:command_name) { 'count' }
84
+ # Command succeeded event occurs before ssn is decrypted
85
+ expect(succeeded_event.reply["cursor"]["firstBatch"].first["ssn"]).to be_ciphertext
86
+ end
93
87
 
94
- before do
95
- encryption_client['users'].count(ssn: ssn)
88
+ it_behaves_like 'it has a non-encrypted key_vault_client'
96
89
  end
97
90
 
98
- it 'has encrypted data in command monitoring' do
99
- # Command started event occurs after ssn is encrypted
100
- # Command succeeded event does not contain any data to be decrypted
101
- expect(started_event.command["query"]["ssn"]["$eq"]).to be_ciphertext
102
- end
91
+ describe '#count' do
92
+ let(:command_name) { 'count' }
103
93
 
104
- it_behaves_like 'it has a non-encrypted key_vault_client'
105
- end
94
+ before do
95
+ encryption_client['users'].count(ssn: ssn)
96
+ end
106
97
 
107
- describe '#distinct' do
108
- let(:command_name) { 'distinct' }
98
+ it 'has encrypted data in command monitoring' do
99
+ # Command started event occurs after ssn is encrypted
100
+ # Command succeeded event does not contain any data to be decrypted
101
+ expect(started_event.command["query"]["ssn"]["$eq"]).to be_ciphertext
102
+ end
109
103
 
110
- before do
111
- encryption_client['users'].distinct(:ssn)
104
+ it_behaves_like 'it has a non-encrypted key_vault_client'
112
105
  end
113
106
 
114
- it 'has encrypted data in command monitoring' do
115
- # Command started event does not contain any data to be encrypted
116
- # Command succeeded event occurs before ssn is decrypted
117
- expect(succeeded_event.reply["values"].first).to be_ciphertext
118
- end
107
+ describe '#distinct' do
108
+ let(:command_name) { 'distinct' }
119
109
 
120
- it_behaves_like 'it has a non-encrypted key_vault_client'
121
- end
110
+ before do
111
+ encryption_client['users'].distinct(:ssn)
112
+ end
122
113
 
123
- describe '#delete_one' do
124
- let(:command_name) { 'delete' }
114
+ it 'has encrypted data in command monitoring' do
115
+ # Command started event does not contain any data to be encrypted
116
+ # Command succeeded event occurs before ssn is decrypted
117
+ expect(succeeded_event.reply["values"].first).to be_ciphertext
118
+ end
125
119
 
126
- before do
127
- encryption_client['users'].delete_one(ssn: ssn)
120
+ it_behaves_like 'it has a non-encrypted key_vault_client'
128
121
  end
129
122
 
130
- it 'has encrypted data in command monitoring' do
131
- # Command started event occurs after ssn is encrypted
132
- # Command succeeded event does not contain any data to be decrypted
133
- expect(started_event.command["deletes"].first["q"]["ssn"]["$eq"]).to be_ciphertext
134
- end
123
+ describe '#delete_one' do
124
+ let(:command_name) { 'delete' }
135
125
 
136
- it_behaves_like 'it has a non-encrypted key_vault_client'
137
- end
126
+ before do
127
+ encryption_client['users'].delete_one(ssn: ssn)
128
+ end
138
129
 
139
- describe '#delete_many' do
140
- let(:command_name) { 'delete' }
130
+ it 'has encrypted data in command monitoring' do
131
+ # Command started event occurs after ssn is encrypted
132
+ # Command succeeded event does not contain any data to be decrypted
133
+ expect(started_event.command["deletes"].first["q"]["ssn"]["$eq"]).to be_ciphertext
134
+ end
141
135
 
142
- before do
143
- encryption_client['users'].delete_many(ssn: ssn)
136
+ it_behaves_like 'it has a non-encrypted key_vault_client'
144
137
  end
145
138
 
146
- it 'has encrypted data in command monitoring' do
147
- # Command started event occurs after ssn is encrypted
148
- # Command succeeded event does not contain any data to be decrypted
149
- expect(started_event.command["deletes"].first["q"]["ssn"]["$eq"]).to be_ciphertext
150
- end
139
+ describe '#delete_many' do
140
+ let(:command_name) { 'delete' }
151
141
 
152
- it_behaves_like 'it has a non-encrypted key_vault_client'
153
- end
142
+ before do
143
+ encryption_client['users'].delete_many(ssn: ssn)
144
+ end
154
145
 
155
- describe '#find' do
156
- let(:command_name) { 'find' }
146
+ it 'has encrypted data in command monitoring' do
147
+ # Command started event occurs after ssn is encrypted
148
+ # Command succeeded event does not contain any data to be decrypted
149
+ expect(started_event.command["deletes"].first["q"]["ssn"]["$eq"]).to be_ciphertext
150
+ end
157
151
 
158
- before do
159
- encryption_client['users'].find(ssn: ssn).first
152
+ it_behaves_like 'it has a non-encrypted key_vault_client'
160
153
  end
161
154
 
162
- it 'has encrypted data in command monitoring' do
163
- # Command started event occurs after ssn is encrypted
164
- expect(started_event.command["filter"]["ssn"]["$eq"]).to be_ciphertext
155
+ describe '#find' do
156
+ let(:command_name) { 'find' }
165
157
 
166
- # Command succeeded event occurs before ssn is decrypted
167
- expect(succeeded_event.reply["cursor"]["firstBatch"].first["ssn"]).to be_ciphertext
168
- end
158
+ before do
159
+ encryption_client['users'].find(ssn: ssn).first
160
+ end
169
161
 
170
- it_behaves_like 'it has a non-encrypted key_vault_client'
171
- end
162
+ it 'has encrypted data in command monitoring' do
163
+ # Command started event occurs after ssn is encrypted
164
+ expect(started_event.command["filter"]["ssn"]["$eq"]).to be_ciphertext
172
165
 
173
- describe '#find_one_and_delete' do
174
- let(:command_name) { 'findAndModify' }
166
+ # Command succeeded event occurs before ssn is decrypted
167
+ expect(succeeded_event.reply["cursor"]["firstBatch"].first["ssn"]).to be_ciphertext
168
+ end
175
169
 
176
- before do
177
- encryption_client['users'].find_one_and_delete(ssn: ssn)
170
+ it_behaves_like 'it has a non-encrypted key_vault_client'
178
171
  end
179
172
 
180
- it 'has encrypted data in command monitoring' do
181
- # Command started event occurs after ssn is encrypted
182
- expect(started_event.command["query"]["ssn"]["$eq"]).to be_ciphertext
173
+ describe '#find_one_and_delete' do
174
+ let(:command_name) { 'findAndModify' }
183
175
 
184
- # Command succeeded event occurs before ssn is decrypted
185
- expect(succeeded_event.reply["value"]["ssn"]).to be_ciphertext
186
- end
176
+ before do
177
+ encryption_client['users'].find_one_and_delete(ssn: ssn)
178
+ end
187
179
 
188
- it_behaves_like 'it has a non-encrypted key_vault_client'
189
- end
180
+ it 'has encrypted data in command monitoring' do
181
+ # Command started event occurs after ssn is encrypted
182
+ expect(started_event.command["query"]["ssn"]["$eq"]).to be_ciphertext
190
183
 
191
- describe '#find_one_and_replace' do
192
- let(:command_name) { 'findAndModify' }
184
+ # Command succeeded event occurs before ssn is decrypted
185
+ expect(succeeded_event.reply["value"]["ssn"]).to be_ciphertext
186
+ end
193
187
 
194
- before do
195
- encryption_client['users'].find_one_and_replace(
196
- { ssn: ssn },
197
- { ssn: '555-555-5555' }
198
- )
188
+ it_behaves_like 'it has a non-encrypted key_vault_client'
199
189
  end
200
190
 
201
- it 'has encrypted data in command monitoring' do
202
- # Command started event occurs after ssn is encrypted
203
- expect(started_event.command["query"]["ssn"]["$eq"]).to be_ciphertext
204
- expect(started_event.command["update"]["ssn"]).to be_ciphertext
191
+ describe '#find_one_and_replace' do
192
+ let(:command_name) { 'findAndModify' }
205
193
 
206
- # Command succeeded event occurs before ssn is decrypted
207
- expect(succeeded_event.reply["value"]["ssn"]).to be_ciphertext
208
- end
194
+ before do
195
+ encryption_client['users'].find_one_and_replace(
196
+ { ssn: ssn },
197
+ { ssn: '555-555-5555' }
198
+ )
199
+ end
209
200
 
210
- it_behaves_like 'it has a non-encrypted key_vault_client'
211
- end
201
+ it 'has encrypted data in command monitoring' do
202
+ # Command started event occurs after ssn is encrypted
203
+ expect(started_event.command["query"]["ssn"]["$eq"]).to be_ciphertext
204
+ expect(started_event.command["update"]["ssn"]).to be_ciphertext
212
205
 
213
- describe '#find_one_and_update' do
214
- let(:command_name) { 'findAndModify' }
206
+ # Command succeeded event occurs before ssn is decrypted
207
+ expect(succeeded_event.reply["value"]["ssn"]).to be_ciphertext
208
+ end
215
209
 
216
- before do
217
- encryption_client['users'].find_one_and_update(
218
- { ssn: ssn },
219
- { ssn: '555-555-5555' }
220
- )
210
+ it_behaves_like 'it has a non-encrypted key_vault_client'
221
211
  end
222
212
 
223
- it 'has encrypted data in command monitoring' do
213
+ describe '#find_one_and_update' do
214
+ let(:command_name) { 'findAndModify' }
224
215
 
225
- # Command started event occurs after ssn is encrypted
226
- expect(started_event.command["query"]["ssn"]["$eq"]).to be_ciphertext
227
- expect(started_event.command["update"]["ssn"]).to be_ciphertext
216
+ before do
217
+ encryption_client['users'].find_one_and_update(
218
+ { ssn: ssn },
219
+ { ssn: '555-555-5555' }
220
+ )
221
+ end
228
222
 
229
- # Command succeeded event occurs before ssn is decrypted
230
- expect(succeeded_event.reply["value"]["ssn"]).to be_ciphertext
231
- end
223
+ it 'has encrypted data in command monitoring' do
232
224
 
233
- it_behaves_like 'it has a non-encrypted key_vault_client'
234
- end
225
+ # Command started event occurs after ssn is encrypted
226
+ expect(started_event.command["query"]["ssn"]["$eq"]).to be_ciphertext
227
+ expect(started_event.command["update"]["ssn"]).to be_ciphertext
235
228
 
236
- describe '#insert_one' do
237
- let(:command_name) { 'insert' }
229
+ # Command succeeded event occurs before ssn is decrypted
230
+ expect(succeeded_event.reply["value"]["ssn"]).to be_ciphertext
231
+ end
238
232
 
239
- before do
240
- encryption_client['users'].insert_one(ssn: ssn)
233
+ it_behaves_like 'it has a non-encrypted key_vault_client'
241
234
  end
242
235
 
243
- it 'has encrypted data in command monitoring' do
244
- # Command started event occurs after ssn is encrypted
245
- # Command succeeded event does not contain any data to be decrypted
246
- expect(started_event.command["documents"].first["ssn"]).to be_ciphertext
247
- end
236
+ describe '#replace_one' do
237
+ let(:command_name) { 'update' }
248
238
 
249
- it_behaves_like 'it has a non-encrypted key_vault_client'
250
- end
239
+ before do
240
+ encryption_client['users'].replace_one(
241
+ { ssn: ssn },
242
+ { ssn: '555-555-5555' }
243
+ )
244
+ end
251
245
 
252
- describe '#replace_one' do
253
- let(:command_name) { 'update' }
246
+ it 'has encrypted data in command monitoring' do
247
+ # Command started event occurs after ssn is encrypted
248
+ # Command succeeded event does not contain any data to be decrypted
249
+ expect(started_event.command["updates"].first["q"]["ssn"]["$eq"]).to be_ciphertext
250
+ expect(started_event.command["updates"].first["u"]["ssn"]).to be_ciphertext
251
+ end
254
252
 
255
- before do
256
- encryption_client['users'].replace_one(
257
- { ssn: ssn },
258
- { ssn: '555-555-5555' }
259
- )
253
+ it_behaves_like 'it has a non-encrypted key_vault_client'
260
254
  end
261
255
 
262
- it 'has encrypted data in command monitoring' do
263
- # Command started event occurs after ssn is encrypted
264
- # Command succeeded event does not contain any data to be decrypted
265
- expect(started_event.command["updates"].first["q"]["ssn"]["$eq"]).to be_ciphertext
266
- expect(started_event.command["updates"].first["u"]["ssn"]).to be_ciphertext
267
- end
256
+ describe '#update_one' do
257
+ let(:command_name) { 'update' }
268
258
 
269
- it_behaves_like 'it has a non-encrypted key_vault_client'
270
- end
259
+ before do
260
+ encryption_client['users'].replace_one({ ssn: ssn }, { ssn: '555-555-5555' })
261
+ end
271
262
 
272
- describe '#update_one' do
273
- let(:command_name) { 'update' }
263
+ it 'has encrypted data in command monitoring' do
264
+ # Command started event occurs after ssn is encrypted
265
+ # Command succeeded event does not contain any data to be decrypted
266
+ expect(started_event.command["updates"].first["q"]["ssn"]["$eq"]).to be_ciphertext
267
+ expect(started_event.command["updates"].first["u"]["ssn"]).to be_ciphertext
268
+ end
274
269
 
275
- before do
276
- encryption_client['users'].replace_one({ ssn: ssn }, { ssn: '555-555-5555' })
270
+ it_behaves_like 'it has a non-encrypted key_vault_client'
277
271
  end
278
272
 
279
- it 'has encrypted data in command monitoring' do
280
- # Command started event occurs after ssn is encrypted
281
- # Command succeeded event does not contain any data to be decrypted
282
- expect(started_event.command["updates"].first["q"]["ssn"]["$eq"]).to be_ciphertext
283
- expect(started_event.command["updates"].first["u"]["ssn"]).to be_ciphertext
284
- end
273
+ describe '#update_many' do
274
+ let(:command_name) { 'update' }
285
275
 
286
- it_behaves_like 'it has a non-encrypted key_vault_client'
276
+ before do
277
+ # update_many does not support replacement-style updates
278
+ encryption_client['users'].update_many({ ssn: ssn }, { "$inc" => { :age => 1 } })
279
+ end
280
+
281
+ it 'has encrypted data in command monitoring' do
282
+ # Command started event occurs after ssn is encrypted
283
+ # Command succeeded event does not contain any data to be decrypted
284
+ expect(started_event.command["updates"].first["q"]["ssn"]["$eq"]).to be_ciphertext
285
+ end
286
+
287
+ it_behaves_like 'it has a non-encrypted key_vault_client'
288
+ end
287
289
  end
288
290
 
289
- describe '#update_many' do
290
- let(:command_name) { 'update' }
291
+ describe '#insert_one' do
292
+ let(:command_name) { 'insert' }
291
293
 
292
294
  before do
293
- # update_many does not support replacement-style updates
294
- encryption_client['users'].update_many({ ssn: ssn }, { "$inc" => { :age => 1 } })
295
+ encryption_client['users'].insert_one(ssn: ssn)
295
296
  end
296
297
 
297
298
  it 'has encrypted data in command monitoring' do
298
299
  # Command started event occurs after ssn is encrypted
299
300
  # Command succeeded event does not contain any data to be decrypted
300
- expect(started_event.command["updates"].first["q"]["ssn"]["$eq"]).to be_ciphertext
301
+ expect(started_event.command["documents"].first["ssn"]).to be_ciphertext
301
302
  end
302
303
 
303
304
  it_behaves_like 'it has a non-encrypted key_vault_client'
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require 'spec_helper'
5
+
6
+ describe 'Decryption events' do
7
+ require_enterprise
8
+ min_server_fcv '4.2'
9
+ require_libmongocrypt
10
+ include_context 'define shared FLE helpers'
11
+ require_topology :replica_set
12
+
13
+
14
+ let(:setup_client) do
15
+ ClientRegistry.instance.new_local_client(
16
+ SpecConfig.instance.addresses,
17
+ SpecConfig.instance.test_options.merge(
18
+ database: SpecConfig.instance.test_db,
19
+ )
20
+ )
21
+ end
22
+
23
+ let(:collection_name) do
24
+ 'decryption_event'
25
+ end
26
+
27
+ let(:client_encryption) do
28
+ Mongo::ClientEncryption.new(
29
+ setup_client,
30
+ key_vault_namespace: "#{key_vault_db}.#{key_vault_coll}",
31
+ kms_providers: local_kms_providers
32
+ )
33
+ end
34
+
35
+ let(:key_id) do
36
+ client_encryption.create_data_key('local')
37
+ end
38
+
39
+ let(:unencrypted_value) do
40
+ 'hello'
41
+ end
42
+
43
+ let(:ciphertext) do
44
+ client_encryption.encrypt(
45
+ unencrypted_value,
46
+ key_id: key_id,
47
+ algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'
48
+ )
49
+ end
50
+
51
+ let(:malformed_ciphertext) do
52
+ ciphertext.dup.tap do |obj|
53
+ obj.data[-1] = 0.chr
54
+ end
55
+ end
56
+
57
+ let(:encrypted_client) do
58
+ ClientRegistry.instance.new_local_client(
59
+ SpecConfig.instance.addresses,
60
+ SpecConfig.instance.test_options.merge(
61
+ auto_encryption_options: {
62
+ key_vault_namespace: "#{key_vault_db}.#{key_vault_coll}",
63
+ kms_providers: local_kms_providers,
64
+ extra_options: extra_options,
65
+ },
66
+ database: SpecConfig.instance.test_db,
67
+ retry_reads: false,
68
+ max_read_retries: 0,
69
+ )
70
+ )
71
+ end
72
+
73
+ let(:collection) do
74
+ encrypted_client[collection_name]
75
+ end
76
+
77
+ let(:subscriber) { Mrss::EventSubscriber.new }
78
+
79
+ before(:each) do
80
+ setup_client[collection_name].drop
81
+ setup_client[collection_name].create
82
+
83
+ encrypted_client.subscribe(Mongo::Monitoring::COMMAND, subscriber)
84
+ end
85
+
86
+ it 'tests command error' do
87
+ setup_client.use(:admin).command(
88
+ {
89
+ "configureFailPoint" => "failCommand",
90
+ "mode" => {
91
+ "times" => 1
92
+ },
93
+ "data" => {
94
+ "errorCode" => 123,
95
+ "failCommands" => [
96
+ "aggregate"
97
+ ]
98
+ }
99
+ }
100
+ )
101
+
102
+ expect do
103
+ collection.aggregate([]).to_a
104
+ end.to raise_error(Mongo::Error::OperationFailure, /Failing command (?:via|due to) 'failCommand' failpoint/)
105
+ expect(subscriber.failed_events.length).to eql(1)
106
+ end
107
+
108
+ it 'tests network error' do
109
+ setup_client.use(:admin).command(
110
+ {
111
+ "configureFailPoint" => "failCommand",
112
+ "mode" => {
113
+ "times" => 1
114
+ },
115
+ "data" => {
116
+ "errorCode" => 123,
117
+ "closeConnection": true,
118
+ "failCommands" => [
119
+ "aggregate"
120
+ ]
121
+ }
122
+ }
123
+ )
124
+
125
+ expect do
126
+ collection.aggregate([]).to_a
127
+ end.to raise_error(Mongo::Error::SocketError)
128
+ expect(subscriber.failed_events.length).to eql(1)
129
+ end
130
+
131
+ it 'tests decrypt error' do
132
+ collection.insert_one(encrypted: malformed_ciphertext)
133
+ expect do
134
+ collection.aggregate([]).to_a
135
+ end.to raise_error(Mongo::Error::CryptError)
136
+ aggregate_event = subscriber.succeeded_events.detect do |evt|
137
+ evt.command_name == 'aggregate'
138
+ end
139
+ expect(aggregate_event).not_to be_nil
140
+ expect(
141
+ aggregate_event.reply.dig('cursor', 'firstBatch')&.first&.dig('encrypted')
142
+ ).to be_a_kind_of(BSON::Binary)
143
+ end
144
+
145
+ it 'tests decrypt success' do
146
+ collection.insert_one(encrypted: ciphertext)
147
+ expect do
148
+ collection.aggregate([]).to_a
149
+ end.not_to raise_error
150
+ aggregate_event = subscriber.succeeded_events.detect do |evt|
151
+ evt.command_name == 'aggregate'
152
+ end
153
+ expect(aggregate_event).not_to be_nil
154
+ expect(
155
+ aggregate_event.reply.dig('cursor', 'firstBatch')&.first&.dig('encrypted')
156
+ ).to be_a_kind_of(BSON::Binary)
157
+ end
158
+ end
@@ -71,13 +71,13 @@ describe 'Explicit Queryable Encryption' do
71
71
 
72
72
  it 'can insert encrypted indexed and find' do
73
73
  insert_payload = client_encryption.encrypt(
74
- value, key_id: key1_id, algorithm: "Indexed"
74
+ value, key_id: key1_id, algorithm: "Indexed", contention_factor: 0
75
75
  )
76
76
  encrypted_client[encrypted_coll].insert_one(
77
77
  "encryptedIndexed" => insert_payload
78
78
  )
79
79
  find_payload = client_encryption.encrypt(
80
- value, key_id: key1_id, algorithm: "Indexed", query_type: :equality
80
+ value, key_id: key1_id, algorithm: "Indexed", query_type: "equality", contention_factor: 0
81
81
  )
82
82
  find_results = encrypted_client[encrypted_coll]
83
83
  .find("encryptedIndexed" => find_payload)
@@ -96,7 +96,7 @@ describe 'Explicit Queryable Encryption' do
96
96
  )
97
97
  end
98
98
  find_payload = client_encryption.encrypt(
99
- value, key_id: key1_id, algorithm: "Indexed", query_type: :equality
99
+ value, key_id: key1_id, algorithm: "Indexed", query_type: "equality", contention_factor: 0
100
100
  )
101
101
  find_results = encrypted_client[encrypted_coll]
102
102
  .find("encryptedIndexed" => find_payload)
@@ -106,7 +106,7 @@ describe 'Explicit Queryable Encryption' do
106
106
  expect(doc["encryptedIndexed"]).to eq(value)
107
107
  end
108
108
  find_payload_2 = client_encryption.encrypt(
109
- value, key_id: key1_id, algorithm: "Indexed", query_type: :equality, contention_factor: 10
109
+ value, key_id: key1_id, algorithm: "Indexed", query_type: "equality", contention_factor: 10
110
110
  )
111
111
  find_results_2 = encrypted_client[encrypted_coll]
112
112
  .find("encryptedIndexed" => find_payload_2)
@@ -131,7 +131,7 @@ describe 'Explicit Queryable Encryption' do
131
131
 
132
132
  it 'can roundtrip encrypted indexed' do
133
133
  payload = client_encryption.encrypt(
134
- value, key_id: key1_id, algorithm: "Indexed"
134
+ value, key_id: key1_id, algorithm: "Indexed", contention_factor: 0
135
135
  )
136
136
  decrypted_value = client_encryption.decrypt(payload)
137
137
  expect(decrypted_value).to eq(value)