Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ stages:
parameters:
removeDeployment: '${{ parameters.removeDeployment }}'
deploymentBlocks:
- path: $(modulePath)/.parameters/min.parameters.json
- path: $(modulePath)/.parameters/parameters.json

- stage: Publishing
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ms.network.networksecuritygroups.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ jobs:
strategy:
fail-fast: false
matrix:
parameterFilePaths: ['parameters.json']
parameterFilePaths: ['min.parameters.json', 'parameters.json']
steps:
- name: 'Checkout'
uses: actions/checkout@v2
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"name": {
"value": "<<namePrefix>>-az-nsg-min-001"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"name": {
"value": "<<namePrefix>>-az-nsg-x-001"
},
"networkSecurityGroupSecurityRules": {
"securityRules": {
"value": [
{
"name": "Specific",
Expand Down Expand Up @@ -57,11 +57,15 @@
"access": "Allow",
"priority": 102,
"direction": "Inbound",
"sourceApplicationSecurityGroupIds": [
"/subscriptions/<<subscriptionId>>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<<namePrefix>>-az-asg-x-001"
"sourceApplicationSecurityGroups": [
{
"id": "/subscriptions/<<subscriptionId>>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<<namePrefix>>-az-asg-x-001"
}
],
"destinationApplicationSecurityGroupIds": [
"/subscriptions/<<subscriptionId>>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<<namePrefix>>-az-asg-x-001"
"destinationApplicationSecurityGroups": [
{
"id": "/subscriptions/<<subscriptionId>>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<<namePrefix>>-az-asg-x-001"
}
]
}
}
Expand Down
59 changes: 41 additions & 18 deletions arm/Microsoft.Network/networkSecurityGroups/deploy.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ param name string
param location string = resourceGroup().location

@description('Optional. Array of Security Rules to deploy to the Network Security Group. When not provided, an NSG including only the built-in roles will be deployed.')
param networkSecurityGroupSecurityRules array = []
param securityRules array = []

@description('Optional. Resource ID of the diagnostic storage account.')
param diagnosticStorageAccountId string = ''
Expand Down Expand Up @@ -70,29 +70,52 @@ resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-05-0
location: location
tags: tags
properties: {
securityRules: [for nsgSecurityRule in networkSecurityGroupSecurityRules: {
name: nsgSecurityRule.name
securityRules: [for securityRule in securityRules: {
name: securityRule.name
properties: {
description: contains(nsgSecurityRule.properties, 'description') ? nsgSecurityRule.properties.description : ''
protocol: nsgSecurityRule.properties.protocol
sourcePortRange: contains(nsgSecurityRule.properties, 'sourcePortRange') ? nsgSecurityRule.properties.sourcePortRange : ''
destinationPortRange: contains(nsgSecurityRule.properties, 'destinationPortRange') ? nsgSecurityRule.properties.destinationPortRange : ''
sourceAddressPrefix: contains(nsgSecurityRule.properties, 'sourceAddressPrefix') ? nsgSecurityRule.properties.sourceAddressPrefix : ''
destinationAddressPrefix: contains(nsgSecurityRule.properties, 'destinationAddressPrefix') ? nsgSecurityRule.properties.destinationAddressPrefix : ''
access: nsgSecurityRule.properties.access
priority: int(nsgSecurityRule.properties.priority)
direction: nsgSecurityRule.properties.direction
sourcePortRanges: contains(nsgSecurityRule.properties, 'sourcePortRanges') ? nsgSecurityRule.properties.sourcePortRanges : null
destinationPortRanges: contains(nsgSecurityRule.properties, 'destinationPortRanges') ? nsgSecurityRule.properties.destinationPortRanges : null
sourceAddressPrefixes: contains(nsgSecurityRule.properties, 'sourceAddressPrefixes') ? nsgSecurityRule.properties.sourceAddressPrefixes : null
destinationAddressPrefixes: contains(nsgSecurityRule.properties, 'destinationAddressPrefixes') ? nsgSecurityRule.properties.destinationAddressPrefixes : null
sourceApplicationSecurityGroups: (contains(nsgSecurityRule.properties, 'sourceApplicationSecurityGroupIds') && (!empty(nsgSecurityRule.properties.sourceApplicationSecurityGroupIds))) ? concat([], array(json('{"id": "${nsgSecurityRule.properties.sourceApplicationSecurityGroupIds[0]}", "location": "${location}"}'))) : null
destinationApplicationSecurityGroups: (contains(nsgSecurityRule.properties, 'destinationApplicationSecurityGroupIds') && (!empty(nsgSecurityRule.properties.destinationApplicationSecurityGroupIds))) ? concat([], array(json('{"id": "${nsgSecurityRule.properties.destinationApplicationSecurityGroupIds[0]}", "location": "${location}"}'))) : null
protocol: securityRule.properties.protocol
access: securityRule.properties.access
priority: securityRule.properties.priority
direction: securityRule.properties.direction
description: contains(securityRule.properties, 'description') ? securityRule.properties.description : ''
sourcePortRange: contains(securityRule.properties, 'sourcePortRange') ? securityRule.properties.sourcePortRange : ''
sourcePortRanges: contains(securityRule.properties, 'sourcePortRanges') ? securityRule.properties.sourcePortRanges : []
destinationPortRange: contains(securityRule.properties, 'destinationPortRange') ? securityRule.properties.destinationPortRange : ''
destinationPortRanges: contains(securityRule.properties, 'destinationPortRanges') ? securityRule.properties.destinationPortRanges : []
sourceAddressPrefix: contains(securityRule.properties, 'sourceAddressPrefix') ? securityRule.properties.sourceAddressPrefix : ''
destinationAddressPrefix: contains(securityRule.properties, 'destinationAddressPrefix') ? securityRule.properties.destinationAddressPrefix : ''
sourceAddressPrefixes: contains(securityRule.properties, 'sourceAddressPrefixes') ? securityRule.properties.sourceAddressPrefixes : []
destinationAddressPrefixes: contains(securityRule.properties, 'destinationAddressPrefixes') ? securityRule.properties.destinationAddressPrefixes : []
sourceApplicationSecurityGroups: contains(securityRule.properties, 'sourceApplicationSecurityGroups') ? securityRule.properties.sourceApplicationSecurityGroups : []
destinationApplicationSecurityGroups: contains(securityRule.properties, 'destinationApplicationSecurityGroups') ? securityRule.properties.destinationApplicationSecurityGroups : []
}
}]
}
}

module networkSecurityGroup_securityRules 'securityRules/deploy.bicep' = [for (securityRule, index) in securityRules: {
name: '${uniqueString(deployment().name, location)}-securityRule-${index}'
params: {
name: securityRule.name
networkSecurityGroupName: networkSecurityGroup.name
protocol: securityRule.properties.protocol
access: securityRule.properties.access
priority: securityRule.properties.priority
direction: securityRule.properties.direction
description: contains(securityRule.properties, 'description') ? securityRule.properties.description : ''
sourcePortRange: contains(securityRule.properties, 'sourcePortRange') ? securityRule.properties.sourcePortRange : ''
sourcePortRanges: contains(securityRule.properties, 'sourcePortRanges') ? securityRule.properties.sourcePortRanges : []
destinationPortRange: contains(securityRule.properties, 'destinationPortRange') ? securityRule.properties.destinationPortRange : ''
destinationPortRanges: contains(securityRule.properties, 'destinationPortRanges') ? securityRule.properties.destinationPortRanges : []
sourceAddressPrefix: contains(securityRule.properties, 'sourceAddressPrefix') ? securityRule.properties.sourceAddressPrefix : ''
destinationAddressPrefix: contains(securityRule.properties, 'destinationAddressPrefix') ? securityRule.properties.destinationAddressPrefix : ''
sourceAddressPrefixes: contains(securityRule.properties, 'sourceAddressPrefixes') ? securityRule.properties.sourceAddressPrefixes : []
destinationAddressPrefixes: contains(securityRule.properties, 'destinationAddressPrefixes') ? securityRule.properties.destinationAddressPrefixes : []
sourceApplicationSecurityGroups: contains(securityRule.properties, 'sourceApplicationSecurityGroups') ? securityRule.properties.sourceApplicationSecurityGroups : []
destinationApplicationSecurityGroups: contains(securityRule.properties, 'destinationApplicationSecurityGroups') ? securityRule.properties.destinationApplicationSecurityGroups : []
}
}]

resource networkSecurityGroup_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') {
name: '${networkSecurityGroup.name}-${lock}-lock'
properties: {
Expand Down
84 changes: 3 additions & 81 deletions arm/Microsoft.Network/networkSecurityGroups/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This template deploys a network security group (NSG) with optional security rule
| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview |
| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview |
| `Microsoft.Network/networkSecurityGroups` | 2021-05-01 |
| `Microsoft.Network/networkSecurityGroups/securityRules` | 2021-05-01 |

## Parameters

Expand All @@ -25,90 +26,10 @@ This template deploys a network security group (NSG) with optional security rule
| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. |
| `logsToEnable` | array | `[NetworkSecurityGroupEvent, NetworkSecurityGroupRuleCounter]` | `[NetworkSecurityGroupEvent, NetworkSecurityGroupRuleCounter]` | Optional. The name of logs that will be streamed. |
| `name` | string | | | Required. Name of the Network Security Group. |
| `networkSecurityGroupSecurityRules` | array | `[]` | | Optional. Array of Security Rules to deploy to the Network Security Group. When not provided, an NSG including only the built-in roles will be deployed. |
| `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' |
| `securityRules` | _[securityRules](securityRules/readme.md)_ array | `[]` | | Optional. Array of Security Rules to deploy to the Network Security Group. When not provided, an NSG including only the built-in roles will be deployed. |
| `tags` | object | `{object}` | | Optional. Tags of the NSG resource. |

### Parameter Usage: `networkSecurityGroupSecurityRules`

The `networkSecurityGroupSecurityRules` parameter accepts a JSON Array of `securityRule` to deploy to the Network Security Group (NSG).

Note that in case of using ASGs (Application Security Groups) - `sourceApplicationSecurityGroupIds` and `destinationApplicationSecurityGroupIds` properties - both the NSG and the ASG(s) have to be in the same Azure region. Currently an NSG can only handle one source and one destination ASG.
Here's an example of specifying a couple security rules:

```json
"networkSecurityGroupSecurityRules": {
"value": [
{
"name": "Port_8080",
"properties": {
"description": "Allow inbound access on TCP 8080",
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "8080",
"sourceAddressPrefix": "*",
"destinationAddressPrefix": "*",
"access": "Allow",
"priority": 100,
"direction": "Inbound",
"sourcePortRanges": [],
"destinationPortRanges": [],
"sourceAddressPrefixes": [],
"destinationAddressPrefixes": [],
"sourceApplicationSecurityGroupIds": [],
"destinationApplicationSecurityGroupIds": []
}
},
{
"name": "Port_8081",
"properties": {
"description": "Allow inbound access on TCP 8081",
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "8081",
"sourceAddressPrefix": "*",
"destinationAddressPrefix": "*",
"access": "Allow",
"priority": 101,
"direction": "Inbound",
"sourcePortRanges": [],
"destinationPortRanges": [],
"sourceAddressPrefixes": [],
"destinationAddressPrefixes": [],
"sourceApplicationSecurityGroupIds": [],
"destinationApplicationSecurityGroupIds": []
}
},
{
"name": "Port_8082",
"properties": {
"description": "Allow inbound access on TCP 8082",
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "8082",
"sourceAddressPrefix": "",
"destinationAddressPrefix": "",
"access": "Allow",
"priority": 102,
"direction": "Inbound",
"sourcePortRanges": [],
"destinationPortRanges": [],
"sourceAddressPrefixes": [],
"destinationAddressPrefixes": [],
//sourceApplicationSecurityGroupIds currently only supports 1 ID !
"sourceApplicationSecurityGroupIds": [
"/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/<rgName>/providers/Microsoft.Network/applicationSecurityGroups/<Application Security Group Name 2>"
],
//destinationApplicationSecurityGroupIds currently only supports 1 ID !
"destinationApplicationSecurityGroupIds": [
"/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/<rgName>/providers/Microsoft.Network/applicationSecurityGroups/<Application Security Group Name 1>"
]
}
}
]
}
```

### Parameter Usage: `roleAssignments`

```json
Expand Down Expand Up @@ -161,4 +82,5 @@ Tag names and tag values can be provided as needed. A tag can be left without a
- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings)
- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks)
- [Networksecuritygroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkSecurityGroups)
- [Networksecuritygroups/Securityrules](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkSecurityGroups/securityRules)
- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
@sys.description('Required. The name of the security rule')
param name string

@sys.description('Required. The name of the network security group to deploy the security rule into')
param networkSecurityGroupName string

@sys.description('Optional. Whether network traffic is allowed or denied.')
@allowed([
'Allow'
'Deny'
])
param access string = 'Deny'

@sys.description('Optional. A description for this rule')
@maxLength(140)
param description string = ''

@sys.description('Optional. The destination address prefix. CIDR or destination IP range. Asterisk "*" can also be used to match all source IPs. Default tags such as "VirtualNetwork", "AzureLoadBalancer" and "Internet" can also be used.')
param destinationAddressPrefix string = ''

@sys.description('Optional. The destination address prefixes. CIDR or destination IP ranges.')
param destinationAddressPrefixes array = []

@sys.description('Optional. The application security group specified as destination.')
param destinationApplicationSecurityGroups array = []

@sys.description('Optional. The destination port or range. Integer or range between 0 and 65535. Asterisk "*" can also be used to match all ports.')
param destinationPortRange string = ''

@sys.description('Optional. The destination port ranges.')
param destinationPortRanges array = []

@sys.description('Required. The direction of the rule. The direction specifies if rule will be evaluated on incoming or outgoing traffic.')
@allowed([
'Inbound'
'Outbound'
])
param direction string

@sys.description('Required. The priority of the rule. The value can be between 100 and 4096. The priority number must be unique for each rule in the collection. The lower the priority number, the higher the priority of the rule.')
param priority int

@sys.description('Required. Network protocol this rule applies to.')
@allowed([
'*'
'Ah'
'Esp'
'Icmp'
'Tcp'
'Udp'
])
param protocol string

@sys.description('Optional. The CIDR or source IP range. Asterisk "*" can also be used to match all source IPs. Default tags such as "VirtualNetwork", "AzureLoadBalancer" and "Internet" can also be used. If this is an ingress rule, specifies where network traffic originates from.')
param sourceAddressPrefix string = ''

@sys.description('Optional. The CIDR or source IP ranges.')
param sourceAddressPrefixes array = []

@sys.description('Optional. The application security group specified as source.')
param sourceApplicationSecurityGroups array = []

@sys.description('Optional. The source port or range. Integer or range between 0 and 65535. Asterisk "*" can also be used to match all ports.')
param sourcePortRange string = ''

@sys.description('Optional. The source port ranges.')
param sourcePortRanges array = []

@sys.description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered')
param cuaId string = ''

module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) {
name: 'pid-${cuaId}'
params: {}
}

resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-05-01' existing = {
name: networkSecurityGroupName
}

resource securityRule 'Microsoft.Network/networkSecurityGroups/securityRules@2021-05-01' = {
name: name
parent: networkSecurityGroup
properties: {
access: access
description: description
destinationAddressPrefix: destinationAddressPrefix
destinationAddressPrefixes: destinationAddressPrefixes
destinationApplicationSecurityGroups: destinationApplicationSecurityGroups
destinationPortRange: destinationPortRange
destinationPortRanges: destinationPortRanges
direction: direction
priority: priority
protocol: protocol
sourceAddressPrefix: sourceAddressPrefix
sourceAddressPrefixes: sourceAddressPrefixes
sourceApplicationSecurityGroups: sourceApplicationSecurityGroups
sourcePortRange: sourcePortRange
sourcePortRanges: sourcePortRanges
}
}

@sys.description('The resource group the security rule was deployed into')
output resourceGroupName string = resourceGroup().name

@sys.description('The resource ID of the security rule')
output resourceId string = securityRule.id

@sys.description('The name of the security rule')
output name string = securityRule.name
Loading