'How does Cosmos DB emulator SSL work in docker compose?

Is it possible to run Cosmos emulator as a docker container and use the instance in another container? I haven't been able to find anything that clearly explains how to manage the SSL for a docker compose. In the following yml example, both containers launch. However, the webapp container cannot connect to the cosmos instance:

version: '3.8'

services:
  sql:
    container_name: cosmos-for-enol-customer-web-ui
    image: microsoft/azure-cosmosdb-emulator
    tty: true
    restart: always
    mem_limit: 2G
    ports:
      - "8081:8081"
      - "8900:8900"
      - "8901:8901"
      - "8979:8979"
      - "10250:10250"
      - "10251:10251"
      - "10252:10252"
      - "10253:10253"
      - "10254:10254"
      - "10255:10255"
      - "10256:10256"
      - "10350:10350"
    volumes:
      - vol_cosmos:C:\CosmosDB.Emulator\bind-mount

  webapp:
    container_name: webapp
    image: webapp:latest
    restart: always
    ports:
      - "8888:80"
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - CosmosSettings__Uri=https://host.docker.internal:8081/
    depends_on:
      sql:
        condition: service_started

volumes:
  vol_cosmos:

The error the webapp throws is as follows:

Host terminated unexpectedly

System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.

---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.

at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)

at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)

at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)

--- End of stack trace from previous location where exception was thrown ---

at System.Net.Security.SslStream.ThrowIfExceptional()

at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)

at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)

at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)

at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__65_1(IAsyncResult iar)

at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)

--- End of stack trace from previous location where exception was thrown ---

at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)

--- End of inner exception stack trace ---

at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)

at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)

at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)

at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)

at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)

at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

at Microsoft.Azure.Cosmos.DocumentClient.HttpRequestMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)

at Microsoft.Azure.Cosmos.GatewayAccountReader.GetDatabaseAccountAsync(Uri serviceEndpoint)

at Microsoft.Azure.Cosmos.Routing.GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync(Uri defaultEndpoint, IList`1 locations, Func`2 getDatabaseAccountFn)

at Microsoft.Azure.Cosmos.GatewayAccountReader.InitializeReaderAsync()

at Microsoft.Azure.Cosmos.CosmosAccountServiceConfiguration.InitializeAsync()

at Microsoft.Azure.Cosmos.DocumentClient.InitializeGatewayConfigurationReaderAsync()

at Microsoft.Azure.Cosmos.DocumentClient.GetInitializationTaskAsync(IStoreClientFactory storeClientFactory)

at Microsoft.Azure.Cosmos.DocumentClient.EnsureValidClientAsync()

at Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler.EnsureValidClientAsync(RequestMessage request)

at Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler.SendAsync(RequestMessage request, CancellationToken cancellationToken)

at Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler.SendAsync(Uri resourceUri, ResourceType resourceType, OperationType operationType, RequestOptions requestOptions, ContainerCore cosmosContainerCore, Nullable`1 partitionKey, Stream streamPayload, Action`1 requestEnricher, CancellationToken cancellationToken)

at Microsoft.Azure.Cosmos.CosmosClient.CreateDatabaseIfNotExistsAsync(String id, Nullable`1 throughput, RequestOptions requestOptions, CancellationToken cancellationToken)

at Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal.CosmosClientWrapper.CreateDatabaseIfNotExistsOnceAsync(DbContext _, Object __, CancellationToken cancellationToken)

at Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal.CosmosClientWrapper.CreateDatabaseIfNotExistsOnce(DbContext context, Object state)

at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementation[TState,TResult](Func`3 operation, Func`3 verifySucceeded, TState state)

at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)

at Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal.CosmosClientWrapper.CreateDatabaseIfNotExists()

at Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal.CosmosDatabaseCreator.EnsureCreated()

at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.EnsureCreated()


Solution 1:[1]

The answer is simple. Your webapp knows about a well-known set of certificates (for example, in Java these are listed in the cacerts file). Your webapp does not know about the self-signed cert that cosmos uses.

So, you need to export the cert and then import it into your client cert store, so it knows to trust it.

To export the cert: while CosmosDB is running, run this command:

curl -k https://$ipaddr:8081/_explorer/emulator.pem > emulatorcert.crt

NOTE1: You can use a program called "Keytool Explorer" to view the contents of the cert. Also, this tool is capable of importing the cert IF you don't know the command line commands to do so.

NOTE2: Chrome will not allow you to connect to Cosmos unless you import the cert (and trust it) into your computer systems keystore.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 djangofan