April 29, 2026

DNS Africa Resource Center

..sharing knowledge.

Application Network Security in Azure: Subnets, Endpoints, DNS, NSGs with Terraform Code – Medium



Sign in

Sign in
Home
Library
Stories
Stats
Bob Code
Follow

Listen
Share
You can find the repo here
github.com
So you have just created and deployed your app to Azure, great!
But, wait a sec, can anyone access it?
So should I cut off all connection?
But then how are my apps going to talk to each other?
First read the Microsoft documentation…..
….well, let’s see how we can secure the network part of our app!
Let me know in the comments if you have a better way of doing things or if you spot any mistakes, that would be much appreciated 🙂
Thank you!
Here’s the final architecture (it will make sense I promise)
Resource covered in this blog:
– Subnet
– Subnet delegation
– Private endpoints
– Azure Private Link
– Private DNS
– A record
– Testing
– Network Security Groups
– External Traffic
– Conclusion & Next steps
Azure recommended approach to securing applications in Azure is to seggregate your apps into subnets for each service.
This way, each part is separated from the rest and accessed only by relevant entities.
Let’s look at a simple example where we have two services that need to communicate with one another and yet be separated.
Now we have two apps, each within the same vnet and sitting in their own subnet.
Let’s look at the code
With this you will get the following error
Subnet dns-vnet in VNET is missing a delegation to…
Subnet delegation enables you to automatically apply networking rules within your subnet for your Azure Service (e.g. here our Azure Function).
Here’s what delegation takes care of:
learn.microsoft.com
Let’s update our code to add service delegation
Great our applications are in the right vnet and subnet.
One question therefore emerges, how do we connect with these entities together whilst keeping them closed-off from the rest?
Basically a private endpoint is just a private IP from your virtual network.
They are akin to NIC (Network Interface Controller)
Actually, when creating a Private Endpoint a NIC will be automatically created
Inside our NIC, we will find our IP(s)
There can be a private and public IP
So our Private Endpoints will allow Azure services (like Azure Functions, App Services, or Azure Database) to be accessed over a private IP address within your virtual network.
So what if we try to attach our Private Endpoints directly in the Subnet of each app?
We will get this error:
│ Private Endpoint Name: “app1-pe”): performing CreateOrUpdate: unexpected status 400 (400 Bad Request) with error: PrivateEndpointCreationNotAllowedAsSubnetIsDelegated: Private endpoint /subscriptions/xxxxx/resourceGroups/dns-rg/providers/Microsoft.Network/privateEndpoints/app1-pe cannot be created as subnet /subscriptions/xxxxx/resourceGroups/dns-rg/providers/Microsoft.Network/virtualNetworks/dns-vnet/subnets/subnet1 is delegated.

Well, we delegated our subnet to resources of type Microsoft.Web/serverFarms so Private Endpoints cannot be added to our subnets.
Subnet delegation and private endpoints cannot coexist in the same subnet due to Azure’s restrictions
Why?
The subnet subnet1 is already delegated to Microsoft.Web/serverFarms, meaning it's intended for use with Azure App Service-related resources like App Plans or Function Apps.
Delegated subnets are reserved exclusively for their assigned services.
Azure recommends using separate subnets for different purposes, such as one for private endpoints and one for delegated services, to avoid conflicts like this.
Which means, we need a dedicated subnet for our PEs!
Let’s update our code
If we were to test the communication between our two apps via private endpoints, they still wouldn’t forward the request!
So how do we connect our private endpoints to our apps?
For this we would need a private link
In our context, a Private Link is the connection between the Private Endpoint and the App.
In the background, the private endpoint forwards the request using the Azure backbone network to the given Azure Service (here our function apps)
Azure Private Link can connects any PaaS service (e.g. SQL Server, Storage account, App Service, AKS…)
Ok, let’s add private links to our Private Endpoints!
The private_service_connection block inside the azurerm_private_endpoint resource is what enables Azure Private Link.
Now our Private Endpoints are linked to our Apps! Great 🙂
Let’s have a look at our Private Endpoint
We can see that:
So it’s all set 🙂
Ok, but then is my app supposed to ping this endpoint using the IP address?
If the IP is dynamic, are we going to have to update the IP and the app name?
Wouldn’t be easier to just call the App name instead of the IP?
How are we going to match the IP and the app name (URL)?
Well, the same way that the internet resolves URLs into IPs!
Introducing DNS (Domain Name System)
When we look for a website we just type the URL name, behind the scene here’s what happens:
In our case, we need to do the same BUT inside our vnet!
This is why we will use a private DNS, just like a mini internet 😉
Azure Private DNS manages and resolves domain names in the virtual network without the need to configure a custom DNS solution.
Let’s create our Private DNS
And that’s it!
Let’s see
Oh wait, there is nothing in there, how come?
Well, we also need to tell the Private DNS Zone which virtual network to get into
Introducing Private DNS Virtual Network Link, the link between our Private DNS and our chosen Virtual Network
Let’s add our vnet link
Now our Private DNS is linked to our Vnet
Next, we need to tell our DNS what IPs correspond to which Application name, also known as FQDN (Fully Qualified Domain Name)
A A record basically matches IPs with our app names (FQDN)
e.g. <service-name>.privatelink.<service-domain>.core.windows.net. to 10.0.1.1
There are two ways of doing it:
Manually
Let’s check our private endpoint
Now our Private Endpoint matches the FQDN and IP of App1!
You can also enable autoregistration on a virtual network link.
When autoregistration gets enabled, Azure DNS will update the zone record whenever a virtual machine gets created, changes its’ IP address, or gets deleted.
Now, it’s been a lot of talk, but let’s see if it actually works 😉
We can either code a simple httpClient or just ssh the other app (we will use the latter)
Go to the portal, to your App1 and select console
Don’t forget to replace code=xxx with the actual FunctionApp2 Key
Then deploy
Test in Portal
Great, it works!
Now, what if we have a 3rd App that is not supposed to connect to App2, so that only App1 connects to App2.
The one tool to manage Azure resources to Azure resources communication are Network security groups!
NSGs are simply a list of rules that filter networking traffic
It filters both ways:
Let’s first create our firstNSG
You can see that NSGs are applied on the Subnet level
So we will have one NSGs per subnet
NSG has rules that are based on whether the traffic is leaving (outbound) or the traffic is incoming (inbound)
Let’s block all traffic to subnet_2
We can either do creating a azurerm_network_security_rule block or adding the rule to the azurerm_network_security_group
Here’s the full list of policies we will apply:
Let’s review it in Azure
Let’s check
Still a 200!
By default, Network Policies are disabled on subnets that host Private Endpoints, meaning NSGs will not work unless explicitly enabled.
We need to explicitely apply our NSGs adding one line of code
Let’s test again, and…
It’s still accessible, how come?
If we look at our diagram, we see that our private endpoints are in subnet_3
PEs use Azure backbone that means that the traffic still goes to Subnet_2.
So our NSGs won’t stop the traffic from our PEs to subnet_2!
Let’s then block all traffic to Subnet_3
And, surely enough, our app1 cannot reach app2 anymore!
Ok, now let’s allow only the app1 from reaching app2
The way to do it, is to allow the originating IP (of App1) to reach PE2
Otherwise Allowing Sub1 to Sub2 OR PE1 to PE2 won’t work!
We can simplify and just add the Sub1 IP range as allowed for inbound to PE2
Let’s view this in Azure
This will basically allow any IP stemming from Sub1 to reach PE2 which in turn will forward our request using Azure backbone to App2
And it works!
Let’s visualise what we’ve done so far
Now, let’s proceed to add a 3rd App and test our networking settings
If we try to ping App2, we get a 403, which confirms that our NSGs for subnet2 are working!
However, this is because our App3 is not yet in our virtual network
So let’s add our app3 to subnet3 and give it a PE.
The idea is that we want to test that only app1 is able to communicate with app2
We will give App 3 its own PE in sub3
And let’s try to ping App 2 from App 3….
If everything works, App3 shoul not be able to reach App2!
And….
Indeed, App3 cannot connect to App2!
Well each of our apps are in a subnet, so surely, our apps is safe (including app2)?
Well, let’s find out
Open Postman and send a request to your Function App URL
And… We get a 200!!!!
Why?
Network Security Groups (NSGs) only control traffic between Azure resources…
…and they do not apply to traffic reaching a Private Endpoint from outside Azure (e.g., public internet or external clients).
So
even though our application is behind a subnet and uses a private endpoint, it is still reachable from anywhere!
Function Apps (PaaS Services) Have a Public Endpoint by Default
There are a couple of things we can — must — do to cut it off from the rest of the world.
But first let’s see how our traffic is routed to our App2
Let’s see how our Postman API call is handled by running the following
What are these IPs?
What is the 20.105.224.37 IP?
Azure automatically adds a public inbound address to our Apps, which in this case for our app2 is 20.105.224.37
Now our app has two inbound addresses:
When making a postman API call, using dns-app2.azurewebsites.net is automatically resolved by Azure to the public IP
Let’s fix that and keep our external access disabled
In your app setting, add this line
With the full code
This will result in a 403! Great 🙂
Great, we’ve finally reached our final goal 🙂
This concludes this blog, thank you for reading this far
Let’s recap the final architecture
So, now our app is cut off from the outside world…
BUT
What if we wanted to give external access to our Applications whilst keeping our backend secured?
An APIM is basically a public IP that exposes our backend (our App in this scenario).
This has several advantages such as:
APIM is one way to expose an app to the outside world by allowing only API calls with a key (SSH or other) to connect to the backend.
Many other policies are available to enforce strong security on the APIM level.
I wrote a separate blog on Azure APIM, which you should — of course — read
The blog:
Using Terraformmedium.com
learn.microsoft.com
– Cloud Adoption Framework Private Link and DNS integration at scalelearn.microsoft.com
learn.microsoft.com
global.hitachi-solutions.com
learn.microsoft.com
learn.microsoft.com
bloggerz.cloud
learn.microsoft.com
learn.microsoft.com
learn.microsoft.com
www.jorgebernhardt.com
www.4dotnet.nl
learn.microsoft.com
learn.microsoft.com


What is Bob? Oh Bobby, Don't hurt me, No more
Help
Status
About
Careers
Press
Blog
Privacy
Terms
Text to speech
Teams

source

About The Author