Data Protection

The Axon Data Protection extension provides field-level encryption capabilities for Framework applications, enabling GDPR compliance and secure handling of personal data in event-sourced systems.

About

The core capability of Axon Data Protection is to encrypt and decrypt individual fields of a Java object, using a key which is determined by the value of another field of the object. Although this capability may have various different use cases, the main use case foreseen when designing the module was to provide the option to later effectively delete the contents of the encrypted fields, by destroying the key used to encrypt them.

This use case is important because of the potential problem combining the event sourcing architecture pattern with mandatory erasure. With event sourcing, all data is stored as a series of immutable, undeletable events. At first, this seems to preclude erasing any data. By encrypting parts of that data, and storing a key outside of the event stream so that it can be deleted, this becomes possible again: deleting the key will effectively delete the data. Of course, other approaches are possible (including changing the immutable events anyway), but these suffer from significant drawbacks and potential operations costs.

Since the majority of Axon-based applications use event sourcing, this issue has been a specific concern to Axoniq as the company behind Axon Framework, and this triggered the creation of this module. The EU’s General Data Protection Regulation (GDPR), which became enforceable in 2018, is an important cause of mandatory erasure, since it specifically describes the data subject’s 'right to be forgotten'. This is why Axon Data Protection was initially called the "GDPR Module". Its current name reflects is broader use.

API overview

The most important design goal of the module was to implement the described functionality while minimizing the impact on existing applications. Business logic code must not be affected at all, and data model code should be affected as little as possible.

The core idea to achieve this is to annotate data classes with the encryption requirements, and then set up some infrastructure to ensure that the required encryption takes place transparently to the rest of the application. On the annotation side, the minimum is to tell the module which field determines the key to be used (referred to as the data subject id), and which fields need to be encrypted.

How it works

A simple example is given below, illustrating the use of the @DataSubjectId and @PersonalData annotations.

public class NewCustomerEvent {
    @DataSubjectId
    private int id;

    @PersonalData
    private String name;
}

Now, encryption and decryption of NewCustomerEvent objects can be performed by invoking the appropriate method on the module’s FieldEncrypter class. When this happens, Axon Data Protection will inspect the class’s annotations and act accordingly. When encrypting, it will look at the value of id and then retrieve the existing key with that id or create a new one if it doesn’t exist yet. Then, it will encrypt the value of name and store this encrypted version in the same field. Because of this architecture, no other changes are necessary.

If your application uses Framework, this process can be even further simplified. The module’s FieldEncryptingConverter is a wrapper around any other Axon Framework Converter which performs encryption before converting and decryption after converting. By simply registering this new converter in the Framework configuration, required encryption and decryption will always be performed transparently to the rest of the application. This concept is illustrated below.

Data Protection integration architecture

Next steps