spring-data-mongodb icon indicating copy to clipboard operation
spring-data-mongodb copied to clipboard

MongoJsonSchemaCreator with encryptedOnly filter generates invalid schema when using collections of objects with encrypted fields

Open Pastissad opened this issue 4 years ago • 1 comments

Hello,

According to the MongoDB automatic CSFLE specs (https://docs.mongodb.com/manual/reference/security-client-side-automatic-json-schema/#std-label-field-level-encryption-encrypt-keyword) :

encrypt cannot be specified within any subschema of the items or additionalItems keywords. Specifically, automatic client-side field level encryption does not support encrypting individual elements of an array.

However, the MongoJsonSchemaCreator::encryptedOnly filter provided to generate Mongo's encryption schema generates a schema with encryption configuration in the subschema of collections' "items" node when encountering a collection of objects containing an @Encrypted annotation.

Exemple :

@Test
public void testCollectionSchema() {
    final MongoMappingContext mappingContext = new MongoMappingContext();
    mappingContext.setSimpleTypeHolder(MongoSimpleTypes.HOLDER);
    mappingContext.setInitialEntitySet(Set.of(Company.class));
    mappingContext.afterPropertiesSet();

    final MappingMongoConverter converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext);
    converter.setCustomConversions(MongoCustomConversions.create(config -> { }));
    converter.afterPropertiesSet();

    final MongoJsonSchemaCreator mongoJsonSchemaCreator = MongoJsonSchemaCreator.create(converter).filter(MongoJsonSchemaCreator.encryptedOnly());

    final MongoJsonSchema companySchema = mongoJsonSchemaCreator.createSchemaFor(Company.class);
    final String jsonSchema = companySchema.schemaDocument().toJson();
}

@Data
static class Company {
    private Person ceo;
    private List<Person> employees;
}

@Data
static class Person {
    @Encrypted
    String name;
}

Will generate this schema :

{
	"type": "object",
	"properties": {
		"ceo": {
			"type": "object",
			"properties": {
				"name": {
					"encrypt": {
						"bsonType": "string",
						"algorithm": null
					}
				}
			}
		},
		"employees": {
			"type": "array",
			"items": {
				"type": "object",
				"properties": {
					"name": {
						"encrypt": {
							"bsonType": "string",
							"algorithm": null
						}
					}
				}
			}
		}
	}
}

The "employees" node is invalid as the generated schema includes encryption inside an 'items' subschema.

This schema generates an error in mongo client at runtime on any command executed :

com.mongodb.MongoCommandException: Command failed with error 51077 (Location51077): 'Invalid schema containing the 'encrypt' keyword.' on server xxx:yyy. The full response is {"ok": 0.0, "errmsg": "Invalid schema containing the 'encrypt' keyword.", "code": 51077, "codeName": "Location51077"}

I'd expect the filter to filter out any collection from the schema when not directly annotated with @Encrypted (full collection encryption, which is sadly the only supported way by CSFLE for those).

Pastissad avatar Nov 17 '21 10:11 Pastissad

Thanks for reporting - we'll look into it. Meanwhile you may want to use a composed Predicate, that filters out collection like elements, along with MongoJsonSchemaCreator#filter().

christophstrobl avatar Dec 13 '21 12:12 christophstrobl