GitHub – Azure/terraform-azurerm-network-security-group: Terraform module to create a network security group and assign it to the specified subnet

Notice on Upgrade to V4.x

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.

Terraform and terraform-provider-azurerm version restrictions

Now Terraform core’s version is v1.x and terraform-provider-azurerm’s version is v3.x.

Example Usage

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.

Create a network security group

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.

Usage with the generic module in Terraform 0.13

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

] }

Usage with for_each iteration instead of count

~> 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

"

} }

Usage with the generic module in Terraform 0.12

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

"

} }

Usage with the Application Security Group module in Terraform 0.12

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

"

} }

Usage with the pre-defined module in Terraform 0.12

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

"

} }

Pre-Commit & Pr-Check & Test

Configurations

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:

  1. Run terraform fmt -recursive command for your Terraform code.
  2. 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.
  3. Run go mod tidy and go mod vendor for test folder to ensure that all the dependencies have been synced.
  4. Run gofmt for all go code files.
  5. Run gofumpt for all go code files.
  6. Run terraform-docs on README.md file, then run markdown-table-formatter to format markdown tables in README.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

Prerequisites

Authors

Originally created by Damien Caro and Richard Guthrie.

Contributing

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.

License

MIT

Requirements

Providers

Name
Version

azurerm
>=3.11.0, < 4.0

Modules

No modules.

Resources

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

Inputs

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)

{
"ActiveDirectory-AllowADDSWebServices": [
"Inbound",
"Allow",
"Tcp",
"",
"9389",
"AllowADDSWebServices"
],
"ActiveDirectory-AllowADGCReplication": [
"Inbound",
"Allow",
"Tcp",
"",
"3268",
"AllowADGCReplication"
],
"ActiveDirectory-AllowADGCReplicationSSL": [
"Inbound",
"Allow",
"Tcp",
"",
"3269",
"AllowADGCReplicationSSL"
],
"ActiveDirectory-AllowADReplication": [
"Inbound",
"Allow",
"",
"",
"389",
"AllowADReplication"
],
"ActiveDirectory-AllowADReplicationSSL": [
"Inbound",
"Allow",
"",
"",
"636",
"AllowADReplicationSSL"
],
"ActiveDirectory-AllowADReplicationTrust": [
"Inbound",
"Allow",
"",
"",
"445",
"AllowADReplicationTrust"
],
"ActiveDirectory-AllowDFSGroupPolicy": [
"Inbound",
"Allow",
"Udp",
"",
"138",
"AllowDFSGroupPolicy"
],
"ActiveDirectory-AllowDNS": [
"Inbound",
"Allow",
"",
"",
"53",
"AllowDNS"
],
"ActiveDirectory-AllowFileReplication": [
"Inbound",
"Allow",
"Tcp",
"",
"5722",
"AllowFileReplication"
],
"ActiveDirectory-AllowKerberosAuthentication": [
"Inbound",
"Allow",
"",
"",
"88",
"AllowKerberosAuthentication"
],
"ActiveDirectory-AllowNETBIOSAuthentication": [
"Inbound",
"Allow",
"Udp",
"",
"137",
"AllowNETBIOSAuthentication"
],
"ActiveDirectory-AllowNETBIOSReplication": [
"Inbound",
"Allow",
"Tcp",
"",
"139",
"AllowNETBIOSReplication"
],
"ActiveDirectory-AllowPasswordChangeKerberes": [
"Inbound",
"Allow",
"",
"",
"464",
"AllowPasswordChangeKerberes"
],
"ActiveDirectory-AllowRPCReplication": [
"Inbound",
"Allow",
"Tcp",
"",
"135",
"AllowRPCReplication"
],
"ActiveDirectory-AllowSMTPReplication": [
"Inbound",
"Allow",
"Tcp",
"",
"25",
"AllowSMTPReplication"
],
"ActiveDirectory-AllowWindowsTime": [
"Inbound",
"Allow",
"Udp",
"",
"123",
"AllowWindowsTime"
],
"Cassandra": [
"Inbound",
"Allow",
"Tcp",
"",
"9042",
"Cassandra"
],
"Cassandra-JMX": [
"Inbound",
"Allow",
"Tcp",
"",
"7199",
"Cassandra-JMX"
],
"Cassandra-Thrift": [
"Inbound",
"Allow",
"Tcp",
"",
"9160",
"Cassandra-Thrift"
],
"CouchDB": [
"Inbound",
"Allow",
"Tcp",
"",
"5984",
"CouchDB"
],
"CouchDB-HTTPS": [
"Inbound",
"Allow",
"Tcp",
"",
"6984",
"CouchDB-HTTPS"
],
"DNS-TCP": [
"Inbound",
"Allow",
"Tcp",
"",
"53",
"DNS-TCP"
],
"DNS-UDP": [
"Inbound",
"Allow",
"Udp",
"",
"53",
"DNS-UDP"
],
"DynamicPorts": [
"Inbound",
"Allow",
"Tcp",
"",
"49152-65535",
"DynamicPorts"
],
"ElasticSearch": [
"Inbound",
"Allow",
"Tcp",
"",
"9200-9300",
"ElasticSearch"
],
"FTP": [
"Inbound",
"Allow",
"Tcp",
"",
"21",
"FTP"
],
"HTTP": [
"Inbound",
"Allow",
"Tcp",
"",
"80",
"HTTP"
],
"HTTPS": [
"Inbound",
"Allow",
"Tcp",
"",
"443",
"HTTPS"
],
"IMAP": [
"Inbound",
"Allow",
"Tcp",
"",
"143",
"IMAP"
],
"IMAPS": [
"Inbound",
"Allow",
"Tcp",
"",
"993",
"IMAPS"
],
"Kestrel": [
"Inbound",
"Allow",
"Tcp",
"",
"22133",
"Kestrel"
],
"LDAP": [
"Inbound",
"Allow",
"Tcp",
"",
"389",
"LDAP"
],
"MSSQL": [
"Inbound",
"Allow",
"Tcp",
"",
"1433",
"MSSQL"
],
"Memcached": [
"Inbound",
"Allow",
"Tcp",
"",
"11211",
"Memcached"
],
"MongoDB": [
"Inbound",
"Allow",
"Tcp",
"",
"27017",
"MongoDB"
],
"MySQL": [
"Inbound",
"Allow",
"Tcp",
"",
"3306",
"MySQL"
],
"Neo4J": [
"Inbound",
"Allow",
"Tcp",
"",
"7474",
"Neo4J"
],
"POP3": [
"Inbound",
"Allow",
"Tcp",
"",
"110",
"POP3"
],
"POP3S": [
"Inbound",
"Allow",
"Tcp",
"",
"995",
"POP3S"
],
"PostgreSQL": [
"Inbound",
"Allow",
"Tcp",
"",
"5432",
"PostgreSQL"
],
"RDP": [
"Inbound",
"Allow",
"Tcp",
"",
"3389",
"RDP"
],
"RabbitMQ": [
"Inbound",
"Allow",
"Tcp",
"",
"5672",
"RabbitMQ"
],
"Redis": [
"Inbound",
"Allow",
"Tcp",
"",
"6379",
"Redis"
],
"Riak": [
"Inbound",
"Allow",
"Tcp",
"",
"8093",
"Riak"
],
"Riak-JMX": [
"Inbound",
"Allow",
"Tcp",
"",
"8985",
"Riak-JMX"
],
"SMTP": [
"Inbound",
"Allow",
"Tcp",
"",
"25",
"SMTP"
],
"SMTPS": [
"Inbound",
"Allow",
"Tcp",
"",
"465",
"SMTPS"
],
"SSH": [
"Inbound",
"Allow",
"Tcp",
"",
"22",
"SSH"
],
"WinRM": [
"Inbound",
"Allow",
"Tcp",
"*",
"5986",
"WinRM"
]
}

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

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

Outputs

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