1

I am using MongoDB's automatic client side field level encryption, But I observed that the fields are not getting encrypted in the collection.

  • The MongoDB-crypt library that I am using is 1.6.1
  • mongo driver core and sync version are 4.9.1
  • The MongoCryptD version is 5.0.3
  • The OS is linux (RHEL 7.9)
  • MongoDB version 4.2.11 Enterprise edition.
  • Java JDK- 17

The Class that represents my document that I want to perform field encryption on is annotated with @Encrypted annotation with the data key ID and the Encryption algorithm and also the fields in that class I want to encrypt is simply annotated with @Encypted annotation.

So it looks something like this ->

@Data  // lombok
@Document
@Encrypted (keyID="<the key id>", algorithm= "<The algorithm>")
public class MyDocument{
   @Id
   private UUID dataID;

   @Encrypted
   private String fieldToBeEncrypted;
   
   private String otherField;
} 

I am using MongoJsonSchemaCreator's createSchemaFor() method with a filter method MongoJsonSchemaCreator.encryptedOnly() in order to generate a Json Schema after which I then create a SchemaMap from.

this schemaMap I am then populating while creating AutoEncryptionSettings.->

MongoClientSettings clientSettings = MongoClientSettings.builder()
.autoEncryptionSettings(AutoEncryptionSettings.builder()
        .keyVaultNamespace(keyVaultNamespace)
        .kmsProviders(kmsProviders)
        .schemaMap(schemaMap)
        .extraOptions(extraOptions)
        .build())
...(other settings)
    .build();

The master key that I am putting in the kmsProviders is a 96 bytes random character that I generate with OpenSSL random command.


Now the problem is that I am not seeing any data being encrypted and also I do not see any failure message in the console logs.

Now my question is ->

  1. Where does the actual encryption happens ? it is definitly not in the mongocryptd as the docs states so. So what is actually handling the encryption ?
  2. Is there any settings we have to enable in the mongo cluster in order to enable auto field encryption.
  3. The versions that I have stated at the top of my question are those inter compatible with each other and the linux OS as well ?
  4. Is there any checklist in general that I can use in order to troubleshoot this issue of encryption not happening ?

It seems that the mongocryptd process is not marking the fields to be encrypted for writes and thus no encryption is taking place but not sure


Edit 1:

Sharing the rough SchemaMap that I tried in my AutoEncryptionSettings but this to has failed ->

schemaMap.put(getDatabaseName() + ".MyDocument", BsonDocument.parse("{"
  + "  bsonType: \"object\","
  + "  encryptMetadata: {"
  + "    keyId: [UUID(\"" + keyUuid + "\")]"
  + "  },"
  + "  properties: {"
  + "    fieldToBeEncrypted: {"
  + "      encrypt: {"
  + "        bsonType: \"string\","
  + "        algorithm: \"AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic\""
  + "      }"
  + "    }"
  + "  }"
  + "}"));

Here the "keyUuid" is the UUID of the datakey that was generated with ClientEncryption class's createDataKey() method. I had commented the @Encrypted annotation on MyDocument class temporarily in order to pass this hard coded SchemaMap.

Edit 2:

So we found that the issue was related to the schemaMap. The key name in the schemaMap was not matching with the document name. The mongo document name was "myDocument" and what I put in the key of schemaMap was "MyDocument" with "M" in caps, thus it was not able to find the proper mapping and was failing.

Wolf17
  • 27
  • 7

2 Answers2

1

Writing it as answer since it's quite big:

  1. Where does the actual encryption happens ? - inside java driver (in particular inside a libmongocrypt library), but mongocryptd is also required daemon for this workflow.
  2. Is there any settings we have to enable in the mongo cluster in order to enable auto field encryption. - there are options to disable encrypting, but by default it should work as long as you specified correct schemaMap.
  3. are those inter compatible with each other - it should, but even if no, such simple functionality were in csfle logic from the beginning.
  4. Where is @Encrypted attribute came from, I'm not java developer, but I didn't find it in documentation. See articles how it should be configured here. Also, in order to troubleshot further, provide schemaMap value you add to the clientSettings.
dododo
  • 3,872
  • 1
  • 14
  • 37
  • Thank you for responding :) . I have added Edit section where I have pasted a rough SchemaMap that I have actually used in the Code for testing, but this too had failed to encrypt the fields. The Data key that I put in the "keyUuid" is generated with the help of generateDataKey() method of the ClientEncyption class, which I then converted into UUID. – Wolf17 Jul 30 '23 at 17:51
  • As I wrote in #4, where @Encrypted attribute has come from, can you point me on some documentation where it's mentioned? The reason why the value is not encrypted is because driver didn't find the field to encrypt. It's about any mismatching between class ans schemaMap. As a side note, did you try making `fieldToBeEncrypted` public? – dododo Jul 30 '23 at 17:57
  • Sure, this is the docs for the @Encrypted Annotation. ->https://docs.spring.io/spring-data/data-mongodb/docs/current-SNAPSHOT/api/org/springframework/data/mongodb/core/mapping/Encrypted.html – Wolf17 Jul 30 '23 at 18:04
  • I was able to generate the SchemaMap for my class with the help of @Encryped annotation and the MongoJsonSchemaCreator class's createSchemaFor() method. – Wolf17 Jul 30 '23 at 18:06
  • Sounds like this attribute is only about generating schemaMap. Then, provide a full code you use. And as I mentioned above, try making field `public` – dododo Jul 30 '23 at 18:11
  • Sure, I will try putting the code here. yes, I also tried it with public but it didn't made any difference :( – Wolf17 Jul 30 '23 at 18:12
  • I have added the code that generates the schemaMap in one answer post – Wolf17 Jul 30 '23 at 18:33
  • wait ` .bypassAutoEncryption(true)` skips encryption at all, why do you configure it? – dododo Jul 30 '23 at 18:46
  • Oh actually sorry it is not part of my original code ... my code is in a remote machine and I cannot copy paste from there to here ... :( so I have to copy things from internet and edit it here :( and I forgot to remove it ... let me fix it in the answer – Wolf17 Jul 30 '23 at 18:51
  • Is it possible that this issue is due to some master key - data key related issue ? I was also thinking if there is a way to get detailed lods of the mongocrypt daemon ... if possible ? – Wolf17 Jul 30 '23 at 20:36
  • unlikely, in this case i would be an error, not a skipped key – dododo Jul 30 '23 at 20:37
  • Is there a way to get a detailed logs of the mongocryprd daemon or to check what it has processed? – Wolf17 Jul 31 '23 at 04:49
  • It won't be easy (by default mongocryptd doesn't produce logs and I'm not sure off the top of my head whether you can find anything helpful there even in theory). What you really need is to realize why your schemaMap doesn't affect encryption. I assume it's something in your schemaMap (mismatch field name in map and class) or because let's say for some reason private fields doesn't participate in this logic (just a guess). Try looking at this https://www.baeldung.com/mongodb-field-level-encryption – dododo Aug 02 '23 at 06:49
  • Hi Dododo, thank you so much for your help :). Yes it was actually the scehmaMap that was really having the issue. We came to know about it after increasing the verbose level of the mongocryptd logs, where we were able to see the issue. – Wolf17 Aug 12 '23 at 04:20
1

I am putting the code that generates the schemaMap below ->

private Map<String, BsonDocument> generateSchemaMap() {
    MongoJsonSchemaCreator schemaCreator = MongoJsonSchemaCreator.create(mappingContext);
    Map<String, BsonDocument> schemaMap = new HashMap<>();
    Class encryptedEntityClass = MyDocument.class ;  //Class that has fields to be encrypted -> MyDocument
    MongoJsonSchema schema = schemaCreator
            .filter(MongoJsonSchemaCreator.encryptedOnly); // this checks for entity marked with @Encrypted annotation only.
            .createSchemaFor(encryptedEntityClass);
    
    schemaMap.put("dbName.MyDocument", 
            schema.schemaDocument().toBsonDocument(encryptedEntityClass,
                 MongoClientSettings.getDefaultCodecRegistry()));
    return schemaMap;
        
}

this SchemaMap then I put inside my AutoEncryptionSettings ->

MongoClientSettings.Builder.autoEncryptionSettings(
          AutoEncryptionSettings.builder()
            .keyVaultNamespace(encryptionConfig.getKeyVaultNamespace())
            .kmsProviders(LocalKmsUtils.providersMap(encryptionConfig.getMasterKeyPath()))
            .schemaMap(generateSchemaMap())
          .build())
         .build();
Wolf17
  • 27
  • 7