We've added a CI pipeline for this module to speed up our code review and to enforce a high code quality standard, if you want to contribute by submitting a pull request, please read Pre-Commit & Pr-Check & Test section, or your pull request might be rejected by CI pipeline.
A pull request will be reviewed when it has passed Pre Pull Request Check in the pipeline, and will be merged when it has passed the acceptance tests. Once the CI pipeline failed, please read the pipeline's output, thanks for your cooperation.
V4.0.0 is a major version upgrade. Extreme caution must be taken during the upgrade to avoid resource replacement and downtime by accident.
Running terraform plan
first to inspect the plan is strongly advised.
Now Terraform core's version is v1.x and terraform-provider-azurerm's version is v3.x.
Please refer to the sub folders under examples
folder. You can execute terraform apply
command in examples
's sub folder to try the module. These examples are tested against every PR with the E2E Test.
This Terraform module deploys a Network Security Group (NSG) in Azure and optionally attach it to the specified vnets.
This module is a complement to the Azure Network module. Use the network_security_group_id from the output of this module to apply it to a subnet in the Azure Network module. NOTE: We are working on adding the support for applying a NSG to a network interface directly as a future enhancement.
This module includes a a set of pre-defined rules for commonly used protocols (for example HTTP or ActiveDirectory) that can be used directly in their corresponding modules or as independent rules.
The following example demonstrate how to use the network-security-group module with a combination of predefined and custom rules.
~> NOTE: source_address_prefix
is defined differently in predefined_rules
and custom_rules
.
predefined_rules
uses var.source_address_prefix
defined in the module.var.source_address_prefix
is of type list(string), but allowed only one element (CIDR, *
, source IP range or Tags). For more source_address_prefixes, please use var.source_address_prefixes
. The same for var.destination_address_prefix
in predefined_rules
.
custom_rules
uses source_address_prefix
defined in the block custom_rules
. source_address_prefix
is of type string (CIDR, *
, source IP range or Tags). For more source_address_prefixes, please use source_address_prefixes
in block custom_rules
. The same for destination_address_prefix
in custom_rules
.
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "example" {
name = "my-resources"
location = "West Europe"
}
module "network-security-group" {
source = "Azure/network-security-group/azurerm"
resource_group_name = azurerm_resource_group.example.name
location = "EastUS" # Optional; if not provided, will use Resource Group location
security_group_name = "nsg"
source_address_prefix = ["10.0.3.0/24"]
predefined_rules = [
{
name = "SSH"
priority = "500"
},
{
name = "LDAP"
source_port_range = "1024-1026"
}
]
custom_rules = [
{
name = "myssh"
priority = 201
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "10.151.0.0/24"
description = "description-myssh"
},
{
name = "myhttp"
priority = 200
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "8080"
source_address_prefixes = ["10.151.0.0/24", "10.151.1.0/24"]
description = "description-http"
},
]
tags = {
environment = "dev"
costcenter = "it"
}
depends_on = [azurerm_resource_group.example]
}
~> IMPORTANT NOTES:
var.custom_rules
-> name
is a mandatory attribute and should be unique across rules.
var.predefined_rules
-> priority
is a mandatory attribute and should be unique across rules.
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "example" {
name = "my-resources"
location = "West Europe"
}
module "network-security-group" {
source = "Azure/network-security-group/azurerm"
resource_group_name = azurerm_resource_group.example.name
location = "EastUS" # Optional; if not provided, will use Resource Group location
security_group_name = "nsg"
source_address_prefix = ["10.0.3.0/24"]
use_for_each = true
predefined_rules = [
{
name = "SSH"
priority = "500"
},
{
name = "LDAP"
source_port_range = "1024-1026"
}
]
custom_rules = [
{
name = "myssh"
priority = 201
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "10.151.0.0/24"
description = "description-myssh"
},
{
name = "myhttp"
priority = 200
direction = "Inbound"
access = "Allow"
protocol = "tcp"
source_port_range = "*"
destination_port_range = "8080"
source_address_prefixes = ["10.151.0.0/24", "10.151.1.0/24"]
description = "description-http"
},
]
tags = {
environment = "dev"
costcenter = "it"
}
}
The following example demonstrate how to use the network-security-group module with a combination of predefined and custom rules.
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "example" {
name = "my-resources"
location = "West Europe"
}
module "network-security-group" {
source = "Azure/network-security-group/azurerm"
resource_group_name = azurerm_resource_group.example.name
location = "EastUS" # Optional; if not provided, will use Resource Group location
security_group_name = "nsg"
source_address_prefix = ["10.0.3.0/24"]
predefined_rules = [
{
name = "SSH"
priority = "500"
},
{
name = "LDAP"
source_port_range = "1024-1026"
}
]
custom_rules = [
{
name = "myhttp"
priority = "200"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
destination_port_range = "8080"
description = "description-myhttp"
}
]
tags = {
environment = "dev"
costcenter = "it"
}
}
The following example demonstrate how to use the network-security-group module with a combination of predefined and custom rules with ASG source or destination.
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "example" {
name = "my-resources"
location = "West Europe"
}
resource "azurerm_application_security_group" "first" {
name = "asg-first"
location = "eastus"
resource_group_name = azurerm_resource_group.example.name
}
resource "azurerm_application_security_group" "second" {
name = "asg-second"
location = "eastus"
resource_group_name = azurerm_resource_group.example.name
}
module "network-security-group" {
source = "Azure/network-security-group/azurerm"
resource_group_name = azurerm_resource_group.example.name
location = "eastus"
security_group_name = "nsg"
predefined_rules = [
{
name = "SSH"
priority = "500"
source_application_security_group_ids = [azurerm_application_security_group.first.id]
}
]
custom_rules = [
{
name = "myhttp"
priority = "200"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
destination_port_range = "8080"
description = "description-myhttp"
destination_application_security_group_ids = [azurerm_application_security_group.second.id]
}
]
tags = {
environment = "dev"
costcenter = "it"
}
}
The following example demonstrate how to use the pre-defined HTTP module with a custom rule for ssh.
resource "azurerm_resource_group" "example" {
name = "my-resources"
location = "West Europe"
}
module "network-security-group" {
source = "Azure/network-security-group/azurerm//examples/HTTP"
resource_group_name = azurerm_resource_group.example.name
security_group_name = "nsg"
custom_rules = [
{
name = "ssh"
priority = "200"
direction = "Inbound"
access = "Allow"
protocol = "tcp"
destination_port_range = "22"
source_address_prefix = "VirtualNetwork"
description = "ssh-for-vm-management"
}
]
tags = {
environment = "dev"
costcenter = "it"
}
}
We're using BridgeCrew Yor and yorbox to help manage tags consistently across infrastructure as code (IaC) frameworks. In this module you might see tags like:
resource "azurerm_resource_group" "rg" {
location = "eastus"
name = random_pet.name
tags = merge(var.tags, (/*<box>*/ (var.tracing_tags_enabled ? { for k, v in /*</box>*/ {
avm_git_commit = "3077cc6d0b70e29b6e106b3ab98cee6740c916f6"
avm_git_file = "main.tf"
avm_git_last_modified_at = "2023-05-05 08:57:54"
avm_git_org = "lonegunmanb"
avm_git_repo = "terraform-yor-tag-test-module"
avm_yor_trace = "a0425718-c57d-401c-a7d5-f3d88b2551a4"
} /*<box>*/ : replace(k, "avm_", var.tracing_tags_prefix) => v } : {}) /*</box>*/))
}
To enable tracing tags, set the variable to true:
module "example" {
source = "{module_source}"
...
tracing_tags_enabled = true
}
The tracing_tags_enabled
is default to false
.
To customize the prefix for your tracing tags, set the tracing_tags_prefix
variable value in your Terraform configuration:
module "example" {
source = "{module_source}"
...
tracing_tags_prefix = "custom_prefix_"
}
The actual applied tags would be:
{
custom_prefix_git_commit = "3077cc6d0b70e29b6e106b3ab98cee6740c916f6"
custom_prefix_git_file = "main.tf"
custom_prefix_git_last_modified_at = "2023-05-05 08:57:54"
custom_prefix_git_org = "lonegunmanb"
custom_prefix_git_repo = "terraform-yor-tag-test-module"
custom_prefix_yor_trace = "a0425718-c57d-401c-a7d5-f3d88b2551a4"
}
We assumed that you have setup service principal's credentials in your environment variables like below:
export ARM_SUBSCRIPTION_ID="<azure_subscription_id>"
export ARM_TENANT_ID="<azure_subscription_tenant_id>"
export ARM_CLIENT_ID="<service_principal_appid>"
export ARM_CLIENT_SECRET="<service_principal_password>"
On Windows Powershell:
$env:ARM_SUBSCRIPTION_ID="<azure_subscription_id>"
$env:ARM_TENANT_ID="<azure_subscription_tenant_id>"
$env:ARM_CLIENT_ID="<service_principal_appid>"
$env:ARM_CLIENT_SECRET="<service_principal_password>"
We provide a docker image to run the pre-commit checks and tests for you: mcr.microsoft.com/azterraform:latest
To run the pre-commit task, we can run the following command:
$ docker run --rm -v $(pwd):/src -w /src mcr.microsoft.com/azterraform:latest make pre-commit
On Windows Powershell:
$ docker run --rm -v ${pwd}:/src -w /src mcr.microsoft.com/azterraform:latest make pre-commit
In pre-commit task, we will:
- Run
terraform fmt -recursive
command for your Terraform code. - Run
terrafmt fmt -f
command for markdown files and go code files to ensure that the Terraform code embedded in these files are well formatted. - Run
go mod tidy
andgo mod vendor
for test folder to ensure that all the dependencies have been synced. - Run
gofmt
for all go code files. - Run
gofumpt
for all go code files. - Run
terraform-docs
onREADME.md
file, then runmarkdown-table-formatter
to format markdown tables inREADME.md
.
Then we can run the pr-check task to check whether our code meets our pipeline's requirement (we strongly recommend you run the following command before you commit):
$ docker run --rm -v $(pwd):/src -w /src -e TFLINT_CONFIG=.tflint_alt.hcl mcr.microsoft.com/azterraform:latest make pr-check
On Windows Powershell:
$ docker run --rm -v ${pwd}:/src -w /src -e TFLINT_CONFIG=.tflint_alt.hcl mcr.microsoft.com/azterraform:latest make pr-check
To run the e2e-test, we can run the following command:
docker run --rm -v $(pwd):/src -w /src -e ARM_SUBSCRIPTION_ID -e ARM_TENANT_ID -e ARM_CLIENT_ID -e ARM_CLIENT_SECRET mcr.microsoft.com/azterraform:latest make e2e-test
On Windows Powershell:
docker run --rm -v ${pwd}:/src -w /src -e ARM_SUBSCRIPTION_ID -e ARM_TENANT_ID -e ARM_CLIENT_ID -e ARM_CLIENT_SECRET mcr.microsoft.com/azterraform:latest make e2e-test
Originally created by Damien Caro and Richard Guthrie.
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.
Name | Version |
---|---|
terraform | >=1.2 |
azurerm | >=3.11.0, < 4.0 |
Name | Version |
---|---|
azurerm | >=3.11.0, < 4.0 |
No modules.
Name | Type |
---|---|
azurerm_network_security_group.nsg | resource |
azurerm_network_security_rule.custom_rules | resource |
azurerm_network_security_rule.custom_rules_for | resource |
azurerm_network_security_rule.predefined_rules | resource |
azurerm_network_security_rule.predefined_rules_for | resource |
azurerm_resource_group.nsg | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
custom_rules | Security rules for the network security group using this format name = [name, priority, direction, access, protocol, source_port_range, destination_port_range, source_address_prefix, destination_address_prefix, description] | any |
[] |
no |
destination_address_prefix | Destination address prefix to be applied to all predefined rules. list(string) only allowed one element (CIDR, * , source IP range or Tags). Example ["10.0.3.0/24"] or ["VirtualNetwork"] |
list(string) |
[ |
no |
destination_address_prefixes | Destination address prefix to be applied to all predefined rules. Example ["10.0.3.0/32","10.0.3.128/32"] | list(string) |
null |
no |
location | Location (Azure Region) for the network security group. | string |
"" |
no |
predefined_rules | Predefined rules | any |
[] |
no |
resource_group_name | Name of the resource group | string |
n/a | yes |
rules | Standard set of predefined rules | map(any) |
{ |
no |
security_group_name | Network security group name | string |
"nsg" |
no |
source_address_prefix | Source address prefix to be applied to all predefined rules. list(string) only allowed one element (CIDR, * , source IP range or Tags). Example ["10.0.3.0/24"] or ["VirtualNetwork"] |
list(string) |
[ |
no |
source_address_prefixes | Destination address prefix to be applied to all predefined rules. Example ["10.0.3.0/32","10.0.3.128/32"] | list(string) |
null |
no |
tags | The tags to associate with your network security group. | map(string) |
{} |
no |
tracing_tags_enabled | Whether enable tracing tags that generated by BridgeCrew Yor. | bool |
false |
no |
tracing_tags_prefix | Default prefix for generated tracing tags | string |
"avm_" |
no |
use_for_each | Choose wheter to use 'for_each' as iteration technic to generate the rules, defaults to false so we will use 'count' for compatibilty with previous module versions, but prefered method is 'for_each' | bool |
false |
no |
Name | Description |
---|---|
network_security_group_id | The id of newly created network security group |
network_security_group_name | The name of newly created network security group |