Version 4.58.0 of the Azure provider for Terraform (I’m always talking about the azurerm provider, not the azapi provider!) introduced new resources to manage network security perimeters.
The new resources (and data sources) for managing network security perimeters are:
- Resource and data source for
azurerm_network_security_perimeter - Resource and data source for
azurerm_network_security_perimeter_profile - Resource for
azurerm_network_security_perimeter_access_rule - Resource for
azurerm_network_security_perimeter_association
A network security perimeter is a feature to create a logical network boundary to protect your platform services (PaaS services) on Azure without the need of a custom virtual network with private links and the rest of the complexity that comes with a virtual network.
Resource hierarchy#
As with a few other resource collections on Azure it might not be immediately clear how the different resources fit together in a hierarchy.
- The main resource is the network security perimeter (
azurerm_network_security_perimeter). - You create one or more profiles (
azurerm_network_security_perimeter_profile) within your network security perimeter. - Each profile contains one or more rules (
azurerm_network_security_perimeter_access_rule) that specify which traffic you want to allow to and from your platform services. - Finally, you associate (
azurerm_network_security_perimeter_association) a profile with the platform service you want to protect.
Manage network security perimeters with Terraform#
It is straightforward to configure network security perimeters using Terraform.
Create the main network security perimeter resource, I’ll name my perimeter terraform because I manage it using Terraform and I will set up a profile for protecting my Terraform state backend:
resource "azurerm_network_security_perimeter" "default" {
name = "terraform"
resource_group_name = azurerm_resource_group.default.name
location = azurerm_resource_group.default.location
}I create a single profile within my perimeter:
resource "azurerm_network_security_perimeter_profile" "default" {
name = "default"
network_security_perimeter_id = azurerm_network_security_perimeter.default.id
}I add one rule to my profile:
resource "azurerm_network_security_perimeter_access_rule" "me" {
name = "me"
direction = "Inbound"
network_security_perimeter_profile_id = azurerm_network_security_perimeter_profile.default.id
address_prefixes = [
"1.2.3.4/32",
]
}In the rule I specify my own static IP address. Obviously I have replaced it with a dummy address in the above code sample. In a production scenario you would likely specify e.g. the addresses of your GitHub runners or similar infrastructure.
Rules can be Inbound or Outbound.
For inbound rules you can specify one or more IP CIDR ranges (like in the example above) that should be allowed to reach the platform service protected by this perimeter. You can also configure service tags and Azure subscription IDs.
For outbound rules you can specify a list of Fully Qualified Domain Names (FQDNs). My Azure storage account will not make any outbound connections, so I will not include any outbound rules.
Finally, I associate the profile with my Azure storage account:
resource "azurerm_network_security_perimeter_association" "storage" {
name = "storage"
resource_id = azurerm_storage_account.state.id
access_mode = "Enforced"
network_security_perimeter_profile_id = azurerm_network_security_perimeter_profile.default.id
}The access mode of the association can be one of:
- Enforced: this mode enforces the rules you add to the perimeter.
- Learning (also referred to as Transition in the documentation): this mode falls back to other network security settings for the storage account if the network security perimeter does not allow a connection. Use this mode during a learning period where you see if the perimeter works as intended, while at the same time not break any existing workflows.
There is also an Audit mode in the provider documentation, but for me this mode does not work and there is no mention of it in the official documentation.
If you apply a network security perimeter to a resource that you manage using Terraform you could lock yourself out of the resource unless the rules you add allow you to connect to it.
You will notice if this is the case when you run a Terraform operation and you get the following error message: This request is not authorized by network security perimeter to perform this operation.
You can still manage the resource from the Azure portal though, so all is not lost!
Use-cases for Terraform#
An immediate use-case of a network security perimeter in a Terraform context is to secure your Azure storage backend for Terraform state storage.
You can achieve the same goals using a traditional approach of setting up a virtual network and using private link. However, for a small-scale Terraform footprint this might be more than what you want. In this case the network security perimeter is a great option.
A different use-case for Terraform is to protect an Azure Key Vault where you store sensitive data that Terraform needs to access during plan and apply operations.
Discussion and key takeaways#
A network security perimeter is a fast way to secure platform-as-a-service services on Azure (seriously, how do you say “PaaS” in a sentence like this without adding another “services” afterwards?) without the need of a full virtual network infrastructure.
Is it a “good enough” replacement for a full virtual network infrastructure? You will have to make this judgement in your context. The combination of Entra ID authentication and a network security perimeter should be sufficient in many situations, but your situation might require additional protection mechanisms.
It is easy to set up with Terraform using the resources introduced in version 4.58.0 of the Azure provider.
Watch out you don’t accidentally lock yourself, or your CI/CD systems, out of your platform services. Use the learning/transition mode while implementing the new security perimeter, and switch to enforce mode when you are sure it works.
A great use-case for Terraform is to secure your Azure storage backend for Terraform state.




