Funsaized
Funsaized

Reputation: 2130

Is it possible to connect to Azure Cosmos DB via a reverse proxy using Java SDK?

I'm trying to use the java sdk to connect to cosmos. I've got an Nginx proxy running in AKS pointed at my cosmos instance (subset of nginx.conf below):

  server {
    listen {{ .Values.cosmosDB.port }} so_keepalive=on;
    proxy_connect_timeout 5s;
    proxy_timeout 60m;
    proxy_buffer_size 30M;
    proxy_socket_keepalive on;
    proxy_ssl_session_reuse on;
    proxy_pass my-instance-cosmos-dev.documents.azure.com:443;
  }

My thought was that by port-forwarding I would be able to use my local as the cosmos host url through this proxy:

kubectl port-forward svc/data-proxy 3308:443

Running the quickstart for java (generated via Azure portal) I am unable to configure a cosmos client that connects. I've tried a couple configurations:

Default gateway mode:

        client = new CosmosClientBuilder()
            .endpoint(AccountSettings.HOST)
            .key(AccountSettings.MASTER_KEY)
            .endpointDiscoveryEnabled(true)
            .gatewayMode()
            .userAgentSuffix("CosmosDBJavaQuickstart")
            .consistencyLevel(ConsistencyLevel.EVENTUAL)
            .buildClient();

However this returns an error on startup Database Account localhost does not exist:

CosmosException{userAgent=azsdk-java-cosmos/4.4.0 MacOSX/10.15.7 JRE/15.0.2, 
error={"code":"Forbidden","message":"Database Account localhost does not exist\r\nActivityId: 742a632d-cd00-42b7-8599-8fc6ff1eccad, Microsoft.Azure.Documents.Common/2.14.0, StatusCode: Forbidden","additionalErrorInfo":null}, resourceAddress='null', requestUri='null', statusCode=403, message=Database Account localhost does not exist

I then tried to pass a proxy configuration as follows, but instead receive SSL validation errors:

    ProxyOptions opts = new ProxyOptions(ProxyOptions.Type.HTTP,  InetSocketAddress.createUnresolved("127.0.0.1", 3308));
    gatewayConnectionConfig.setProxy(opts);


    gatewayConnectionConfig.setMaxConnectionPoolSize(5);
    
    //  Create sync client
    client = new CosmosClientBuilder()
        .endpoint(AccountSettings.HOST)
        .key(AccountSettings.MASTER_KEY)
        .endpointDiscoveryEnabled(true)
        .gatewayMode(gatewayConnectionConfig)
        .userAgentSuffix("CosmosDBJavaQuickstart")
        .consistencyLevel(ConsistencyLevel.EVENTUAL)
        .buildClient();

Output:

INFO: Getting database account endpoint from http://localhost:3308
Oct 07, 2021 10:01:31 AM com.azure.cosmos.implementation.RxGatewayStoreModel 
lambda$toDocumentServiceResponse$2
SEVERE: Network failure
javax.net.ssl.SSLException: failure when writing TLS control frames
    at io.netty.handler.ssl.SslHandler.setHandshakeFailureTransportFailure(SslHandler.java:1863)
    at io.netty.handler.ssl.SslHandler.access$600(SslHandler.java:167)
    at io.netty.handler.ssl.SslHandler$2.operationComplete(SslHandler.java:978)
    at io.netty.handler.ssl.SslHandler$2.operationComplete(SslHandler.java:973)
    at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:577)
    at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:551)
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:490)
    at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:615)
    at io.netty.util.concurrent.DefaultPromise.setFailure0(DefaultPromise.java:608)
    at io.netty.util.concurrent.DefaultPromise.tryFailure(DefaultPromise.java:117)
    at io.netty.channel.PendingWriteQueue.safeFail(PendingWriteQueue.java:279)
    at io.netty.channel.PendingWriteQueue.removeAndFailAll(PendingWriteQueue.java:177)
    at io.netty.handler.proxy.ProxyHandler.failPendingWrites(ProxyHandler.java:435)
    at io.netty.handler.proxy.ProxyHandler.failPendingWritesAndClose(ProxyHandler.java:352)
    at io.netty.handler.proxy.ProxyHandler.setConnectFailure(ProxyHandler.java:347)
    at io.netty.handler.proxy.ProxyHandler.access$100(ProxyHandler.java:39)
    at io.netty.handler.proxy.ProxyHandler$2.run(ProxyHandler.java:199)
    at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98)
    at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:170)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: io.netty.handler.proxy.ProxyConnectException: http, none, /127.0.0.1:3308 => localhost/<unresolved>:3308, timeout
    ... 10 more

I'm not sure how to proceed. Is this a supported connection pattern? Perhaps I am misunderstanding the client setup via the SDK here...

Upvotes: 3

Views: 1273

Answers (1)

burna
burna

Reputation: 2962

I think the proxy approach should work, but you have to write the original Cosmos-DB-URL in the connection-String, that you are using in AccountSettings.HOST.

I guess there is still "localhost" referenced in there, because of your first try with direct access. But as you are going through the proxy now, there should be the real URL. (my-instance-cosmos-dev.documents.azure.com)

Furthermore, you don't get a SSL validation error, it looks like a timeout. (Because the proxy tried to connect to localhost)


If you do want to use the first (direct) approach, then you could add an entry to your /etc/hosts, that should get the cosmos-db SDK to send the right Host-header in the request.

127.0.0.1 my-instance-cosmos-dev.documents.azure.com

And then you also need to reference the real URL in the connection-string, which then points to localhost.

Upvotes: 1

Related Questions