Azure Network Security Groups - Complete Implementation Guide

Table of Contents

1. Azure Network Security Overview and Architecture

graph TB subgraph "Azure Subscription" subgraph "Resource Group" subgraph "Virtual Network (VNet)" subgraph "Subnet 1" VM1[Virtual Machine 1] NIC1[Network Interface 1] end subgraph "Subnet 2" VM2[Virtual Machine 2] NIC2[Network Interface 2] end end NSG1[Network Security Group 1] NSG2[Network Security Group 2] ASG1[Application Security Group 1] ASG2[Application Security Group 2] Bastion[Azure Bastion] end end Internet((Internet)) OnPrem[On-Premises Network] Internet --> Bastion Internet --> NSG1 OnPrem --> NSG2 NSG1 --> Subnet1 NSG2 --> Subnet2 NSG1 --> NIC1 NSG2 --> NIC2 ASG1 --> NIC1 ASG2 --> NIC2 VM1 --> NIC1 VM2 --> NIC2 style NSG1 fill:#e1f5fe style NSG2 fill:#e1f5fe style ASG1 fill:#f3e5f5 style ASG2 fill:#f3e5f5 style Bastion fill:#fff3e0

Architecture Explanation:

This diagram illustrates the complete Azure network security architecture:

  • Network Security Groups (NSGs) - Act as virtual firewalls controlling traffic flow at subnet and NIC levels
  • Application Security Groups (ASGs) - Logical grouping of resources for simplified rule management
  • Azure Bastion - Secure RDP/SSH connectivity without exposing VMs to the internet
  • Traffic Flow - Internet traffic flows through NSGs, while on-premises traffic uses separate NSG rules
  • Multi-layer Security - NSGs can be applied at both subnet and NIC levels for defense in depth

2. Prerequisites and Initial Setup

Foundation Requirements:

Before implementing NSG security, ensure you have the basic infrastructure in place:

  • Resource Group: Create "rg-network-security" in your preferred region
  • Virtual Network: Create "vnet-security-demo" with address space 10.0.0.0/16
  • Subnets: Create three subnets:
    • subnet-web (10.0.1.0/24) - for web tier resources
    • subnet-app (10.0.2.0/24) - for application tier resources
    • subnet-db (10.0.3.0/24) - for database tier resources

These foundational components are standard Azure networking basics and provide the infrastructure where we'll implement our security policies.

3. Creating Network Security Groups (NSGs)

Step 1 Create the NSG resource first

Step 2 Define security rules within the NSG

Step 3 Associate NSG to subnet or NIC

graph LR A[Create NSG] --> B[Add Security Rules] B --> C[Associate to Subnet] B --> D[Associate to NIC] C --> E[Traffic Filtering Active] D --> E subgraph "NSG Rules Processing" F[Inbound Rules] --> G[Rule Priority Check] H[Outbound Rules] --> G G --> I[Allow/Deny Decision] end E --> F E --> H style A fill:#e3f2fd style B fill:#e8f5e8 style C fill:#fff3e0 style D fill:#fff3e0 style E fill:#ffebee

NSG Creation and Rule Processing Flow:

This diagram shows the sequential process of NSG implementation and how traffic filtering works:

  • Creation Phase - NSG must be created before rules can be added
  • Rule Definition - Security rules define traffic filtering criteria
  • Association - NSGs can be associated with subnets (affects all resources) or NICs (specific resources)
  • Traffic Processing - Rules are evaluated by priority (lower numbers first) until a match is found

Creating Web Tier NSG

# Create NSG for Web Tier az network nsg create \ --resource-group "rg-network-security" \ --name "nsg-web-tier" \ --location "East US" \ --tags Tier=Web Environment=Production

Parameters Explanation:

ParameterDescriptionBest Practice
--nameNSG identifierUse descriptive naming convention (nsg-{purpose})
--locationAzure regionShould match VNet location
--tagsMetadata for organizationInclude tier, environment, purpose

Purpose: Creates an empty NSG that will contain security rules for web tier resources. This NSG will typically allow HTTP/HTTPS traffic while blocking direct administrative access.

Creating Application Tier NSG

# Create NSG for Application Tier az network nsg create \ --resource-group "rg-network-security" \ --name "nsg-app-tier" \ --location "East US" \ --tags Tier=Application Environment=Production

Purpose: Creates NSG for application servers that typically receive traffic only from the web tier and communicate with the database tier. This implements network segmentation principles.

Creating Database Tier NSG

# Create NSG for Database Tier az network nsg create \ --resource-group "rg-network-security" \ --name "nsg-db-tier" \ --location "East US" \ --tags Tier=Database Environment=Production

Purpose: Creates the most restrictive NSG for database resources, allowing only necessary database traffic from application tier and administrative access through bastion.

4. Associating NSGs to Resources

graph TB subgraph "NSG Association Options" NSG[Network Security Group] subgraph "Subnet Level" Subnet[Subnet] VM1[VM 1] VM2[VM 2] VM3[VM 3] end subgraph "NIC Level" NIC1[NIC 1] NIC2[NIC 2] VMa[VM A] VMb[VM B] end end NSG --> Subnet NSG --> NIC1 NSG --> NIC2 Subnet --> VM1 Subnet --> VM2 Subnet --> VM3 NIC1 --> VMa NIC2 --> VMb style NSG fill:#e1f5fe style Subnet fill:#e8f5e8 style NIC1 fill:#fff3e0 style NIC2 fill:#fff3e0

NSG Association Strategy:

This diagram illustrates two association approaches:

  • Subnet-level Association - One NSG affects all resources in the subnet (easier management, broader scope)
  • NIC-level Association - Individual NSG per network interface (granular control, complex management)
  • Dual Association - Both subnet and NIC NSGs can be applied (rules are additive - both must allow traffic)
  • Traffic Flow - Subnet NSG processes first, then NIC NSG for inbound traffic (reverse for outbound)

Associate NSG to Subnet

# Associate Web NSG to Web Subnet az network vnet subnet update \ --resource-group "rg-network-security" \ --vnet-name "vnet-security-demo" \ --name "subnet-web" \ --network-security-group "nsg-web-tier"

Parameters Explanation:

ParameterDescriptionImpact
--network-security-groupNSG to associateAll VMs in subnet inherit these rules
--nameTarget subnet nameMust exist in the specified VNet

Purpose: Associates the NSG with the entire subnet, meaning all current and future resources in this subnet will be subject to the NSG rules. This is the most common and efficient approach for applying consistent security policies.

# Associate Application NSG to App Subnet az network vnet subnet update \ --resource-group "rg-network-security" \ --vnet-name "vnet-security-demo" \ --name "subnet-app" \ --network-security-group "nsg-app-tier" # Associate Database NSG to DB Subnet az network vnet subnet update \ --resource-group "rg-network-security" \ --vnet-name "vnet-security-demo" \ --name "subnet-db" \ --network-security-group "nsg-db-tier"

Associate NSG to Network Interface (Alternative/Additional)

# Create a VM first to get NIC, then associate NSG to specific NIC az vm create \ --resource-group "rg-network-security" \ --name "vm-web-01" \ --image "Ubuntu2204" \ --admin-username "azureuser" \ --generate-ssh-keys \ --subnet "subnet-web" \ --vnet-name "vnet-security-demo" \ --public-ip-sku "Standard" \ --size "Standard_B2s" # Associate NSG to the VM's NIC az network nic update \ --resource-group "rg-network-security" \ --name "vm-web-01VMNic" \ --network-security-group "nsg-web-tier"

Purpose: Demonstrates NIC-level NSG association. This provides granular control but is more complex to manage. Use this approach when you need different security rules for specific VMs within the same subnet.

Note: When both subnet and NIC NSGs are present, traffic must pass through both sets of rules. For inbound traffic: Subnet NSG → NIC NSG. For outbound traffic: NIC NSG → Subnet NSG.

5. Application Security Groups (ASGs)

🏢 NSG vs ASG: The Office Building Analogy

🚪 NSG = Security Guards & Doors

What it is: NSGs are like security guards stationed at building entrances and elevator doors.

What they do:

  • Check IDs: "Are you from the internet or internal network?"
  • Verify purpose: "What port/service do you need access to?"
  • Allow/deny entry: "You can enter" or "Access denied"
  • Guard locations: At building entrance (subnet-level) or office door (NIC-level)

Example: "Only people from the internet can access the web servers on port 80, but no one from the internet can access the database servers on port 1433."

👥 ASG = Employee Departments/Groups

What it is: ASGs are like department badges or employee groups (Sales, IT, HR, etc.)

What they do:

  • Group similar people: "All web servers belong to the Web Team"
  • Simplify rules: Instead of naming each person, say "Web Team can talk to App Team"
  • Dynamic membership: New web servers automatically join the "Web Team"
  • Make rules readable: "Sales can access CRM" vs "IP 10.1.1.5 can access IP 10.2.1.8"

Example: "All servers in the 'Web-Servers' group can communicate with all servers in the 'App-Servers' group, regardless of their specific IP addresses."

🔄 How They Work Together:

Traditional approach (NSG only):

"Security guard, allow John Smith (IP: 10.0.1.4), Mary Johnson (IP: 10.0.1.5), and Bob Wilson (IP: 10.0.1.6) to access the database room."

Modern approach (NSG + ASG):

"Security guard, allow anyone with a 'Web-Developer' badge to access the database room."

Benefits:

  • When a new web developer joins, just give them the badge - no need to update security guard instructions
  • When someone leaves, remove their badge - automatic access revocation
  • Rules are easier to understand: "Web-Developers can access Database-Servers" vs a list of IP addresses
  • Scales better: Adding 10 new web servers doesn't require updating 10 different security rules

⚠️ Key Difference:

NSG: The actual security enforcement mechanism (the guard who checks and allows/denies)

ASG: A logical grouping tool that makes NSG rules easier to manage (the department badges)

You need both: ASGs without NSGs are like having department badges but no security guards. NSGs without ASGs work but require managing individual IP addresses.

🚦 CRITICAL: There's NO "NSG vs ASG Precedence" - They Work Together!

❌ Common Misconception:

WRONG: "If I have both NSG and ASG rules, which one wins?"

WHY IT'S WRONG: ASGs are not a separate security layer - they're just labels used WITHIN NSG rules!

✅ Correct Understanding:

RIGHT: ASGs are used as targets or sources in NSG rules instead of IP addresses

Example NSG Rules:

Traditional NSG Rule:
Allow traffic from 10.0.1.4 to 10.0.2.5 on port 8080
ASG-Enhanced NSG Rule:
Allow traffic from asg-web-servers to asg-app-servers on port 8080

Both are NSG rules! The second one just uses ASG names instead of IP addresses.

🔄 What ACTUALLY Determines Precedence:

Precedence FactorDescriptionExample
Rule Priority NumberLower numbers processed firstPriority 100 beats Priority 200
NSG Layer (Subnet vs NIC)Both must allow trafficSubnet NSG → NIC NSG (inbound)
First Match WinsProcessing stops at first matchAllow rule at 100 stops Deny rule at 200
Security Admin RulesOverride all NSG rulesAzure VNet Manager admin rules

🎯 Real-World Example:

Scenario: VM "web-01" is in ASG "asg-web-servers" and has these NSG rules:

  1. Priority 100: DENY traffic from Internet to asg-web-servers on port 22
  2. Priority 200: ALLOW traffic from Internet to 10.0.1.4 on port 22

Result: SSH is DENIED because Priority 100 (ASG-based rule) is processed first and matches, so Priority 200 (IP-based rule) never gets evaluated.

Key Point: The ASG didn't "override" the IP rule - the PRIORITY did!

graph TB subgraph "Traditional NSG Rules" NSG1[NSG Rule] IP1[10.0.1.4] IP2[10.0.1.5] IP3[10.0.2.6] IP4[10.0.2.7] end subgraph "ASG-Based Rules" NSG2[NSG Rule with ASG] ASG_Web[ASG: WebServers] ASG_App[ASG: AppServers] VM1[VM-Web-01] VM2[VM-Web-02] VM3[VM-App-01] VM4[VM-App-02] end NSG1 --> IP1 NSG1 --> IP2 NSG1 --> IP3 NSG1 --> IP4 NSG2 --> ASG_Web NSG2 --> ASG_App ASG_Web --> VM1 ASG_Web --> VM2 ASG_App --> VM3 ASG_App --> VM4 style NSG1 fill:#ffebee style NSG2 fill:#e8f5e8 style ASG_Web fill:#f3e5f5 style ASG_App fill:#f3e5f5

ASG vs Traditional IP-based Rules:

This diagram compares traditional IP-based NSG rules with ASG-based rules:

  • Traditional Approach - NSG rules reference specific IP addresses, requiring updates when VMs change
  • ASG Approach - NSG rules reference logical groups, automatically including all group members
  • Scalability - ASGs eliminate the need to update rules when adding/removing VMs
  • Maintainability - Logical grouping makes rules more readable and manageable

Creating Application Security Groups

# Create ASG for Web Servers az network asg create \ --resource-group "rg-network-security" \ --name "asg-web-servers" \ --location "East US" \ --tags Function=WebServer Tier=Frontend

Parameters Explanation:

ParameterDescriptionBest Practice
--nameASG identifierUse descriptive names (asg-{function})
--locationAzure regionMust match associated resources
--tagsLogical categorizationInclude function, tier, purpose

Purpose: Creates a logical container for web server resources. VMs assigned to this ASG can be referenced collectively in NSG rules, simplifying rule management and improving scalability.

# Create ASG for Application Servers az network asg create \ --resource-group "rg-network-security" \ --name "asg-app-servers" \ --location "East US" \ --tags Function=ApplicationServer Tier=Backend # Create ASG for Database Servers az network asg create \ --resource-group "rg-network-security" \ --name "asg-db-servers" \ --location "East US" \ --tags Function=DatabaseServer Tier=Data

Associating ASG to Network Interface Cards

# Create additional VMs for demonstration az vm create \ --resource-group "rg-network-security" \ --name "vm-app-01" \ --image "Ubuntu2204" \ --admin-username "azureuser" \ --generate-ssh-keys \ --subnet "subnet-app" \ --vnet-name "vnet-security-demo" \ --public-ip-sku "Standard" \ --size "Standard_B2s" \ --no-wait # Associate Web VM NIC to Web ASG az network nic ip-config update \ --resource-group "rg-network-security" \ --nic-name "vm-web-01VMNic" \ --name "ipconfigvm-web-01" \ --application-security-groups "asg-web-servers"

🔍 Azure VM Auto-Generated Resource Names:

Understanding Azure's Naming Convention:

When you create a VM named "vm-web-01", Azure automatically creates these resources with predictable names:

Resource TypeAuto-Generated NamePattern
Network Interfacevm-web-01VMNic{VM-Name}VMNic
IP Configurationipconfigvm-web-01ipconfig{VM-Name}
Public IPvm-web-01PublicIP{VM-Name}PublicIP
OS Diskvm-web-01_OsDisk_1_...{VM-Name}_OsDisk_1_{guid}

💡 Pro Tip: You can discover the actual NIC name using this command:

# Find the NIC name for any VM az vm show --resource-group "rg-network-security" --name "vm-web-01" \ --query "networkProfile.networkInterfaces[0].id" --output tsv | \ awk -F'/' '{print $NF}' # Or get all network interface details az vm show --resource-group "rg-network-security" --name "vm-web-01" \ --query "networkProfile.networkInterfaces[].id" --output table

⚠️ Important Notes:

  • This naming convention applies when Azure creates the NIC automatically during VM creation
  • If you create the NIC separately first, you control the naming
  • Some special characters in VM names may be modified in the NIC name
  • Always verify the actual NIC name in production environments

Parameters Explanation:

ParameterDescriptionUsage
--nic-nameNetwork interface nameUsually {VMName}VMNic for Azure-created NICs
--nameIP configuration nameDefault is ipconfig{VMName}
--application-security-groupsASG assignmentsCan specify multiple ASGs separated by spaces

Purpose: Associates the VM's network interface with an ASG, making it a member of that logical group. The VM will now be included in any NSG rules that reference this ASG.

Important: You must update the IP configuration, not the NIC directly. Each NIC can have multiple IP configurations, and ASGs are associated at the IP configuration level.
# Associate App VM NIC to App ASG (after VM creation completes) az network nic ip-config update \ --resource-group "rg-network-security" \ --nic-name "vm-app-01VMNic" \ --name "ipconfigvm-app-01" \ --application-security-groups "asg-app-servers"

6. Creating and Configuring NSG Rules

flowchart TD A[Incoming Traffic] --> B{Rule Priority Check} B --> C[Priority 100] B --> D[Priority 200] B --> E[Priority 300] B --> F[Default Rules 65000+] C --> G{Match Conditions?} D --> H{Match Conditions?} E --> I{Match Conditions?} F --> J{Match Conditions?} G -->|Yes| K[Allow/Deny Action] G -->|No| H H -->|Yes| L[Allow/Deny Action] H -->|No| I I -->|Yes| M[Allow/Deny Action] I -->|No| J J -->|Yes| N[Default Action] J -->|No| O[Implicit Deny] K --> P[Traffic Processed] L --> P M --> P N --> P O --> Q[Traffic Blocked] style A fill:#e3f2fd style B fill:#fff3e0 style K fill:#e8f5e8 style L fill:#e8f5e8 style M fill:#e8f5e8 style N fill:#e8f5e8 style O fill:#ffebee style Q fill:#ffebee

NSG Rule Processing Logic:

This flowchart shows how NSG rules are evaluated:

  • Priority Order - Rules are processed in ascending priority order (100, 200, 300, etc.)
  • First Match Wins - Once a rule matches, processing stops and the action is taken
  • Default Rules - Built-in rules (65000+) handle common scenarios if no custom rules match
  • Implicit Deny - If no rules match, traffic is blocked by default

Web Tier NSG Rules

# Allow HTTP traffic from Internet to Web Servers az network nsg rule create \ --resource-group "rg-network-security" \ --nsg-name "nsg-web-tier" \ --name "Allow-HTTP-Inbound" \ --priority 100 \ --source-address-prefixes "Internet" \ --source-port-ranges "*" \ --destination-application-security-groups "asg-web-servers" \ --destination-port-ranges "80" \ --protocol "Tcp" \ --access "Allow" \ --direction "Inbound" \ --description "Allow HTTP traffic from Internet to Web Servers"

Parameters Explanation:

ParameterDescriptionOptions/Values
--priorityRule processing order100-4096 (lower = higher priority)
--source-address-prefixesTraffic sourceIP, CIDR, Service Tag (Internet, VirtualNetwork)
--source-port-rangesSource port* (any), specific port, or range (e.g., 8000-8080)
--destination-application-security-groupsTarget ASGASG name(s) - alternative to IP addresses
--destination-port-rangesTarget portSpecific port or range
--protocolNetwork protocolTcp, Udp, Icmp, Esp, Ah, * (any)
--accessRule actionAllow, Deny
--directionTraffic directionInbound, Outbound

Purpose: Allows HTTP traffic from the internet to reach web servers. This rule uses ASG for destination, making it automatically apply to all VMs in the web servers ASG without specifying IP addresses.

# Allow HTTPS traffic from Internet to Web Servers az network nsg rule create \ --resource-group "rg-network-security" \ --nsg-name "nsg-web-tier" \ --name "Allow-HTTPS-Inbound" \ --priority 110 \ --source-address-prefixes "Internet" \ --source-port-ranges "*" \ --destination-application-security-groups "asg-web-servers" \ --destination-port-ranges "443" \ --protocol "Tcp" \ --access "Allow" \ --direction "Inbound"

Purpose: Allows HTTPS traffic for secure web communication. Priority 110 ensures it's processed after the HTTP rule (priority 100) but will be the second rule evaluated.

# Allow Web Servers to communicate with App Servers az network nsg rule create \ --resource-group "rg-network-security" \ --nsg-name "nsg-web-tier" \ --name "Allow-Web-to-App" \ --priority 200 \ --source-application-security-groups "asg-web-servers" \ --source-port-ranges "*" \ --destination-application-security-groups "asg-app-servers" \ --destination-port-ranges "8080" \ --protocol "Tcp" \ --access "Allow" \ --direction "Outbound"

Purpose: Enables communication from web tier to application tier. This outbound rule allows web servers to send requests to application servers on port 8080, supporting a typical web application architecture.

Application Tier NSG Rules

# Allow traffic from Web Servers to App Servers az network nsg rule create \ --resource-group "rg-network-security" \ --nsg-name "nsg-app-tier" \ --name "Allow-Web-to-App-Inbound" \ --priority 100 \ --source-application-security-groups "asg-web-servers" \ --source-port-ranges "*" \ --destination-application-security-groups "asg-app-servers" \ --destination-port-ranges "8080" \ --protocol "Tcp" \ --access "Allow" \ --direction "Inbound"

Purpose: Complements the outbound rule from web tier. This inbound rule allows application servers to receive traffic from web servers, creating a secure communication channel between tiers.

# Allow App Servers to communicate with Database Servers az network nsg rule create \ --resource-group "rg-network-security" \ --nsg-name "nsg-app-tier" \ --name "Allow-App-to-DB" \ --priority 200 \ --source-application-security-groups "asg-app-servers" \ --source-port-ranges "*" \ --destination-application-security-groups "asg-db-servers" \ --destination-port-ranges "1433" \ --protocol "Tcp" \ --access "Allow" \ --direction "Outbound"

Database Tier NSG Rules

# Allow traffic from App Servers to Database Servers az network nsg rule create \ --resource-group "rg-network-security" \ --nsg-name "nsg-db-tier" \ --name "Allow-App-to-DB-Inbound" \ --priority 100 \ --source-application-security-groups "asg-app-servers" \ --source-port-ranges "*" \ --destination-application-security-groups "asg-db-servers" \ --destination-port-ranges "1433" \ --protocol "Tcp" \ --access "Allow" \ --direction "Inbound"

Purpose: Creates the most restrictive access to database servers, allowing only application servers to connect on the database port (1433 for SQL Server). This implements the principle of least privilege.

Deny Rules for Security Hardening

# Explicitly deny direct RDP/SSH from Internet to all tiers az network nsg rule create \ --resource-group "rg-network-security" \ --nsg-name "nsg-web-tier" \ --name "Deny-Internet-RDP-SSH" \ --priority 4000 \ --source-address-prefixes "Internet" \ --source-port-ranges "*" \ --destination-address-prefixes "*" \ --destination-port-ranges "22" "3389" \ --protocol "Tcp" \ --access "Deny" \ --direction "Inbound"

Purpose: Explicitly blocks direct administrative access from the internet. This rule has lower priority (4000) so legitimate bastion traffic (if configured with higher priority) can still be allowed while blocking general internet access.

Security Best Practice: Always use explicit deny rules for sensitive ports like RDP (3389) and SSH (22) to prevent accidental exposure, even if you believe no allow rules exist.

7. Virtual Network Flow Logs Implementation

graph TB subgraph "Flow Logs Architecture" subgraph "Network Traffic" VM1[Virtual Machine] NIC1[Network Interface] NSG1[Network Security Group] end subgraph "Flow Logs Collection" FL[Flow Logs Service] SA[Storage Account] LA[Log Analytics] end subgraph "Analysis & Monitoring" TA[Traffic Analytics] AM[Azure Monitor] AL[Alert Rules] end end VM1 --> NIC1 NIC1 --> NSG1 NSG1 --> FL FL --> SA FL --> LA SA --> TA LA --> TA TA --> AM AM --> AL style FL fill:#e3f2fd style SA fill:#e8f5e8 style TA fill:#fff3e0 style AL fill:#ffebee

Flow Logs Data Flow:

This diagram illustrates the complete flow logs ecosystem:

  • Data Collection - Flow logs capture network traffic metadata from NSGs
  • Storage Options - Logs can be stored in Storage Account and/or Log Analytics workspace
  • Traffic Analytics - Processes flow logs to provide insights and visualizations
  • Monitoring Integration - Enables alerts and automated responses based on traffic patterns

Create Storage Account for Flow Logs

# Create Storage Account for Flow Logs az storage account create \ --resource-group "rg-network-security" \ --name "saflowlogs$(date +%s)" \ --location "East US" \ --sku "Standard_LRS" \ --kind "StorageV2" \ --access-tier "Hot" \ --tags Purpose=FlowLogs Environment=Production

Parameters Explanation:

ParameterDescriptionRecommendation
--nameStorage account nameMust be globally unique, use timestamp or random suffix
--skuReplication typeStandard_LRS for cost efficiency, Standard_GRS for geo-redundancy
--kindAccount typeStorageV2 for latest features and performance
--access-tierDefault access tierHot for frequently accessed flow logs

Purpose: Creates a dedicated storage account for flow logs. Flow logs generate significant data volume, so proper storage configuration is crucial for cost management and performance.

Create Log Analytics Workspace

# Create Log Analytics Workspace az monitor log-analytics workspace create \ --resource-group "rg-network-security" \ --workspace-name "law-network-security" \ --location "East US" \ --sku "PerGB2018" \ --retention-time 30 \ --tags Purpose=NetworkAnalytics Environment=Production

Parameters Explanation:

ParameterDescriptionOptions
--skuPricing tierPerGB2018 (pay-per-GB), CapacityReservation
--retention-timeData retention days30-730 days (affects cost significantly)

Purpose: Creates a Log Analytics workspace for storing and analyzing flow log data. This enables advanced querying, alerting, and integration with Azure Monitor and Traffic Analytics.

Enable NSG Flow Logs

# Get NSG Resource ID NSG_ID=$(az network nsg show \ --resource-group "rg-network-security" \ --name "nsg-web-tier" \ --query "id" --output tsv) # Get Storage Account ID STORAGE_ID=$(az storage account show \ --resource-group "rg-network-security" \ --name "saflowlogs$(date +%s)" \ --query "id" --output tsv) # Enable Flow Logs az network watcher flow-log create \ --resource-group "NetworkWatcherRG" \ --name "fl-web-tier" \ --nsg $NSG_ID \ --storage-account $STORAGE_ID \ --enabled true \ --retention 7 \ --log-format JSON \ --log-version 2

Parameters Explanation:

ParameterDescriptionBest Practice
--resource-groupNetwork Watcher RGUsually "NetworkWatcherRG" (auto-created)
--retentionStorage retention daysBalance compliance needs with storage costs
--log-formatOutput formatJSON recommended for analysis tools
--log-versionFlow log schema versionVersion 2 includes more metadata

Purpose: Enables NSG flow logging with optimized settings for analysis. Version 2 logs include flow state information and byte/packet counts, providing richer data for security analysis.

Note: Network Watcher must be enabled in the region before creating flow logs. Azure typically auto-creates the NetworkWatcherRG resource group.

Configure Traffic Analytics

# Get Log Analytics Workspace ID LA_WORKSPACE_ID=$(az monitor log-analytics workspace show \ --resource-group "rg-network-security" \ --workspace-name "law-network-security" \ --query "customerId" --output tsv) # Update Flow Log with Traffic Analytics az network watcher flow-log update \ --resource-group "NetworkWatcherRG" \ --name "fl-web-tier" \ --workspace $LA_WORKSPACE_ID \ --interval 10 \ --traffic-analytics true

Purpose: Enables Traffic Analytics for advanced flow log analysis. Traffic Analytics processes raw flow logs to provide insights into traffic patterns, top talkers, blocked traffic, and security threats.

Interpreting Flow Logs

graph LR subgraph "Flow Log Entry Components" A[Timestamp] --> B[Source IP] B --> C[Destination IP] C --> D[Source Port] D --> E[Destination Port] E --> F[Protocol] F --> G[Traffic Decision] G --> H[Flow State] end subgraph "Analysis Perspectives" I[Security Analysis] J[Performance Analysis] K[Compliance Audit] end A --> I B --> I C --> I G --> I F --> J H --> J A --> K G --> K style I fill:#ffebee style J fill:#e8f5e8 style K fill:#fff3e0

Flow Log Analysis Dimensions:

Flow logs provide multiple analysis perspectives:

  • Security Analysis - Identify blocked traffic, failed connections, and potential threats
  • Performance Analysis - Monitor flow states, connection patterns, and throughput
  • Compliance Audit - Track access patterns and verify security policy compliance

Query Flow Logs with KQL

// Query blocked traffic in Log Analytics AzureNetworkAnalytics_CL | where FlowStatus_s == "D" // Denied traffic | where TimeGenerated > ago(1h) | summarize Count = count() by SrcIP_s, DestIP_s, DestPort_d | order by Count desc | take 10 // Query top talking hosts AzureNetworkAnalytics_CL | where TimeGenerated > ago(24h) | summarize TotalBytes = sum(OutboundBytes_d + InboundBytes_d) by SrcIP_s | order by TotalBytes desc | take 20

Purpose: Demonstrates KQL queries for analyzing flow log data. These queries help identify security issues (blocked traffic) and performance patterns (high-volume communications).

8. Remote Server Administration with Azure Bastion

graph TB subgraph "Traditional Access (Insecure)" Internet1[Internet] PublicIP[Public IP + NSG Rules] VM1[Virtual Machine] Internet1 --> PublicIP PublicIP --> VM1 end subgraph "Azure Bastion Access (Secure)" Internet2[Internet] Bastion[Azure Bastion] BastionSubnet[AzureBastionSubnet] PrivateVM[Private Virtual Machine] Internet2 -->|HTTPS/SSL| Bastion Bastion --> BastionSubnet BastionSubnet -->|RDP/SSH over Private IP| PrivateVM end style PublicIP fill:#ffebee style VM1 fill:#ffebee style Bastion fill:#e8f5e8 style PrivateVM fill:#e8f5e8

Bastion vs Traditional Remote Access:

This comparison shows the security benefits of Azure Bastion:

  • Traditional Method - Requires public IPs and open RDP/SSH ports, creating attack surface
  • Azure Bastion - Provides secure access over HTTPS without public IPs on target VMs
  • Network Isolation - VMs remain completely private while still accessible for administration
  • Protocol Security - All traffic encrypted and authenticated through Azure portal

Create Azure Bastion Subnet

# Create dedicated subnet for Azure Bastion (must be named AzureBastionSubnet) az network vnet subnet create \ --resource-group "rg-network-security" \ --vnet-name "vnet-security-demo" \ --name "AzureBastionSubnet" \ --address-prefix "10.0.100.0/24"

Subnet Requirements:

RequirementValueReason
NameAzureBastionSubnetRequired by Azure platform
Minimum Size/27 (32 addresses)Azure Bastion service requirements
Dedicated UseBastion onlyNo other resources allowed

Purpose: Creates the dedicated subnet required for Azure Bastion deployment. This subnet must follow strict naming and sizing requirements and cannot host any other resources.

Create Public IP for Bastion

# Create Public IP for Azure Bastion az network public-ip create \ --resource-group "rg-network-security" \ --name "pip-bastion" \ --sku "Standard" \ --allocation-method "Static" \ --location "East US"

Purpose: Creates the public IP address required for Azure Bastion. This is the only public IP needed for secure access to all private VMs in the VNet.

Deploy Azure Bastion

# Create Azure Bastion az network bastion create \ --resource-group "rg-network-security" \ --name "bastion-security-demo" \ --public-ip-address "pip-bastion" \ --vnet-name "vnet-security-demo" \ --location "East US" \ --sku "Standard"

Parameters Explanation:

ParameterDescriptionOptions
--skuBastion service tierBasic, Standard (Standard enables features like file transfer)
--public-ip-addressAssociated public IPMust be Standard SKU, static allocation

Purpose: Deploys the Azure Bastion service that provides secure RDP/SSH connectivity to VMs without exposing them to the internet. This significantly reduces the attack surface while maintaining administrative access.

Deployment Time: Azure Bastion deployment typically takes 10-15 minutes. The service must be fully deployed before it can be used for VM connections.

Configure NSG Rules for Bastion

# Create NSG for Bastion Subnet az network nsg create \ --resource-group "rg-network-security" \ --name "nsg-bastion-subnet" \ --location "East US" # Allow HTTPS inbound from Internet to Bastion az network nsg rule create \ --resource-group "rg-network-security" \ --nsg-name "nsg-bastion-subnet" \ --name "Allow-HTTPS-Inbound" \ --priority 100 \ --source-address-prefixes "Internet" \ --source-port-ranges "*" \ --destination-address-prefixes "*" \ --destination-port-ranges "443" \ --protocol "Tcp" \ --access "Allow" \ --direction "Inbound" # Allow Gateway Manager inbound az network nsg rule create \ --resource-group "rg-network-security" \ --nsg-name "nsg-bastion-subnet" \ --name "Allow-GatewayManager-Inbound" \ --priority 110 \ --source-address-prefixes "GatewayManager" \ --source-port-ranges "*" \ --destination-address-prefixes "*" \ --destination-port-ranges "443" \ --protocol "Tcp" \ --access "Allow" \ --direction "Inbound" # Allow Bastion to reach target VMs az network nsg rule create \ --resource-group "rg-network-security" \ --nsg-name "nsg-bastion-subnet" \ --name "Allow-SSH-RDP-Outbound" \ --priority 100 \ --source-address-prefixes "*" \ --source-port-ranges "*" \ --destination-address-prefixes "VirtualNetwork" \ --destination-port-ranges "22" "3389" \ --protocol "Tcp" \ --access "Allow" \ --direction "Outbound" # Associate NSG to Bastion Subnet az network vnet subnet update \ --resource-group "rg-network-security" \ --vnet-name "vnet-security-demo" \ --name "AzureBastionSubnet" \ --network-security-group "nsg-bastion-subnet"

Purpose: Configures the required NSG rules for Azure Bastion operation. These rules allow the Bastion service to receive HTTPS connections from users and establish RDP/SSH connections to target VMs.

Required Rules: Azure Bastion requires specific NSG rules to function properly. Missing rules will prevent the service from connecting to target VMs.

Update Target VM NSG for Bastion Access

# Allow RDP/SSH from Bastion subnet to target VMs az network nsg rule create \ --resource-group "rg-network-security" \ --nsg-name "nsg-web-tier" \ --name "Allow-Bastion-RDP-SSH" \ --priority 150 \ --source-address-prefixes "10.0.100.0/24" \ --source-port-ranges "*" \ --destination-application-security-groups "asg-web-servers" \ --destination-port-ranges "22" "3389" \ --protocol "Tcp" \ --access "Allow" \ --direction "Inbound" # Repeat for other tiers az network nsg rule create \ --resource-group "rg-network-security" \ --nsg-name "nsg-app-tier" \ --name "Allow-Bastion-RDP-SSH" \ --priority 150 \ --source-address-prefixes "10.0.100.0/24" \ --source-port-ranges "*" \ --destination-application-security-groups "asg-app-servers" \ --destination-port-ranges "22" "3389" \ --protocol "Tcp" \ --access "Allow" \ --direction "Inbound"

Purpose: Enables Azure Bastion to connect to target VMs by allowing RDP/SSH traffic from the Bastion subnet. This rule is added to each tier's NSG to enable administrative access through Bastion.

9. Azure Virtual Network Manager Implementation

graph TB subgraph "Azure Virtual Network Manager" AVNM[VNet Manager Instance] subgraph "Network Groups" NG1[Production Group] NG2[Development Group] NG3[DMZ Group] end subgraph "Configurations" SC[Security Configuration] CC[Connectivity Configuration] end subgraph "Managed VNets" VNet1[Production VNet] VNet2[Development VNet] VNet3[DMZ VNet] end end AVNM --> NG1 AVNM --> NG2 AVNM --> NG3 AVNM --> SC AVNM --> CC NG1 --> VNet1 NG2 --> VNet2 NG3 --> VNet3 SC --> VNet1 SC --> VNet2 SC --> VNet3 CC --> VNet1 CC --> VNet2 CC --> VNet3 style AVNM fill:#e3f2fd style SC fill:#ffebee style CC fill:#e8f5e8

Azure Virtual Network Manager Architecture:

This diagram shows how Azure VNet Manager provides centralized network management:

  • Network Groups - Logical collections of VNets for policy application
  • Security Configurations - Centrally managed security rules applied across network groups
  • Connectivity Configurations - Hub-spoke or mesh connectivity patterns
  • Centralized Management - Single point of control for multiple VNets across subscriptions

Create Azure Virtual Network Manager

# Create Azure Virtual Network Manager az network manager create \ --resource-group "rg-network-security" \ --name "avnm-enterprise-security" \ --location "East US" \ --description "Enterprise Network Security Management" \ --scope-accesses "SecurityAdmin" "Connectivity" \ --network-manager-scopes subscriptions="/subscriptions/$(az account show --query id -o tsv)"

Parameters Explanation:

ParameterDescriptionOptions
--scope-accessesManagement capabilitiesSecurityAdmin, Connectivity
--network-manager-scopesManagement scopeSubscription, Management Group, or specific resources

Purpose: Creates the central Azure Virtual Network Manager instance that will manage security and connectivity across multiple VNets. The scope defines which subscriptions and management groups this instance can manage.

Create Network Groups

# Create Network Group for Production VNets az network manager group create \ --resource-group "rg-network-security" \ --network-manager-name "avnm-enterprise-security" \ --name "ng-production" \ --description "Production Virtual Networks" \ --group-members '[{ "resourceId": "/subscriptions/'$(az account show --query id -o tsv)'/resourceGroups/rg-network-security/providers/Microsoft.Network/virtualNetworks/vnet-security-demo" }]' # Create Network Group for Management VNets az network manager group create \ --resource-group "rg-network-security" \ --network-manager-name "avnm-enterprise-security" \ --name "ng-management" \ --description "Management and Bastion Networks"

Purpose: Creates logical groupings of VNets that will be managed together. Network groups enable you to apply consistent policies across multiple VNets without managing each individually.

Create Security Admin Configuration

# Create Security Admin Configuration az network manager security-admin-config create \ --resource-group "rg-network-security" \ --network-manager-name "avnm-enterprise-security" \ --name "sec-admin-config-enterprise" \ --description "Enterprise Security Administration Rules" \ --apply-on-network-intent-policy-based-services "AllowRulesOnly"

Parameters Explanation:

ParameterDescriptionOptions
--apply-on-network-intent-policy-based-servicesPolicy enforcement modeAllowRulesOnly, All

Purpose: Creates a security configuration that can enforce security rules across all VNets in the managed scope. This provides centralized security policy management.

Create Security Admin Rule Collection

# Create Rule Collection for Production Security az network manager security-admin-config rule-collection create \ --resource-group "rg-network-security" \ --network-manager-name "avnm-enterprise-security" \ --configuration-name "sec-admin-config-enterprise" \ --name "rc-production-security" \ --description "Production Environment Security Rules" \ --applies-to-groups '[{ "networkGroupId": "/subscriptions/'$(az account show --query id -o tsv)'/resourceGroups/rg-network-security/providers/Microsoft.Network/networkManagers/avnm-enterprise-security/networkGroups/ng-production" }]'

Purpose: Creates a container for security rules that will be applied to specific network groups. Rule collections allow for organized management of related security policies.

Create Admin Security Rules

# Create high-priority security rule to block malicious traffic az network manager security-admin-config rule-collection rule create \ --resource-group "rg-network-security" \ --network-manager-name "avnm-enterprise-security" \ --configuration-name "sec-admin-config-enterprise" \ --rule-collection-name "rc-production-security" \ --name "rule-block-malicious-ips" \ --description "Block Known Malicious IP Ranges" \ --access "Deny" \ --direction "Inbound" \ --priority 10 \ --protocol "Any" \ --sources '[{ "addressPrefixType": "IPPrefix", "addressPrefix": "192.0.2.0/24" }]' \ --destinations '[{ "addressPrefixType": "IPPrefix", "addressPrefix": "*" }]' # Create rule to enforce HTTPS only for web traffic az network manager security-admin-config rule-collection rule create \ --resource-group "rg-network-security" \ --network-manager-name "avnm-enterprise-security" \ --configuration-name "sec-admin-config-enterprise" \ --rule-collection-name "rc-production-security" \ --name "rule-https-only" \ --description "Deny HTTP Traffic, Enforce HTTPS" \ --access "Deny" \ --direction "Inbound" \ --priority 20 \ --protocol "Tcp" \ --sources '[{ "addressPrefixType": "ServiceTag", "addressPrefix": "Internet" }]' \ --destinations '[{ "addressPrefixType": "IPPrefix", "addressPrefix": "*" }]' \ --destination-ports '["80"]'

Purpose: Creates high-priority security rules that override local NSG rules. These admin rules can enforce organization-wide security policies that cannot be modified at the local level, ensuring consistent security posture.

Admin Rule Priority: Security admin rules always take precedence over local NSG rules. Use them carefully to avoid unintended blocking of legitimate traffic.

Deploy Configuration

# Deploy the security configuration az network manager post-commit \ --resource-group "rg-network-security" \ --network-manager-name "avnm-enterprise-security" \ --target-locations "East US" \ --configuration-ids '/subscriptions/'$(az account show --query id -o tsv)'/resourceGroups/rg-network-security/providers/Microsoft.Network/networkManagers/avnm-enterprise-security/securityAdminConfigurations/sec-admin-config-enterprise' \ --commit-type "SecurityAdmin"

Purpose: Deploys the security configuration to the target regions. This action applies the security admin rules to all VNets in the specified network groups within those regions.

10. Command Execution Flow and Dependencies

graph TD A[1. Create Resource Group] --> B[2. Create VNet] B --> C[3. Create Subnets] C --> D[4. Create NSGs] C --> E[5. Create ASGs] D --> F[6. Create NSG Rules] E --> F D --> G[7. Associate NSGs to Subnets] F --> H[8. Create VMs] G --> H E --> I[9. Associate ASGs to NICs] H --> I J[10. Create Storage Account] --> K[11. Create Log Analytics] K --> L[12. Enable Flow Logs] C --> M[13. Create Bastion Subnet] M --> N[14. Create Bastion Public IP] N --> O[15. Deploy Azure Bastion] O --> P[16. Configure Bastion NSG Rules] Q[17. Create VNet Manager] --> R[18. Create Network Groups] R --> S[19. Create Security Config] S --> T[20. Create Rule Collections] T --> U[21. Create Admin Rules] U --> V[22. Deploy Configuration] style A fill:#e3f2fd style B fill:#e3f2fd style C fill:#e3f2fd style F fill:#e8f5e8 style I fill:#e8f5e8 style L fill:#fff3e0 style O fill:#ffebee style V fill:#f3e5f5

Command Execution Dependencies:

This flowchart shows the required order for implementing the complete solution:

  • Foundation (1-3) - Basic infrastructure must be created first
  • Security Groups (4-5) - NSGs and ASGs can be created in parallel
  • Rule Configuration (6-9) - Rules and associations require existing infrastructure
  • Monitoring (10-12) - Flow logs require storage and can be configured independently
  • Remote Access (13-16) - Bastion requires dedicated subnet and specific configuration
  • Centralized Management (17-22) - VNet Manager can be implemented after basic infrastructure

Complete Implementation Script

Phase 1 Foundation Infrastructure

Phase 2 Security Configuration

Phase 3 Monitoring and Logging

Phase 4 Remote Access

Phase 5 Centralized Management

#!/bin/bash # Complete Azure Network Security Implementation Script # Phase 1: Foundation Infrastructure echo "Phase 1: Creating Foundation Infrastructure..." # Set variables RG_NAME="rg-network-security" LOCATION="East US" VNET_NAME="vnet-security-demo" # Create Resource Group az group create --name $RG_NAME --location "$LOCATION" # Create VNet and Subnets az network vnet create --resource-group $RG_NAME --name $VNET_NAME --address-prefix "10.0.0.0/16" az network vnet subnet create --resource-group $RG_NAME --vnet-name $VNET_NAME --name "subnet-web" --address-prefix "10.0.1.0/24" az network vnet subnet create --resource-group $RG_NAME --vnet-name $VNET_NAME --name "subnet-app" --address-prefix "10.0.2.0/24" az network vnet subnet create --resource-group $RG_NAME --vnet-name $VNET_NAME --name "subnet-db" --address-prefix "10.0.3.0/24" # Phase 2: Security Configuration echo "Phase 2: Configuring Security Groups and Rules..." # Create NSGs az network nsg create --resource-group $RG_NAME --name "nsg-web-tier" az network nsg create --resource-group $RG_NAME --name "nsg-app-tier" az network nsg create --resource-group $RG_NAME --name "nsg-db-tier" # Create ASGs az network asg create --resource-group $RG_NAME --name "asg-web-servers" az network asg create --resource-group $RG_NAME --name "asg-app-servers" az network asg create --resource-group $RG_NAME --name "asg-db-servers" # Associate NSGs to Subnets az network vnet subnet update --resource-group $RG_NAME --vnet-name $VNET_NAME --name "subnet-web" --network-security-group "nsg-web-tier" az network vnet subnet update --resource-group $RG_NAME --vnet-name $VNET_NAME --name "subnet-app" --network-security-group "nsg-app-tier" az network vnet subnet update --resource-group $RG_NAME --vnet-name $VNET_NAME --name "subnet-db" --network-security-group "nsg-db-tier" # Create comprehensive NSG rules # [Include all the NSG rules from previous sections] echo "Implementation complete! Verify resources in Azure Portal."

Purpose: Provides a complete automation script that implements the entire solution in the correct sequence. This script can be used for consistent deployments across environments.

Validation and Testing Commands

# Validate NSG effective rules az network nic list-effective-nsg \ --resource-group "rg-network-security" \ --name "vm-web-01VMNic" # Test IP flow verification az network watcher test-ip-flow \ --resource-group "NetworkWatcherRG" \ --vm "vm-web-01" \ --direction "Inbound" \ --protocol "TCP" \ --local "10.0.1.4:80" \ --remote "0.0.0.0:12345" # Verify flow logs status az network watcher flow-log show \ --resource-group "NetworkWatcherRG" \ --name "fl-web-tier" # Check Network Security Group associations az network nsg show \ --resource-group "rg-network-security" \ --name "nsg-web-tier" \ --query "{Name:name, Subnets:subnets[].id, NetworkInterfaces:networkInterfaces[].id}"

Purpose: Provides essential validation commands to verify that the configuration is working as expected. These commands help troubleshoot connectivity issues and confirm security policy effectiveness.

Summary and Best Practices

Key Implementation Points:

  • Defense in Depth - Use both subnet-level and NIC-level NSGs where appropriate
  • Least Privilege - Start with deny-all and add only necessary allow rules
  • Application Security Groups - Use ASGs for scalable, maintainable rule management
  • Flow Logs - Enable comprehensive logging for security analysis and compliance
  • Azure Bastion - Eliminate public IPs on VMs while maintaining administrative access
  • Centralized Management - Use Azure VNet Manager for enterprise-scale security governance

Common Pitfalls to Avoid:

  • Not planning IP address spaces carefully before implementation
  • Forgetting to enable Network Watcher before configuring flow logs
  • Using overly permissive rules instead of specific port and protocol restrictions
  • Not testing connectivity after implementing security rules
  • Failing to monitor and analyze flow logs for security insights