问题
Apologies for the long post, but I've been working for days on this issue and I can't seem to find the solution.
Situation
I want to restrict access to a Cosmos DB in Azure by placing it in a Virtual Network (VNet) and only allow access via a Function app.
Approach
The first part is simple: Create a Cosmos DB and a VNet and configure the service endpoint of the database as described here.
Connecting a Function app to a VNet can be done in two ways.
Using a Gateway
Following this guide, I've configured my VNet with a Gateway subnet and added and configured a VPN Gateway as described.
After that I added the Gateway subnet to the Cosmos DB service endpoint configuration and setup my Function App
Choosing a subnet using the VNet (preview) functionality
This approach is easier to setup, but as described in the microsoft docs it's not available for production workloads.
Configuration is easier, but as the results are the same, I've omitted this option in the rest of this post.
Configuration
VNet
Gateway
Cosmos DB
Function App
Problem
I keep getting connection errors when trying to connect to the Cosmos DB from my function app:
{
"Message": "An error has occurred.",
"ExceptionMessage": "Unable to proceed with the request. Please check the authorization claims to ensure the required permissions to process the request.\r\nActivityId: f784890f-2e1a-4e36-bfb9-8f62ff32c034, Microsoft.Azure.Documents.Common/2.2.0.0, Windows/10.0.14393 documentdb-netcore-sdk/2.2.2",
"ExceptionType": "Microsoft.Azure.Documents.DocumentClientException",
"StackTrace": " at Microsoft.Azure.Documents.Client.ClientExtensions.ParseResponseAsync(HttpResponseMessage responseMessage, JsonSerializerSettings serializerSettings, Boolean throwOnKnownClientErrorCodes)\r\n at Microsoft.Azure.Documents.Client.GatewayServiceConfigurationReader.GetDatabaseAccountAsync(Uri serviceEndpoint)\r\n at Microsoft.Azure.Documents.Routing.GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync(Uri defaultEndpoint, IList`1 locations, Func`2 getDatabaseAccountFn)\r\n at Microsoft.Azure.Documents.Client.GatewayServiceConfigurationReader.InitializeReaderAsync()\r\n at Microsoft.Azure.Documents.Client.DocumentClient.InitializeGatewayConfigurationReader()\r\n at Microsoft.Azure.Documents.Client.DocumentClient.GetInitializationTask()\r\n at Microsoft.Azure.Documents.Client.DocumentClient.EnsureValidClientAsync()\r\n at Microsoft.Azure.Documents.Client.DocumentClient.ReadDatabasePrivateAsync(String databaseLink, RequestOptions options, IDocumentClientRetryPolicy retryPolicyInstance)\r\n at Microsoft.Azure.Documents.BackoffRetryUtility`1.<>c__DisplayClass1_0.<<ExecuteAsync>b__0>d.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at Microsoft.Azure.Documents.BackoffRetryUtility`1.ExecuteRetryAsync(Func`1 callbackMethod, Func`3 callShouldRetry, Func`1 inBackoffAlternateCallbackMethod, TimeSpan minBackoffForInBackoffCallback, CancellationToken cancellationToken, Action`1 preRetryCallback)\r\n at Microsoft.Azure.Documents.ShouldRetryResult.ThrowIfDoneTrying(ExceptionDispatchInfo capturedException)\r\n at Microsoft.Azure.Documents.BackoffRetryUtility`1.ExecuteRetryAsync(Func`1 callbackMethod, Func`3 callShouldRetry, Func`1 inBackoffAlternateCallbackMethod, TimeSpan minBackoffForInBackoffCallback, CancellationToken cancellationToken, Action`1 preRetryCallback)\r\n at Microsoft.Azure.Documents.BackoffRetryUtility`1.ExecuteAsync(Func`1 callbackMethod, IRetryPolicy retryPolicy, CancellationToken cancellationToken, Action`1 preRetryCallback)\r\n at Microsoft.Azure.Documents.Client.DocumentClient.CreateDatabaseIfNotExistsPrivateAsync(Database database, RequestOptions options)\r\n at VnetTestFunction.Function1.Run(HttpRequest req, ILogger log) in C:\\Development\\VnetTestFunction\\VnetTestFunction\\Function1.cs:line 39"
}
There is no difference between the approaches. In both cases there's no connection between my function app and the database.
As a test, I've followed this tutorial and added a VM and setup a proxy. This works, so the Function app has access to the VNet.
My gut feeling says that this is some configuration issue somewhere, but I'm unable to find out where. I'll keep searching, but any help is greatly appreciated.
Used online resources
- Integrate your app with an Azure Virtual Network
- Configure access from virtual networks (VNet)
- Integrate a Function App with an Azure Virtual Network
回答1:
I believe your configuration is correct since both approaches should not work as you desire.
For VNet Integration feature, you could use this gateway to access securely the resources in a VNet.
VNet Integration gives your web app(or function app) access to resources in your virtual network but doesn't grant private access to your web app from the virtual network.
Also, Cosmos DB is not a resource inside Azure VNet, actually you have not restricted the access from Azure function to Cosmos DB using this method. Your Function App is connected to both the Internet and your VNET. It still works from Function App to Cosmos DB over the Internet.
Also, once you enable the Cosmos DB service endpoint in a specific subnet, this indeed limits access to an Azure Cosmos DB account with connections from this authorized subnet in a virtual network. If you only configure the authorized subnet in the firewall of Cosmos DB, I think only the request from the authorized subnet could bypass the firewall. In this case, Azure function is not a resource in the authorized subnet as well.
When you add a VM inside the Azure VNet and setup a proxy following the process of integrating a Function App with an Azure Virtual Network. In this scenario, VMs are resources deployed in an Azure VNet. So you could access it in a private VNet using VNet Integration features.
As far as I know, if you want the Azure Function App inside a VNet, you could deploy the app service in an App Service Environments, which deploys Azure App Service directly into an Azure virtual network. Sure, It's a very high scale and cost.
来源:https://stackoverflow.com/questions/54901038/access-a-cosmos-db-in-a-virtual-network-from-a-function-app