Securing Azure Applications: A Guide to Terraform Network Architecture

  • Thread Author
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.

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
 

Back
Top