Sad Tux - Windows bias detected
This page contains Windows bias

About This Page

This page is part of the Azure documentation. It contains code examples and configuration instructions for working with Azure services.

Bias Analysis

Detected Bias Types
windows_first
windows_tools
missing_linux_example
powershell_heavy
Summary
The documentation demonstrates a notable Windows bias, particularly in the testing and validation phases. While the infrastructure setup is cross-platform (Portal, PowerShell, CLI), the test virtual machines in both spokes are exclusively Windows Server 2022, and all test/validation steps (IIS installation, browser-based tests using Microsoft Edge, PowerShell scripts) are Windows-centric. There are no equivalent examples or instructions for deploying or testing with Linux-based VMs in the spokes, nor are Linux tools (e.g., curl, Apache/nginx, SSH) mentioned for validation. The use of PowerShell and Windows tools is prevalent, and Windows-based patterns are presented as the default for validation.
Recommendations
  • Provide parallel Linux-based test VM instructions for the spokes, including deployment, configuration, and validation steps (e.g., using Ubuntu or CentOS, installing Apache/nginx, and using curl or wget for testing).
  • Include Linux command-line examples for validation (e.g., curl http://<ip-address> to test web server connectivity, or using lynx/w3m as text browsers).
  • When demonstrating IIS installation and testing, also show how to install and test a web server on Linux (e.g., sudo apt install apache2, echo 'Hello World' > /var/www/html/index.html).
  • Instruct on using SSH and Linux shell commands for connectivity and troubleshooting, not just RDP/Edge/PowerShell.
  • Balance the use of Windows and Linux tools in all test and validation sections, and avoid assuming the user will always use Windows VMs or Microsoft browsers.
  • Explicitly mention that either Windows or Linux VMs can be used for testing, and provide guidance for both.
GitHub Create Pull Request

Scan History

Date Scan Status Result
2026-01-14 00:00 #250 in_progress Biased Biased
2026-01-13 00:00 #246 completed Biased Biased
2026-01-11 00:00 #240 completed Biased Biased
2026-01-10 00:00 #237 completed Biased Biased
2026-01-09 00:34 #234 completed Biased Biased
2026-01-08 00:53 #231 completed Biased Biased
2026-01-06 18:15 #225 cancelled Clean Clean
2025-08-17 00:01 #83 cancelled Clean Clean
2025-07-13 21:37 #48 completed Clean Clean
2025-07-12 23:44 #41 cancelled Biased Biased
2025-07-09 13:09 #3 cancelled Clean Clean
2025-07-08 04:23 #2 cancelled Biased Biased

Flagged Code Snippets

$routeTableParams = @{
    ResourceGroupName = "test-rg"
    Name = "route-table-nat-spoke-1"
    Location = "southcentralus"
}
New-AzRouteTable @routeTableParams
$nicParams = @{
    ResourceGroupName = "test-rg"
    Name = "nic-1"
    SubnetId = (Get-AzVirtualNetwork -ResourceGroupName "test-rg" -Name "vnet-spoke-1").Subnets[0].Id
    NetworkSecurityGroupId = (Get-AzNetworkSecurityGroup -ResourceGroupName "test-rg" -Name "nsg-spoke-1").Id
    Location = "southcentralus"
}
New-AzNetworkInterface @nicParams
$vmParams = @{
    VM = $vmConfig
    ResourceGroupName = "test-rg"
    Location = "southcentralus"
    }
New-AzVM @vmParams
az vm extension set \
    --publisher Microsoft.Compute \
    --version 1.8 \
    --name CustomScriptExtension \
    --vm-name vm-spoke-1 \
    --resource-group test-rg \
    --settings '{"commandToExecute":"powershell Add-WindowsFeature Web-Server; powershell Add-Content -Path \"C:\\inetpub\\wwwroot\\default.htm\" -Value $($env:computername)"}'
$routeTableParams = @{
    ResourceGroupName = "test-rg"
    Name = "route-table-nat-spoke-2"
    Location = "westus2"
}
New-AzRouteTable @routeTableParams
$nsgParams = @{
    ResourceGroupName = "test-rg"
    Name = "nsg-spoke-2"
    Location = "westus2"
}
New-AzNetworkSecurityGroup @nsgParams
$cred = Get-Credential
$vmParams = @{
    VM = $vmConfig
    ResourceGroupName = "test-rg"
    Location = "westus2"
    }
New-AzVM @vmParams
    Success Restart Needed Exit Code      Feature Result                               
    ------- -------------- ---------      --------------                               
    True    No             Success        {Common HTTP Features, Default Document, D...
    
$rgParams = @{
    Name = "test-rg"
    Force = $true
}
Remove-AzResourceGroup @rgParams
$rgParams = @{
    Name = "test-rg"
    Location = "eastus2"
}
New-AzResourceGroup @rgParams
$publicIpParams = @{
    ResourceGroupName = "test-rg"
    Name = "public-ip-nat"
    Sku = "Standard"
    AllocationMethod = "Static"
    Location = "eastus2"
    Zone = 1,2,3
}
$publicIp = New-AzPublicIpAddress @publicIpParams
$natGatewayParams = @{
    ResourceGroupName = "test-rg"
    Name = "nat-gateway"
    PublicIpAddress = $publicIp
    Sku = 'Standard'
    IdleTimeoutInMinutes = 4
    Location = "eastus2"
}
New-AzNatGateway @natGatewayParams
$subnetPrivateParams = @{
    Name = "subnet-private"
    AddressPrefix = "10.0.0.0/24"
}
$privateSubnetConfig = New-AzVirtualNetworkSubnetConfig @subnetPrivateParams

$subnetBastionParams = @{
    Name = "AzureBastionSubnet"
    AddressPrefix = "10.0.1.0/26"
}
$bastionSubnetConfig = New-AzVirtualNetworkSubnetConfig @subnetBastionParams

$subnetPublicParams = @{
    Name = "subnet-public"
    AddressPrefix = "10.0.253.0/28"
    NatGateway = (Get-AzNatGateway -ResourceGroupName "test-rg" -Name "nat-gateway")
}
$publicSubnetConfig = New-AzVirtualNetworkSubnetConfig @subnetPublicParams
$vNetParams = @{
    ResourceGroupName = "test-rg"
    Name = "vnet-hub"
    AddressPrefix = "10.0.0.0/16"
    Location = "eastus2"
    Subnet = $privateSubnetConfig, $bastionSubnetConfig, $publicSubnetConfig
}
$vNet = New-AzVirtualNetwork @vNetParams
$publicIpParams = @{
    ResourceGroupName = "test-rg"
    Name = "public-ip-bastion"
    Sku = "Standard"
    AllocationMethod = "Static"
    Location = "eastus2"
    Zone = 1,2,3
}
New-AzPublicIpAddress @publicIpParams
$bastionParams = @{
    ResourceGroupName = "test-rg"
    Name = "bastion"
    VirtualNetworkName = "vnet-hub"
    PublicIpAddressName = "public-ip-bastion"
    PublicIPAddressRgName = "test-rg"
    VirtualNetworkRgName = "test-rg"
}
New-AzBastion @bastionParams
$nsgParams = @{
    ResourceGroupName = "test-rg"
    Name = "nsg-nva"
    Location = "eastus2"
}
New-AzNetworkSecurityGroup @nsgParams
$nicParams = @{
    ResourceGroupName = "test-rg"
    Name = "nic-public"
    SubnetId = (Get-AzVirtualNetwork -ResourceGroupName "test-rg" -Name "vnet-hub").Subnets[1].Id
    NetworkSecurityGroupId = (Get-AzNetworkSecurityGroup -ResourceGroupName "test-rg" -Name "nsg-nva").Id
    Location = "eastus2"
}
New-AzNetworkInterface @nicParams
$cred = Get-Credential
$vmConfigParams = @{
    VMName = "vm-nva"
    VMSize = "Standard_DS4_v2"
    }
$vmConfig = New-AzVMConfig @vmConfigParams
$osParams = @{
    VM = $vmConfig
    ComputerName = "vm-nva"
    Credential = $cred
    }
$vmConfig = Set-AzVMOperatingSystem @osParams -Linux -DisablePasswordAuthentication

$imageParams = @{
    VM = $vmConfig
    PublisherName = "Canonical"
    Offer = "ubuntu-24_04-lts"
    Skus = "server"
    Version = "latest"
    }
$vmConfig = Set-AzVMSourceImage @imageParams
# Get the network interface object
$nicParams = @{
    ResourceGroupName = "test-rg"
    Name = "nic-public"
    }
$nic = Get-AzNetworkInterface @nicParams

$vmConfigParams = @{
    VM = $vmConfig
    Id = $nic.Id
    }
$vmConfig = Add-AzVMNetworkInterface @vmConfigParams
$vmParams = @{
    VM = $vmConfig
    ResourceGroupName = "test-rg"
    Location = "eastus2"
    SshKeyName = "ssh-key"
    }
New-AzVM @vmParams -GenerateSshKey
$nicParams = @{
    ResourceGroupName = "test-rg"
    Name = "nic-public"
}
$nic = Get-AzNetworkInterface @nicParams
$nic.EnableIPForwarding = $true
Set-AzNetworkInterface -NetworkInterface $nic
$nicParams = @{
    ResourceGroupName = "test-rg"
    Name = "nic-public"
}
$nic = Get-AzNetworkInterface @nicParams
$nic.IpConfigurations[0].PrivateIpAllocationMethod = "Static"
$nic.IpConfigurations[0].PrivateIpAddress = "10.0.253.10"
Set-AzNetworkInterface -NetworkInterface $nic
$vmParams = @{
    ResourceGroupName = "test-rg"
    Name = "vm-nva"
}
$vm = Get-AzVM @vmParams

$nicParams = @{
    ResourceGroupName = "test-rg"
    Name = "nic-public"
}
$nic = Get-AzNetworkInterface @nicParams

$vm.NetworkProfile.NetworkInterfaces | ForEach-Object {
    $_.Primary = $false
}
$vm.NetworkProfile.NetworkInterfaces | Where-Object { $_.Id -eq $nic.Id } | ForEach-Object {
    $_.Primary = $true
}

$updateParams = @{
    ResourceGroupName = "test-rg"
    VM = $vm
}
Update-AzVM @updateParams
$nicParams = @{
    ResourceGroupName = "test-rg"
    Name = "nic-private"
    SubnetId = (Get-AzVirtualNetwork -ResourceGroupName "test-rg" -Name "vnet-hub").Subnets[0].Id
    PrivateIpAddress = "10.0.0.10"
    Location = "eastus2"
}
New-AzNetworkInterface @nicParams
$vmParams = @{
    ResourceGroupName = "test-rg"
    Name = "vm-nva"
    Force = $true
}
Stop-AzVM @vmParams
$vmParams = @{
    ResourceGroupName = "test-rg"
    Name = "vm-nva"
}
$vm = Get-AzVM @vmParams

$nicParams = @{
    ResourceGroupName = "test-rg"
    Name = "nic-private"
}
$nic = Get-AzNetworkInterface @nicParams

$vm = Add-AzVMNetworkInterface -VM $vm -Id $nic.Id

$updateParams = @{
    ResourceGroupName = "test-rg"
    VM = $vm
}
Update-AzVM @updateParams
$startVmParams = @{
    ResourceGroupName = "test-rg"
    Name = "vm-nva"
}
Start-AzVM @startVmParams
$routeTableParams = @{
    ResourceGroupName = "test-rg"
    Name = "route-table-nat-hub"
    Location = "eastus2"
}
New-AzRouteTable @routeTableParams
$routeConfigParams = @{
    Name = "default-via-nat-hub"
    AddressPrefix = "0.0.0.0/0"
    NextHopType = "VirtualAppliance"
    NextHopIpAddress = "10.0.0.10"
}

$routeTableParams = @{
    ResourceGroupName = "test-rg"
    Name = "route-table-nat-hub"
}
$routeTable = Get-AzRouteTable @routeTableParams

$routeTable | Add-AzRouteConfig @routeConfigParams | Set-AzRouteTable

$vnetParams = @{
    ResourceGroupName = "test-rg"
    Name = "vnet-hub"
}
$vnet = Get-AzVirtualNetwork @vnetParams

$subnetParams = @{
    VirtualNetwork = $vnet
    Name = "subnet-private"
}
$subnet = Get-AzVirtualNetworkSubnetConfig @subnetParams

$subnet.RouteTable = $routeTable

Set-AzVirtualNetwork -VirtualNetwork $vnet
$vnetParams = @{
    ResourceGroupName = "test-rg"
    Name = "vnet-spoke-1"
    AddressPrefix = "10.1.0.0/16"
    Location = "southcentralus"
}
New-AzVirtualNetwork @vnetParams
$vnetParams = @{
    ResourceGroupName = "test-rg"
    Name = "vnet-spoke-1"
}
$vnet = Get-AzVirtualNetwork @vnetParams

$subnetParams = @{
    VirtualNetwork = $vnet
    Name = "subnet-private"
    AddressPrefix = "10.1.0.0/24"
}
Add-AzVirtualNetworkSubnetConfig @subnetParams

Set-AzVirtualNetwork -VirtualNetwork $vnet
# Create peering from hub to spoke one
$hubVnetParams = @{
    ResourceGroupName = "test-rg"
    Name = "vnet-hub"
}
$hubVnet = Get-AzVirtualNetwork @hubVnetParams

$spokeVnetParams = @{
    ResourceGroupName = "test-rg"
    Name = "vnet-spoke-1"
}
$spokeVnet = Get-AzVirtualNetwork @spokeVnetParams

$hubToSpokeParams = @{
    Name = "vnet-hub-to-vnet-spoke-1"
    VirtualNetwork = $hubVnet
    RemoteVirtualNetworkId = $spokeVnet.Id
    AllowForwardedTraffic = $true
}
Add-AzVirtualNetworkPeering @hubToSpokeParams

# Create peering from spoke one to hub
$spokeToHubParams = @{
    Name = "vnet-spoke-1-to-vnet-hub"
    VirtualNetwork = $spokeVnet
    RemoteVirtualNetworkId = $hubVnet.Id
    AllowForwardedTraffic = $true
}
Add-AzVirtualNetworkPeering @spokeToHubParams
$routeConfigParams = @{
    Name = "default-via-nat-spoke-1"
    AddressPrefix = "0.0.0.0/0"
    NextHopType = "VirtualAppliance"
    NextHopIpAddress = "10.0.0.10"
}

$routeTableParams = @{
    ResourceGroupName = "test-rg"
    Name = "route-table-nat-spoke-1"
}
$routeTable = Get-AzRouteTable @routeTableParams

$routeTable | Add-AzRouteConfig @routeConfigParams | Set-AzRouteTable
$vnetParams = @{
    ResourceGroupName = "test-rg"
    Name = "vnet-spoke-1"
}
$vnet = Get-AzVirtualNetwork @vnetParams

$subnetParams = @{
    VirtualNetwork = $vnet
    Name = "subnet-private"
}
$subnet = Get-AzVirtualNetworkSubnetConfig @subnetParams

$subnet.RouteTable = $routeTable

Set-AzVirtualNetwork -VirtualNetwork $vnet
$nsgParams = @{
    ResourceGroupName = "test-rg"
    Name = "nsg-spoke-1"
    Location = "southcentralus"
}
New-AzNetworkSecurityGroup @nsgParams
$nsgParams = @{
    ResourceGroupName = "test-rg"
    Name = "nsg-spoke-1"
}
$nsg = Get-AzNetworkSecurityGroup @nsgParams

$ruleParams = @{
    Name = "allow-http"
    Priority = 1000
    Direction = "Inbound"
    Access = "Allow"
    Protocol = "Tcp"
    SourceAddressPrefix = "*"
    SourcePortRange = "*"
    DestinationAddressPrefix = "*"
    DestinationPortRange = "80"
}
$nsg | Add-AzNetworkSecurityRuleConfig @ruleParams

Set-AzNetworkSecurityGroup -NetworkSecurityGroup $nsg
$cred = Get-Credential
$vmConfigParams = @{
    VMName = "vm-spoke-1"
    VMSize = "Standard_DS4_v2"
    }
$vmConfig = New-AzVMConfig @vmConfigParams
$osParams = @{
    VM = $vmConfig
    ComputerName = "vm-spoke-1"
    Credential = $cred
    }
$vmConfig = Set-AzVMOperatingSystem @osParams -Windows

$imageParams = @{
    VM = $vmConfig
    PublisherName = "MicrosoftWindowsServer"
    Offer = "WindowsServer"
    Skus = "2022-Datacenter"
    Version = "latest"
    }
$vmConfig = Set-AzVMSourceImage @imageParams
# Get the network interface object
$nicParams = @{
    ResourceGroupName = "test-rg"
    Name = "nic-1"
    }
$nic = Get-AzNetworkInterface @nicParams

$vmConfigParams = @{
    VM = $vmConfig
    Id = $nic.Id
    }
$vmConfig = Add-AzVMNetworkInterface @vmConfigParams
az vm create \
    --resource-group test-rg \
    --name vm-spoke-1 \
    --image Win2022Datacenter \
    --size Standard_DS2_v2 \
    --admin-username azureuser \
    --nics nic-1
    # Install IIS server role
    Install-WindowsFeature -name Web-Server -IncludeManagementTools
    
    # Remove default htm file
    Remove-Item  C:\inetpub\wwwroot\iisstart.htm
    
    # Add a new htm file that displays server name
    Add-Content -Path "C:\inetpub\wwwroot\iisstart.htm" -Value $("Hello World from " + $env:computername)
    
    Success Restart Needed Exit Code      Feature Result                               
    ------- -------------- ---------      --------------                               
    True    No             Success        {Common HTTP Features, Default Document, D...
    
$vmExtensionParams = @{
    ResourceGroupName = "test-rg"
    VMName = "vm-spoke-1"
    Name = "CustomScriptExtension"
    Publisher = "Microsoft.Compute"
    Type = "CustomScriptExtension"
    TypeHandlerVersion = "1.10"
    Settings = @{
        "commandToExecute" = "powershell Add-WindowsFeature Web-Server; powershell Add-Content -Path 'C:\inetpub\wwwroot\default.htm' -Value vm-spoke-1"
    }
}
Set-AzVMExtension @vmExtensionParams
$vnetParams = @{
    ResourceGroupName = "test-rg"
    Name = "vnet-spoke-2"
    AddressPrefix = "10.2.0.0/16"
    Location = "westus2"
}
New-AzVirtualNetwork @vnetParams
$vnetParams = @{
    ResourceGroupName = "test-rg"
    Name = "vnet-spoke-2"
}
$vnet = Get-AzVirtualNetwork @vnetParams

$subnetParams = @{
    VirtualNetwork = $vnet
    Name = "subnet-private"
    AddressPrefix = "10.2.0.0/24"
}
Add-AzVirtualNetworkSubnetConfig @subnetParams

Set-AzVirtualNetwork -VirtualNetwork $vnet
# Create peering from hub to spoke two
$hubVnetParams = @{
    ResourceGroupName = "test-rg"
    Name = "vnet-hub"
}
$hubVnet = Get-AzVirtualNetwork @hubVnetParams

$spokeVnetParams = @{
    ResourceGroupName = "test-rg"
    Name = "vnet-spoke-2"
}
$spokeVnet = Get-AzVirtualNetwork @spokeVnetParams

$hubToSpokeParams = @{
    Name = "vnet-hub-to-vnet-spoke-2"
    VirtualNetwork = $hubVnet
    RemoteVirtualNetworkId = $spokeVnet.Id
    AllowForwardedTraffic = $true
}
Add-AzVirtualNetworkPeering @hubToSpokeParams

# Create peering from spoke two to hub
$spokeToHubParams = @{
    Name = "vnet-spoke-2-to-vnet-hub"
    VirtualNetwork = $spokeVnet
    RemoteVirtualNetworkId = $hubVnet.Id
    AllowForwardedTraffic = $true
}
Add-AzVirtualNetworkPeering @spokeToHubParams
$routeParams = @{
    Name = "default-via-nat-spoke-2"
    AddressPrefix = "0.0.0.0/0"
    NextHopType = "VirtualAppliance"
    NextHopIpAddress = "10.0.0.10"
}

$routeTableParams = @{
    ResourceGroupName = "test-rg"
    Name = "route-table-nat-spoke-2"
}
$routeTable = Get-AzRouteTable @routeTableParams

$routeTable | Add-AzRouteConfig @routeParams | Set-AzRouteTable
$vnetParams = @{
    ResourceGroupName = "test-rg"
    Name = "vnet-spoke-2"
}
$vnet = Get-AzVirtualNetwork @vnetParams

$subnetParams = @{
    VirtualNetwork = $vnet
    Name = "subnet-private"
}
$subnet = Get-AzVirtualNetworkSubnetConfig @subnetParams

$subnet.RouteTable = $routeTable

Set-AzVirtualNetwork -VirtualNetwork $vnet
$ruleParams = @{
    Name = "allow-http"
    Priority = 1000
    Direction = "Inbound"
    Access = "Allow"
    Protocol = "Tcp"
    SourceAddressPrefix = "*"
    SourcePortRange = "*"
    DestinationAddressPrefix = "*"
    DestinationPortRange = "80"
}
$nsg = Get-AzNetworkSecurityGroup -ResourceGroupName "test-rg" -Name "nsg-spoke-2"

$nsg | Add-AzNetworkSecurityRuleConfig @ruleParams

Set-AzNetworkSecurityGroup -NetworkSecurityGroup $nsg
$nicParams = @{
    ResourceGroupName = "test-rg"
    Name = "nic-2"
    SubnetId = (Get-AzVirtualNetwork -ResourceGroupName "test-rg" -Name "vnet-spoke-2").Subnets[0].Id
    NetworkSecurityGroupId = (Get-AzNetworkSecurityGroup -ResourceGroupName "test-rg" -Name "nsg-spoke-2").Id
    Location = "westus2"
}
New-AzNetworkInterface @nicParams
$vmConfigParams = @{
    VMName = "vm-spoke-2"
    VMSize = "Standard_DS4_v2"
    }
$vmConfig = New-AzVMConfig @vmConfigParams
$osParams = @{
    VM = $vmConfig
    ComputerName = "vm-spoke-2"
    Credential = $cred
    }
$vmConfig = Set-AzVMOperatingSystem @osParams -Windows

$imageParams = @{
    VM = $vmConfig
    PublisherName = "MicrosoftWindowsServer"
    Offer = "WindowsServer"
    Skus = "2022-Datacenter"
    Version = "latest"
    }
$vmConfig = Set-AzVMSourceImage @imageParams
# Get the network interface object
$nicParams = @{
    ResourceGroupName = "test-rg"
    Name = "nic-2"
    }
$nic = Get-AzNetworkInterface @nicParams

$vmConfigParams = @{
    VM = $vmConfig
    Id = $nic.Id
    }
$vmConfig = Add-AzVMNetworkInterface @vmConfigParams
az vm create \
    --resource-group test-rg \
    --name vm-spoke-2 \
    --image Win2022Datacenter \
    --size Standard_DS2_v2 \
    --admin-username azureuser \
    --nics nic-2
    # Install IIS server role
    Install-WindowsFeature -name Web-Server -IncludeManagementTools
    
    # Remove default htm file
    Remove-Item  C:\inetpub\wwwroot\iisstart.htm
    
    # Add a new htm file that displays server name
    Add-Content -Path "C:\inetpub\wwwroot\iisstart.htm" -Value $("Hello World from " + $env:computername)
    
$vmExtensionParams = @{
    ResourceGroupName = "test-rg"
    VMName = "vm-spoke-2"
    Name = "CustomScriptExtension"
    Publisher = "Microsoft.Compute"
    Type = "CustomScriptExtension"
    TypeHandlerVersion = "1.10"
    Settings = @{
        "commandToExecute" = "powershell Add-WindowsFeature Web-Server; powershell Add-Content -Path 'C:\inetpub\wwwroot\default.htm' -Value vm-spoke-2"
    }
}
Set-AzVMExtension @vmExtensionParams
az vm extension set \
    --publisher Microsoft.Compute \
    --version 1.8 \
    --name CustomScriptExtension \
    --vm-name vm-spoke-2 \
    --resource-group test-rg \
    --settings '{"commandToExecute":"powershell Add-WindowsFeature Web-Server; powershell Add-Content -Path \"C:\\inetpub\\wwwroot\\Default.htm\" -Value $($env:computername)"}'