NSG Bicep/ARM-mal for Azure Bastion

| 4 min lesing

Nyleg arbeidde eg med eit prosjekt der eg måtte distribuere eit nytt miljø i Azure. Dette omfatta eit Virtual Network (VNet) som ikkje skulle koplast til resten av nettverket og måtte vere isolert. Virtual Machines (VMs) som blei distribuerte her, måtte òg vere tilgjengelege via Remote Desktop Protocol og Secure Shell (SSH). Heldigvis har Microsoft ei løysing for dette i Azure Bastion. For å integrere Azure Bastion med VNet-et må du ha eit dedikert subnett kalla AzureBastionSubnet (ingen variantar av namnet blir støtta), med minst eit /26-adresserom. Eit anna krav er å ha ei Network Security Group (NSG) med rette reglar, som i praksis fungerer som ein brannmur på lag 4, slik det er dokumentert her: Working with VMs and NSGs in Azure Bastion | Microsoft Learn. Dokumentasjonen er god, men han gjev ingen kodebasert måte å distribuere dei nødvendige reglane på.

Eg har laga både Bicep- og ARM-malar som opprettar NSG-en og distribuerer dei nødvendige reglane. Implementeringa mi går endå lenger enn dei dokumenterte reglane: Alt som ikkje er spesifisert i reglar høgare oppe i prioritetslista, blir blokkert som standard med eksplisitte deny-reglar.

Bruk og del dei gjerne. Eg har òg lagt koden på GitHub her.

Bicep-mal

param networkSecurityGroupName string
param resourceLocation string

resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2022-11-01' = {
  name: networkSecurityGroupName
  location: resourceLocation
  properties: {
    flushConnection: false
    securityRules: [
      {
        name: 'AllowHttpsInbound'
        properties: {
          access: 'Allow'
          destinationAddressPrefix: '*'
          destinationPortRange: '443'
          direction: 'Inbound'
          priority: 100
          protocol: 'TCP'
          sourceAddressPrefix: 'Internet'
          sourcePortRange: '*'
        }
      }
      {
        name: 'AllowGatewayManagerInbound'
        properties: {
          access: 'Allow'
          destinationAddressPrefix: '*'
          destinationPortRange: '443'
          direction: 'Inbound'
          priority: 110
          protocol: 'TCP'
          sourceAddressPrefix: 'GatewayManager'
          sourcePortRange: '*'
        }
      }
      {
        name: 'AllowBastionHostCommunication'
        properties: {
          access: 'Allow'
          destinationAddressPrefix: 'VirtualNetwork'
          destinationPortRanges: [
            '5701'
            '8080'
          ]
          direction: 'Inbound'
          priority: 120
          protocol: '*'
          sourceAddressPrefix: 'VirtualNetwork'
          sourcePortRange: '*'
        }
      }
      {
        name: 'AllowAzureLoadBalancerInbound'
        properties: {
          access: 'Allow'
          destinationAddressPrefix: '*'
          destinationPortRange: '443'
          direction: 'Inbound'
          priority: 4095
          protocol: 'TCP'
          sourceAddressPrefix: 'AzureLoadBalancer'
          sourcePortRange: '*'
        }
      }
      {
        name: 'DenyAllInbound'
        properties: {
          access: 'Deny'
          destinationAddressPrefix: '*'
          destinationPortRange: '*'
          direction: 'Inbound'
          priority: 4096
          protocol: '*'
          sourceAddressPrefix: '*'
          sourcePortRange: '*'
        }
      }
      {
        name: 'AllowSshRDPOutbound'
        properties: {
          access: 'Allow'
          destinationAddressPrefix: 'VirtualNetwork'
          destinationPortRanges: [
            '22'
            '3389'
          ]
          direction: 'Outbound'
          priority: 100
          protocol: '*'
          sourceAddressPrefix: '*'
          sourcePortRange: '*'
        }
      }
      {
        name: 'AllowAzureCloudOutbound'
        properties: {
          access: 'Allow'
          destinationAddressPrefix: 'AzureCloud'
          destinationPortRange: '443'
          direction: 'Outbound'
          priority: 110
          protocol: 'TCP'
          sourceAddressPrefix: '*'
          sourcePortRange: '*'
        }
      }
      {
        name: 'AllowBastionCommunication'
        properties: {
          access: 'Allow'
          destinationAddressPrefix: 'VirtualNetwork'
          destinationPortRanges: [
            '5701'
            '8080'
          ]
          direction: 'Outbound'
          priority: 120
          protocol: '*'
          sourceAddressPrefix: 'VirtualNetwork'
          sourcePortRange: '*'
        }
      }
      {
        name: 'AllowHttpOutbound'
        properties: {
          access: 'Allow'
          destinationAddressPrefix: 'Internet'
          destinationPortRange: '80'
          direction: 'Outbound'
          priority: 130
          protocol: 'TCP'
          sourceAddressPrefix: '*'
          sourcePortRange: '*'
        }
      }
      {
        name: 'DenyAllOutbound'
        properties: {
          access: 'Deny'
          destinationAddressPrefix: '*'
          destinationPortRange: '*'
          direction: 'Outbound'
          priority: 140
          protocol: '*'
          sourceAddressPrefix: '*'
          sourcePortRange: '*'
        }
      }
    ]
  }
}

ARM-mal

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.17.1.54307",
      "templateHash": "4751223750055747166"
    }
  },
  "parameters": {
    "networkSecurityGroupName": {
      "type": "string"
    },
    "resourceLocation": {
      "type": "string"
    }
  },
  "resources": [
    {
      "type": "Microsoft.Network/networkSecurityGroups",
      "apiVersion": "2022-11-01",
      "name": "[parameters('networkSecurityGroupName')]",
      "location": "[parameters('resourceLocation')]",
      "properties": {
        "flushConnection": false,
        "securityRules": [
          {
            "name": "AllowHttpsInbound",
            "properties": {
              "access": "Allow",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "443",
              "direction": "Inbound",
              "priority": 100,
              "protocol": "TCP",
              "sourceAddressPrefix": "Internet",
              "sourcePortRange": "*"
            }
          },
          {
            "name": "AllowGatewayManagerInbound",
            "properties": {
              "access": "Allow",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "443",
              "direction": "Inbound",
              "priority": 110,
              "protocol": "TCP",
              "sourceAddressPrefix": "GatewayManager",
              "sourcePortRange": "*"
            }
          },
          {
            "name": "AllowBastionHostCommunication",
            "properties": {
              "access": "Allow",
              "destinationAddressPrefix": "VirtualNetwork",
              "destinationPortRanges": [
                "5701",
                "8080"
              ],
              "direction": "Inbound",
              "priority": 120,
              "protocol": "*",
              "sourceAddressPrefix": "VirtualNetwork",
              "sourcePortRange": "*"
            }
          },
          {
            "name": "AllowAzureLoadBalancerInbound",
            "properties": {
              "access": "Allow",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "443",
              "direction": "Inbound",
              "priority": 4095,
              "protocol": "TCP",
              "sourceAddressPrefix": "AzureLoadBalancer",
              "sourcePortRange": "*"
            }
          },
          {
            "name": "DenyAllInbound",
            "properties": {
              "access": "Deny",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "*",
              "direction": "Inbound",
              "priority": 4096,
              "protocol": "*",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*"
            }
          },
          {
            "name": "AllowSshRDPOutbound",
            "properties": {
              "access": "Allow",
              "destinationAddressPrefix": "VirtualNetwork",
              "destinationPortRanges": [
                "22",
                "3389"
              ],
              "direction": "Outbound",
              "priority": 100,
              "protocol": "*",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*"
            }
          },
          {
            "name": "AllowAzureCloudOutbound",
            "properties": {
              "access": "Allow",
              "destinationAddressPrefix": "AzureCloud",
              "destinationPortRange": "443",
              "direction": "Outbound",
              "priority": 110,
              "protocol": "TCP",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*"
            }
          },
          {
            "name": "AllowBastionCommunication",
            "properties": {
              "access": "Allow",
              "destinationAddressPrefix": "VirtualNetwork",
              "destinationPortRanges": [
                "5701",
                "8080"
              ],
              "direction": "Outbound",
              "priority": 120,
              "protocol": "*",
              "sourceAddressPrefix": "VirtualNetwork",
              "sourcePortRange": "*"
            }
          },
          {
            "name": "AllowHttpOutbound",
            "properties": {
              "access": "Allow",
              "destinationAddressPrefix": "Internet",
              "destinationPortRange": "80",
              "direction": "Outbound",
              "priority": 130,
              "protocol": "TCP",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*"
            }
          },
          {
            "name": "DenyAllOutbound",
            "properties": {
              "access": "Deny",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "*",
              "direction": "Outbound",
              "priority": 140,
              "protocol": "*",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*"
            }
          }
        ]
      }
    }
  ]
}