Skip to content

CLZ-180 - Network Security Groups

Network Security Groups architecture
Service or workflow illustration. The lesson defines the exact resource settings. Open at full size.

Goal

Protect the web subnet with deterministic NSG priorities, public HTTP for the teaching service, and RDP limited to one administrator IPv4 address.

CLZ-180 learning sequence
Arrows show the learning sequence, not service traffic. Azure deployment. Open at full size.

Prerequisites

  • Complete CLZ-170.
  • Discover your current public IPv4 address and express it as a /32 CIDR.

Architecture

CLZ-180 — Three illustrated inbound requests pass through ordered NSG decisions: priority 100 permits Internet TCP 80, priority 110 permits TCP 3389 from admin_cidr, and priority 120 denies other TCP 3389 sources. The NSG is associated with web-snet; no VM is present. First matching rule wins, and /32 validation checks format rather than public routability.
Lesson-specific teaching diagram. Read the arrow legend and the accompanying architecture explanation. Azure deployment. On narrow screens, scroll the diagram horizontally. Open at full size.

The CLZ-170 network is recreated in this independent lesson. A web NSG is associated with the web subnet. HTTP is allowed for the example service, while RDP is admitted only from admin_cidr; Azure's default deny rules handle other unsolicited inbound traffic.

Resources And Cost

Relative cost: Low. NSGs and rules have no direct charge; traffic processing and later workloads can be billable.

Component Purpose and principal cost driver
VNet and four subnets Network boundary used to teach subnet-level policy.
Web NSG association Applies all web rules to NICs placed in the subnet.
HTTP and RDP rules Port 80 teaching access and tightly scoped port 3389 administration.

Inputs

Input Required substitution or decision
subscription_id Required for plan, apply, and destroy; use the exact subscription GUID.
environment Keep dev for an ephemeral lab unless testing an environment boundary.
location Select a supported region with adequate quota.
name_prefix Use a short lowercase prefix for derived names.
admin_cidr Required: replace the documentation address with your current public IPv4 plus /32; broad ranges are rejected.

Keep real subscription IDs, CIDRs, and secrets in untracked terraform.tfvars or environment variables.

The CIDR validation verifies IPv4 /32 syntax, not public routability. Confirm that the value is your actual current public administrator address.

Deploy

Review the plan and lesson-specific gates before deliberate execution. Local-only and read-only lessons create no Azure resources.
Review the plan and lesson-specific gates before deliberate execution. Local-only and read-only lessons create no Azure resources. Open at full size.

Run from the repository root in PowerShell 7:

Set-Location CLZ-180-network-security-groups
if (-not (Test-Path terraform.tfvars)) {
  Copy-Item terraform.tfvars.example terraform.tfvars
}
$subscriptionId = az account show --query id --output tsv
terraform init -lockfile=readonly
terraform fmt -check
terraform validate
terraform plan -var "subscription_id=$subscriptionId" -out tfplan
terraform show tfplan
terraform apply tfplan

Validate

$resourceGroup = terraform output -raw resource_group_name
$nsg = terraform output -raw web_nsg_name
az network nsg rule list --resource-group $resourceGroup --nsg-name $nsg --query '[].{name:name,priority:priority,source:sourceAddressPrefix,port:destinationPortRange,access:access}' --output table
terraform plan -var "subscription_id=$subscriptionId" -var 'admin_cidr=0.0.0.0/0'

Expected result:

  • HTTP and administrator RDP rules have unique priorities and Allow access.
  • The RDP rule source is exactly the supplied /32.
  • The deliberately broad negative plan fails before Azure is changed.

Troubleshooting

Gather evidence, repair the cause, and rerun verification.
Gather evidence, repair the cause, and rerun verification. Open at full size.
Symptom Resolution
The safety check rejects the CIDR Use a routable IPv4 /32; do not substitute 0.0.0.0/0, *, or a large network.
A rule priority conflicts Give each custom rule a unique value from 100 through 4096.
RDP remains unreachable later Confirm both the NSG path and whether the workload actually has a public, NAT, or Bastion ingress path.

Cleanup

Use the lesson state and cleanup instructions. Preserve remote-state dependencies until consumers are removed.
Use the lesson state and cleanup instructions. Preserve remote-state dependencies until consumers are removed. Open at full size.
$resourceGroup = terraform output -raw resource_group_name
terraform destroy -var "subscription_id=$subscriptionId"
az group exists --name $resourceGroup

Azure CLI returns false; no NSG remains associated with a deleted subnet.

Production Delta

  • Prefer Azure Bastion, Just-In-Time access, VPN, or private management over direct Internet RDP.
  • Restrict web ingress to the real proxy/load-balancer path and use Application Security Groups where they simplify intent.

Exercises

  1. Change the RDP source to another safe /32 and identify the in-place rule update.
  2. Add a deny rule with a valid priority and explain how Azure evaluates it against the allow rules.

← CLZ-170 - Virtual Network Foundation | Curriculum | CLZ-190 - Windows VM Basics →