Marco Sousa
Marco Sousa

Reputation: 185

Proxy for MongoDB Client-Side Field Level Encrytion AWS KMS Connection

We have implemented a Client-Side Field Level Encryption on a Spring Boot application, using AWS KMS to save the master key.

I followed the tutorial created by Visweshwar Ganesh and everything works perfectly. MongoDB Client-Side Field Level Encryption using Java-Spring

The problem is that we need to connect to the AWS KMS through a proxy, and I can't find any documentation to inject proxy configs for MongoEncription.

Does anyone know how to solve this?

Regards!


Edit:

We are using: spring-boot-starter-data-mongodb-2.2.4.RELEASE which uses mongodb-driver 3.11.2

And this is the official MongoDB Documentation

We want to proxy the call to retrieve the CMK from Thrid-Party KMS (AWS) to Encrypt and Decrypt data:

enter image description here

When application starts it creates a mongoClient with the encryption settings and validates if alteady exists a vault with encrypton keys, if not tries to create one, and for that needs to have the CMK stored on AWS KMS It's on this call that occurs on buildOrValidateVault() method that we want to inject the proxy.

PS: This application is running on a kubernetes container.

MongoEncryptionConfig

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bson.BsonDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.AutoEncryptionSettings;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoDriverInformation;
import com.mongodb.client.MongoClient;
import com.mongodb.client.internal.MongoClientImpl;
import com.mongodb.internal.build.MongoDriverVersion;

@Configuration
public class MongoEncryptionConfig extends AbstractMongoClientConfiguration {

@Value(value = "${mongodb.student.name}")
private String dbDatabase;
@Value(value = "${mongodb.student.uri}")
private String dbConnection;
@Value(value = "${encryption.schema-path}")
private String schemaPath;
@Autowired
private KmsHandlerAws kmsHandler;

private static Logger logger = LogManager.getLogger("MongoEncryptionConfig");


private MongoDriverInformation getMongoDriverInfo() {
    return MongoDriverInformation.builder()
        .driverName(MongoDriverVersion.NAME)
        .driverVersion(MongoDriverVersion.VERSION)
        .driverPlatform(java.lang.String.format("Java/%s/%s", java.lang.System.getProperty("java.vendor", "unknown-vendor"),
            java.lang.System.getProperty("java.runtime.version", "unknown-version")))
        .build();
}

private MongoClientSettings getAutoEncryptMongoClientSettings() {
    return MongoClientSettings.builder()
        .applyConnectionString(new ConnectionString(dbConnection))
        .autoEncryptionSettings(autoEncryptionSettings())
        .build();
}

private AutoEncryptionSettings autoEncryptionSettings() {
    return AutoEncryptionSettings.builder()
        .keyVaultNamespace(kmsHandler.getEncryptionCollectionName())
        .kmsProviders(kmsHandler.getKmsProvider())
        .extraOptions(kmsHandler.getExtraOptsMap())
        .schemaMap(buildOrValidateVault())
        .build();
}

private Map<String, BsonDocument> buildOrValidateVault() {
    try {
        ObjectMapper objectMapper = new ObjectMapper();
        for (Path path : loadSchemasPaths(this.schemaPath)) {
            logger.debug("Path being iterated: " + path.getFileName().toString());
            String encryptKey = this.kmsHandler.buildOrValidateVault();
            JsonNode jsonDocument = objectMapper.readTree(Files.readString(path));
            return Collections.singletonMap(
                this.dbDatabase + "." + jsonDocument.get("metadata").get("collection").asText(),
                BsonDocument.parse(String.format(objectMapper.writeValueAsString(jsonDocument.get("schema")), encryptKey)));
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    return null;
}

private List<Path> loadSchemasPaths(String encryptionPath) throws IOException {
    List<Path> paths = new ArrayList<>();

    logger.debug("Encryption Path: " + encryptionPath);

    Files.list(Paths.get(encryptionPath))
        .forEach(path -> {
            logger.debug("Path trying to be add: " + path.getFileName());
            if (path.getFileName().toString().endsWith(".json")) {
                logger.debug(path.getFileName() + " ends with .json! Yes!");
                paths.add(path);
            } else {
                logger.debug(path.getFileName() + " Doesn't end with .json :(");
            }
        });

    return paths;
}

@Override
public MongoClient mongoClient() {
    return new MongoClientImpl(getAutoEncryptMongoClientSettings(), getMongoDriverInfo());
}

@Override
protected String getDatabaseName() {
    return dbDatabase;
}
}

KMSHandler

import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.bson.BsonBinary;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;

public abstract class KmsHandler {

Logger logger = LoggerFactory.getLogger(KmsHandler.class);
@Value(value = "${mongodb.student.uri}")
String dbConnection;
@Value(value = "${encryption.vault.database}")
String encryptionVaultDatabase;
@Value(value = "${encryption.vault.collection}")
String encryptionVaultCollection;
@Value(value = "${encryption.vault.name}")
String encryptionVaultName;
private String encryptionKeyBase64;
private UUID encryptionKeyUuid;

public String getEncryptionKeyBase64() {
    return encryptionKeyBase64;
}

public void setEncryptionKeyBase64(String encryptionKeyBase64) {
    this.encryptionKeyBase64 = encryptionKeyBase64;
}

public UUID getEncryptionKeyUuid() {
    return encryptionKeyUuid;
}

public void setEncryptionKeyUuid(UUID encryptionKeyUuid) {
    this.encryptionKeyUuid = encryptionKeyUuid;
}

public String getEncryptionCollectionName() {
    return encryptionVaultDatabase + "." + encryptionVaultCollection;
}

public Map<String, Object> getExtraOptsMap() {
    Map<String, Object> extraOps = new HashMap<>();
    //extraOps.put("mongocryptdBypassSpawn", true);
    //extraOps.put("mongocryptdURI", "mongodb://localhost:27020");
    return extraOps;
}

/**
 * Check in database if encryption was already created
 * dd
 *
 * @return true or false
 */
protected String doesEncryptionKeyExist() {
    MongoClient mongoClient = MongoClients.create(dbConnection);
    MongoCollection<Document> collection = mongoClient.getDatabase(encryptionVaultDatabase).getCollection(encryptionVaultCollection);
    Document doc = collection.find(Filters.in("keyAltNames", encryptionVaultName)).first();
    if (doc != null) {
        return Base64.getEncoder().encodeToString(new BsonBinary((UUID) doc.get("_id")).getData());
    } else {
        return null;
    }
}
}

KMSHandlerAWS

import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.bson.BsonBinary;
import org.bson.BsonDocument;
import org.bson.BsonString;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.mongodb.ClientEncryptionSettings;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.model.vault.DataKeyOptions;
import com.mongodb.client.vault.ClientEncryption;
import com.mongodb.client.vault.ClientEncryptions;

@Component
public class KmsHandlerAws extends KmsHandler implements IKmsHandler {
@Value(value = "${encryption.kms.aws.region}")
private String encryptionKmsRegion;
@Value(value = "${encryption.kms.aws.key}")
private String encryptionKmsKey;
@Value(value = "${encryption.kms.aws.iam.accessKeyId}")
private String encryptionKmsIamAccessKey;
@Value(value = "${encryption.kms.aws.iam.secretAccessKey}")
private String encryptionKmsIamSecretAccessKey;

public String buildOrValidateVault() {
    try {
        // Check if encryption key exists
        String encryptKey = doesEncryptionKeyExist();
        if (encryptKey != null) {
            return encryptKey;
        }
        // Create Encryption Key
        BsonBinary dataKeyId = getClientEncryption().createDataKey("aws", this.getDataKeyOptions());
        // Save key in instance
        this.setEncryptionKeyUuid(dataKeyId.asUuid());
        logger.debug("DataKeyID [UUID]{}", dataKeyId.asUuid());
        System.out.println("DataKeyID [UUID]: " + dataKeyId.asUuid());
        String base64DataKeyId = Base64.getEncoder().encodeToString(dataKeyId.getData());
        this.setEncryptionKeyBase64(base64DataKeyId);
        logger.debug("DataKeyID [base64]: {}", base64DataKeyId);
        System.out.println("DataKeyID [base64]: " + base64DataKeyId);
        return super.getEncryptionKeyBase64();
    } catch (Exception ex) {
        String exceptionMessage = "Exception at buildOrValidateVault(): " + ex.getMessage();
        System.out.println(exceptionMessage);
        ex.printStackTrace();
        return exceptionMessage;
    }
}

public Map<String, Map<String, Object>> getKmsProvider() {
    Map<String, Object> providerDetails = new HashMap<>();
    providerDetails.put("accessKeyId", new BsonString(this.encryptionKmsIamAccessKey).getValue());
    providerDetails.put("secretAccessKey", new BsonString(this.encryptionKmsIamSecretAccessKey).getValue());
    Map<String, Map<String, Object>> kmsProviders = new HashMap<>();
    kmsProviders.put("aws", providerDetails);
    return kmsProviders;
}

public ClientEncryption getClientEncryption() {
    return ClientEncryptions.create(ClientEncryptionSettings.builder()
        .keyVaultMongoClientSettings(MongoClientSettings.builder()
            .applyConnectionString(new ConnectionString(this.dbConnection))
            .build())
        .keyVaultNamespace(this.encryptionVaultDatabase + "." + this.encryptionVaultCollection)
        .kmsProviders(this.getKmsProvider())
        .build());
}

public DataKeyOptions getDataKeyOptions() {
    return new DataKeyOptions().masterKey(
        new BsonDocument()
            .append("region", new BsonString(this.encryptionKmsRegion))
            .append("key", new BsonString(this.encryptionKmsKey))
            )
        .keyAltNames(Collections.singletonList(this.encryptionVaultName));
}
}

Log Error:

Exception at buildOrValidateVault(): Exception opening connection to Key Management Service
com.mongodb.MongoSocketOpenException: Exception opening connection to Key Management Service
    at com.mongodb.client.internal.KeyManagementService.stream(KeyManagementService.java:57)
    at com.mongodb.client.internal.Crypt.decryptKey(Crypt.java:299)
    at com.mongodb.client.internal.Crypt.decryptKeys(Crypt.java:289)
    at com.mongodb.client.internal.Crypt.executeStateMachine(Crypt.java:242)
    at com.mongodb.client.internal.Crypt.createDataKey(Crypt.java:155)
    at com.mongodb.client.internal.ClientEncryptionImpl.createDataKey(ClientEncryptionImpl.java:50)
    at com.example.student.nosql.config.kms.KmsHandlerAws.buildOrValidateVault(KmsHandlerAws.java:40)
    at com.example.student.nosql.config.MongoEncryptionConfig.buildOrValidateVault(MongoEncryptionConfig.java:77)
    at com.example.student.nosql.config.MongoEncryptionConfig.autoEncryptionSettings(MongoEncryptionConfig.java:68)
    at com.example.student.nosql.config.MongoEncryptionConfig.getAutoEncryptMongoClientSettings(MongoEncryptionConfig.java:59)
    at com.example.student.nosql.config.MongoEncryptionConfig.mongoClient(MongoEncryptionConfig.java:110)
    at org.springframework.data.mongodb.config.AbstractMongoClientConfiguration.mongoDbFactory(AbstractMongoClientConfiguration.java:71)
    at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d.CGLIB$mongoDbFactory$3(<generated>)
    at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d$$FastClassBySpringCGLIB$$6e240ce0.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
    at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d.mongoDbFactory(<generated>)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:484)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$172/0x00000000b0807980.getObject(Unknown Source)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.resolveBeanReference(ConfigurationClassEnhancer.java:394)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:366)
    at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d.mongoDbFactory(<generated>)
    at org.springframework.data.mongodb.config.AbstractMongoClientConfiguration.mongoTemplate(AbstractMongoClientConfiguration.java:58)
    at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d.CGLIB$mongoTemplate$2(<generated>)
    at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d$$FastClassBySpringCGLIB$$6e240ce0.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
    at com.example.student.nosql.config.MongoEncryptionConfig$$EnhancerBySpringCGLIB$$acc0967d.mongoTemplate(<generated>)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:484)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$172/0x00000000b0807980.getObject(Unknown Source)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:330)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:113)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1699)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1444)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$172/0x00000000b0807980.getObject(Unknown Source)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1287)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:885)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:228)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1358)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$172/0x00000000b0807980.getObject(Unknown Source)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:454)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:543)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:513)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:653)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:224)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:116)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$172/0x00000000b0807980.getObject(Unknown Source)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1287)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:885)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:228)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1358)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$172/0x00000000b0807980.getObject(Unknown Source)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
    at com.example.student.StudentApplication.main(StudentApplication.java:16)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:51)
    at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:597)
Caused by: java.net.SocketTimeoutException: connect timed out
    at java.base/java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
    at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
    at java.base/java.net.AbstractPlainSocketImpl.connect(Unknown Source)
    at java.base/java.net.SocksSocketImpl.connect(Unknown Source)
    at java.base/java.net.Socket.connect(Unknown Source)
    at java.base/sun.security.ssl.SSLSocketImpl.connect(Unknown Source)
    at com.mongodb.client.internal.KeyManagementService.stream(KeyManagementService.java:54)
    ... 131 more

Upvotes: 0

Views: 1230

Answers (1)

D. SM
D. SM

Reputation: 14520

I don't think this is supported.

The contents of the KMS request is constructed by libmongocrypt; the request itself is performed by the driver. The payload being sent is opaque to the driver. This is described under MONGOCRYPT_CTX_NEED_KMS state in https://github.com/mongodb/libmongocrypt/blob/master/integrating.md.

I find it unlikely that you would be able to use a proxy with the described integration flow because:

  • The payload must be correctly constructed by libmongocrypt to account for the request being proxied (for example, to use the full URL including the protocol and host in the HTTP URI).
  • The driver needs to be told about the proxy. To my knowledge there isn't any such guidance across drivers. Generally speaking, proxy configuration in different environments is different.
  • The language as written doesn't (to me) have any indicators that the proxy use case was considered.

Looking at the Ruby driver implementation of this flow (https://github.com/mongodb/mongo-ruby-driver/blob/master/lib/mongo/crypt/encryption_io.rb feed_kms method), the driver creates a socket directly to the requested host/port. There is no provision for using proxies.

If you are a paying customer I suggest submitting this request through official support channels. Otherwise I suggest adding it to https://feedback.mongodb.com/.

Upvotes: 0

Related Questions