New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
update for libmongocrypt 1.5.2 #1037
Changes from all commits
05226d6
2719c33
143047c
83f73b3
da89e92
cc643a5
3a374dd
79932a5
3385d6d
1c9b34c
5004181
8b6cace
7c10825
68c96f3
f6922ae
feed4b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -241,7 +241,7 @@ | |
} | ||
}, | ||
"result": { | ||
"errorContains": "Cannot query" | ||
"errorContains": "encrypt" | ||
} | ||
} | ||
] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -249,9 +249,17 @@ func setRewrapManyDataKeyWriteModels(rewrappedDocuments []bsoncore.Document, wri | |
// RewrapManyDataKey decrypts and encrypts all matching data keys with a possibly new masterKey value. For all | ||
// matching documents, this method will overwrite the "masterKey", "updateDate", and "keyMaterial". On error, some | ||
// matching data keys may have been rewrapped. | ||
// libmongocrypt 1.5.2 is required. An error is returned if the detected version of libmongocrypt is less than 1.5.2. | ||
func (ce *ClientEncryption) RewrapManyDataKey(ctx context.Context, filter interface{}, | ||
opts ...*options.RewrapManyDataKeyOptions) (*RewrapManyDataKeyResult, error) { | ||
|
||
// libmongocrypt versions 1.5.0 and 1.5.1 have a severe bug in RewrapManyDataKey. | ||
// Check if the version string starts with 1.5.0 or 1.5.1. This accounts for pre-release versions, like 1.5.0-rc0. | ||
libmongocryptVersion := mongocrypt.Version() | ||
if strings.HasPrefix(libmongocryptVersion, "1.5.0") || strings.HasPrefix(libmongocryptVersion, "1.5.1") { | ||
return nil, fmt.Errorf("RewrapManyDataKey requires libmongocrypt 1.5.2 or newer. Detected version: %v", libmongocryptVersion) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These updates will only apply to users who update to Go Driver v1.10.1+ and could be missed by users who are using Go Driver v1.10.0. Are there other ways we're messaging to Go Driver users that they shouldn't use libmongocrypt v1.5.0/v1.5.1 (e.g. retraction notices on the libmongocrypt download page)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question. I updated the libmongocrypt release notes and changelog to add a warning. There is no libmongocrypt downloads page. Go users are advised to download libmongocrypt from Homebrew, the Linux packages we maintain, or the Windows download URL. One option is to update the Go driver 1.10.0 release notes to add a notice like the following. I have asked in the team channel. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good. |
||
|
||
rmdko := options.MergeRewrapManyDataKeyOptions(opts...) | ||
if ctx == nil { | ||
ctx = context.Background() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -107,10 +107,17 @@ | |
// | ||
// The libmongocrypt C library is required when using client-side encryption. Specific versions of libmongocrypt | ||
// are required for different versions of the Go Driver: | ||
// | ||
// - Go Driver v1.2.0 requires libmongocrypt v1.0.0 or higher | ||
// | ||
// - Go Driver v1.5.0 requires libmongocrypt v1.1.0 or higher | ||
// | ||
// - Go Driver v1.8.0 requires libmongocrypt v1.3.0 or higher | ||
// - Go Driver v1.10.0 requires libmongocrypt v1.5.0 or higher | ||
// | ||
// - Go Driver v1.10.0 requires libmongocrypt v1.5.0 or higher. | ||
// There is a severe bug when calling RewrapManyDataKey with libmongocrypt versions less than 1.5.2. | ||
// This bug may result in data corruption. | ||
// Please use libmongocrypt 1.5.2 or higher when calling RewrapManyDataKey. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great godoc format improvement! |
||
// | ||
// To install libmongocrypt, follow the instructions for your | ||
// operating system: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1855,6 +1855,140 @@ func TestClientSideEncryptionProse(t *testing.T) { | |
}) | ||
|
||
}) | ||
|
||
mt.RunOpts("16. Rewrap", runOpts, func(mt *mtest.T) { | ||
mt.Run("Case 1: Rewrap with separate ClientEncryption", func(mt *mtest.T) { | ||
dataKeyMap := map[string]bson.M{ | ||
"aws": { | ||
"region": "us-east-1", | ||
"key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", | ||
}, | ||
"azure": { | ||
"keyVaultEndpoint": "key-vault-csfle.vault.azure.net", | ||
"keyName": "key-name-csfle", | ||
}, | ||
"gcp": { | ||
"projectId": "devprod-drivers", | ||
"location": "global", | ||
"keyRing": "key-ring-csfle", | ||
"keyName": "key-name-csfle", | ||
}, | ||
"kmip": {}, | ||
} | ||
|
||
tlsConfig := make(map[string]*tls.Config) | ||
if tlsCAFileKMIP != "" && tlsClientCertificateKeyFileKMIP != "" { | ||
tlsOpts := map[string]interface{}{ | ||
"tlsCertificateKeyFile": tlsClientCertificateKeyFileKMIP, | ||
"tlsCAFile": tlsCAFileKMIP, | ||
} | ||
kmipConfig, err := options.BuildTLSConfig(tlsOpts) | ||
assert.Nil(mt, err, "BuildTLSConfig error: %v", err) | ||
tlsConfig["kmip"] = kmipConfig | ||
} | ||
|
||
kmsProviders := []string{"local", "aws", "gcp", "azure", "kmip"} | ||
for _, srcProvider := range kmsProviders { | ||
for _, dstProvider := range kmsProviders { | ||
mt.Run(fmt.Sprintf("%s to %s", srcProvider, dstProvider), func(mt *mtest.T) { | ||
var err error | ||
// Drop the collection ``keyvault.datakeys``. | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm is the point of these empty blocks just to emphasize what the steps of this test are? Or are you using them for some scope logic that I'm not understanding 🧑🔧 . If it's just for emphasizing the steps, I'm not sure it's necessary. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it is to emphasize what code accomplishes the step. It is not necessary. |
||
err = mt.Client.Database("keyvault").Collection("datakeys").Drop(context.Background()) | ||
assert.Nil(mt, err, "error on Drop: %v", err) | ||
} | ||
|
||
// Create a ``ClientEncryption`` object named ``clientEncryption1``. | ||
var clientEncryption1 *mongo.ClientEncryption | ||
{ | ||
var keyVaultClient *mongo.Client | ||
{ | ||
co := options.Client().ApplyURI(mtest.ClusterURI()) | ||
keyVaultClient, err = mongo.Connect(context.Background(), co) | ||
defer keyVaultClient.Disconnect(context.Background()) | ||
testutil.AddTestServerAPIVersion(co) | ||
assert.Nil(mt, err, "error on Connect: %v", err) | ||
} | ||
ceOpts := options.ClientEncryption(). | ||
SetKeyVaultNamespace("keyvault.datakeys"). | ||
SetKmsProviders(fullKmsProvidersMap). | ||
SetTLSConfig(tlsConfig) | ||
clientEncryption1, err = mongo.NewClientEncryption(keyVaultClient, ceOpts) | ||
assert.Nil(mt, err, "error in NewClientEncryption: %v", err) | ||
defer clientEncryption1.Close(context.Background()) | ||
} | ||
|
||
// Call ``clientEncryption1.createDataKey``. | ||
var keyID primitive.Binary | ||
{ | ||
dkOpts := options.DataKey() | ||
if val, ok := dataKeyMap[srcProvider]; ok { | ||
dkOpts.SetMasterKey(val) | ||
} | ||
keyID, err = clientEncryption1.CreateDataKey(context.Background(), srcProvider, dkOpts) | ||
assert.Nil(mt, err, "error in CreateDataKey: %v", err) | ||
} | ||
|
||
// Call ``clientEncryption1.encrypt`` with the value "test". | ||
var ciphertext primitive.Binary | ||
{ | ||
t, value, err := bson.MarshalValue("test") | ||
assert.Nil(mt, err, "error in MarshalValue: %v", err) | ||
plaintext := bson.RawValue{Type: t, Value: value} | ||
eOpts := options.Encrypt().SetKeyID(keyID).SetAlgorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic") | ||
ciphertext, err = clientEncryption1.Encrypt(context.Background(), plaintext, eOpts) | ||
assert.Nil(mt, err, "error in Encrypt: %v", err) | ||
} | ||
|
||
// Create a ``ClientEncryption`` object named ``clientEncryption2``. | ||
var clientEncryption2 *mongo.ClientEncryption | ||
{ | ||
var keyVaultClient *mongo.Client | ||
{ | ||
co := options.Client().ApplyURI(mtest.ClusterURI()) | ||
keyVaultClient, err = mongo.Connect(context.Background(), co) | ||
defer keyVaultClient.Disconnect(context.Background()) | ||
testutil.AddTestServerAPIVersion(co) | ||
assert.Nil(mt, err, "error on Connect: %v", err) | ||
} | ||
ceOpts := options.ClientEncryption(). | ||
SetKeyVaultNamespace("keyvault.datakeys"). | ||
SetKmsProviders(fullKmsProvidersMap). | ||
SetTLSConfig(tlsConfig) | ||
clientEncryption2, err = mongo.NewClientEncryption(keyVaultClient, ceOpts) | ||
assert.Nil(mt, err, "error in NewClientEncryption: %v", err) | ||
defer clientEncryption2.Close(context.Background()) | ||
} | ||
|
||
// Call ``clientEncryption2.rewrapManyDataKey`` with an empty ``filter``. | ||
{ | ||
rwOpts := options.RewrapManyDataKey().SetProvider(dstProvider) | ||
if val, ok := dataKeyMap[dstProvider]; ok { | ||
rwOpts.SetMasterKey(val) | ||
} | ||
res, err := clientEncryption2.RewrapManyDataKey(context.Background(), bson.D{}, rwOpts) | ||
assert.Nil(mt, err, "error in RewrapManyDataKey: %v", err) | ||
assert.Equal(mt, res.BulkWriteResult.ModifiedCount, int64(1), "expected ModifiedCount of 1, got %v", res.BulkWriteResult.ModifiedCount) | ||
} | ||
|
||
// Call ``clientEncryption1.decrypt`` with the ``ciphertext``. | ||
{ | ||
plaintext, err := clientEncryption1.Decrypt(context.Background(), ciphertext) | ||
assert.Nil(mt, err, "error in Decrypt: %v", err) | ||
assert.Equal(mt, plaintext.StringValue(), "test", "expected plaintext 'test', got %q", plaintext.StringValue()) | ||
} | ||
|
||
// Call ``clientEncryption2.decrypt`` with the ``ciphertext``. | ||
{ | ||
plaintext, err := clientEncryption2.Decrypt(context.Background(), ciphertext) | ||
assert.Nil(mt, err, "error in Decrypt: %v", err) | ||
assert.Equal(mt, plaintext.StringValue(), "test", "expected plaintext 'test', got %q", plaintext.StringValue()) | ||
} | ||
}) | ||
} | ||
} | ||
}) | ||
}) | ||
} | ||
|
||
func getWatcher(mt *mtest.T, streamType mongo.StreamType, cpt *cseProseTest) watcher { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[opt] also missing newline in the spec PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The .yml file is generated from a template: https://github.com/mongodb/specifications/blob/07260166cb48ef6d9455661ad5f1166a87bc7291/source/client-side-encryption/etc/generate-test.py#L614
I will leave this as-is for now.