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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/mongo/bulk_write.rb +8 -2
- data/lib/mongo/client.rb +19 -5
- data/lib/mongo/client_encryption.rb +86 -4
- data/lib/mongo/cluster.rb +6 -4
- data/lib/mongo/collection/view/aggregation.rb +3 -0
- data/lib/mongo/collection/view/change_stream.rb +9 -0
- data/lib/mongo/collection/view/iterable.rb +1 -0
- data/lib/mongo/collection/view/readable.rb +11 -3
- data/lib/mongo/collection.rb +9 -1
- data/lib/mongo/config.rb +11 -0
- data/lib/mongo/crypt/auto_encrypter.rb +49 -21
- data/lib/mongo/crypt/binding.rb +73 -48
- data/lib/mongo/crypt/data_key_context.rb +6 -1
- data/lib/mongo/crypt/encryption_io.rb +66 -0
- data/lib/mongo/crypt/explicit_encrypter.rb +116 -5
- data/lib/mongo/crypt/explicit_encryption_context.rb +3 -8
- data/lib/mongo/crypt/handle.rb +26 -8
- data/lib/mongo/crypt/kms/aws.rb +11 -3
- data/lib/mongo/crypt/kms/azure.rb +14 -6
- data/lib/mongo/crypt/kms/gcp.rb +12 -5
- data/lib/mongo/crypt/kms/kmip.rb +15 -9
- data/lib/mongo/crypt/kms/local.rb +9 -1
- data/lib/mongo/crypt/kms/master_key_document.rb +1 -1
- data/lib/mongo/crypt/rewrap_many_data_key_context.rb +46 -0
- data/lib/mongo/crypt/rewrap_many_data_key_result.rb +37 -0
- data/lib/mongo/crypt/status.rb +8 -2
- data/lib/mongo/crypt.rb +2 -0
- data/lib/mongo/database.rb +10 -27
- data/lib/mongo/error/missing_file_chunk.rb +8 -2
- data/lib/mongo/grid/stream/read.rb +6 -0
- data/lib/mongo/index/view.rb +1 -0
- data/lib/mongo/operation/create/op_msg.rb +1 -13
- data/lib/mongo/operation/distinct/op_msg.rb +4 -1
- data/lib/mongo/protocol/msg.rb +0 -16
- data/lib/mongo/server/connection_pool.rb +5 -4
- data/lib/mongo/server/monitor/connection.rb +10 -4
- data/lib/mongo/server/monitor.rb +4 -0
- data/lib/mongo/server/push_monitor.rb +4 -0
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo.rb +2 -0
- data/spec/README.md +14 -0
- data/spec/integration/change_stream_spec.rb +1 -1
- data/spec/integration/client_construction_spec.rb +73 -7
- data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +165 -164
- data/spec/integration/client_side_encryption/decryption_events_prose_spec.rb +158 -0
- data/spec/integration/client_side_encryption/explicit_queryable_encryption_spec.rb +5 -5
- data/spec/integration/client_side_encryption/kms_tls_options_spec.rb +50 -8
- data/spec/integration/client_side_encryption/unique_index_on_key_alt_names_prose_spec.rb +85 -0
- data/spec/integration/ocsp_verifier_spec.rb +1 -1
- data/spec/integration/reconnect_spec.rb +2 -0
- data/spec/integration/sdam_events_spec.rb +40 -0
- data/spec/integration/srv_monitoring_spec.rb +1 -0
- data/spec/integration/srv_spec.rb +1 -0
- data/spec/lite_spec_helper.rb +5 -4
- data/spec/mongo/bulk_write_spec.rb +13 -0
- data/spec/mongo/client_construction_spec.rb +45 -2
- data/spec/mongo/client_encryption_spec.rb +0 -12
- data/spec/mongo/client_spec.rb +1 -1
- data/spec/mongo/collection/view/aggregation_spec.rb +119 -0
- data/spec/mongo/collection/view/readable_spec.rb +630 -5
- data/spec/mongo/collection_spec.rb +32 -0
- data/spec/mongo/crypt/auto_encrypter_spec.rb +110 -0
- data/spec/mongo/crypt/binding/context_spec.rb +3 -35
- data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
- data/spec/mongo/crypt/explicit_encryption_context_spec.rb +8 -3
- data/spec/mongo/crypt/handle_spec.rb +39 -3
- data/spec/mongo/crypt/kms/credentials_spec.rb +0 -47
- data/spec/mongo/index/view_spec.rb +56 -0
- data/spec/mongo/operation/create/op_msg_spec.rb +0 -42
- data/spec/mongo/server/connection_pool_spec.rb +26 -4
- data/spec/mongo/socket/ssl_spec.rb +3 -3
- data/spec/runners/crud/requirement.rb +6 -1
- data/spec/runners/crud/test.rb +1 -1
- data/spec/runners/transactions/spec.rb +2 -2
- data/spec/runners/transactions/test.rb +4 -20
- data/spec/runners/transactions.rb +2 -2
- data/spec/runners/unified/assertions.rb +32 -2
- data/spec/runners/unified/change_stream_operations.rb +3 -0
- data/spec/runners/unified/client_side_encryption_operations.rb +83 -0
- data/spec/runners/unified/crud_operations.rb +17 -2
- data/spec/runners/unified/ddl_operations.rb +27 -2
- data/spec/runners/unified/grid_fs_operations.rb +21 -0
- data/spec/runners/unified/test.rb +59 -1
- data/spec/shared/lib/mrss/docker_runner.rb +2 -0
- data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
- data/spec/shared/shlib/set_env.sh +3 -0
- data/spec/solo/clean_exit_spec.rb +5 -0
- data/spec/spec_tests/client_side_encryption_spec.rb +1 -1
- data/spec/spec_tests/client_side_encryption_unified_spec.rb +16 -0
- data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +298 -0
- data/spec/spec_tests/data/client_side_encryption/create-and-createIndexes.yml +58 -0
- data/spec/spec_tests/data/client_side_encryption/fle2-Delete.yml +1 -1
- data/spec/spec_tests/data/client_side_encryption/fle2-EncryptedFields-vs-jsonSchema.yml +1 -1
- data/spec/spec_tests/data/client_side_encryption/fle2-FindOneAndUpdate.yml +2 -2
- data/spec/spec_tests/data/client_side_encryption/fle2-InsertFind-Indexed.yml +1 -1
- data/spec/spec_tests/data/client_side_encryption/fle2-Update.yml +2 -2
- data/spec/spec_tests/data/client_side_encryption/unified/addKeyAltName.yml +194 -0
- data/spec/spec_tests/data/client_side_encryption/unified/createDataKey-kms_providers-invalid.yml +67 -0
- data/spec/spec_tests/data/client_side_encryption/unified/createDataKey.yml +309 -0
- data/spec/spec_tests/data/client_side_encryption/unified/deleteKey.yml +159 -0
- data/spec/spec_tests/data/client_side_encryption/unified/getKey.yml +105 -0
- data/spec/spec_tests/data/client_side_encryption/unified/getKeyByAltName.yml +104 -0
- data/spec/spec_tests/data/client_side_encryption/unified/getKeys.yml +122 -0
- data/spec/spec_tests/data/client_side_encryption/unified/removeKeyAltName.yml +157 -0
- data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-decrypt_failure.yml +69 -0
- data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-encrypt_failure.yml +122 -0
- data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey.yml +432 -0
- data/spec/spec_tests/data/client_side_encryption/validatorAndPartialFieldExpression.yml +166 -0
- data/spec/spec_tests/data/command_monitoring_unified/bulkWrite.yml +68 -0
- data/spec/spec_tests/data/command_monitoring_unified/command.yml +50 -0
- data/spec/spec_tests/data/command_monitoring_unified/deleteMany.yml +79 -0
- data/spec/spec_tests/data/command_monitoring_unified/deleteOne.yml +79 -0
- data/spec/spec_tests/data/command_monitoring_unified/find.yml +254 -0
- data/spec/spec_tests/data/command_monitoring_unified/insertMany.yml +79 -0
- data/spec/spec_tests/data/command_monitoring_unified/insertOne.yml +77 -0
- data/spec/spec_tests/data/command_monitoring_unified/unacknowledgedBulkWrite.yml +55 -0
- data/spec/spec_tests/data/command_monitoring_unified/updateMany.yml +87 -0
- data/spec/spec_tests/data/command_monitoring_unified/updateOne.yml +118 -0
- data/spec/spec_tests/data/crud_unified/distinct-comment.yml +98 -0
- data/spec/spec_tests/data/gridfs_unified/delete.yml +198 -0
- data/spec/spec_tests/data/gridfs_unified/download.yml +241 -0
- data/spec/spec_tests/data/gridfs_unified/downloadByName.yml +159 -0
- data/spec/spec_tests/data/gridfs_unified/upload-disableMD5.yml +92 -0
- data/spec/spec_tests/data/gridfs_unified/upload.yml +288 -0
- data/spec/spec_tests/gridfs_unified_spec.rb +13 -0
- data/spec/stress/connection_pool_timing_spec.rb +2 -2
- data/spec/support/background_thread_registry.rb +3 -13
- data/spec/support/certificates/atlas-ocsp-ca.crt +40 -47
- data/spec/support/certificates/atlas-ocsp.crt +101 -106
- data/spec/support/crypt.rb +57 -13
- data/spec/support/macros.rb +10 -0
- data/spec/support/spec_config.rb +4 -0
- data.tar.gz.sig +0 -0
- metadata +1271 -1219
- metadata.gz.sig +0 -0
- data/spec/spec_tests/command_monitoring_spec.rb +0 -71
- data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +0 -49
- data/spec/spec_tests/data/command_monitoring/command.yml +0 -61
- data/spec/spec_tests/data/command_monitoring/deleteMany.yml +0 -55
- data/spec/spec_tests/data/command_monitoring/deleteOne.yml +0 -55
- data/spec/spec_tests/data/command_monitoring/find.yml +0 -266
- data/spec/spec_tests/data/command_monitoring/insertMany.yml +0 -75
- data/spec/spec_tests/data/command_monitoring/insertOne.yml +0 -51
- data/spec/spec_tests/data/command_monitoring/unacknowledgedBulkWrite.yml +0 -34
- data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -65
- 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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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'].
|
|
68
|
+
result = encryption_client['users'].insert_one(ssn: ssn, age: 23)
|
|
76
69
|
end
|
|
77
70
|
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
74
|
+
before do
|
|
75
|
+
encryption_client['users'].aggregate([{ '$match' => { 'ssn' => ssn } }]).first
|
|
76
|
+
end
|
|
87
77
|
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
92
|
-
|
|
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
|
-
|
|
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
|
-
|
|
99
|
-
|
|
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
|
-
|
|
105
|
-
|
|
94
|
+
before do
|
|
95
|
+
encryption_client['users'].count(ssn: ssn)
|
|
96
|
+
end
|
|
106
97
|
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
111
|
-
encryption_client['users'].distinct(:ssn)
|
|
104
|
+
it_behaves_like 'it has a non-encrypted key_vault_client'
|
|
112
105
|
end
|
|
113
106
|
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
121
|
-
|
|
110
|
+
before do
|
|
111
|
+
encryption_client['users'].distinct(:ssn)
|
|
112
|
+
end
|
|
122
113
|
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
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
|
-
|
|
131
|
-
|
|
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
|
-
|
|
137
|
-
|
|
126
|
+
before do
|
|
127
|
+
encryption_client['users'].delete_one(ssn: ssn)
|
|
128
|
+
end
|
|
138
129
|
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
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
|
-
|
|
147
|
-
|
|
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
|
-
|
|
153
|
-
|
|
142
|
+
before do
|
|
143
|
+
encryption_client['users'].delete_many(ssn: ssn)
|
|
144
|
+
end
|
|
154
145
|
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
|
|
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
|
-
|
|
163
|
-
|
|
164
|
-
expect(started_event.command["filter"]["ssn"]["$eq"]).to be_ciphertext
|
|
155
|
+
describe '#find' do
|
|
156
|
+
let(:command_name) { 'find' }
|
|
165
157
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
158
|
+
before do
|
|
159
|
+
encryption_client['users'].find(ssn: ssn).first
|
|
160
|
+
end
|
|
169
161
|
|
|
170
|
-
|
|
171
|
-
|
|
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
|
-
|
|
174
|
-
|
|
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
|
-
|
|
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
|
-
|
|
181
|
-
|
|
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
|
-
|
|
185
|
-
|
|
186
|
-
|
|
176
|
+
before do
|
|
177
|
+
encryption_client['users'].find_one_and_delete(ssn: ssn)
|
|
178
|
+
end
|
|
187
179
|
|
|
188
|
-
|
|
189
|
-
|
|
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
|
-
|
|
192
|
-
|
|
184
|
+
# Command succeeded event occurs before ssn is decrypted
|
|
185
|
+
expect(succeeded_event.reply["value"]["ssn"]).to be_ciphertext
|
|
186
|
+
end
|
|
193
187
|
|
|
194
|
-
|
|
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
|
-
|
|
202
|
-
|
|
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
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
|
|
211
|
-
|
|
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
|
-
|
|
214
|
-
|
|
206
|
+
# Command succeeded event occurs before ssn is decrypted
|
|
207
|
+
expect(succeeded_event.reply["value"]["ssn"]).to be_ciphertext
|
|
208
|
+
end
|
|
215
209
|
|
|
216
|
-
|
|
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
|
-
|
|
213
|
+
describe '#find_one_and_update' do
|
|
214
|
+
let(:command_name) { 'findAndModify' }
|
|
224
215
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
|
|
230
|
-
expect(succeeded_event.reply["value"]["ssn"]).to be_ciphertext
|
|
231
|
-
end
|
|
223
|
+
it 'has encrypted data in command monitoring' do
|
|
232
224
|
|
|
233
|
-
|
|
234
|
-
|
|
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
|
-
|
|
237
|
-
|
|
229
|
+
# Command succeeded event occurs before ssn is decrypted
|
|
230
|
+
expect(succeeded_event.reply["value"]["ssn"]).to be_ciphertext
|
|
231
|
+
end
|
|
238
232
|
|
|
239
|
-
|
|
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
|
-
|
|
244
|
-
|
|
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
|
-
|
|
250
|
-
|
|
239
|
+
before do
|
|
240
|
+
encryption_client['users'].replace_one(
|
|
241
|
+
{ ssn: ssn },
|
|
242
|
+
{ ssn: '555-555-5555' }
|
|
243
|
+
)
|
|
244
|
+
end
|
|
251
245
|
|
|
252
|
-
|
|
253
|
-
|
|
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
|
-
|
|
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
|
-
|
|
263
|
-
|
|
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
|
-
|
|
270
|
-
|
|
259
|
+
before do
|
|
260
|
+
encryption_client['users'].replace_one({ ssn: ssn }, { ssn: '555-555-5555' })
|
|
261
|
+
end
|
|
271
262
|
|
|
272
|
-
|
|
273
|
-
|
|
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
|
-
|
|
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
|
-
|
|
280
|
-
|
|
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
|
-
|
|
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 '#
|
|
290
|
-
let(:command_name) { '
|
|
291
|
+
describe '#insert_one' do
|
|
292
|
+
let(:command_name) { 'insert' }
|
|
291
293
|
|
|
292
294
|
before do
|
|
293
|
-
|
|
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["
|
|
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: :
|
|
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: :
|
|
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:
|
|
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)
|