Domenico U.
Domenico U.

Reputation: 76

Does spring-data-couchbase support Field Level Encryption with @EncryptField annotation?

I'm trying to persist/retrieve a Document in couchbase with an encrypted field via the CrudRepository or the CouchbaseTemplate

Starting from the example in the devguide of couchbase i've added the crypto provider in my spring configuration like this

@Configuration
@EnableCouchbaseRepositories(basePackages = { "com.example.demo.db" })
public class MyCouchbaseConfig extends AbstractCouchbaseConfiguration {

    private static final Logger log = LoggerFactory.getLogger(MyCouchbaseConfig.class);

    @Override
    protected List<String> getBootstrapHosts() {
        return Arrays.asList("localhost", "127.0.0.1");
    }

    @Override
    protected String getBucketName() {
        return "TEST";
    }

    @Override
    protected String getUsername() {
        return "user";
    }

    @Override
    protected String getBucketPassword() {
        return "p4$$w0rd";
    }

    @Override
    public String typeKey() {
        return MappingCouchbaseConverter.TYPEKEY_SYNCGATEWAY_COMPATIBLE;
    }

    @Override
    protected CouchbaseEnvironment getEnvironment() {
        try {
            JceksKeyStoreProvider kp = new JceksKeyStoreProvider("secret");
            kp.publicKeyName("mypublickey");
            kp.storeKey("mypublickey", "!mysecretkey#9^5usdk39d&dlf)03sL".getBytes(Charset.forName("UTF-8")));
            kp.signingKeyName("HMACsecret");
            kp.storeKey("HMACsecret", "myauthpassword".getBytes(Charset.forName("UTF-8")));
            AES256CryptoProvider aes256CryptoProvider = new AES256CryptoProvider(kp);
            CryptoManager cryptoManager = new CryptoManager();
            cryptoManager.registerProvider("MyAESProvider", aes256CryptoProvider);
            return DefaultCouchbaseEnvironment.builder().cryptoManager(cryptoManager).build();
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            return null;
        }
    }

this is the document to persist

@Document
public class Person {

    @Id
    public String id;

    @EncryptedField(provider = "MyAESProvider")
    public String password;

    //The rest will be transported and stored unencrypted
    public String firstName;
    public String lastName;
    public String userName;
    public int age;
}

and this is the repository

public interface PersonRepository extends CrudRepository<Person, String> {

}

call to (autowired)

personRepository.save(person);

or

couchbaseTemplate.insert(person);

will store the object in clear

{
  "firstName": "John",
  "lastName": "Doe",
  "password": "password",
  "javaClass": "com.example.demo.db.Person",
  "userName": "jdoe",
  "age": 20
}

while this code (from the example but with my spring configuration)

Bucket bucket = couchConfig.couchbaseClient();
EntityDocument<Person> document = EntityDocument.create(person);
bucket.repository().upsert(document);
EntityDocument<Person> stored = bucket.repository().get(person.id, Person.class);
System.out.println("Password: " + stored.content().password);

store this object

{
  "firstName": "John",
  "lastName": "Doe",
  "__crypt_password": {
    "sig": "h1QS9JacNxTBrep4TEkZj/N7EsV3zJQ6vXmYtzADdG8=",
    "ciphertext": "G3rAivta7NOnLP5Qb1nEfw==",
    "alg": "AES-256-HMAC-SHA256",
    "iv": "cGjOOgA4M+wg4WcM0pHAFw==",
    "kid": "mypublickey"
  },
  "userName": "jdoe",
  "age": 20
}

It seems to me that Spring Data Couchbase use the Bucket interface (that ignore annotations on the document) instead of the Bucket.repository() (that takes the FLE into account instead).

So finally the question is: "How can I use spring Spring Data Couchbase Repository or CouchbaseTemplate to store @EncryptedField of a @Document with the FLE feature of Couchbase?"

Upvotes: 1

Views: 429

Answers (1)

Hern&#225;n Tenjo
Hern&#225;n Tenjo

Reputation: 198

I have exactly the same problem right now but unfortunately, I found it's a future improvement in the SpringDataCouchbase team Jira board.

https://jira.spring.io/projects/DATACOUCH/issues/DATACOUCH-455?filter=allopenissuess.

So, no much to do for now. Did you find a better approach than using the bucket.repository().upsert(document); @Domenico U.?

Upvotes: 0

Related Questions