Skip to content

Commit e1bf885

Browse files
GODRIVER-2433 Support explicit encryption for Range Index (#1145)
* add test data files for range prose tests * add RangeOptions API * add ClientEncryption.EncryptExpression * add prose test 22 * use libmongocrypt 1.7.0-alpha1 Co-authored-by: Benjamin Rewis <[email protected]>
1 parent 4e038d8 commit e1bf885

15 files changed

+772
-20
lines changed

.evergreen/config.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ functions:
9494
go env
9595
9696
# TODO(GODRIVER-2676): use libmongocrypt 1.7.0 once it is released.
97-
LIBMONGOCRYPT_TAG="1.7.0-alpha0"
97+
LIBMONGOCRYPT_TAG="1.7.0-alpha1"
9898
# Install libmongocrypt based on OS.
9999
if [ "Windows_NT" = "$OS" ]; then
100100
mkdir -p c:/libmongocrypt/include
@@ -106,7 +106,7 @@ functions:
106106
# TODO(GODRIVER-2676): replace this URL once libmongocrypt 1.7.0 is released with the following:
107107
# curl https://mciuploads.s3.amazonaws.com/libmongocrypt/all/$LIBMONGOCRYPT_TAG/libmongocrypt-all.tar.gz -o libmongocrypt-all.tar.gz
108108
# There is no tag URL for libmongocrypt pre-releases.
109-
LIBMONGOCRYPT_COMMIT=a162f4871cface46bdade94cdf7e3ad9459297af
109+
LIBMONGOCRYPT_COMMIT=2cd2f77ae806a3a4c12750b39b0be92b0ca3b2c1
110110
curl https://mciuploads.s3.amazonaws.com/libmongocrypt/all/master/$LIBMONGOCRYPT_COMMIT/libmongocrypt-all.tar.gz -o libmongocrypt-all.tar.gz
111111
tar -xf libmongocrypt-all.tar.gz
112112
cd ..

mongo/client_encryption.go

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,8 @@ func (ce *ClientEncryption) CreateDataKey(ctx context.Context, kmsProvider strin
116116
return primitive.Binary{Subtype: subtype, Data: data}, nil
117117
}
118118

119-
// Encrypt encrypts a BSON value with the given key and algorithm. Returns an encrypted value (BSON binary of subtype 6).
120-
func (ce *ClientEncryption) Encrypt(ctx context.Context, val bson.RawValue,
121-
opts ...*options.EncryptOptions) (primitive.Binary, error) {
122-
119+
// transformExplicitEncryptionOptions creates explicit encryption options to be passed to libmongocrypt.
120+
func transformExplicitEncryptionOptions(opts ...*options.EncryptOptions) *mcopts.ExplicitEncryptionOptions {
123121
eo := options.MergeEncryptOptions(opts...)
124122
transformed := mcopts.ExplicitEncryption()
125123
if eo.KeyID != nil {
@@ -135,13 +133,69 @@ func (ce *ClientEncryption) Encrypt(ctx context.Context, val bson.RawValue,
135133
transformed.SetContentionFactor(*eo.ContentionFactor)
136134
}
137135

136+
if eo.RangeOptions != nil {
137+
var transformedRange mcopts.ExplicitRangeOptions
138+
if eo.RangeOptions.Min != nil {
139+
transformedRange.Min = &bsoncore.Value{Type: eo.RangeOptions.Min.Type, Data: eo.RangeOptions.Min.Value}
140+
}
141+
if eo.RangeOptions.Max != nil {
142+
transformedRange.Max = &bsoncore.Value{Type: eo.RangeOptions.Max.Type, Data: eo.RangeOptions.Max.Value}
143+
}
144+
if eo.RangeOptions.Precision != nil {
145+
transformedRange.Precision = eo.RangeOptions.Precision
146+
}
147+
transformedRange.Sparsity = eo.RangeOptions.Sparsity
148+
transformed.SetRangeOptions(transformedRange)
149+
}
150+
return transformed
151+
}
152+
153+
// Encrypt encrypts a BSON value with the given key and algorithm. Returns an encrypted value (BSON binary of subtype 6).
154+
func (ce *ClientEncryption) Encrypt(ctx context.Context, val bson.RawValue,
155+
opts ...*options.EncryptOptions) (primitive.Binary, error) {
156+
157+
transformed := transformExplicitEncryptionOptions(opts...)
138158
subtype, data, err := ce.crypt.EncryptExplicit(ctx, bsoncore.Value{Type: val.Type, Data: val.Value}, transformed)
139159
if err != nil {
140160
return primitive.Binary{}, err
141161
}
142162
return primitive.Binary{Subtype: subtype, Data: data}, nil
143163
}
144164

165+
// EncryptExpression encrypts an expression to query a range index.
166+
// On success, `result` is populated with the resulting BSON document.
167+
// `expr` is expected to be a BSON document of one of the following forms:
168+
// 1. A Match Expression of this form:
169+
// {$and: [{<field>: {$gt: <value1>}}, {<field>: {$lt: <value2> }}]}
170+
// 2. An Aggregate Expression of this form:
171+
// {$and: [{$gt: [<fieldpath>, <value1>]}, {$lt: [<fieldpath>, <value2>]}]
172+
// $gt may also be $gte. $lt may also be $lte.
173+
// Only supported for queryType "rangePreview"
174+
// NOTE(kevinAlbs): The Range algorithm is experimental only. It is not intended for public use. It is subject to breaking changes.
175+
func (ce *ClientEncryption) EncryptExpression(ctx context.Context, expr interface{}, result interface{}, opts ...*options.EncryptOptions) error {
176+
transformed := transformExplicitEncryptionOptions(opts...)
177+
178+
exprDoc, err := transformBsoncoreDocument(bson.DefaultRegistry, expr, true, "expr")
179+
if err != nil {
180+
return err
181+
}
182+
183+
encryptedExprDoc, err := ce.crypt.EncryptExplicitExpression(ctx, exprDoc, transformed)
184+
if err != nil {
185+
return err
186+
}
187+
if raw, ok := result.(*bson.Raw); ok {
188+
// Avoid the cost of Unmarshal.
189+
*raw = bson.Raw(encryptedExprDoc)
190+
return nil
191+
}
192+
err = bson.Unmarshal([]byte(encryptedExprDoc), result)
193+
if err != nil {
194+
return err
195+
}
196+
return nil
197+
}
198+
145199
// Decrypt decrypts an encrypted value (BSON binary of subtype 6) and returns the original BSON value.
146200
func (ce *ClientEncryption) Decrypt(ctx context.Context, val primitive.Binary) (bson.RawValue, error) {
147201
decrypted, err := ce.crypt.DecryptExplicit(ctx, val.Subtype, val.Data)

mongo/doc.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@
122122
// This bug may result in data corruption.
123123
// Please use libmongocrypt 1.5.2 or higher when calling RewrapManyDataKey.
124124
//
125+
// - Go Driver v1.12.0 requires libmongocrypt v1.7.0 or higher.
126+
//
125127
// To install libmongocrypt, follow the instructions for your
126128
// operating system:
127129
//

0 commit comments

Comments
 (0)