• Thread Author
Securing your Azure-deployed applications is much like fortifying a medieval castle—every gate, corridor, and tower must be defended to keep unwanted visitors at bay. In this deep-dive, we explore how to use Terraform code to ensure that your Azure solutions are not only functionally robust but also secured from network vulnerabilities. For Windows administrators and cloud enthusiasts alike, understanding how subnets, private endpoints, DNS, and network security groups (NSGs) work together is essential when building a hardened application environment.

brightly lit server racks with network cables in a data center room.
Azure Blueprint for a Secured Application Infrastructure​

Modern IT infrastructures demand a layered approach to security. Microsoft’s recommended strategy for Azure app security is to segment your application into dedicated subnets. This strategy isolates services so that each application component can communicate only with authorized counterparts rather than being openly accessible. Such isolation reduces the “blast radius” if one service becomes compromised.
Consider a scenario where you deploy two function apps, each residing in separate subnets but within the same virtual network (VNet). By segregating the environment:
• Each service gains its own secure perimeter.
• You limit potential lateral movement in case an attacker manages to breach one part of your network.
• Network policies and routing become more manageable, as each subnet is tailored for specific service types.
Terraform, the popular Infrastructure as Code tool, lets you codify this architecture with precision. The initial steps involve provisioning critical resources like a storage account, a service plan, and the individual function apps. Here’s a snippet that establishes the foundation:

resource "azurerm_storage_account" "sa1" {
name = "dnsexamplesa"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
account_tier = "Standard"
account_replication_type = "LRS"
}
resource "azurerm_service_plan" "asp" {
name = "dns-asp"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
os_type = "Windows"
sku_name = "P1v2"
}

resource "azurerm_windows_function_app" "app1" {​

name = "dns-app1"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
storage_account_name = azurerm_storage_account.sa1.name
storage_account_access_key = azurerm_storage_account.sa1.primary_access_key
service_plan_id = azurerm_service_plan.asp.id
virtual_network_subnet_id = azurerm_subnet.subnet1.id
site_config {
application_stack {
dotnet_version = "v8.0"
}
cors {
allowed_origins = ["Microsoft Azure"]
support_credentials = true
}
}
app_settings = {
"WEBSITE_RUN_FROM_PACKAGE" = "1"
"WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED" = "1"
}
}
A similar configuration creates a second app in its own subnet. The key takeaway? Segregating apps into dedicated subnets is the first line of defense in network security.
Summary: By architecting your apps with dedicated subnets within a VNet, you reinforce your security posture and simplify access control.

Implementing Subnet Delegation​

When deploying services in Azure, automatic management of IP allocation, routing, and security policies is critical. This is where subnet delegation comes into play. By delegating a subnet, you empower the Azure platform to enforce service-specific rules, thereby reducing manual overhead and the risk of misconfiguration.
Subnet delegation works by “reserving” a subnet exclusively for particular services. For example, if you delegate a subnet to Microsoft.Web/serverFarms (used by App Services and Function Apps), Azure handles:
• IP allocation, so you don’t have to manually reserve IP ranges.
• Routing—Azure manages the best routes for traffic within this subnet.
• Conflict prevention by ensuring that your subnet isn’t accidentally used for other services.
• Automatic application of security and network policies tailored for your app.
Below is the Terraform code that defines a subnet with service delegation:

resource "azurerm_subnet" "subnet1" {
name = "subnet1"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.1.0/24"]

delegation {​

name = "delegation"
service_delegation {
name = "Microsoft.Web/serverFarms"
actions = [
"Microsoft.Network/virtualNetworks/subnets/join/action",
"Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action"
]
}
}
}
This configuration directs Azure to apply specific networking rules to the subnet where your function apps reside, effectively “locking in” the necessary policies.
Summary: Subnet delegation simplifies your configuration management while ensuring that routing, IP addressing, and access policies are correctly applied to your services.

Overcoming Private Endpoint Configuration Hurdles​

While subnet delegation offers many benefits, it also introduces a limitation: delegated subnets cannot host private endpoints. A private endpoint is essentially a secure network interface (NIC) managed by Azure, which provides private IP connectivity to a service. It’s a powerful tool that allows you to access PaaS services over a private link. However, if you try to attach a private endpoint directly within a delegated subnet, you’ll face an error like:
  "PrivateEndpointCreationNotAllowedAsSubnetIsDelegated"
This error indicates that the subnet, already reserved for a specific service (in our case, Microsoft.Web/serverFarms), cannot accommodate additional networking resources like the private endpoint.
The solution is straightforward: create a dedicated subnet solely for private endpoints. Here’s the Terraform code that sets up such a subnet and assigns private endpoints to it:

resource "azurerm_subnet" "subnet3" {
name = "subnet3"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.3.0/24"]
}
resource "azurerm_private_endpoint" "app1_pe" {
name = "app1-pe"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
subnet_id = azurerm_subnet.subnet3.id
}

resource "azurerm_private_endpoint" "app2_pe" {​

name = "app2-pe"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
subnet_id = azurerm_subnet.subnet3.id
}
Why the extra step? Because segregation of duties within your virtual network isn’t just a best practice—it’s a necessity. Private endpoints allow your apps to integrate securely through Azure’s backbone network, eliminating exposure to the public internet.
Summary: A dedicated subnet for private endpoints ensures that you avoid conflicts with delegated subnets, allowing secure connectivity between your services via Azure Private Link.

Integrating Privacy with Azure Private Link and DNS​

At its core, Azure Private Link establishes a private connection between your virtual network and the Azure service, ensuring that the communication traverses only trusted Microsoft infrastructure. Think of it as a private tunnel within an interconnected underground that shields your traffic from prying eyes.
Alongside private endpoints, Private Link typically works in tandem with Private DNS. By automating the resolution of private IP addresses, Private DNS ensures that your apps always resolve to the correct, secure endpoints rather than inadvertently reverting to public addresses.
• Private endpoints are assigned a dedicated NIC, with their own IP, from a secure subnet.
• Private Link securely bridges your subnet with the target Azure service over the internal network.
• Private DNS ensures smooth resolution so that traffic is automatically routed to the secure endpoint.
For IT administrators tasked with managing Windows environments on Azure, this seamless integration means that applications running Windows, and indeed across mixed environments, can confidently rely on internal communications that are resilient and shielded from external threats.
Summary: Azure Private Link and Private DNS work together to ensure that your services remain accessible only via secure, managed paths within your virtual network.

Leveraging Network Security Groups for Traffic Filtering​

Adding another layer of defense, Network Security Groups (NSGs) provide granular control over network traffic. NSGs allow you to define inbound and outbound rules, ensuring your apps are not exposed to unwanted traffic. Whether it’s filtering public internet requests or simply isolating inter-service communications, NSGs serve as the digital bouncers that control who gets in—and who doesn’t.
Key considerations when integrating NSGs include:
• Define specific rules based on ports, protocols, or IP ranges.
• Apply NSGs to subnets or individual virtual machine or service resources.
• Regularly review and update your rules to match evolving threat landscapes.
While our example didn’t include detailed NSG code, understanding their role is crucial. For instance, an NSG rule might allow only secure HTTPS traffic from a designated range of IP addresses, providing enhanced protection for a Windows server hosting critical applications on Azure.
Summary: NSGs complement subnet delegation and private endpoints by filtering network traffic to ensure only legitimate access to your resources.

Testing, Troubleshooting, and Next Steps​

Even after deploying comprehensive security measures, regular testing and monitoring are indispensable. Here are some recommendations to keep your Azure network security on point:
  • Deploy your infrastructure using Terraform and verify resource alignment via the Azure portal.
  • Use network monitoring tools and NSG flow logs to verify that traffic is routed correctly.
  • Conduct connectivity tests between your function apps using private endpoints.
  • Regularly review error messages (like the aforementioned PrivateEndpointCreationNotAllowedAsSubnetIsDelegated) and adjust configurations as necessary.
  • Involve team members or community experts by discussing improvements and sharing your insights on specialized forums.
It’s also worth considering further enhancements such as integrating automated security scanning tools, frequent compliance checks, and even tapping into Azure’s evolving security recommendations for both PaaS and IaaS deployments.
Summary: Regular testing, community engagement, and ongoing review are the keystones of a resilient Azure deployment.

The Bigger Picture: Why Network Segmentation Matters​

In today’s cybersecurity landscape, the adage “don’t put all your eggs in one basket” rings truer than ever. Network segmentation limits the potential damage of a security breach, preventing attackers from gaining unfettered access to your entire environment. By isolating functions into dedicated subnets, enforcing delegation, and isolating private endpoints, you’re effectively building a zero-trust environment that minimizes risk.
For Windows administrators and IT professionals navigating the complexities of hybrid environments and multi-cloud networks, these practices can transform how you secure and manage your resources. The integration of Terraform in this process not only accelerates deployment but also ensures consistency across environments—making infrastructure management both agile and secure.
Summary: A well-segmented, delegated, and controlled network environment is a critical defense mechanism in modern IT security, reducing risk and enhancing operational agility.

Final Thoughts​

Securing your cloud infrastructure is much more than a one-off setup—it’s a continuous process that evolves alongside emerging threats and technological advancements. As you deploy and manage Windows applications on Azure, consider the following actionable insights:
• Always isolate services into dedicated subnets where possible.
• Use subnet delegation to offload routine network configuration to Azure and enforce service-specific policies.
• Create dedicated subnets for private endpoints to avoid conflicts and enable secure connectivity via Azure Private Link.
• Leverage NSGs as flexible gatekeepers to control the flow of network traffic.
• Regularly test, monitor, and update your configurations to meet evolving security requirements.
In the rapidly shifting landscape of cloud security, staying informed and agile can be your best defense. Whether you’re a seasoned Windows administrator or a cloud enthusiast embracing Terraform’s power, adopting these best practices will help you build an infrastructure that is as secure as it is dynamic.
By integrating these strategies into your Azure deployments, you’re not only adhering to Microsoft’s recommended practices but also setting up your applications for success in an ever-evolving digital battleground. Happy securing, and may your endpoints always remain private!

Source: Medium
 

Last edited:
Securing your cloud applications isn’t just about keeping hackers at bay—it’s an art form. In today’s deep dive, we explore how to secure application networks in Azure using Terraform, deploying subnets, private endpoints, private DNS, and network security groups (NSGs) like a pro. Whether you’re a seasoned cloud architect or just starting out, buckle up for a detailed walk through a modern, segmented approach to application security in Azure.

A server tower surrounded by glowing icons representing data security and connectivity.
Designing a Secure Azure Architecture​

When you deploy an application to Azure, one of the first questions you should ask is: “Who can get in?” Azure’s recommended approach is not to leave your app wide open to the internet. Instead, separate your services into dedicated segments, giving you granular control over access. In our example, the architecture separates two services—each in its own subnet—while ensuring they can communicate securely.
Key components of this approach include:
• Subnet creation and delegation
• Deployment of private endpoints
• Integration of Azure Private Link
• Configuration of private DNS and NSGs
By keeping your resources organized and isolated within their designated subnets, you automatically gain enhanced security features such as IP allocation, automatic routing, and service-specific policy enforcement.

Understanding Subnet Delegation​

Before we get to the Terraform code, let’s understand why subnet delegation is a game changer. In Azure, subnet delegation automates many networking tasks. When you delegate a subnet—for example, to Microsoft.Web/serverFarms—you allow Azure to manage:
• IP Allocation: No need to manually calculate IP reserves
• Routing: Azure finely tunes routing protocols behind the scenes
• Conflict Prevention: Exclusive subnet usage avoids accidental overlaps
• Policy Enforcement: Security and routing policies are automatically applied
In our sample Terraform code, the initial error encountered was something like:
  "PrivateEndpointCreationNotAllowedAsSubnetIsDelegated"
This error occurs because a subnet, once delegated to a service (such as Azure Functions under Microsoft.Web/serverFarms), is reserved exclusively for that purpose. Attempting to create a private endpoint directly in that subnet violates Azure’s rules. The solution? Use separate, dedicated subnets for different functionalities.

Private Endpoints and the Role of Azure Private Link​

A private endpoint in Azure provides your resource with a private IP address within your virtual network—essentially serving as a secure connection between services. When you set up a private endpoint, an underlying network interface (NIC) is automatically created, carrying your private IP.
However, as mentioned above, trying to mix delegated subnets (used for App Services or function apps) and private endpoints doesn’t work. Azure won’t allow a private endpoint to be attached to a subnet that’s already been delegated.
Enter Azure Private Link. Think of it as the missing bridge between your private endpoint and your target Azure service. But why do you need it? Simply put, Private Link ensures that requests sent via a private endpoint traverse the secure, internal Azure backbone network rather than the public internet. This dramatically reduces your app’s exposure to external threats while ensuring that the connection remains robust and efficient.

Terraform in Action: Building a Secure Deployment​

The beauty of Terraform is that it allows you to codify your entire infrastructure. Let’s break down the Terraform code excerpt provided in our case study. The first part of the code sets up essential resources like the storage account, service plan, and Function Apps.

Example snippet for creating a storage account and service plan:​

resource "azurerm_storage_account" "sa1" {
name = "dnsexamplesa"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
account_tier = "Standard"
account_replication_type = "LRS"
}

resource "azurerm_service_plan" "asp" {​

name = "dns-asp"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
os_type = "Windows"
sku_name = "P1v2"
}
Following that, each Function App (app1 and app2) is created within its own subnet. In the initial code, both Function Apps were deployed into subnets (subnet1 and subnet2) without delegation, which would lead to the error noted above. To fix this, a delegation block was added in the subnet definitions:

resource "azurerm_subnet" "subnet1" {
name = "subnet1"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = [ "10.0.1.0/24" ]

delegation {​

name = "delegation"
service_delegation {
name = "Microsoft.Web/serverFarms"
actions = [
"Microsoft.Network/virtualNetworks/subnets/join/action",
"Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action",
]
}
}
}
Now, with subnet delegation in place, our Function Apps are neatly isolated and managed. But what about private endpoints? As we already encountered, trying to add a private endpoint directly to these delegated subnets results in a conflict because Azure reserves them exclusively for App Service-related traffic.
The solution is to create a third, new subnet specifically for private endpoints.

resource "azurerm_subnet" "subnet3" {
name = "subnet3"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = [ "10.0.3.0/24" ]
}
resource "azurerm_private_endpoint" "app1_pe" {
name = "app1-pe"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
subnet_id = azurerm_subnet.subnet3.id
}

resource "azurerm_private_endpoint" "app2_pe" {​

name = "app2-pe"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
subnet_id = azurerm_subnet.subnet3.id
}
By isolating private endpoints in a dedicated subnet (subnet3), you steer clear of any conflicts with delegated subnets and maintain the integrity of both your application deployments and private connectivity.

Bringing It All Together: A Practical Perspective​

Imagine deploying two critical services that need to interact securely—each service can be thought of as residing in its own secure vault (subnet). Their communications are safe because they’re connected by a dedicated private bridge (via Azure Private Link), ensuring no unauthorized entry can occur. Moreover, by using subnet delegation for the vaults containing your function apps, you reduce the risk of configuration errors and let Azure take care of complex networking details.
Here’s a quick rundown of the best practices highlighted in this approach:
  • Segregate your services into distinct subnets.
  • Use subnet delegation to ensure that services like Function Apps get dedicated network policies and routing.
  • Create dedicated subnets for private endpoints to avoid conflicts with delegated subnets.
  • Employ Azure Private Link to securely bridge the gap between private endpoints and your Azure services.
  • Optionally, integrate network security groups (NSGs) to further control traffic flows and manage inbound/outbound access.
Each of these steps not only improves security but also simplifies management by compartmentalizing responsibilities within your virtual network.

Lessons Learned and Further Considerations​

This deployment scenario provides several crucial lessons:
• Plan Ahead: Networking errors like “PrivateEndpointCreationNotAllowedAsSubnetIsDelegated” could otherwise cost you valuable time. Knowing that delegated subnets cannot host private endpoints encourages proactive infrastructure planning.
• Leverage Azure’s Automation: With delegation, Azure handles many low-level tasks—including IP allocation and routing—allowing you to focus on higher-order security policies and application logic.
• Embrace Terraform: Infrastructure as Code tools like Terraform offer the power to reproduce exact network configurations. This repeatability boosts reliability and streamlines troubleshooting.
• Security is Layered: While segregating applications via subnets and private endpoints shields your core services, further security can be applied with NSGs. These groups can define granular rules ensuring only approved traffic reaches your services.
An inquisitive mind might ask: Is this extra complexity worth it? When you consider the threat landscape today—where cyberattacks are increasingly common—the answer is a resounding yes. By investing time in a segmented, well-delegated network architecture, you are proactively reducing potential attack vectors. It’s like building a fortress with moats, drawbridges, and secret passageways, each layer adding an extra hurdle for intruders.

Conclusion and the Road Ahead​

In summary, securing your application network in Azure using Terraform is both a powerful and flexible way to ensure that your services are safely compartmentalized. By dividing your deployment into segregated subnets, applying delegated policies, and establishing private endpoints with dedicated subnets, you create an environment where security is a fundamental design principle rather than an afterthought.
As you continue to evolve your Azure deployments, consider further enhancements:
• Integrate NSGs to fine-tune your security posture.
• Monitor network traffic closely to detect anomalies.
• Regularly update your Terraform scripts as Azure adds new features or tweaks existing ones.
• Explore additional Azure security services like Azure Firewall or DDoS protection for a multi-layered defense strategy.
By following these best practices, you not only safeguard your applications but also streamline network management—ensuring that scaling up doesn’t mean opening up the doors to unwanted visitors.
Remember, in the ever-changing landscape of cloud security, a secure network design made today sets the stage for robust, enduring defenses tomorrow. Happy coding and may your networks remain impenetrable!

Source: Medium
 

Last edited:
Blue glowing network of interconnected lines and nodes on a dark background.

Securing Your Azure Application with Terraform: A Deep Dive into Subnets, Endpoints, DNS, and NSGs
Azure’s cloud-first mindset demands that applications not only scale but also remain secure. With the proliferation of microservices and distributed architectures, proper network segmentation becomes a cornerstone of any robust security model. Today, we explore how to configure network security in Azure using Terraform, focusing on subnets, private endpoints, DNS, and network security groups (NSGs).
────────────────────────────
Introduction
Imagine launching your shiny new application on Azure only to realize that its doors are wide open for the entire internet. That’s where network security steps in. By isolating services in dedicated subnets, enforcing delegated networking policies, and establishing private links between services, you can protect your applications from unnecessary exposure while ensuring seamless communication between trusted components.
In this piece, we break down an architecture built using Terraform. It demonstrates how to map out a secure environment by constructing the ideal Azure Virtual Network (VNet) and segregating services into multiple subnets. We’ll also cover the complexities of subnet delegation and how private endpoints demand a dedicated subnet—ensuring your application’s internal communications remain safe.
────────────────────────────
Network Segregation: The Foundation of Azure Security
Following Microsoft’s recommendations, a secure Azure blueprint starts with segregation. The idea is simple: isolate each service into its own environment. In our illustrative example, two applications (in this case Azure Functions) are deployed within the same VNet but placed into separate subnets. This design not only limits potential blast radius in the event of an attack but also simplifies communication channels by only exposing what is necessary.
For instance, Terraform code snippets create a storage account, a service plan, and the function apps themselves. Each function app ties to a specific subnet, as shown below:
 • A storage account ("dnsexamplesa") for app data
 • A service plan ("dns-asp") for hosting the Windows-based functions
 • Two function apps ("dns-app1" and "dns-app2") each linked to a different subnet
This segregation paves the way for controlled network boundaries, offering a first line of defense by ensuring that only designated services can communicate with one another.
────────────────────────────
Subnet Delegation: How It Strengthens Networking Rules
Subnet delegation is a critical Azure feature that lets you apply service-specific networking configurations automatically. In our Terraform deployment, attempting to deploy the function apps in the VNet without delegation triggers an error. Azure requires that subnets, designed to host specific services (in this case, Azure App Service related resources), be explicitly delegated.
The Terraform code reveals the solution:
 • Each subnet (e.g., subnet1) is updated with a delegation block
 • The ‘Microsoft.Web/serverFarms’ delegation specifies actions such as joining the subnet and preparing network policies
By delegating the subnet, Azure:
 – Automatically manages IP allocation
 – Enforces dedicated routing rules
 – Prevents conflicts and applies service-specific security policies
This delegation reduces manual overhead and ensures that your configuration complies with Azure’s standards—a surefire way to maintain order in a sprawling cloud environment.
────────────────────────────
Private Endpoints & Private Link: Securing Inbound Connectivity
Once your services reside securely in their delegated subnets, the question arises: How do they connect privately? The answer lies in the use of private endpoints and private links.
A private endpoint is essentially a private IP address allocated from your virtual network. It acts as a network interface (NIC) through which a service (for instance, Azure Functions or SQL Server) is accessed. When deploying private endpoints in a subnet that has been delegated, however, you encounter a stumbling block: Azure enforces a rigid separation.
Azure prevents the deployment of a private endpoint in a subnet that is already delegated to a specific service type (Microsoft.Web/serverFarms, in our case). Doing so results in an error message like:
 “PrivateEndpointCreationNotAllowedAsSubnetIsDelegated”
The resolution is straightforward but crucial: allocate a dedicated subnet just for private endpoints. For example, adding a new subnet (subnet3) solely for private endpoints ensures that the communication pathway to your services stays both secure and compliant with Azure’s restrictions.
By creating a private endpoint in this dedicated subnet, you effectively forge a private link between your internal services. The private link works behind the scenes, routing traffic over Azure’s secure backbone rather than the public internet. This arrangement is especially beneficial for sensitive applications that require both isolation and seamless dependency intercommunication.
────────────────────────────
DNS, A Records, and NSGs: Fine-Tuning Your Network Security
While subnets and endpoints establish the physical and logical separations, DNS configurations and NSGs add a layer of granularity to control who can access what on your network.
Modern network security relies on:
 • Private DNS zones to resolve names without exposing them externally
 • A records ensuring that service names map correctly to private IPs
 • Network Security Groups (NSGs) to regulate traffic flow, specifying allowed protocols, ports, and source/destination constraints
Although our Terraform guide focuses on subnets and endpoints, it hints at additional considerations such as NSGs. Implementing NSGs allows you to filter and monitor network traffic per subnet or even individual virtual network interfaces, offering another safeguard against potential vulnerabilities.
For Windows administrators transitioning to a cloud-first strategy, leveraging NSGs is an indispensable step. They add granular control, similar to a robust Windows Firewall in traditional environments, but at the network layer.
────────────────────────────
Troubleshooting & Best Practices
Designing a secure application network architecture is as much about the planning as it is about handling the occasional hiccup. Consider this common scenario: attempting to attach a private endpoint to a delegated subnet results in a 400 Bad Request error. When you see messages like:
 “Private endpoint cannot be created as subnet is delegated,”
it's a signal to reassess your subnet configurations. Here’s a quick troubleshooting checklist:
  • Confirm that the subnet containing your application resources is correctly delegated (e.g., to Microsoft.Web/serverFarms).
  • Allocate a separate subnet for private endpoints.
  • Ensure that NSG rules are appropriately configured to allow internal traffic between subnets.
  • Validate your private DNS settings (A records and zones) so that network resolution occurs seamlessly.
By following these steps, not only do you align with best practices, but you also set up your network for both operational excellence and long-term security.
────────────────────────────
Conclusion
As organizations increasingly pivot to cloud-native environments, securing application networks with precision is critical. By harnessing Terraform to automate resource provisioning in Azure, you gain a dual advantage: streamlined deployments and robust security. Key takeaways include:
• Segregate applications across dedicated subnets to minimize risk.
• Use subnet delegation to ensure service-specific rules and policies are automatically enforced.
• Separate private endpoints into their own subnet to comply with Azure’s restrictions and establish private links.
• Enhance security further with private DNS configurations and granular NSG rules.
For Windows administrators and IT engineers, these techniques highlight how cloud security mirrors traditional methodologies while embracing innovation. Integrating these practices into your Azure strategy is an essential step towards a more secure, efficient, and resilient network infrastructure.
At WindowsForum.com, you’ll find further discussions on best practices in Azure resource management, advanced NSG configurations, and Terraform strategies for cloud deployments. Remember, the key to robust security is not just in configuring the tools but also in constantly evolving with the cloud landscape.

Source: Medium
 

Last edited:
Securing your applications in Azure is more than just deploying code—it's about building a robust network architecture that ensures services communicate safely while remaining isolated from unwanted external access. In this deep dive, we explore how to use Terraform to implement a layered network security approach in Azure by leveraging subnets, subnet delegation, private endpoints, DNS, and network security groups (NSGs).

A row of server racks illuminated with blue lighting in a data center room.
The Philosophy of Network Segmentation in Azure​

Microsoft’s best practices emphasize isolating each component of your application by deploying them into separate subnets within a virtual network (vNet). This segmentation means that each service only interacts with the entities it absolutely needs to. Not only does this reduce the attack surface, but it also simplifies both monitoring and management.
In our sample architecture, we have two services—each represented as a Windows Function App—that need to communicate with one another. By placing them in separate subnets, we ensure controlled and secure communication. The approach starts with core resources such as a storage account and a service plan, then moves into app deployments via Terraform.

Deploying Azure Resources with Terraform​

Let’s break down the Terraform code that initiates the deployment. The process begins by creating essential Azure resources:
• A storage account for holding application data
• A service plan that supports the Windows Function Apps
• Two Function Apps (app1 and app2), each assigned its own subnet within a vNet
Here’s an abbreviated version of the Terraform code used to deploy these resources:
Code:
resource "azurerm_storage_account" "sa1" {
  name                     = "dnsexamplesa"
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_service_plan" "asp" {
  name                = "dns-asp"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  os_type             = "Windows"
  sku_name            = "P1v2"
}

resource "azurerm_windows_function_app" "app1" {
  name                       = "dns-app1"
  resource_group_name        = azurerm_resource_group.rg.name
  location                   = azurerm_resource_group.rg.location
  storage_account_name       = azurerm_storage_account.sa1.name
  storage_account_access_key = azurerm_storage_account.sa1.primary_access_key
  service_plan_id            = azurerm_service_plan.asp.id
  virtual_network_subnet_id  = azurerm_subnet.subnet1.id

  site_config {
    application_stack {
      dotnet_version = "v8.0"
    }
    cors {
      allowed_origins   = ["[Microsoft Azure](https://portal.azure.com)"]
      support_credentials = true
    }
  }

  app_settings = {
    "WEBSITE_RUN_FROM_PACKAGE"        = "1"
    "WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED" = "1"
  }
}
The code for app2 follows a similar pattern, but with its subnet reference adjusted accordingly. This illustrates not just resource creation but also the importance of properly assigning network segments to each service.

Understanding Subnet Delegation​

One of the key elements in this architecture is subnet delegation. Subnet delegation in Azure allows you to dedicate a subnet to a specific service (for example, Azure App Services). Delegation helps automate functions like IP allocation, routing, conflict prevention, and policy application. Essentially, Azure applies service-specific rules to the subnet, ensuring that resources within it adhere to best practices without manual interference.
The Terraform code to add delegation to a subnet is straightforward. For example, here’s how you delegate a subnet for your Function Apps:
Code:
resource "azurerm_subnet" "subnet1" {
  name                 = "subnet1"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = [ "10.0.1.0/24" ]

  delegation {
    name = "delegation"
    service_delegation {
      name    = "Microsoft.Web/serverFarms"
      actions = [
        "Microsoft.Network/virtualNetworks/subnets/join/action",
        "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action"
      ]
    }
  }
}
By delegating a subnet to Microsoft.Web/serverFarms, you ensure that Azure manages the networking aspects for resources like App Service Plans and Function Apps automatically.

The Private Endpoint Conundrum​

Once your applications are part of their respective subnets, the next puzzle is secure connectivity between them. That’s where private endpoints come into play. A private endpoint assigns a private IP address from your virtual network to a resource, functioning much like a network interface card (NIC). Under the hood, Azure creates this NIC and attaches it to the private endpoint, facilitating internal communication over the Azure backbone.
However, a challenge emerges if you attempt to place private endpoints directly into a subnet that’s already delegated for a particular service. Azure won’t allow this, and you might encounter an error like:
"Private endpoint cannot be created as subnet … is delegated."
This error occurs because the subnet is reserved exclusively for the delegated service (in this case, Microsoft.Web/serverFarms). The takeaway? Separate subnets for delegated resources and private endpoints are a must.

Creating Dedicated Subnets for Private Endpoints​

To work around the conflict mentioned above, you need to provision a dedicated subnet for private endpoints. Here’s how you can update your Terraform code:
Code:
resource "azurerm_subnet" "subnet3" {
  name                 = "subnet3"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = [ "10.0.3.0/24" ]
}

resource "azurerm_private_endpoint" "app1_pe" {
  name                = "app1-pe"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  subnet_id           = azurerm_subnet.subnet3.id
}

resource "azurerm_private_endpoint" "app2_pe" {
  name                = "app2-pe"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  subnet_id           = azurerm_subnet.subnet3.id
}
By isolating your private endpoints on a dedicated subnet (subnet3), you avoid any interference with the subnet delegation rules for your Function Apps. This separation reinforces security boundaries and simplifies network management—a practice that aligns with the zero-trust principle.

Bridging Communication with Azure Private Link​

Even though private endpoints assign internal IP addresses, they need a way to direct traffic securely to the application. This is exactly where Azure Private Link comes into play. Private Link creates a secure connection between your private endpoint and the target Azure service (such as your Function App) over the Azure backbone network. Essentially, while the private endpoint serves as a door, Private Link acts as the secure corridor ensuring that requests remain within the trusted network pathway.
With Private Link, you can:
• Access PaaS services—such as Storage Accounts, App Services, and Azure SQL—via a private IP address
• Keep traffic off the public Internet, drastically reducing exposure to potential attacks
• Simplify network routing and improve governance by consolidating network policies
This model fits seamlessly with the idea of separating duties via dedicated subnets, where one subnet handles delegated app services and another handles private endpoint connectivity.

DNS, NSGs, and Further Hardening​

While our focus so far has been on segmentation and private connectivity, comprehensive network security often involves additional facets such as DNS configuration and network security groups. In a fully hardened environment, you would need to:
• Configure Private DNS Zones to ensure that your private endpoints resolve correctly without leaking to the public DNS
• Implement NSGs to enforce granular traffic rules, both inbound and outbound, on your subnets
• Create A records linking your private IP addresses to internal domain names, further streamlining and securing communications
By integrating these elements, you create a robust security model where every piece of network communication is scrutinized and allowed only if it meets predetermined criteria. This layered approach forms the backbone of a truly secure application landscape on Azure.

Automating Secure Infrastructure with Terraform​

Terraform brings immense value by codifying your infrastructure as code (IaC). This approach promotes repeatability, transparency, and version control. When you script out your network security constructs—subnets, delegation, private endpoints, DNS configurations, and NSGs—you reduce the risk of human error and ensure that every deployment complies with your organization’s security policies.
Automation with Terraform isn’t just about speed; it’s about discipline. It forces you to adhere to best practices by eliminating ad hoc manual configurations. In a world where cybersecurity threats are evolving rapidly, having your infrastructure defined and auditable in code adds an extra layer of trust.

Lessons Learned and Best Practices​

Drawing from the architecture and code examples discussed, here are some best practices every Windows and cloud administrator should incorporate:
• Segregate application services into dedicated subnets for maximal isolation
• Use subnet delegation to offload network management to Azure for specific services
• Avoid conflicts by placing private endpoints within their own isolated subnet
• Leverage Azure Private Link to ensure service-to-service communication remains secure
• Harden your network further with properly configured NSGs and Private DNS zones
• Automate your network setup with Terraform to enforce consistency and security across deployments
As you refine your architecture, it’s worth questioning the traditional “one-size-fits-all” approach to cloud networking. Could further separation of duties or a refined NSG rule set add another layer of security? The answer often lies in the unique demands of your applications and their threat profiles.

Conclusion​

Deploying a secure application in Azure involves a confluence of best practices—from carefully segmenting your network with subnets and subnet delegation to ensuring private endpoints and Azure Private Link work harmoniously. By leveraging Terraform, you not only accelerate the deployment process but also enforce a disciplined, repeatable, and auditable security model.
This approach underlines that a secure network is not simply an off-the-shelf feature; it’s built through deliberate design choices that balance convenience, isolation, and strict access control. The sample code and configuration techniques we discussed serve as a comprehensive blueprint for those looking to secure their Azure applications while maintaining the agility needed for modern cloud deployments.
For Windows administrators and cloud professionals alike, applying these concepts can dramatically improve the resilience of your applications, keeping your data and services secure while ensuring seamless internal connectivity. As always, feedback and discussions are encouraged—your insights could be the next step in evolving these best practices further.

Source: Medium
 

Last edited:
Securing your Azure applications isn’t just about locking the front door—it’s about architecting a fortress where each service has its own dedicated chamber. In today’s deep-dive, we unravel how Azure’s networking features—subnets, service delegations, private endpoints, and Private Link—combine with Terraform’s automation prowess to create a hardened application network.

A 3D grid network with interconnected colorful nodes and lines on a dark background.
The Need for Network Segmentation in Azure​

Azure’s recommended approach is as pragmatic as it is secure: segregate application components into dedicated subnets. When you deploy apps (such as Azure Function Apps or App Services) into isolated subnets, you control access on a granular level. The benefits are numerous:
• Isolation of services to prevent lateral movement in case of breaches
• Simplified management of routing and security policies
• Reduced risk of accidental exposure through shared network resources
In our case study, two distinct applications are each placed in their own subnet within a virtual network. While they reside in the same overarching network space (for example, using an address space like 10.0.0.0/16), each service operates within its own slice—such as 10.0.1.0/24 and 10.0.2.0/24. This approach echoes the best practices outlined in Microsoft documentation and helps ensure that your Windows-based services and backend integrations remain tightly controlled.

Terraform-Powered Deployment: A Code Walkthrough​

Terraform code makes it easier to manage these segmented deployments consistently. Consider a scenario where you’re deploying resources including a storage account, a service plan, and Windows Function Apps. The code defines a virtual network alongside two subnets:
• The virtual network (vnet) is declared with an address space like 10.0.0.0/16
• Two subnets (subnet1 and subnet2) are created for separate apps, each with its own address range
When you assign a Function App to a specific subnet using the virtual_network_subnet_id property, you’re effectively channeling traffic through that isolated segment. However, during deployment, an error might pop up:
  "PrivateEndpointCreationNotAllowedAsSubnetIsDelegated"
This error is a direct consequence of Azure’s restrictions. When a subnet is delegated to a service (in this example, Microsoft.Web/serverFarms for our Function Apps), it’s exclusively configured for that service type. Adding a Private Endpoint to such a subnet is akin to trying to mix oil and water—it just doesn’t work.

Code Insights: Delegation and the Private Endpoint Dilemma​

Here’s the typical Terraform snippet for subnet delegation:
  resource "azurerm_subnet" "subnet1" {
   name = "subnet1"
   resource_group_name = azurerm_resource_group.rg.name
   virtual_network_name = azurerm_virtual_network.vnet.name
   address_prefixes = [ "10.0.1.0/24" ]
   delegation {
    name = "delegation"
    service_delegation {
     name = "Microsoft.Web/serverFarms"
     actions = [
      "Microsoft.Network/virtualNetworks/subnets/join/action",
      "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action"
     ]
    }
   }
  }
Delegation tells Azure that the subnet is dedicated for specific services and automatically applies networking rules such as IP allocation, routing, and conflict prevention. This is invaluable when managing multiple services, but it becomes a roadblock if you try to mix in private endpoints, which also require a dedicated network interface (NIC) attached to them.
The solution? Always separate the lanes. Instead of trying to attach private endpoints within the delegated subnets, create an entirely new subnet—say subnet3 (perhaps using 10.0.3.0/24)—solely for hosting your private endpoints:
  resource "azurerm_subnet" "subnet3" {
   name = "subnet3"
   resource_group_name = azurerm_resource_group.rg.name
   virtual_network_name = azurerm_virtual_network.vnet.name
   address_prefixes = [ "10.0.3.0/24" ]
  }
Then, assign your private endpoint resources to subnet3. This dedicated separation not only resolves Azure’s restrictions but also enhances clarity in your infrastructure design.

Private Endpoints and Azure Private Link: Locking Down Connectivity​

A private endpoint in Azure is essentially a private IP address from your virtual network assigned to a specific Azure service. When you deploy a private endpoint, Azure automatically provisions a network interface with its own IP, ensuring that traffic to your service doesn’t traverse the public internet. But there’s a twist: if you place this endpoint in a subnet already delegated to another service, Azure will reject the configuration.
This is where Azure Private Link comes into play. Private Link connects your private endpoint to the actual Azure service over the Azure backbone network. Think of it as a dedicated tunnel that securely bridges your application with the service—bypassing the public internet entirely.
By creating a dedicated subnet for private endpoints and then configuring Private Link, you ensure that your services remain communicable with each other in a secure, closed-loop. This setup not only enhances security but also streamlines management since all private communication occurs over a fault-tolerant, dedicated network path.

Best Practices for Azure Application Network Security​

When designing your network architecture in Azure with Terraform, consider these best practices:
• Use separate subnets for service deployments and private endpoints.
• Delegate subnets specifically for services, leveraging Azure’s automatic IP allocation and routing features.
• Configure Network Security Groups (NSGs) and private DNS settings (like A records) to further refine access controls.
• Test inter-service communication thoroughly to ensure that private endpoints and Private Links are set up correctly.
• Keep your Terraform code modular—this makes it easier to adjust configurations as your application scales.
These guidelines help fortify your application’s network, reducing attack surfaces while maintaining streamlined connectivity between services.

Summing It Up​

In essence, effective network security on Azure demands meticulous planning and a keen understanding of how its various components interact. By using Terraform to orchestrate your Azure deployments, you not only automate the process but also enforce best practices like segregation of subnets, proper delegation for service-specific resources, and the dedicated use of private endpoints for secure connectivity.
This blueprint exemplifies how to balance flexibility with security. Much like designing a modern mansion with dedicated wings for different functions, a well-planned Azure network ensures each component is both secure and efficiently accessible.
Got thoughts on the approach? Does your organization have a unique twist on implementing Azure network security? Share your experiences and join the conversation as we keep our applications—and our networks—as secure as Fort Knox while running smooth on Windows.
Happy securing, and may your pipelines always be free of errors!

Source: Medium
 

Last edited:
Application deployment is only half the battle—securing communication between services in cloud environments like Azure is what truly makes or breaks your infrastructure’s integrity. With the rise of sophisticated cyberattacks, understanding how to enforce robust application network security remains a top priority for IT professionals and Windows enthusiasts alike. In this article, we delve into how Terraform code can be leveraged to design Azure network architectures that incorporate subnets, private endpoints, DNS, and even Network Security Groups (NSGs), ensuring that your apps enjoy both connectivity and isolation.

A monitor displays complex data visualizations and code in a dark tech environment.
Understanding Azure’s Network Security Blueprint​

Azure’s recommended approach for securing applications revolves around one key concept: segmentation. Instead of deploying all parts of your application into a single network, Microsoft advises that you separate services into distinct subnets. This isolate-and-conquer methodology ensures that only relevant entities communicate with each other—dramatically reducing the potential attack surface.
Imagine your application as a fortified castle. Each service or function is a separate wing of the castle, with its own dedicated access routes. Without proper separation, an intruder might roam freely between vulnerable areas. By dividing your services into isolated subnets, you prevent unwanted lateral movement in the event of a breach.
Key points include:
  • Segregation of services within a virtual network (vnet).
  • Dedicated subnets for different types of functionality.
  • Enhanced control over traffic with targeted policies.

Terraform Code: The Architect’s Toolkit​

Terraform, the Infrastructure as Code (IaC) powerhouse, allows you to define and provision your infrastructure with declarative configuration files. In our discussion, we see Terraform being used to create essential resources:
  • Storage accounts
  • Service plans
  • Function apps (running Windows functions)
  • Virtual networks and subnets tailored for specific use cases
Below is an excerpt of how the Terraform code initiates the setup:

resource "azurerm_storage_account" "sa1" {
name = "dnsexamplesa"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
account_tier = "Standard"
account_replication_type = "LRS"
}
resource "azurerm_service_plan" "asp" {
name = "dns-asp"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
os_type = "Windows"
sku_name = "P1v2"
}
resource "azurerm_windows_function_app" "app1" {
name = "dns-app1"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
storage_account_name = azurerm_storage_account.sa1.name
storage_account_access_key = azurerm_storage_account.sa1.primary_access_key
service_plan_id = azurerm_service_plan.asp.id
virtual_network_subnet_id = azurerm_subnet.subnet1.id
site_config {
application_stack {
dotnet_version = "v8.0"
}
cors {
allowed_origins = ["Microsoft Azure"]
support_credentials = true
}
}

app_settings = {​

"WEBSITE_RUN_FROM_PACKAGE" = "1"
"WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED" = "1"
}
}
In this code block, two function apps (app1 and app2) are created inside a shared virtual network. They reside in separate subnets, albeit with their own delegation configurations—a concept we’re about to unpack into further detail.

Navigating Subnet Delegation​

Delegation in Azure subnets is crucial for applying specific network rules tailored to a given service. When a subnet is delegated, Azure automatically manages several vital aspects:
  • IP allocation without the need for manual calculation and reservation
  • Automatic routing configuration
  • Enforcement of service-specific rules that prevent overlapping or conflicts
  • Application of pre-defined security and network policies
In the provided sample, after defining the basic subnet structure, additional code is used to incorporate delegation:

resource "azurerm_subnet" "subnet1" {
name = "subnet1"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = [ "10.0.1.0/24" ]

delegation {​

name = "delegation"
service_delegation {
name = "Microsoft.Web/serverFarms"
actions = [
"Microsoft.Network/virtualNetworks/subnets/join/action",
"Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action",
]
}
}
}
Here, the subnet is explicitly delegated to Microsoft.Web/serverFarms. This means it’s reserved solely for hosting resources like function apps or App Service plans. While this delegation smooths out IP allocation and routing issues, it also introduces an inherent restriction: adding private endpoints to a delegated subnet is not allowed.
A common error message you might encounter is:
"PrivateEndpointCreationNotAllowedAsSubnetIsDelegated: Private endpoint ... cannot be created as subnet ... is delegated."
This error is a direct result of Azure enforcing segregation—ensuring that subnets dedicated to specific services remain isolated from other network components. The takeaway? When combining subnet delegation with private endpoints, the two cannot coexist in the same subnet.

Private Endpoints and The Role of Private Link​

So, if you can’t place a private endpoint in the same subnet as a delegated resource, how do your services securely communicate? The answer lies in creating dedicated subnets for private endpoints and employing Azure Private Link.
A private endpoint is essentially a private IP address from your vnet that serves as an entry point to an Azure service, much like a dedicated network interface card (NIC). It allows your app to access other Azure resources over the secure, internal Azure backbone network.
However, attempting to integrate private endpoints into a delegated subnet leads to conflicts. To resolve this, a separate subnet—often called something like “subnet3” in the configuration—is provisioned specifically for private endpoints:

resource "azurerm_subnet" "subnet3" {
name = "subnet3"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = [ "10.0.3.0/24" ]
}
resource "azurerm_private_endpoint" "app1_pe" {
name = "app1-pe"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
subnet_id = azurerm_subnet.subnet3.id
}

resource "azurerm_private_endpoint" "app2_pe" {​

name = "app2-pe"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
subnet_id = azurerm_subnet.subnet3.id
}
By designating a specific subnet for private endpoints, you avoid conflicts with delegated subnets while preserving the essential security benefits that both features provide. In the background, Azure Private Link ties the private endpoints to the corresponding service (in our case, function apps), seamlessly forwarding traffic through a secure, managed network.
In essence, think of Azure Private Link as the dedicated, secure bridge connecting two fort-like structures. It ensures that while the subnets remain isolated for security, they can still communicate efficiently through carefully controlled channels.

DNS, NSGs, and Managing External Traffic​

While subnets and private endpoints form the backbone of your network security infrastructure, they are not the only pieces of the puzzle. DNS configuration and Network Security Groups (NSGs) play equally pivotal roles.

DNS Considerations​

When you are dealing with private endpoints, ensuring that your DNS records are correctly configured is key. Azure Private DNS zones enable secure name resolution for your private endpoint connections. By creating an A record in a Private DNS Zone, you ensure that requests within your virtual network correctly resolve to the private IP address of the Azure service instead of a public endpoint. This configuration helps maintain the security perimeter and ensures that communication never leaves the trusted network.

Network Security Groups (NSGs)​

NSGs serve as the digital bouncers for your network traffic. They are used to control inbound and outbound traffic on a per-subnet or per-interface basis. In the context of our secured Azure application:
  • NSGs can block unauthorized external traffic while permitting only trusted communications.
  • You can define granular rules to allow traffic only from specific sources or destined for particular ports.
For instance, while configuring connectivity for our function apps, NSGs can be applied to the subnets housing private endpoints to ensure that only legitimate traffic reaches these hallmark services.
Together, DNS configurations and NSGs not only safeguard your cloud resources but also provide the necessary controls to fine-tune access. This layered security perspective—combining subnet segmentation, delegated subnets, private endpoints, and NSGs—creates a multi-dimensional defense strategy that is resilient against potential threats.

Testing and Beyond​

After setting up the architecture, thorough testing is crucial. It’s one thing to have the infrastructure in place; it’s another to ensure that your private endpoints and delegated subnets are working harmoniously. Testing involves:
  • Verifying that requests between the separate function apps traverse through the designated private endpoints.
  • Checking DNS resolution to confirm that the Azure Private DNS zones are routing traffic through the internal IP addresses.
  • Ensuring that the NSG rules are effectively filtering traffic, blocking any unauthorized access from external sources.
Once the testing phase confirms that connectivity is seamless and secure, you have successfully established a robust network security blueprint on Azure using Terraform.

Final Thoughts and Next Steps​

Azure’s cloud environment offers a plethora of security mechanisms designed to keep your applications insulated from threats while ensuring that essential services remain accessible to one another. By splitting your application into carefully controlled subnets, using delegation to streamline network policies, and employing dedicated subnets for private endpoints—all woven together with Azure Private Link, DNS configurations, and NSGs—you are embracing a best-practice blueprint that has proven effective in real-world scenarios.
Before you rest on your laurels, consider these next steps:
  • Explore additional security features such as Azure Monitor for continuous insights and alerts.
  • Consider integrating more sophisticated NSG rules tailored to your specific application traffic patterns.
  • Evaluate other Azure native security tools to further harden your infrastructure, like Azure Security Center, for comprehensive security posture management.
In a world where cyber threats are ever-evolving, ensuring robust application network security isn’t just about following guidelines—it’s about proactive architecture design. What strategies have you implemented in your Azure environments? Does your approach mirror these best practices, or are there other innovations you’ve embraced? As always, your insights and experiences matter, and the conversation here on WindowsForum.com helps us all grow stronger together.
Deploy smartly and secure wisely—your applications deserve nothing less.

Source: Medium
 

Last edited:
Deploying and securing an application in Azure is a bit like getting a brand-new sports car off the showroom floor—it looks fantastic and runs great, but you need to lock it up to keep the riffraff at bay. When you’ve just set up your Windows-based app in Azure using Terraform, the next challenge is protecting its network. Let’s break down how to use subnets, private endpoints, DNS, and NSGs to create a robust application network security posture in Azure.

A glowing central server unit stands on the floor amid multiple server racks in a data center.
Introduction​

Imagine you’ve just deployed your latest business-critical application in Azure. You’re proud of your work—until you wonder, “Is this app open for anyone to access?” The answer is an emphatic no. In today’s post, we dive into the architecture and Terraform code required to secure your application’s network in Azure, ensuring that only the right entities can communicate with each other while keeping external traffic firmly at bay.
We’ll explore:
  • How segregating applications into separate subnets increases security.
  • The role of subnet delegation.
  • The importance of private endpoints and private links.
  • How to configure DNS and network security groups (NSGs).
  • Practical Terraform code examples to help you implement these features.

The Blueprint: Segregating Applications in Azure​

Azure’s recommended approach for network security involves isolating your app’s components across different subnets. This way, each service is effectively “caged” in its own compartment, making it harder for unwanted traffic to hop from one service to another. In our case, consider two services that need to talk to each other—but only on a need-to-know basis. This is achieved by placing them in separate subnets within the same virtual network (vnet).
The initial Terraform code might look something like this:
Code:
resource "azurerm_storage_account" "sa1" {
  name                     = "dnsexamplesa"
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_service_plan" "asp" {
  name                = "dns-asp"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  os_type             = "Windows"
  sku_name            = "P1v2"
}

resource "azurerm_windows_function_app" "app1" {
  name                       = "dns-app1"
  resource_group_name        = azurerm_resource_group.rg.name
  location                   = azurerm_resource_group.rg.location
  storage_account_name       = azurerm_storage_account.sa1.name
  storage_account_access_key = azurerm_storage_account.sa1.primary_access_key
  service_plan_id            = azurerm_service_plan.asp.id
  virtual_network_subnet_id  = azurerm_subnet.subnet1.id

  site_config {
    application_stack {
      dotnet_version = "v8.0"
    }
    cors {
      allowed_origins    = ["[Microsoft Azure](https://portal.azure.com)"]
      support_credentials = true
    }
  }
  app_settings = {
    "WEBSITE_RUN_FROM_PACKAGE"         = "1"
    "WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED" = "1"
  }
}
This code sets up two important pieces: your storage and service plan, followed by the deployment of your function apps. Each containerized app is then associated with its own subnet, establishing the foundation for a secured network.

Understanding Subnet Delegation​

When you place your app’s services into subnets, there’s an extra step required called subnet delegation. Think of it as designating a VIP area in your network where Azure enforces special rules on what can connect and what can’t. Delegation automatically manages:
  • IP allocation: Reserving IPs and handling routing behind the scenes.
  • Conflict prevention: Avoiding address or routing conflicts by ensuring exclusive use.
  • Policy application: Automatically enforcing network and security policies for the delegated resources.
Without delegation, your function apps may throw errors or find themselves unprotected. For example, you might encounter an error like:
"Subnet dns-vnet in VNET is missing a delegation to…"
To rectify this, update your subnet configuration to include a delegation block. Here’s how you can adjust the code:
Code:
resource "azurerm_subnet" "subnet1" {
  name                 = "subnet1"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = [ "10.0.1.0/24" ]

  delegation {
    name = "delegation"
    service_delegation {
      name    = "Microsoft.Web/serverFarms"
      actions = [
        "Microsoft.Network/virtualNetworks/subnets/join/action",
        "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action"
      ]
    }
  }
}
With this change, your subnet is now explicitly prepared for hosting Azure App Service-related resources such as function apps and app service plans.

Private Endpoints and the Role of Private Links​

Once your apps are correctly isolated in subnets, the next challenge is ensuring secure communication. This is where private endpoints come into play. A private endpoint is simply a private IP address from your virtual network that connects to an Azure service – akin to a network interface card (NIC) that’s automatically configured when you establish the endpoint.
These endpoints are crucial because:
  • They enable direct communication over a private network, entirely bypassing the public Internet.
  • They simplify connectivity between services by automatically configuring the necessary IP settings and routing.
However, there’s a hiccup: if you try to attach a private endpoint directly into a subnet that’s already delegated for your function apps, Azure will object with an error similar to:
"Private endpoint ... cannot be created as subnet ... is delegated."
This is because delegated subnets are exclusively reserved for the specified Azure services. The solution? Allocate a dedicated subnet for your private endpoints. For example:
Code:
resource "azurerm_subnet" "subnet3" {
  name                 = "subnet3"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = [ "10.0.3.0/24" ]
}

resource "azurerm_private_endpoint" "app1_pe" {
  name                = "app1-pe"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  subnet_id           = azurerm_subnet.subnet3.id
}

resource "azurerm_private_endpoint" "app2_pe" {
  name                = "app2-pe"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  subnet_id           = azurerm_subnet.subnet3.id
}
By segregating private endpoint traffic into its own subnet, you sidestep any conflicts with delegated subnets and ensure that traffic flows securely within Azure’s backbone network. The behind-the-scenes magic that connects your private endpoints with your apps is handled via Azure Private Link.

DNS, NSGs, and Managing External Traffic​

Once private endpoints are established, you’re left with one final piece of the security puzzle: ensuring that DNS and network security groups (NSGs) work their magic.

Private DNS and A Records​

Azure Private Link relies on Private DNS zones to resolve the private endpoint IP addresses. By properly associating a private DNS zone and creating the necessary A records, you guarantee that your app’s domain names resolve correctly to their private IP addresses on the Azure backbone. This eliminates the need for public DNS resolution and helps secure your connections further.

Network Security Groups (NSGs)​

Network Security Groups act as the gatekeepers for your virtual network. They enable you to define granular security rules that specify which traffic can flow to and from your subnets and resources. Integrating NSGs into your architecture ensures that external traffic is filtered based on your defined policies while allowing legitimate, internal communication.
Some best practices include:
  • Deploying NSGs on both individual subnets and network interfaces.
  • Defining rules to allow only trusted traffic, such as management traffic from trusted IP ranges.
  • Regularly reviewing and updating NSG rules to reflect evolving security requirements.

Practical Implications and Best Practices​

Here’s a step-by-step breakdown to ensure your application network in Azure is secure:
  • Deploy your essential Azure services (storage, function apps, service plans) using Terraform.
  • Create a virtual network and segregate your services into separate subnets.
  • Enable subnet delegation for those subnets hosting Azure App Service resources.
  • Allocate a dedicated subnet for private endpoints to avoid conflicting with delegated subnets.
  • Configure Azure Private Link to ensure secure, private connectivity between your apps.
  • Set up Private DNS zones and A records for seamless resolution of private IPs.
  • Apply NSGs to filter external traffic and secure your network boundaries.
These steps not only prevent unauthorized access but also optimize the operational efficiency and security of your application network, making it a robust solution suitable for production environments.

Final Thoughts​

Network security in Azure, especially when orchestrated via Terraform, is all about precision and adherence to best practices. Delegated subnets, private endpoints, and the use of NSGs collectively create a multi-layered defensive strategy that aligns with Microsoft’s recommendations. As you might have noticed, errors like "PrivateEndpointCreationNotAllowedAsSubnetIsDelegated" serve as a stern reminder that mixing and matching network components without proper planning can lead to deployment headaches.
Have a look at your network design next time you deploy an app—are your subnets properly partitioned? Have you set aside the necessary space for private endpoints? And most importantly, are your NSGs up to the task of blocking unwanted traffic?
This comprehensive approach not only secures your application environment but also provides a clear roadmap for managing communication between different services. The next steps might involve layering additional security measures like enhanced logging, automated patching via Microsoft security patches, or even integration with other Azure security services.
For Windows enthusiasts and IT pros alike, mastering network security in Azure using Terraform is a critical skill set—one that not only keeps your apps safe but also ensures they run smoothly in today’s dynamic cloud environment.
What are your thoughts or experiences with securing application networks on Azure? Feel free to share your ideas and questions on this intricate balance between openness and security in our vibrant Windows community.

Source: Medium
 

Last edited:
Back
Top