Uploaded image for project: 'Go Driver'
  1. Go Driver
  2. GODRIVER-2147

Automatic FLE decryption does not work with session

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 1.7.3
    • Affects Version/s: None
    • Component/s: None
    • Labels:
      None

      We are using manual mongo field level encryption with automatic decryption.

      Starting in go mongo driver 1.5.1 we get this error on decryption: "key vault communication error: session was not created by this client"

      To reproduce, I have taken the go mongo driver example 

      Test_Example_explictEncryptionWithAutomaticDecryption and modified it to use a session (instead of empty context):

       

      // code placeholder
      //taken from mongo_driver 1.5.1
      func Test_Example_explictEncryptionWithAutomaticDecryption(t *testing.T) {
         // Automatic encryption requires MongoDB 4.2 enterprise, but automatic decryption is supported for all users.
      
         //var localMasterKey []byte // This must be the same master key that was used to create the encryption key.
         kmsProviders := map[string]map[string]interface{}{
            "local": {
               "key": fakeKey,
            },
         }
      
         // The MongoDB namespace (db.collection) used to store the encryption data keys.
         keyVaultDBName, keyVaultCollName := "encryption", "testKeyVault"
         keyVaultNamespace := keyVaultDBName + "." + keyVaultCollName
      
         // Create the Client for reading/writing application data. Configure it with BypassAutoEncryption=true to disable
         // automatic encryption but keep automatic decryption. Setting BypassAutoEncryption will also bypass spawning
         // mongocryptd in the driver.
         autoEncryptionOpts := options.AutoEncryption().
            SetKmsProviders(kmsProviders).
            SetKeyVaultNamespace(keyVaultNamespace).
            SetBypassAutoEncryption(true)
         clientOpts := options.Client().
            ApplyURI("mongodb://localhost:27017").
            SetAutoEncryptionOptions(autoEncryptionOpts)
         client, err := mongo.Connect(context.TODO(), clientOpts)
         if err != nil {
            panic(err)
         }
         defer func() { _ = client.Disconnect(context.TODO()) }()
      
         // Get a handle to the application collection and clear existing data.
         coll := client.Database("test").Collection("coll")
         _ = coll.Drop(context.TODO())
      
         // Set up the key vault for this example.
         keyVaultColl := client.Database(keyVaultDBName).Collection(keyVaultCollName)
         _ = keyVaultColl.Drop(context.TODO())
         // Ensure that two data keys cannot share the same keyAltName.
         keyVaultIndex := mongo.IndexModel{
            Keys: bson.D{{"keyAltNames", 1}},
            Options: options.Index().
               SetUnique(true).
               SetPartialFilterExpression(bson.D{
                  {"keyAltNames", bson.D{
                     {"$exists", true},
                  }},
               }),
         }
         if _, err = keyVaultColl.Indexes().CreateOne(context.TODO(), keyVaultIndex); err != nil {
            panic(err)
         }
      
         // Create the ClientEncryption object to use for explicit encryption/decryption. The Client passed to
         // NewClientEncryption is used to read/write to the key vault. This can be the same Client used by the main
         // application.
         clientEncryptionOpts := options.ClientEncryption().
            SetKmsProviders(kmsProviders).
            SetKeyVaultNamespace(keyVaultNamespace)
         clientEncryption, err := mongo.NewClientEncryption(client, clientEncryptionOpts)
         if err != nil {
            panic(err)
         }
         defer func() { _ = clientEncryption.Close(context.TODO()) }()
      
         // Create a new data key for the encrypted field.
         dataKeyOpts := options.DataKey().SetKeyAltNames([]string{"go_encryption_example"})
         dataKeyID, err := clientEncryption.CreateDataKey(context.TODO(), "local", dataKeyOpts)
         if err != nil {
            panic(err)
         }
      
         // Create a bson.RawValue to encrypt and encrypt it using the key that was just created.
         rawValueType, rawValueData, err := bson.MarshalValue("123456789")
         if err != nil {
            panic(err)
         }
         rawValue := bson.RawValue{Type: rawValueType, Value: rawValueData}
         encryptionOpts := options.Encrypt().
            SetAlgorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").
            SetKeyID(dataKeyID)
         encryptedField, err := clientEncryption.Encrypt(context.TODO(), rawValue, encryptionOpts)
         if err != nil {
            panic(err)
         }
      
         // Insert a document with the encrypted field and then find it. The FindOne call will automatically decrypt the
         // field in the document.
         if _, err = coll.InsertOne(context.TODO(), bson.D{{"encryptedField", encryptedField}}); err != nil {
            panic(err)
         }
         var foundDoc bson.M
         //if err = coll.FindOne(context.TODO(), bson.D{}).Decode(&foundDoc); err != nil {
         // panic(err)
         //}
         //fmt.Printf("Decrypted document: %v\n", foundDoc)
         ctx := context.Background()
         err = client.UseSessionWithOptions(ctx, nil, func(sessionContext mongo.SessionContext) error { //sess
            if err = coll.FindOne(sessionContext, bson.D{}).Decode(&foundDoc); err != nil {
               panic(err)
            }
            fmt.Printf("Decrypted document: %v\n", foundDoc)
            return nil
         })
      }
      

      This throws error "key vault communication error: session was not created by this client".

      When going back to driver 1.5.0-beta1, things work because if 

      SetKeyVaultClientOptions are not provided as part of AutoEncryption options on client creation, client is re-used for key vault communication.

      When going to driver 1.5.1 (also checked 1.7.2), we get this error.

       

       

            Assignee:
            kevin.albertson@mongodb.com Kevin Albertson
            Reporter:
            eflat@league.com Elena Flat
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: