mirror of
https://github.com/BagelHole/DevOps-Security-Agent-Skills.git
synced 2026-08-22 12:49:53 +02:00
555 lines
16 KiB
Markdown
555 lines
16 KiB
Markdown
---
|
|
name: azure-networking
|
|
description: Configure Azure VNets, NSGs, and Azure Firewall. Implement hub-spoke topology and private endpoints. Use when designing Azure network infrastructure.
|
|
license: MIT
|
|
metadata:
|
|
author: devops-skills
|
|
version: "1.0"
|
|
---
|
|
|
|
# Azure Networking
|
|
|
|
Design and implement Azure network infrastructure including VNets, subnets, NSGs, VNet peering, private endpoints, Azure Firewall, and Application Gateway. Covers both az CLI commands and Terraform configurations for production hub-spoke topologies.
|
|
|
|
## When to Use
|
|
|
|
- You are designing the network foundation for Azure workloads.
|
|
- You need to isolate environments with VNets and NSGs.
|
|
- You are connecting on-premises networks to Azure via VPN or ExpressRoute.
|
|
- You need private connectivity to PaaS services via private endpoints.
|
|
- You are implementing centralized egress filtering with Azure Firewall.
|
|
- You need to set up load balancing or application-layer routing with Application Gateway.
|
|
|
|
## Prerequisites
|
|
|
|
```bash
|
|
# Install Azure CLI
|
|
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
|
|
|
|
# Login and set subscription
|
|
az login
|
|
az account set --subscription "my-subscription-id"
|
|
|
|
# Register required providers
|
|
az provider register --namespace Microsoft.Network
|
|
|
|
# Create resource group
|
|
az group create --name networking-rg --location eastus
|
|
```
|
|
|
|
## VNet and Subnet Creation
|
|
|
|
### Hub VNet
|
|
|
|
```bash
|
|
# Create hub VNet for shared services
|
|
az network vnet create \
|
|
--resource-group networking-rg \
|
|
--name hub-vnet \
|
|
--address-prefix 10.0.0.0/16 \
|
|
--location eastus \
|
|
--tags environment=prod role=hub
|
|
|
|
# Add subnets to hub
|
|
az network vnet subnet create \
|
|
--resource-group networking-rg \
|
|
--vnet-name hub-vnet \
|
|
--name AzureFirewallSubnet \
|
|
--address-prefix 10.0.1.0/26
|
|
|
|
az network vnet subnet create \
|
|
--resource-group networking-rg \
|
|
--vnet-name hub-vnet \
|
|
--name GatewaySubnet \
|
|
--address-prefix 10.0.2.0/27
|
|
|
|
az network vnet subnet create \
|
|
--resource-group networking-rg \
|
|
--vnet-name hub-vnet \
|
|
--name SharedServicesSubnet \
|
|
--address-prefix 10.0.3.0/24
|
|
|
|
az network vnet subnet create \
|
|
--resource-group networking-rg \
|
|
--vnet-name hub-vnet \
|
|
--name AzureBastionSubnet \
|
|
--address-prefix 10.0.4.0/26
|
|
```
|
|
|
|
### Spoke VNet
|
|
|
|
```bash
|
|
# Create spoke VNet for application workloads
|
|
az network vnet create \
|
|
--resource-group networking-rg \
|
|
--name spoke-prod-vnet \
|
|
--address-prefix 10.1.0.0/16 \
|
|
--location eastus \
|
|
--tags environment=prod role=spoke
|
|
|
|
az network vnet subnet create \
|
|
--resource-group networking-rg \
|
|
--vnet-name spoke-prod-vnet \
|
|
--name web-subnet \
|
|
--address-prefix 10.1.1.0/24
|
|
|
|
az network vnet subnet create \
|
|
--resource-group networking-rg \
|
|
--vnet-name spoke-prod-vnet \
|
|
--name app-subnet \
|
|
--address-prefix 10.1.2.0/24
|
|
|
|
az network vnet subnet create \
|
|
--resource-group networking-rg \
|
|
--vnet-name spoke-prod-vnet \
|
|
--name data-subnet \
|
|
--address-prefix 10.1.3.0/24 \
|
|
--private-endpoint-network-policies Enabled
|
|
|
|
# List all subnets in a VNet
|
|
az network vnet subnet list \
|
|
--resource-group networking-rg \
|
|
--vnet-name spoke-prod-vnet \
|
|
--output table
|
|
```
|
|
|
|
## Network Security Groups
|
|
|
|
```bash
|
|
# Create NSG for web tier
|
|
az network nsg create \
|
|
--resource-group networking-rg \
|
|
--name web-nsg \
|
|
--tags tier=web
|
|
|
|
# Allow HTTPS from internet
|
|
az network nsg rule create \
|
|
--resource-group networking-rg \
|
|
--nsg-name web-nsg \
|
|
--name AllowHTTPS \
|
|
--priority 100 \
|
|
--direction Inbound \
|
|
--access Allow \
|
|
--protocol Tcp \
|
|
--source-address-prefixes Internet \
|
|
--destination-port-ranges 443
|
|
|
|
# Allow HTTP for redirect
|
|
az network nsg rule create \
|
|
--resource-group networking-rg \
|
|
--nsg-name web-nsg \
|
|
--name AllowHTTP \
|
|
--priority 110 \
|
|
--direction Inbound \
|
|
--access Allow \
|
|
--protocol Tcp \
|
|
--source-address-prefixes Internet \
|
|
--destination-port-ranges 80
|
|
|
|
# Deny all other inbound traffic
|
|
az network nsg rule create \
|
|
--resource-group networking-rg \
|
|
--nsg-name web-nsg \
|
|
--name DenyAllInbound \
|
|
--priority 4096 \
|
|
--direction Inbound \
|
|
--access Deny \
|
|
--protocol '*' \
|
|
--source-address-prefixes '*' \
|
|
--destination-port-ranges '*'
|
|
|
|
# Create NSG for app tier -- only allow from web subnet
|
|
az network nsg create \
|
|
--resource-group networking-rg \
|
|
--name app-nsg
|
|
|
|
az network nsg rule create \
|
|
--resource-group networking-rg \
|
|
--nsg-name app-nsg \
|
|
--name AllowFromWeb \
|
|
--priority 100 \
|
|
--direction Inbound \
|
|
--access Allow \
|
|
--protocol Tcp \
|
|
--source-address-prefixes 10.1.1.0/24 \
|
|
--destination-port-ranges 8080
|
|
|
|
# Create NSG for data tier -- only allow from app subnet
|
|
az network nsg create \
|
|
--resource-group networking-rg \
|
|
--name data-nsg
|
|
|
|
az network nsg rule create \
|
|
--resource-group networking-rg \
|
|
--nsg-name data-nsg \
|
|
--name AllowSQLFromApp \
|
|
--priority 100 \
|
|
--direction Inbound \
|
|
--access Allow \
|
|
--protocol Tcp \
|
|
--source-address-prefixes 10.1.2.0/24 \
|
|
--destination-port-ranges 1433
|
|
|
|
# Associate NSG with subnet
|
|
az network vnet subnet update \
|
|
--resource-group networking-rg \
|
|
--vnet-name spoke-prod-vnet \
|
|
--name web-subnet \
|
|
--network-security-group web-nsg
|
|
|
|
az network vnet subnet update \
|
|
--resource-group networking-rg \
|
|
--vnet-name spoke-prod-vnet \
|
|
--name app-subnet \
|
|
--network-security-group app-nsg
|
|
|
|
az network vnet subnet update \
|
|
--resource-group networking-rg \
|
|
--vnet-name spoke-prod-vnet \
|
|
--name data-subnet \
|
|
--network-security-group data-nsg
|
|
|
|
# View effective NSG rules
|
|
az network nic list-effective-nsg \
|
|
--resource-group networking-rg \
|
|
--name myvm-nic \
|
|
--output table
|
|
```
|
|
|
|
## VNet Peering
|
|
|
|
```bash
|
|
# Peer hub to spoke
|
|
az network vnet peering create \
|
|
--resource-group networking-rg \
|
|
--name hub-to-spoke-prod \
|
|
--vnet-name hub-vnet \
|
|
--remote-vnet spoke-prod-vnet \
|
|
--allow-vnet-access \
|
|
--allow-forwarded-traffic \
|
|
--allow-gateway-transit
|
|
|
|
# Peer spoke to hub
|
|
az network vnet peering create \
|
|
--resource-group networking-rg \
|
|
--name spoke-prod-to-hub \
|
|
--vnet-name spoke-prod-vnet \
|
|
--remote-vnet hub-vnet \
|
|
--allow-vnet-access \
|
|
--allow-forwarded-traffic \
|
|
--use-remote-gateways false
|
|
|
|
# Verify peering status
|
|
az network vnet peering list \
|
|
--resource-group networking-rg \
|
|
--vnet-name hub-vnet \
|
|
--output table
|
|
```
|
|
|
|
## Private Endpoints
|
|
|
|
```bash
|
|
# Create private endpoint for Azure SQL
|
|
az network private-endpoint create \
|
|
--resource-group networking-rg \
|
|
--name sql-private-endpoint \
|
|
--vnet-name spoke-prod-vnet \
|
|
--subnet data-subnet \
|
|
--private-connection-resource-id "/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Sql/servers/myserver" \
|
|
--group-id sqlServer \
|
|
--connection-name sql-connection
|
|
|
|
# Create private DNS zone for SQL
|
|
az network private-dns zone create \
|
|
--resource-group networking-rg \
|
|
--name privatelink.database.windows.net
|
|
|
|
# Link DNS zone to VNet
|
|
az network private-dns link vnet create \
|
|
--resource-group networking-rg \
|
|
--zone-name privatelink.database.windows.net \
|
|
--name spoke-dns-link \
|
|
--virtual-network spoke-prod-vnet \
|
|
--registration-enabled false
|
|
|
|
# Create DNS record for the private endpoint
|
|
az network private-endpoint dns-zone-group create \
|
|
--resource-group networking-rg \
|
|
--endpoint-name sql-private-endpoint \
|
|
--name sql-dns-group \
|
|
--private-dns-zone privatelink.database.windows.net \
|
|
--zone-name privatelink.database.windows.net
|
|
|
|
# Create private endpoint for Storage Account
|
|
az network private-endpoint create \
|
|
--resource-group networking-rg \
|
|
--name storage-private-endpoint \
|
|
--vnet-name spoke-prod-vnet \
|
|
--subnet data-subnet \
|
|
--private-connection-resource-id "/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Storage/storageAccounts/mystorageacct" \
|
|
--group-id blob \
|
|
--connection-name storage-blob-connection
|
|
|
|
# Create private endpoint for Key Vault
|
|
az network private-endpoint create \
|
|
--resource-group networking-rg \
|
|
--name kv-private-endpoint \
|
|
--vnet-name spoke-prod-vnet \
|
|
--subnet app-subnet \
|
|
--private-connection-resource-id "/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.KeyVault/vaults/myvault" \
|
|
--group-id vault \
|
|
--connection-name kv-connection
|
|
```
|
|
|
|
## Azure Firewall
|
|
|
|
```bash
|
|
# Create public IP for firewall
|
|
az network public-ip create \
|
|
--resource-group networking-rg \
|
|
--name fw-public-ip \
|
|
--sku Standard \
|
|
--allocation-method Static
|
|
|
|
# Create Azure Firewall
|
|
az network firewall create \
|
|
--resource-group networking-rg \
|
|
--name hub-firewall \
|
|
--location eastus \
|
|
--sku AZFW_VNet \
|
|
--tier Standard
|
|
|
|
# Configure firewall IP
|
|
az network firewall ip-config create \
|
|
--resource-group networking-rg \
|
|
--firewall-name hub-firewall \
|
|
--name fw-ipconfig \
|
|
--public-ip-address fw-public-ip \
|
|
--vnet-name hub-vnet
|
|
|
|
# Get firewall private IP for route tables
|
|
FW_PRIVATE_IP=$(az network firewall show \
|
|
--resource-group networking-rg \
|
|
--name hub-firewall \
|
|
--query "ipConfigurations[0].privateIpAddress" \
|
|
--output tsv)
|
|
|
|
# Create application rule allowing web traffic
|
|
az network firewall application-rule create \
|
|
--resource-group networking-rg \
|
|
--firewall-name hub-firewall \
|
|
--collection-name AllowWeb \
|
|
--name AllowGoogle \
|
|
--protocols Https=443 Http=80 \
|
|
--source-addresses 10.1.0.0/16 \
|
|
--target-fqdns "*.google.com" "*.microsoft.com" \
|
|
--action Allow \
|
|
--priority 100
|
|
|
|
# Create network rule for DNS
|
|
az network firewall network-rule create \
|
|
--resource-group networking-rg \
|
|
--firewall-name hub-firewall \
|
|
--collection-name AllowDNS \
|
|
--name AllowDNS \
|
|
--protocols UDP \
|
|
--source-addresses 10.1.0.0/16 \
|
|
--destination-addresses 168.63.129.16 \
|
|
--destination-ports 53 \
|
|
--action Allow \
|
|
--priority 200
|
|
|
|
# Create route table to send traffic through firewall
|
|
az network route-table create \
|
|
--resource-group networking-rg \
|
|
--name spoke-route-table
|
|
|
|
az network route-table route create \
|
|
--resource-group networking-rg \
|
|
--route-table-name spoke-route-table \
|
|
--name default-to-firewall \
|
|
--address-prefix 0.0.0.0/0 \
|
|
--next-hop-type VirtualAppliance \
|
|
--next-hop-ip-address "$FW_PRIVATE_IP"
|
|
|
|
# Associate route table with spoke subnet
|
|
az network vnet subnet update \
|
|
--resource-group networking-rg \
|
|
--vnet-name spoke-prod-vnet \
|
|
--name app-subnet \
|
|
--route-table spoke-route-table
|
|
```
|
|
|
|
## Application Gateway with WAF
|
|
|
|
```bash
|
|
# Create public IP
|
|
az network public-ip create \
|
|
--resource-group networking-rg \
|
|
--name appgw-public-ip \
|
|
--sku Standard \
|
|
--allocation-method Static
|
|
|
|
# Create Application Gateway subnet
|
|
az network vnet subnet create \
|
|
--resource-group networking-rg \
|
|
--vnet-name spoke-prod-vnet \
|
|
--name AppGatewaySubnet \
|
|
--address-prefix 10.1.10.0/24
|
|
|
|
# Create Application Gateway with WAF v2
|
|
az network application-gateway create \
|
|
--resource-group networking-rg \
|
|
--name myapp-appgw \
|
|
--location eastus \
|
|
--sku WAF_v2 \
|
|
--capacity 2 \
|
|
--vnet-name spoke-prod-vnet \
|
|
--subnet AppGatewaySubnet \
|
|
--public-ip-address appgw-public-ip \
|
|
--http-settings-port 80 \
|
|
--http-settings-protocol Http \
|
|
--frontend-port 443 \
|
|
--servers 10.1.2.4 10.1.2.5
|
|
|
|
# Enable WAF policy
|
|
az network application-gateway waf-policy create \
|
|
--resource-group networking-rg \
|
|
--name myapp-waf-policy
|
|
|
|
az network application-gateway waf-policy managed-rule rule-set add \
|
|
--resource-group networking-rg \
|
|
--policy-name myapp-waf-policy \
|
|
--type OWASP \
|
|
--version 3.2
|
|
```
|
|
|
|
## Terraform Configuration
|
|
|
|
```hcl
|
|
resource "azurerm_virtual_network" "hub" {
|
|
name = "hub-vnet"
|
|
location = azurerm_resource_group.networking.location
|
|
resource_group_name = azurerm_resource_group.networking.name
|
|
address_space = ["10.0.0.0/16"]
|
|
tags = var.tags
|
|
}
|
|
|
|
resource "azurerm_subnet" "firewall" {
|
|
name = "AzureFirewallSubnet"
|
|
resource_group_name = azurerm_resource_group.networking.name
|
|
virtual_network_name = azurerm_virtual_network.hub.name
|
|
address_prefixes = ["10.0.1.0/26"]
|
|
}
|
|
|
|
resource "azurerm_virtual_network" "spoke" {
|
|
name = "spoke-prod-vnet"
|
|
location = azurerm_resource_group.networking.location
|
|
resource_group_name = azurerm_resource_group.networking.name
|
|
address_space = ["10.1.0.0/16"]
|
|
tags = var.tags
|
|
}
|
|
|
|
resource "azurerm_subnet" "web" {
|
|
name = "web-subnet"
|
|
resource_group_name = azurerm_resource_group.networking.name
|
|
virtual_network_name = azurerm_virtual_network.spoke.name
|
|
address_prefixes = ["10.1.1.0/24"]
|
|
}
|
|
|
|
resource "azurerm_network_security_group" "web" {
|
|
name = "web-nsg"
|
|
location = azurerm_resource_group.networking.location
|
|
resource_group_name = azurerm_resource_group.networking.name
|
|
|
|
security_rule {
|
|
name = "AllowHTTPS"
|
|
priority = 100
|
|
direction = "Inbound"
|
|
access = "Allow"
|
|
protocol = "Tcp"
|
|
source_port_range = "*"
|
|
destination_port_range = "443"
|
|
source_address_prefix = "Internet"
|
|
destination_address_prefix = "*"
|
|
}
|
|
|
|
security_rule {
|
|
name = "DenyAllInbound"
|
|
priority = 4096
|
|
direction = "Inbound"
|
|
access = "Deny"
|
|
protocol = "*"
|
|
source_port_range = "*"
|
|
destination_port_range = "*"
|
|
source_address_prefix = "*"
|
|
destination_address_prefix = "*"
|
|
}
|
|
|
|
tags = var.tags
|
|
}
|
|
|
|
resource "azurerm_subnet_network_security_group_association" "web" {
|
|
subnet_id = azurerm_subnet.web.id
|
|
network_security_group_id = azurerm_network_security_group.web.id
|
|
}
|
|
|
|
resource "azurerm_virtual_network_peering" "hub_to_spoke" {
|
|
name = "hub-to-spoke"
|
|
resource_group_name = azurerm_resource_group.networking.name
|
|
virtual_network_name = azurerm_virtual_network.hub.name
|
|
remote_virtual_network_id = azurerm_virtual_network.spoke.id
|
|
allow_forwarded_traffic = true
|
|
allow_gateway_transit = true
|
|
}
|
|
|
|
resource "azurerm_virtual_network_peering" "spoke_to_hub" {
|
|
name = "spoke-to-hub"
|
|
resource_group_name = azurerm_resource_group.networking.name
|
|
virtual_network_name = azurerm_virtual_network.spoke.name
|
|
remote_virtual_network_id = azurerm_virtual_network.hub.id
|
|
allow_forwarded_traffic = true
|
|
use_remote_gateways = false
|
|
}
|
|
|
|
resource "azurerm_private_endpoint" "sql" {
|
|
name = "sql-private-endpoint"
|
|
location = azurerm_resource_group.networking.location
|
|
resource_group_name = azurerm_resource_group.networking.name
|
|
subnet_id = azurerm_subnet.data.id
|
|
|
|
private_service_connection {
|
|
name = "sql-connection"
|
|
private_connection_resource_id = azurerm_mssql_server.main.id
|
|
subresource_names = ["sqlServer"]
|
|
is_manual_connection = false
|
|
}
|
|
|
|
private_dns_zone_group {
|
|
name = "sql-dns-group"
|
|
private_dns_zone_ids = [azurerm_private_dns_zone.sql.id]
|
|
}
|
|
}
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
| Symptom | Cause | Fix |
|
|
|---------|-------|-----|
|
|
| VMs cannot reach the internet | NSG blocking outbound or missing route | Check NSG rules with `az network nic list-effective-nsg`; verify route table |
|
|
| VNet peering shows `Disconnected` | Peering created in one direction only | Create peering from both sides (hub-to-spoke AND spoke-to-hub) |
|
|
| Private endpoint DNS not resolving | Private DNS zone not linked to VNet | Link DNS zone with `az network private-dns link vnet create` |
|
|
| NSG rule not taking effect | Higher-priority rule overriding | List rules with `az network nsg rule list` and check priority ordering |
|
|
| Application Gateway health probes failing | Backend pool servers unreachable | Verify NSG allows traffic from the AppGateway subnet |
|
|
| Azure Firewall blocking legitimate traffic | Missing application or network rule | Check firewall logs in Log Analytics; add appropriate rule |
|
|
| Cross-VNet communication failing | Peering not configured or route missing | Verify peering status and that `allow-vnet-access` is enabled |
|
|
| High latency between regions | Traffic routing through unexpected path | Use `az network watcher next-hop` to diagnose routing |
|
|
|
|
## Related Skills
|
|
|
|
- `azure-vms` -- VM network interface and NSG configuration.
|
|
- `azure-aks` -- AKS VNet integration with Azure CNI.
|
|
- `azure-sql` -- Private endpoint configuration for database access.
|
|
- `terraform-azure` -- Network infrastructure provisioning with Terraform.
|
|
- `azure-functions` -- VNet integration for Premium plan functions.
|