Skip to content

Commit fcedc87

Browse files
authored
RUBY-3226 Update libmongocrypt payloads to new QE protocol (#2718)
* update the QE specs * bump libmongocrypt-helper to 1.8.0 * update prose specs (server version >= 7, linting) * linting * didn't mean to commit this file * more prose specs to be updated * use the right version of fle2v2 specs they do a funky thing where they treat nil values as implying the absence of a field; had to do some work arounds to make that work. Hopefully it doesn't break anything new... * disallow encrypted collections on older servers * eccCollection is not to be created * enable linting on a couple more files * allow constants to be loaded after the file loads * some of these constants need to be in the utils namespace * don't need both the min_fcv and min_server_version constraints
1 parent 0feee3a commit fcedc87

File tree

76 files changed

+2160
-2147
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+2160
-2147
lines changed

.rubocop.yml

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,56 @@ Bundler/OrderedGems:
4444
Gemspec/OrderedDependencies:
4545
Enabled: false
4646

47+
Layout/SpaceInsideArrayLiteralBrackets:
48+
EnforcedStyle: space
49+
50+
Layout/SpaceInsidePercentLiteralDelimiters:
51+
Enabled: false
52+
53+
Metrics/ModuleLength:
54+
Enabled: false
55+
56+
Metrics/MethodLength:
57+
Max: 20
58+
59+
RSpec/BeforeAfterAll:
60+
Enabled: false
61+
62+
# Ideally, we'd use this one, too, but our tests have not historically followed
63+
# this style and it's not worth changing right now, IMO
64+
RSpec/DescribeClass:
65+
Enabled: false
66+
67+
RSpec/ImplicitExpect:
68+
EnforcedStyle: is_expected
69+
70+
RSpec/MultipleExpectations:
71+
Enabled: false
72+
73+
RSpec/MultipleMemoizedHelpers:
74+
Enabled: false
75+
76+
RSpec/NestedGroups:
77+
Enabled: false
78+
4779
Style/Documentation:
4880
Exclude:
4981
- 'spec/**/*'
5082

51-
Metrics/MethodLength:
52-
Max: 20
83+
Style/ModuleFunction:
84+
EnforcedStyle: extend_self
85+
86+
Style/OptionalBooleanParameter:
87+
Enabled: false
88+
89+
Style/ParallelAssignment:
90+
Enabled: false
91+
92+
Style/TernaryParentheses:
93+
EnforcedStyle: require_parentheses_when_complex
94+
95+
Style/TrailingCommaInArrayLiteral:
96+
Enabled: false
97+
98+
Style/TrailingCommaInHashLiteral:
99+
Enabled: false

gemfiles/standard.rb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# frozen_string_literal: true
2-
# rubocop:todo all
32

3+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/BlockLength
44
def standard_dependencies
55
gem 'yard'
66
gem 'ffi'
@@ -29,7 +29,7 @@ def standard_dependencies
2929

3030
# for static analysis -- ignore ruby < 2.6 because of rubocop
3131
# version incompatibilities
32-
if RUBY_VERSION > "2.5.99"
32+
if RUBY_VERSION > '2.5.99'
3333
gem 'rubocop', '~> 1.45.1'
3434
gem 'rubocop-performance', '~> 1.16.0'
3535
gem 'rubocop-rake', '~> 0.6.0'
@@ -66,7 +66,6 @@ def standard_dependencies
6666
gem 'solargraph', platforms: :mri
6767
end
6868

69-
if ENV['FLE'] == 'helper'
70-
gem 'libmongocrypt-helper', '~> 1.7.0'
71-
end
69+
gem 'libmongocrypt-helper', '~> 1.8.0' if ENV['FLE'] == 'helper'
7270
end
71+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/BlockLength
Lines changed: 76 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# frozen_string_literal: true
2-
# rubocop:todo all
32

43
# Copyright (C) 2014-2022 MongoDB Inc.
54
#
@@ -22,6 +21,8 @@ class Collection
2221
#
2322
# @api private
2423
module QueryableEncryption
24+
# The minimum wire version for QE2 support
25+
QE2_MIN_WIRE_VERSION = 21
2526

2627
# Creates auxiliary collections and indices for queryable encryption if necessary.
2728
#
@@ -32,32 +33,17 @@ module QueryableEncryption
3233
#
3334
# @return [ Result ] The result of provided block.
3435
def maybe_create_qe_collections(encrypted_fields, client, session)
35-
encrypted_fields = if encrypted_fields
36-
encrypted_fields
37-
elsif encrypted_fields_map
38-
encrypted_fields_map[namespace] || {}
39-
else
40-
{}
41-
end
42-
if encrypted_fields.empty?
43-
return yield
44-
end
36+
encrypted_fields = encrypted_fields_from(encrypted_fields)
37+
return yield if encrypted_fields.empty?
38+
39+
check_wire_version!
4540

4641
emm_collections(encrypted_fields).each do |coll|
4742
context = Operation::Context.new(client: client, session: session)
48-
Operation::Create.new(
49-
selector: {
50-
create: coll,
51-
clusteredIndex: {
52-
key: {
53-
_id: 1
54-
},
55-
unique: true
56-
}
57-
},
58-
db_name: database.name,
59-
).execute(next_primary(nil, session), context: context)
43+
create_operation_for(coll)
44+
.execute(next_primary(nil, session), context: context)
6045
end
46+
6147
yield(encrypted_fields).tap do |result|
6248
indexes.create_one(__safeContent__: 1) if result
6349
end
@@ -73,31 +59,25 @@ def maybe_create_qe_collections(encrypted_fields, client, session)
7359
# @return [ Result ] The result of provided block.
7460
def maybe_drop_emm_collections(encrypted_fields, client, session)
7561
encrypted_fields = if encrypted_fields
76-
encrypted_fields
77-
elsif encrypted_fields_map
78-
if encrypted_fields_map[namespace]
79-
encrypted_fields_map[namespace]
80-
else
81-
database.list_collections(filter: { name: name })
82-
.first
83-
&.fetch(:options, {})
84-
&.fetch(:encryptedFields, {}) || {}
85-
end
86-
else
87-
{}
88-
end
89-
if encrypted_fields.empty?
90-
return yield
91-
end
62+
encrypted_fields
63+
elsif encrypted_fields_map
64+
encrypted_fields_for_drop_from_map
65+
else
66+
{}
67+
end
68+
69+
return yield if encrypted_fields.empty?
70+
9271
emm_collections(encrypted_fields).each do |coll|
9372
context = Operation::Context.new(client: client, session: session)
9473
operation = Operation::Drop.new(
9574
selector: { drop: coll },
9675
db_name: database.name,
97-
session: session,
76+
session: session
9877
)
9978
do_drop(operation, session, context)
10079
end
80+
10181
yield
10282
end
10383

@@ -112,11 +92,66 @@ def maybe_drop_emm_collections(encrypted_fields, client, session)
11292
def emm_collections(encrypted_fields)
11393
[
11494
encrypted_fields['escCollection'] || "enxcol_.#{name}.esc",
115-
encrypted_fields['eccCollection'] || "enxcol_.#{name}.ecc",
11695
encrypted_fields['ecocCollection'] || "enxcol_.#{name}.ecoc",
11796
]
11897
end
11998

99+
# Creating encrypted collections is only supported on 7.0.0 and later
100+
# (wire version 21+).
101+
#
102+
# @raise [ Mongo::Error ] if the wire version is not
103+
# recent enough
104+
def check_wire_version!
105+
return unless next_primary.max_wire_version < QE2_MIN_WIRE_VERSION
106+
107+
raise Mongo::Error,
108+
'Driver support of Queryable Encryption is incompatible with server. ' \
109+
'Upgrade server to use Queryable Encryption.'
110+
end
111+
112+
# Tries to return the encrypted fields from the argument. If the argument
113+
# is nil, tries to find the encrypted fields from the
114+
# encrypted_fields_map.
115+
#
116+
# @param [ Hash | nil ] fields the encrypted fields
117+
#
118+
# @return [ Hash ] the encrypted fields
119+
def encrypted_fields_from(fields)
120+
fields ||
121+
(encrypted_fields_map && encrypted_fields_map[namespace]) ||
122+
{}
123+
end
124+
125+
# Tries to return the encrypted fields from the {{encrypted_fields_map}}
126+
# value, for the current namespace.
127+
#
128+
# @return [ Hash | nil ] the encrypted fields, if found
129+
def encrypted_fields_for_drop_from_map
130+
encrypted_fields_map[namespace] ||
131+
database.list_collections(filter: { name: name })
132+
.first
133+
&.fetch(:options, {})
134+
&.fetch(:encryptedFields, {}) ||
135+
{}
136+
end
137+
138+
# Returns a new create operation for the given collection.
139+
#
140+
# @param [ String ] coll the name of the collection to create.
141+
#
142+
# @return [ Operation::Create ] the new create operation.
143+
def create_operation_for(coll)
144+
Operation::Create.new(
145+
selector: {
146+
create: coll,
147+
clusteredIndex: {
148+
key: { _id: 1 },
149+
unique: true
150+
}
151+
},
152+
db_name: database.name
153+
)
154+
end
120155
end
121156
end
122157
end

lib/mongo/crypt/kms/azure/credentials_retriever.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# frozen_string_literal: true
2+
# rubocop:todo all
23

34
# Copyright (C) 2019-2021 MongoDB Inc.
45
#

0 commit comments

Comments
 (0)