mongo 2.18.0.beta1 → 2.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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)