# Network Security Group

Source: /azure/services/network-security-group/

## Introduction

An Azure network security group (NSG) filters network traffic to and from Azure resources in a virtual network.
It holds a prioritized list of security rules that allow or deny inbound and outbound traffic by source, destination, port and protocol, and it is associated with subnets or network interfaces.
For more information, see [Network security groups](https://learn.microsoft.com/en-us/azure/virtual-network/network-security-groups-overview).

LocalStack for Azure provides a local environment for building and testing applications that make use of network security groups.
The supported APIs are available on our [API Coverage section](#api-coverage), which provides information on the extent of Network Security Group's integration with LocalStack.

## Getting started

This guide is designed for users new to network security groups and assumes basic knowledge of the Azure CLI and our `lstk az` proxy.

Launch LocalStack using your preferred method. For more information, see [Introduction to LocalStack for Azure](/azure/getting-started/). Once the container is running, enable Azure CLI interception by running:

```bash
lstk az start-interception
```

This command points the `az` CLI away from the public Azure management REST API and toward the LocalStack for Azure emulator API.
To revert this configuration, run:

```bash
lstk az stop-interception
```

This reconfigures the `az` CLI to send commands to the official Azure management REST API.

### Create a resource group

Create a resource group to hold all resources created in this guide:

```bash
az group create \
  --name rg-nsg-demo \
  --location westeurope
```

```bash title="Output"
{
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-nsg-demo",
  "location": "westeurope",
  "managedBy": null,
  "name": "rg-nsg-demo",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null,
  "type": "Microsoft.Resources/resourceGroups"
}
```

### Create a network security group

Create a network security group:

```bash
az network nsg create \
  --name nsg-demo \
  --resource-group rg-nsg-demo \
  --location westeurope
```

The response contains the six default security rules that Azure adds to every network security group, followed by the group's own (still empty) list of security rules:

```bash title="Output"
{
  "NewNSG": {
    "defaultSecurityRules": [
      {
        "access": "Allow",
        "description": "Allow inbound traffic from all VMs in VNET",
        "destinationAddressPrefix": "VirtualNetwork",
        "destinationPortRange": "*",
        "direction": "Inbound",
        "name": "AllowVnetInBound",
        "priority": 65000,
        "protocol": "*",
        "sourceAddressPrefix": "VirtualNetwork",
        "sourcePortRange": "*",
        "type": "Microsoft.Network/networkSecurityGroups/defaultSecurityRules"
        ...
      },
      ...
    ],
    "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-nsg-demo/providers/Microsoft.Network/networkSecurityGroups/nsg-demo",
    "location": "westeurope",
    "name": "nsg-demo",
    "provisioningState": "Succeeded",
    "resourceGroup": "rg-nsg-demo",
    "securityRules": [],
    "type": "Microsoft.Network/networkSecurityGroups"
  }
}
```

### Add security rules

Allow inbound HTTPS traffic from the internet:

```bash
az network nsg rule create \
  --nsg-name nsg-demo \
  --resource-group rg-nsg-demo \
  --name allow-https \
  --priority 100 \
  --direction Inbound \
  --access Allow \
  --protocol Tcp \
  --source-address-prefixes Internet \
  --source-port-ranges '*' \
  --destination-address-prefixes '*' \
  --destination-port-ranges 443
```

```bash title="Output"
{
  "access": "Allow",
  "destinationAddressPrefix": "*",
  "destinationAddressPrefixes": [],
  "destinationPortRange": "443",
  "destinationPortRanges": [],
  "direction": "Inbound",
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-nsg-demo/providers/Microsoft.Network/networkSecurityGroups/nsg-demo/securityRules/allow-https",
  "name": "allow-https",
  "priority": 100,
  "protocol": "Tcp",
  "provisioningState": "Succeeded",
  "resourceGroup": "rg-nsg-demo",
  "sourceAddressPrefix": "Internet",
  "sourceAddressPrefixes": [],
  "sourcePortRange": "*",
  "sourcePortRanges": [],
  "type": "Microsoft.Network/networkSecurityGroups/securityRules"
}
```

Then deny inbound SSH traffic:

```bash
az network nsg rule create \
  --nsg-name nsg-demo \
  --resource-group rg-nsg-demo \
  --name deny-ssh \
  --priority 200 \
  --direction Inbound \
  --access Deny \
  --protocol Tcp \
  --source-address-prefixes '*' \
  --source-port-ranges '*' \
  --destination-address-prefixes '*' \
  --destination-port-ranges 22
```

### List the rules

List the custom rules, followed by the default rules:

```bash
az network nsg rule list \
  --nsg-name nsg-demo \
  --resource-group rg-nsg-demo \
  --include-default \
  --output table
```

```bash title="Output"
Name                           ResourceGroup    Priority    SourcePortRanges    SourceAddressPrefixes    SourceASG    Access    Protocol    Direction    DestinationPortRanges    DestinationAddressPrefixes    DestinationASG
-----------------------------  ---------------  ----------  ------------------  -----------------------  -----------  --------  ----------  -----------  -----------------------  ----------------------------  ----------------
allow-https                    rg-nsg-demo      100         *                   Internet                 None         Allow     Tcp         Inbound      443                      *                             None
deny-ssh                       rg-nsg-demo      200         *                   *                        None         Deny      Tcp         Inbound      22                       *                             None
AllowVnetInBound               rg-nsg-demo      65000       *                   VirtualNetwork           None         Allow     *           Inbound      *                        VirtualNetwork                None
AllowAzureLoadBalancerInBound  rg-nsg-demo      65001       *                   AzureLoadBalancer        None         Allow     *           Inbound      *                        *                             None
DenyAllInBound                 rg-nsg-demo      65500       *                   *                        None         Deny      *           Inbound      *                        *                             None
AllowVnetOutBound              rg-nsg-demo      65000       *                   VirtualNetwork           None         Allow     *           Outbound     *                        VirtualNetwork                None
AllowInternetOutBound          rg-nsg-demo      65001       *                   *                        None         Allow     *           Outbound     *                        Internet                      None
DenyAllOutBound                rg-nsg-demo      65500       *                   *                        None         Deny      *           Outbound     *                        *                             None
```

### Update a rule

Change the priority of the `deny-ssh` rule:

```bash
az network nsg rule update \
  --nsg-name nsg-demo \
  --resource-group rg-nsg-demo \
  --name deny-ssh \
  --priority 150
```

```bash title="Output"
{
  "access": "Deny",
  "destinationPortRange": "22",
  "direction": "Inbound",
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-nsg-demo/providers/Microsoft.Network/networkSecurityGroups/nsg-demo/securityRules/deny-ssh",
  "name": "deny-ssh",
  "priority": 150,
  "protocol": "Tcp",
  "provisioningState": "Succeeded",
  "type": "Microsoft.Network/networkSecurityGroups/securityRules"
  ...
}
```

### Associate the group with a subnet

Create a virtual network with a subnet, then associate the network security group with the subnet:

```bash
az network vnet create \
  --name vnet-nsg-demo \
  --resource-group rg-nsg-demo \
  --location westeurope \
  --address-prefixes 10.0.0.0/16 \
  --subnet-name subnet-app \
  --subnet-prefixes 10.0.1.0/24

az network vnet subnet update \
  --vnet-name vnet-nsg-demo \
  --resource-group rg-nsg-demo \
  --name subnet-app \
  --network-security-group nsg-demo
```

```bash title="Output"
{
  "addressPrefix": "10.0.1.0/24",
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-nsg-demo/providers/Microsoft.Network/virtualNetworks/vnet-nsg-demo/subnets/subnet-app",
  "name": "subnet-app",
  "networkSecurityGroup": {
    "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-nsg-demo/providers/Microsoft.Network/networkSecurityGroups/nsg-demo",
    "resourceGroup": "rg-nsg-demo"
  },
  "provisioningState": "Succeeded",
  "type": "Microsoft.Network/virtualNetworks/subnets"
  ...
}
```

### Delete the rule and the group

Remove the association from the subnet, then delete a rule and the network security group:

```bash
az network vnet subnet update \
  --vnet-name vnet-nsg-demo \
  --resource-group rg-nsg-demo \
  --name subnet-app \
  --network-security-group null

az network nsg rule delete \
  --nsg-name nsg-demo \
  --resource-group rg-nsg-demo \
  --name deny-ssh

az network nsg delete \
  --name nsg-demo \
  --resource-group rg-nsg-demo
```

Then list the network security groups in the resource group to confirm the group was removed:

```bash
az network nsg list \
  --resource-group rg-nsg-demo
```

```bash title="Output"
[]
```

## Features

The Network Security Group emulator supports the following features:

- **Create and manage network security groups**: Full lifecycle management including create, get, update tags, list, and delete.
- **Security rules**: Create, get, update, list, and delete security rules for inbound and outbound traffic.
- **Default security rules**: Every network security group returns the six default rules Azure creates (`AllowVnetInBound`, `AllowAzureLoadBalancerInBound`, `DenyAllInBound`, `AllowVnetOutBound`, `AllowInternetOutBound` and `DenyAllOutBound`).
- **Subnet and network interface associations**: Subnets and network interfaces store and return a reference to their network security group.
- **Subscription-scoped listing**: List all network security groups across a subscription using `az network nsg list`.

## Limitations

- **No traffic filtering**: Security rules are stored and returned, but no traffic in the emulator is evaluated against them, including traffic to and from AKS clusters and container workloads.
- **No priority validation**: Rule priorities are not checked for range or uniqueness, so two rules with the same priority and direction are accepted.
- **Associations are not reflected on the group**: A subnet or network interface shows its network security group, but the group does not return `subnets` or `networkInterfaces` properties.
- **No default rule lookups**: The default rules are part of the group's response, but they cannot be retrieved one by one through the `defaultSecurityRules` API.
- **Application security groups**: Application security groups (`Microsoft.Network/applicationSecurityGroups`) are not emulated, and security rules do not keep references to them.

## API Coverage


### Network Security Group API coverage

Source service: `network-security-group`. 10 of 12 tracked operations are implemented.

Service documentation: /azure/services/network-security-group/

| Operation | Status |
| --- | --- |
| DefaultSecurityRules.Get | Not implemented |
| DefaultSecurityRules.List | Not implemented |
| NetworkSecurityGroups.CreateOrUpdate | Implemented |
| NetworkSecurityGroups.Delete | Implemented |
| NetworkSecurityGroups.Get | Implemented |
| NetworkSecurityGroups.List | Implemented |
| NetworkSecurityGroups.ListAll | Implemented |
| NetworkSecurityGroups.UpdateTags | Implemented |
| SecurityRules.CreateOrUpdate | Implemented |
| SecurityRules.Delete | Implemented |
| SecurityRules.Get | Implemented |
| SecurityRules.List | Implemented |
