Encrypt and Decrypt specific field in Apache Solr

59 Views Asked by At

I'm working on a project where I need to secure a specific content field in Apache Solr by encrypting the data during indexing and decrypting it during search.

First approach: I've already attempted to implement a custom UpdateRequestProcessorFactory and a search component, but I'm facing challenges in achieving the desired encryption and decryption.

Second approach: I have also tried with another approach i.e How to create a custom search component in solr In second approach, solr is not storing the content in encrypted form. Also when I pass the keyword in analysis section (UI), it properly encrypts and decrypts the data.

Is there any tried and tested way to implement such scenario.

For the first approach I tried following code: Here encryption is working fine but not decryption. responseBuilder.getResponseDocs() returns null.

package com.emorphis.solr.search.component;

import com.emorphis.solr.encrypt.util.EncryptUtil;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SearchComponent;
import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocList;
import org.apache.solr.search.SolrIndexSearcher;

import java.io.IOException;

public class MyDecryptionSearchComponent extends SearchComponent {
    @Override
    public void prepare(ResponseBuilder responseBuilder) throws IOException {
        // Implement decryption logic
        // ...
        System.out.println("Executing MyDecryptionSearchComponent - prepare");
        executeDecryptionLogic(responseBuilder);
    }

    @Override
    public void process(ResponseBuilder responseBuilder) throws IOException {
        // Implement decryption logic
        // ...
        System.out.println("Executing MyDecryptionSearchComponent - process");
        executeDecryptionLogic(responseBuilder);
    }

    @Override
    public void finishStage(ResponseBuilder rb) {
        System.out.println("Executing MyDecryptionSearchComponent - finishStage");
        executeDecryptionLogic(rb);
        super.finishStage(rb);
    }

    @Override
    public String getDescription() {
        return "MyDecryptionSearchComponent";
    }
    private static void executeDecryptionLogic(ResponseBuilder responseBuilder) {
        System.out.println("=======responseBuilder==========="+responseBuilder.getResults().docList);
        SolrDocumentList results = responseBuilder.getResponseDocs();
        if (results == null) {
            System.out.println("No documents found for decryption.");
            return;
        } else {
            System.out.println("Document found for decryption." + results.size());
        }

        for (SolrDocument document : results) {
            Object fieldValue = document.getFieldValue("content");
            System.out.println("======fieldValue===="+fieldValue);

            if (fieldValue != null && fieldValue instanceof String) {
                String encryptedContent = (String) fieldValue;
                System.out.println("==========encryptedContent============"+encryptedContent);

                // Decrypt the content
                String decryptedContent = EncryptUtil.decrypt(encryptedContent);
                System.out.println("============decryptedContent==============="+decryptedContent);

                // Replace the encrypted content with the decrypted content
                document.setField("content", decryptedContent);
            }
        }
    }
}

In second approach I have added fieldType and custom classes. The problem with second approach is the logs are printed for encryption but encrypted data is not stored. And when I search the data using /select it does not call decryption logic.

+  <fieldType name="encrypted_content_text" class="solr.TextField" positionIncrementGap="100" multiValued="false">
+    <analyzer type="index">
+      <tokenizer name="standard"/>
+     <filter name="stop" words="stopwords.txt" ignoreCase="true"/>
+     <filter name="lowercase"/>
+     <filter class="com.emorphis.solr.filter.EncryptionFilterFactory" />
+    </analyzer>
+    <analyzer type="query">
+      <tokenizer name="whitespace"/>
+     <filter class="com.emorphis.solr.filter.DecryptionFilterFactory" />
+      <filter name="stop" words="stopwords.txt" ignoreCase="true"/>
+      <filter expand="true" name="synonymGraph" synonyms="synonyms.txt" ignoreCase="true"/>
+      <filter name="lowercase"/>
+    </analyzer>
+  </fieldType>
+
0

There are 0 best solutions below