Efcore: Cosmos: Support IWebProxy configuration

Created on 6 Jan 2020  路  6Comments  路  Source: dotnet/efcore

CosmoDb connection using Entity Framework Core 3.1 is not working as expected behind a Corporate Proxy environment, as it is being kicked out by Proxy as authorization required.
There is no way to override the HttpClientHandler --> to explicitly specify the proxy credentials and parameters.

This issue is highly visible in a Console application using .NET Core. Where we were trying to create a data migration component. The same issue is reproducible if you are using the Cosmos Db Data migration tool.

Steps to reproduce

1.) Create a console app behind Corp Proxy environment
2.) Set DB context and connection strings to live Cosmos Db instance in Azure
3.) In program.cs ==> Main method add this code and debug the application.

``` C#
AppDbContext appDbContext = new AppDbContext();
appDbContext.Database.EnsureCreated();


{"ActivityId":"00000000-0000-0000-0000-000000000000","StatusCode":"407","SubStatusCode":"Unknown","RequestCharge":"0","ErrorMessage":"Microsoft.Azure.Documents.DocumentClientException: RequestUri: https://xxxxxx-endpoint.documents.azure.com/;RequestMethod: GET;Header: x-ms-version Length: 10;Header: User-Agent Length: 133;Header: x-ms-date Length: 29;Header: Authorization Length: 84;, Request URI: /, RequestStats: , SDK: Windows/10.0.17134 cosmos-netstandard-sdk/3.4.2 at Microsoft.Azure.Cosmos.GatewayStoreClient.ParseResponseAsync(HttpResponseMessage responseMessage, JsonSerializerSettings serializerSettings, DocumentServiceRequest request) at Microsoft.Azure.Cosmos.GatewayAccountReader.GetDatabaseAccountAsync(Uri serviceEndpoint) at Microsoft.Azure.Cosmos.Routing.GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync(Uri defaultEndpoint, IList1 locations, Func2 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)","Method":"GET","RequestUri":"dbs/SomeDatabase","RequestSessionToken":"","ResponseSessionToken":""}
```

Further technical details

EF Core version: 3.1 (cosmos-netstandard-sdk/3.4.2)
Database provider: (e.g. Microsoft.EntityFrameworkCore.Cosmos)
Target framework: (e.g. .NET Core 3.1)
Operating system: Windows/10.0.17134
IDE: Visual Studio 2019 16.5 Preview 1

area-cosmos closed-fixed customer-reported type-enhancement

Most helpful comment

@slaneyrw Unfortunately no. We cache the configured services and need to calculate the cache key based on the configured values, Exposing CosmosClientOptions directly is likely to lead to the wrong service being returned or cause false cache misses. Having said that if someone is willing to contribute a PR that exposes all or most of the options in one go we'd gladly review it.

All 6 comments

We should allow passing IWebProxy to the CosmosClient

But it should be added through - Microsoft.EntityFrameworkCore.Cosmos provider, because we don't bother about CosmosClient object, when working with DbContext.

Can you expose a configuration point to allow ALL CosmosClientOptions to be modified, or a least try and get a CosmosClientOptions from the DI container instead of created a new one in SingletonCosmosClientWrapper and merge your specifically configured values.

Enscapulating these selected configuration concepts, one by one, in your own CosmosOptionsExtensions will mean a lot of inidividual requests.

@slaneyrw Unfortunately no. We cache the configured services and need to calculate the cache key based on the configured values, Exposing CosmosClientOptions directly is likely to lead to the wrong service being returned or cause false cache misses. Having said that if someone is willing to contribute a PR that exposes all or most of the options in one go we'd gladly review it.

Hi All, please think in the perspective of a customer company with corporate proxy, that actually blocking Cosmos DB calls, as proxy settings are not being able to inject into for local debugging purposes of the developer. Essentially it is a critical requirement for any developer.
Can we add this feature quickly?

"Works on my machine warning..."

You can do this, just need to use Reflection to set some fields on the SingletonCosmosClientWrapper singleton, before first use...

I did this creating a static "patcher"the first time the DbContext is created - very fragile but works

If MS simply exposed these properties on the CosmosOption option and all this goes away.

`

public class CosmosClientOptionsPatcher
{
    public Microsoft.Azure.Cosmos.CosmosClientOptions Options { get; }

    public CosmosClientOptionsPatcher()
    {
    }
    public CosmosClientOptionsPatcher(Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal.SingletonCosmosClientWrapper wrapper)
    {
        Type type = wrapper.GetType();
        System.Reflection.FieldInfo[] fields = type.GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);

        var cosmosOptions = fields.Single(_ => _.FieldType == typeof(Microsoft.Azure.Cosmos.CosmosClientOptions))
            .GetValue(wrapper) as Microsoft.Azure.Cosmos.CosmosClientOptions ?? throw new InvalidCastException();

        cosmosOptions.ConnectionMode = Microsoft.Azure.Cosmos.ConnectionMode.Gateway;
        cosmosOptions.WebProxy = new System.Net.WebProxy() { BypassProxyOnLocal = true };
    }
}

public class MyDbContext : DbContext
{
    static CosmosClientOptionsPatcher? patcher = default;

    public MyDbContextt(DbContextOptions options) : base(options)
    {
        patcher ??= new CosmosClientOptionsPatcher(this.GetService<Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal.SingletonCosmosClientWrapper>());
    }
}

`

Was this page helpful?
0 / 5 - 0 ratings