Securing Azure Applications Using Terraform: A Guide

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

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:
  1. Deploy your infrastructure using Terraform and verify resource alignment via the Azure portal.
  2. Use network monitoring tools and NSG flow logs to verify that traffic is routed correctly.
  3. Conduct connectivity tests between your function apps using private endpoints.
  4. Regularly review error messages (like the aforementioned PrivateEndpointCreationNotAllowedAsSubnetIsDelegated) and adjust configurations as necessary.
  5. 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
 


Back
Top