Having deployed Function App and Cognitive Search components into Azure (via terraform) we are running into issues of the Function App not being able to connect to Cognitive Search (unless it's public).
Configuration of Cognitive Search:
Public network access disabled
Private endpoint added
Is sitting on a subnet within the virtual network
Private DNS Zone added for "privatelink.search.windows.net"
Private DNS Zone is connected to the virtual network
It is accessible from a Container Instance that sits on the same vnet, which makes me believe it's a configuration in the Function App.
Configuration of Function App:
dotnet function app
Subnet created with a delegation for Microsoft.Web/serverFarms
VNet integration is switched on against the function app subnet
Is linked to an Elastic Premium service plan
Service endpoint to Microsoft.Storage has been added to the function app subnet
The Function App is otherwise accessible via a Health endpoint and when the Cognitive Search component is marked as publicly accessible, the search function runs correctly.
If I set the "vnet_route_all_enabled" flag in the terraform or set the "WEBSITE_VNET_ROUTE_ALL" value in the app_settings block of the azurerm_windows_function_app resource to true/"1", then all connections to the Function App return a 500 error (even to the HealthCheck endpoint).
The exception generated by the Azure.Search.Documents.SearchClient class when calling SearchAsync is that the target failed to respond. I'm suspecting that the function app is NOT using the vnet to route the connection and is attempting to use the public one.
Is there anything obvious that I've missed?
Related
I am trying to expose my Front End and Function Web Apps using App Gateway. Both of those apps belong to one app service plan.
They are also private endpoint enabled and VNET integrated.
I have databricks in another tenant which needs to feed data to my Function App
So for that reason i need to expose my Function App.
As for the Front End App, it needs to be accessed by all the employees belonging to a particular business unit.
So my question is , when i am configuring listeners, and the backend pool, should i be using the *.privatelink.azurewebsites.net FQDN or the normal *.azurewebsites.net FQDN as the backend pool ?
When you are using Private Endpoint, you already have a CNAME which maps *.privatelink.azurewebsites.net to *.azurewebsites.net and you also have an 'A' record for your private endpoint.
So while configuring App Gateway with Private Endpoint enabled web apps, what is it that you should be using as your backend
You have to use the normal *.azurewebsites.net FQDN instead of the private link one. This normal FQDN automatically resolves to the private link FQDN. The normal FQDN will throw an error when called from a public network when a private endpoint is attached to it because it cannot resolve the private address so your service isn't exposed anymore for the outside world (unless they have public access through your application gateway of course)
I have configured my app serivce to be part of a subnet within a VNET.
Now i have integrated my app service with a private endpoint within the same VNET.
With the private endpoint integration, i'm now not able to access the app service (i.e. my API) on a public internet, where i'm getting 403 forbidden error. Which is an expected behaviour to restrict the access on the public network
But the issue is, i want to expose this API via APIM (which is internal) configured within a separate subnet in the same VNET, but i'm not not access the API now with the private endpoint IP address. I was hoping that the resources with in the VNET will be able to reach the App service using its private IP address
I also tried to configure a VM in a separate subnet with in the same VNET, but when i ping the API private IP from the VM, i'm getting request timedout.
Current there have not been any rules setup with NSG to restrict the subnets to talk between each other.
Please let me know how to expose the API with private endpoint via APIM which is also configured to be only internal
You also need to configure private dns zone as now your app's FQDN needs to be resolved to the private IP, instead of a public one.
https://learn.microsoft.com/en-us/azure/private-link/create-private-endpoint-powershell
Update:
Just want to add that app service cannot be accessed via the IP as it is assigned to the app service plan, which can be shared by other app services. The FQDN is required for app service plan to do L7 routing
I have two NodeJS App Services.
They can connect to each other with no problem using the URL which is created for App Services by default. (That is through the public internet.)
Then I successfully enabled VNet Integration for both App Services, and assigned the same VNet and also subnet two both of them.
How should I modify the connection URL now to connect to appservice2 from appservice1 (without using the URLs which are publicly available on the internet)?
I could not find any host name or IP address information in Azure Portal using which I could have successfully established the connection.
Thanks for any suggestions!
When you want two app services to connect to each other over a private network, there are generally two steps you have to take to set this up correctly. Note that the app service URL will always stay the same, it is only the networking part that changes.
Both app services should have vnet integration enabled, which allows the app service to route its traffic through the vnet.
If you want others (e.g. another app service) to connect to an app service via a vnet you can choose between:
a) Service endpoints
b) Private endpoints
Reading your question, I assume you completed the first step correctly. But you have to complete either step 2a or 2b to get this to work properly. I would recommend you choose service endpoints because they are more straightforward than working with private endpoints. Below you'll find a detailed description and considerations for every step.
1. Vnet Integration
The subnet you use as an integration subnet has to be a dedicated subnet. This means it is only used for vnet integration.
Only one app service plan can be used with this dedicated subnet, this one app service plan may include multiple app services.
If there is a network security group attached to that subnet, it needs to allow outbound traffic.
If there is an azure firewall attached to your vnet and you want to make a call to a public endpoint, it should allow outbound traffic.
Vnet route all should be enabled if you want all the outbound traffic to travel over the vnet.
If you want to read more, I would recommend reading this documentation.
Here is a simple example of how you would create vnet integration by selecting the dedicated subnet:
Service Endpoints
Service endpoints allow you to lock down inbound access to your app so that the source address must come from a set of subnets that you select.
Service endpoints are automatically provisioned by azure when you enable access restrictions to the app service.
This is a much simpler alternative to private endpoints.
Does not work in large-scale networks where you want to connect from an on-prem network to an azure vnet.
You may turn to this documentation to read about all the features and limitations of service endpoints.
Here is an example of how you would enable services endpoints for your app service by creating an access restriction:
Private Endpoints
Private endpoints also need a subnet, but you can connect as many private endpoints to the subnet as there are IP addresses available.
When you use private endpoints, you also need to have a private DNS zone. Otherwise, the app service URL does not resolve correctly to an IP address.
Private endpoints are more complex than service endpoints because of the extra subnet and DNS requirements.
Here is a nice tutorial that let's you set up an app service with private endpoint.
The following example shows you how to create a private endpoint for your app service. You have the option to let azure create a private DNS zone automatically, or you can do this manually:
If you want to access app services without public internet, then enabling VNET integration in those services alone won't be enough. You need to create a private endpoint that provides the IP from the virtual network to access the app service internally within the VNET and it also disables public access to the app service over the internet. Also please be aware that the private endpoint implementation will have some cost implications as well.
If your requirement is just to establish a secure connection between your virtual network & app service and to avoid access over the public internet, a service endpoint is the simplest solution. If you also need to access the app service from on-premises through an express route or Azure Gateway, a regionally peered virtual network, or a globally peered virtual network, Private Endpoint is the solution.
Steps to set up a service endpoint are detailed in the provisioning service endpoint link
Steps to set up a private endpoint are detailed in the connect to the web app using private endpoint link
Also if you want to deep dive into private endpoint configuration for app service, I would recommend you to read through the following tutorial
I've created a SQL Server and then created a private link with my TESTVNET/SUBNET1 with private IP 10.1.1.4. I've now disabled Public access for the SQL server.
I have an Azure function running on App Service which I've VNET Integrated with VNET/SUBNET2.
Subnet 2 shows it's delegated to server farms. (also if someone can explain what does delegate to means, I found I cannot create any VM in that subnet as well, probably it's just can't be useful for any other purpose)
Now when my azure function tries to connect to DB. it fails with below error:
2020-08-30T15:25:45.216 [Error] Unhandled rejection SequelizeAccessDeniedError: Cannot open server "10.1.1.4" requested by the login. The login failed.
However, if I give the public FQDN it gives me below error.
2020-08-30T15:29:43.654 [Error] Unhandled rejection SequelizeAccessDeniedError: Reason: An instance-specific error occurred while establishing a connection to SQL Server. The public network interface on this server is not accessible. To connect to this server, use the Private Endpoint from inside your virtual network.
Here the Private DNS created by Private endpoint should have been ideally used to get the private IP of the SQL database, but it seems the function is not using the private DNS probably because not running in an isolated environment.
Now in my Azure function Application settings, I've added WEBSITE_VNET_ROUTE_ALL =1 which should mean that all the requests should be routed to VNET. So now If I enable public access internet, and allow Azure services to access DB (I think azure added the public IP by default). The function gets connected to the DB.
Now I want to understand where I'm going wrong and why is the private endpoint connection not working. Any help is appreciated.
In the DB firewall settings, I've allowed traffic from below to subnets:
Network Configuration
TESTVNET: 10.1.0.0/16
SUBNET 1: 10.1.1.0/24
SUBNET 2: 10.1.2.0/24
I've disabled Service endpoint for SQL in both SUBNET 1 and SUBNET 2. My NSG has default settings i.e.
AllowVnetInBound, AllowAzureLoadBalancerInBound, DenyAllInBound
AllowVnetOutBound, AllowInternetOutBound, DenyAllOutBound.
Since my private link has a private IP present in the same VNET I don't think NSG should have any impact.
New to Azure, testing things out. Thank you for your patience.
To make Azure Function connect to a private endpoint you will need to use VNET integration.
After your app integrates with your VNet, it uses the same DNS server that your VNet is configured with. By default, your app won't work with Azure DNS Private Zones. To work with Azure DNS Private Zones you need to add the following app settings:
WEBSITE_DNS_SERVER with value 168.63.129.16
WEBSITE_VNET_ROUTE_ALL with value 1
These settings will send all of your outbound calls from your app into your VNet in addition to enabling your app to use Azure DNS private zones. Reference here.
Then you could set up Private Link for Azure SQL Database. You can create an Azure VM from a new subnet in the same VNet to check connectivity using SQL Server Management Studio (SSMS). If you enable the private endpoint, you should get a client private IP from that Azure VM to connect the Azure SQL database with its FQDN.
For more information, you could read private endpoint VS service endpoint in this blog.
I can't get vNet integration between an Azure App Service / WebJob and it's connected Storage Account to work correctly. I have added both the App Service and the storage account to the same vNet and enabled service endpoint binding for Microsoft.Storage. From what I can see in the docs, this is what is needed to get the communication to work between the services. Unfortunately, I get this error in the WebJob log when I try to run it:
"Unhandled Exception: Microsoft.WindowsAzure.Storage.StorageException:
The remote server returned an error: (403) Forbidden. --->
System.Net.WebException: The remote server returned an error: (403)
Forbidden."
If I disable the firewall on the storage account everything works just fine.
All the services are placed in the same resource group and region (West Europe).
I have tried both the "normal" (with gateway) and the new (Preview) vNet integration version on the App Service and both are failing the same way.
I am not using ASE (App Service Environment).
I have also added the following exceptions on the storage firewall:
Storage firewall exceptions
First, when you allow the set of trusted Microsoft services to bypass the network rules. These services will then use strong authentication to access the storage account.
In this case, you may think Microsoft.Networking service will be allowed in firewall rule. But basically, VNet Integration does not mean App Service is inside a VNet. VNet Integration gives your web app access to resources in your virtual network but doesn't grant private access to your web app from the virtual network. We usually used to securely access the resource in a VNet.
If you want to put your App Service in a VNet, you need to deploy it in App Service Environment, then it's already in a VNet.
Alternatively, you could whitelist the outbound web app service IP address in the firewall rule of the storage account.
Hope this helps, feel free to let me know if you have any concerns.
I've struggled myself on this topic.
First off, if you're restricting access to storage using the firewall you need to add your VNET to the storage firewall. Use your delegate subnet when adding your VNET.
When you add the private link between your storage and your VNET, Azure creates a private DNS zone but your app doesn't automatically use it, even when integrated to the VNET.
You can find more here https://learn.microsoft.com/en-us/azure/app-service/web-sites-integrate-with-vnet
But specifically this passage applies:
After your app integrates with your VNet, it uses the same DNS server that your VNet is configured with. By default, your app won't work with Azure DNS private zones. To work with Azure DNS private zones, you need to add the following app settings:
WEBSITE_DNS_SERVER with value 168.63.129.16
WEBSITE_VNET_ROUTE_ALL with value 1
These settings send all of your outbound calls from your app into your VNet and enable your app to access an Azure DNS private zone. With these settings, your app can use Azure DNS by querying the DNS private zone at the worker level.
You can test the DNS resolution your app is using by opening the debug console and using the NameResolver command
NameResolver mystorageaccount.blob.core.windows.net or
NameResolver mystorageaccount.queue.core.windows.net
should return your private address. If not you have a DNS issue.