CSFLE - Using Hashicorp vault

Hello, Am trying to do POC on CSFLE using Java application. Where am trying to write some data into MongoDB / Reading the same by Encrypting few fields .

When am using KMSProviders as local and keeping my master key file in my local working as expected , Fields are getting encrypted properly.

When am using the KMIP based KMS Providers (Particularly with Hasicorp vault) . Am getting exception while connecting to Vault .


  private ClientEncryption createKMIPncryptionClient() {
        MongoClientSettings kvmcs = MongoClientSettings.builder().applyConnectionString(CONNECTION_STR).build();
        ClientEncryptionSettings ces = ClientEncryptionSettings.builder()
                .keyVaultMongoClientSettings(kvmcs)
                .keyVaultNamespace(VAULT_NS.getFullName())
                .kmsProviders(kmipKmsProviders)
                .build();
        System.out.println("=> Creating KMIP encryption client.");
        return ClientEncryptions.create(ces);
    }
private Map<String, Map<String, Object>> generateKmipKmsProviders(byte[] masterKey) {
        System.out.println("=> Creating KMIP Key Management System using the master key.");
        Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>();
        Map<String, Object> providerDetails = new HashMap<>();
        providerDetails.put("endpoint", "localhost:8200");
        kmsProviders.put(KMIP, providerDetails);
        return kmsProviders;

Here am using the endpoint as local (as i have hashicorp vault running in my local machine in DEV mode).

while running the application , I haven’t passed any JVM parameters . Below is the exception am getting.


Exception in thread "main" com.mongodb.MongoClientException: Exception in encryption library: Unrecognized SSL message, plaintext connection?
	at com.mongodb.client.internal.Crypt.wrapInClientException(Crypt.java:363)
	at com.mongodb.client.internal.Crypt.decryptKeys(Crypt.java:344)
	at com.mongodb.client.internal.Crypt.executeStateMachine(Crypt.java:286)
	at com.mongodb.client.internal.Crypt.createDataKey(Crypt.java:174)
	at com.mongodb.client.internal.ClientEncryptionImpl.createDataKey(ClientEncryptionImpl.java:93)
	at csfle.ClientSideFieldLevelEncryption.readOrCreateDEKUsingKMIP(ClientSideFieldLevelEncryption.java:139)
	at csfle.ClientSideFieldLevelEncryption.demo(ClientSideFieldLevelEncryption.java:75)
	at csfle.ClientSideFieldLevelEncryption.main(ClientSideFieldLevelEncryption.java:45)
Caused by: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
	at sun.security.ssl.InputRecord.handleUnknownRecord(InputRecord.java:710)
	at sun.security.ssl.InputRecord.read(InputRecord.java:527)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
	at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:757)
	at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
	at java.io.OutputStream.write(OutputStream.java:75)
	at com.mongodb.client.internal.KeyManagementService.stream(KeyManagementService.java:75)
	at com.mongodb.client.internal.Crypt.decryptKey(Crypt.java:349)
	at com.mongodb.client.internal.Crypt.decryptKeys(Crypt.java:339)
	... 6 more

I’m not sure what the root cause is, but that SSLException about a plaintext connection is weird. I think KMIP requires TLS, even for local dev environment. Is the Hashicorp vault running locally configured that way?

Instructions are here, in case you haven’t seen them: https://www.mongodb.com/docs/manual/core/csfle/tutorials/kmip/kmip-automatic/#specify-your-certificates

No , Hashicorp vault running in local doesn’t have the configuration to enable TLS. In this case we cant use KMIP(via Hashicorp vault running in local) is it ?

Also as per the link specify your certificate. Will it access only PKCS12 format of certs ?

Use of “localhost:8200” might suggest the application is connecting to the vault server (not using KMIP). Hashicorp Vault needs to run the KMIP Secrets Engine. The default port is 5696.

KMIP - Secrets Engines | Vault | HashiCorp Developer may help to enable the KMIP Secrets Engine and generate client certificates.

@Kevin_Albertson /@Jeffrey_Yemin - Now i have got my HasiCorp vault setup(Enterprise) with license. As mentioned in the Initial update am still using both of those Methods.

Along with the below Method

  private <bytes> void readOrCreateDEKUsingKMIP(ClientEncryption encryption) {

        // start-datakeyopts
        BsonDocument masterKeyProperties = new BsonDocument(); // an empty key object prompts your KMIP-compliant key provider to generate a new Customer Master Key
        System.out.println("=> Empty Master Key Properties :" + masterKeyProperties);
        // end-datakeyopts

         List<String> list_DEK_ALIAS_NAME= Arrays.asList(DEK_ALIAS_NAME.split("\\,"));
        System.out.println("=> DEK as a list  :" + list_DEK_ALIAS_NAME);

        BsonDocument key = encryption.getKeyByAltName(DEK_ALIAS_NAME);
        if (key != null) {
            BsonBinary DEK_FROM_DB = (BsonBinary) key.get("_id");
            System.out.println("=> Retrieved Data Key From Encryption DB:" + DEK_FROM_DB);
        }
        else{
            System.out.println("=> No DEK present in the Encryption DB for the given DEK Alias Name :" + DEK_ALIAS_NAME );
            BsonBinary DEK_CREATED_INTO_DB = encryption.createDataKey(KMIP, new DataKeyOptions().masterKey(masterKeyProperties).keyAltNames(list_DEK_ALIAS_NAME));
            System.out.println("=> Created DEK for "+DEK_ALIAS_NAME+" : " + DEK_CREATED_INTO_DB.toString());
        }

    }

Where im having an empty master key , and DEK alias (ex:MyDEK-1) , Since my Master Key is NULL , It goes to ELSE part on the above code.

When trying to create a DEK. It uses the ENCRYPTION returned from createKMIPncryptionClient method given in my first update.

This time generateKmipKmsProviders method is updated with Actual Hashicorp vault URI.

private Map<String, Map<String, Object>> generateKmipKmsProviders(byte[] masterKey) {
        System.out.println("=> Creating KMIP Key Management System using the master key.");
        Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>();
        Map<String, Object> providerDetails = new HashMap<>();
        String vault_endpoint="vault-dev-xxx.xxx.xxxxxxx.xxxxxxxx.net:5696";
        providerDetails.put("endpoint", vault_endpoint);
        kmsProviders.put(KMIP, providerDetails);
        return kmsProviders;

    }

Also am passing the certificate parameters for connecting the vault. As Java system property.

Now am getting error as below

Exception in thread "main" com.mongodb.MongoClientException: Exception in encryption library: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
	at com.mongodb.client.internal.Crypt.wrapInClientException(Crypt.java:363)
	at com.mongodb.client.internal.Crypt.decryptKeys(Crypt.java:344)
	at com.mongodb.client.internal.Crypt.executeStateMachine(Crypt.java:286)
	at com.mongodb.client.internal.Crypt.createDataKey(Crypt.java:174)
	at com.mongodb.client.internal.ClientEncryptionImpl.createDataKey(ClientEncryptionImpl.java:93)
	at csfle.ClientSideFieldLevelEncryption.readOrCreateDEKUsingKMIP(ClientSideFieldLevelEncryption.java:151)
	at csfle.ClientSideFieldLevelEncryption.demo(ClientSideFieldLevelEncryption.java:75)
	at csfle.ClientSideFieldLevelEncryption.main(ClientSideFieldLevelEncryption.java:45)
Caused by: java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
	at javax.net.ssl.DefaultSSLSocketFactory.throwException(SSLSocketFactory.java:248)
	at javax.net.ssl.DefaultSSLSocketFactory.createSocket(SSLSocketFactory.java:255)
	at com.mongodb.client.internal.KeyManagementService.stream(KeyManagementService.java:58)
	at com.mongodb.client.internal.Crypt.decryptKey(Crypt.java:349)
	at com.mongodb.client.internal.Crypt.decryptKeys(Crypt.java:339)
	... 6 more
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
	at java.security.Provider$Service.newInstance(Provider.java:1617)
	at sun.security.jca.GetInstance.getInstance(GetInstance.java:236)
	at sun.security.jca.GetInstance.getInstance(GetInstance.java:164)
	at javax.net.ssl.SSLContext.getInstance(SSLContext.java:156)
	at javax.net.ssl.SSLContext.getDefault(SSLContext.java:96)
	at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:122)
	at com.mongodb.client.internal.KeyManagementService.stream(KeyManagementService.java:57)
	... 8 more
Caused by: java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.
	at sun.security.util.DerInputStream.getLength(DerInputStream.java:599)
	at sun.security.util.DerValue.init(DerValue.java:391)
	at sun.security.util.DerValue.<init>(DerValue.java:332)
	at sun.security.util.DerValue.<init>(DerValue.java:345)
	at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1938)
	at java.security.KeyStore.load(KeyStore.java:1445)
	at sun.security.ssl.SSLContextImpl$DefaultManagersHolder.getKeyManagers(SSLContextImpl.java:851)
	at sun.security.ssl.SSLContextImpl$DefaultManagersHolder.<clinit>(SSLContextImpl.java:758)
	at sun.security.ssl.SSLContextImpl$DefaultSSLContext.<init>(SSLContextImpl.java:913)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at java.security.Provider$Service.newInstance(Provider.java:1595)
	... 14 more

Hashicorp vault provides us only PEM formatted file. I have converted that into PKCS12 and added that into local java trust store location. Which i passed as an argument.

Please help me in this proceed further.

Thanks,

Searching for that error suggests it may be an error reading the certificate. Example: Java Certificate Issue - IOException: DerInputStream.getLength(): lengthTag=109, too big | Jira | Atlassian Documentation