rules/Azure.Common.Rule.ps1
# # Helper functions for rules # # Add a custom function to filter by resource type function global:ResourceType { param ( [String]$ResourceType ) process { return $Rule.TargetType -eq $ResourceType; } } function global:IsAllowedRegion { process { $region = $Configuration.azureAllowedRegions; foreach ($r in $Configuration.azureAllowedRegions) { $region += ($r -replace ' ', '') } return $TargetObject.Location -in $region; } } # Certain rules only apply if resource data has been exported function global:IsExport { [CmdletBinding()] [OutputType([System.Boolean])] param () process { return $Null -ne $TargetObject.SubscriptionId; } } function global:HasPeerNetwork { [CmdletBinding()] [OutputType([System.Boolean])] param () process { if ($Rule.TargetType -ne 'Microsoft.Network/virtualNetworks') { return $False; } $peers = $TargetObject.Properties.virtualNetworkPeerings; if ($Null -eq $peers) { return $False; } $item = @($peers); return $item.Length -gt 0; } } # Get a sorted list of NSG rules function global:GetOrderedNSGRules { param ( [Parameter(Mandatory = $True)] [ValidateSet('Inbound', 'Outbound')] [String]$Direction ) process { $TargetObject.properties.securityRules | Where-Object { $_.properties.direction -eq $Direction } | Sort-Object @{ Expression = { $_.Properties.priority }; Descending = $False } } } function global:SupportsAcceleratedNetworking { process { if ($Rule.TargetType -ne 'Microsoft.Compute/virtualMachines' -or !(IsExport)) { return $False; } if ($Null -eq ($TargetObject.Resources | Where-Object { $_.ResourceType -eq 'Microsoft.Network/networkInterfaces'})) { return $False; } $vmSize = $TargetObject.Properties.hardwareProfile.vmSize; if ($vmSize -notlike 'Standard_*_*') { return $False; } $vmSizeParts = $vmSize.Split('_'); if ($Null -eq $vmSizeParts) { return $False; } $generation = $vmSizeParts[2]; $size = $vmSizeParts[1]; # Generation v2 if ($generation -eq 'v2') { if ($size -notmatch 'Standard_(A|NC|DS1_|D1_)') { return $True; } } # Generation v3 elseif ($generation -eq 'v3') { if ($size -notmatch 'Standard_(E2s?_|E[2-8]-2|D2s?|NC)') { return $True; } } return $False; } } function global:IsAppGwPublic { [CmdletBinding()] [OutputType([System.Boolean])] param () process { if ($Rule.TargetType -ne 'Microsoft.Network/applicationGateways') { return $False; } $result = $False; foreach ($ip in $TargetObject.Properties.frontendIPConfigurations) { if (Exists 'properties.publicIPAddress.id' -InputObject $ip) { $result = $True; } } return $result; } } # Determine if the resource is an Application Gateway with WAF enabled function global:IsAppGwWAF { [CmdletBinding()] [OutputType([System.Boolean])] param () process { if ($Rule.TargetType -ne 'Microsoft.Network/applicationGateways') { return $False; } if ($TargetObject.Properties.sku.tier -notin ('WAF', 'WAF_v2')) { return $False; } if ($TargetObject.Properties.webApplicationFirewallConfiguration.enabled -ne $True) { return $False; } return $True; } } function global:IsWindowsOS { [CmdletBinding()] [OutputType([System.Boolean])] param () process { if ($Rule.TargetType -ne 'Microsoft.Compute/virtualMachines') { return $False; } return $TargetObject.Properties.storageProfile.osDisk.osType -eq 'Windows'; } } function global:IsLinuxOS { [CmdletBinding()] [OutputType([System.Boolean])] param () process { if ($Rule.TargetType -ne 'Microsoft.Compute/virtualMachines') { return $False; } return $TargetObject.Properties.storageProfile.osDisk.osType -eq 'Linux'; } } # Determines if the object supports tags function global:SupportsTags { [CmdletBinding()] [OutputType([System.Boolean])] param () process { if ( ($Rule.TargetType -eq 'Microsoft.Subscription') -or ($Rule.TargetType -like 'Microsoft.Authorization/*') -or ($Rule.TargetType -like 'Microsoft.Billing/*') -or ($Rule.TargetType -like 'Microsoft.Classic*') -or ($Rule.TargetType -like 'Microsoft.Consumption/*') -or ($Rule.TargetType -like 'Microsoft.Gallery/*') -or ($Rule.TargetType -like 'Microsoft.Resources/*') -or ($Rule.TargetType -like 'Microsoft.Security/*') -or ($Rule.TargetType -like 'microsoft.support/*') -or ($Rule.TargetType -like 'Microsoft.WorkloadMonitor/*') -or ($Rule.TargetType -like '*/providers/roleAssignments') ) { return $False; } return $True; } } # Determines if the object supports regions function global:SupportsRegions { [CmdletBinding()] [OutputType([System.Boolean])] param () process { if ( ($Rule.TargetType -eq 'Microsoft.Subscription') -or ($Rule.TargetType -eq 'Microsoft.AzureActiveDirectory/b2cDirectories') -or ($Rule.TargetType -eq 'Microsoft.Network/trafficManagerProfiles') -or ($Rule.TargetType -like 'Microsoft.Authorization/*') -or ($Rule.TargetType -like 'Microsoft.Consumption/*') -or ($Rule.TargetType -like '*/providers/roleAssignments') -or ($TargetObject.Location -eq 'global') ) { return $False; } return $True; } } function global:ConvertToUInt64 { param ( [Parameter(Mandatory = $True)] [System.Net.IPAddress]$IP ) process { $bytes = $IP.GetAddressBytes(); $size = $bytes.Length; [System.UInt64]$result = 0; for ($i = 0; $i -lt $size; $i++) { $result = ($result -shl 8) + $bytes[$i]; } return $result; } } function global:GetIPAddressCount { [CmdletBinding()] [OutputType([System.UInt64])] param ( [Parameter(Mandatory = $True)] [String]$Start, [Parameter(Mandatory = $True)] [String]$End ) process { $startIP = [System.Net.IPAddress]::Parse($Start); $endIP = [System.Net.IPAddress]::Parse($End); $startAddress = ConvertToUInt64 -IP $startIP; $endAddress = ConvertToUInt64 -IP $endIP; if ($endAddress -ge $startAddress) { return $endAddress - $startAddress + 1; } else { return $startAddress - $endAddress + 1; } } } function global:GetIPAddressSummary { [CmdletBinding()] [OutputType([PSObject])] param () process { $firewallRules = @($TargetObject.resources | Where-Object -FilterScript { $_.Type -like "*/firewallRules" } | ForEach-Object -Process { if (!($_.ResourceName -eq 'AllowAllWindowsAzureIps' -or ($_.properties.startIpAddress -eq '0.0.0.0' -and $_.properties.endIpAddress -eq '0.0.0.0'))) { $_; } }) $private = 0; $public = 0; foreach ($fwRule in $firewallRules) { if ($fwRule.Properties.startIpAddress -like "10.*" -or $fwRule.Properties.startIpAddress -like "172.*" -or $fwRule.Properties.startIpAddress -like "192.168.*") { $private += GetIPAddressCount -Start $fwRule.Properties.startIpAddress -End $fwRule.Properties.endIpAddress; } else { $public += GetIPAddressCount -Start $fwRule.Properties.startIpAddress -End $fwRule.Properties.endIpAddress; } } return [PSCustomObject]@{ Private = $private Public = $public } } } function global:GetCIDRMask { [CmdletBinding()] [OutputType([PSObject])] param ( [Parameter(Mandatory = $True)] [String]$CIDR ) process { $cidrParts = $CIDR.Split('/'); $ip = ConvertToUInt64 -IP ([System.Net.IPAddress]::Parse($cidrParts[0])); [System.UInt64]$mask = 4294967295; if ($cidrParts.Length -eq 2) { $mask = [System.UInt64](4294967295 -shl (32-([System.Byte]::Parse($cidrParts[1])))) -band 4294967295; } return [PSCustomObject]@{ Mask = $mask IP = $ip; } } } function global:WithinCIDR { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $True)] [String]$IP, [Parameter(Mandatory = $True)] [String[]]$CIDR ) process { [System.UInt64]$address = ConvertToUInt64 -IP ([System.Net.IPAddress]::Parse($IP)); $result = $False; for ($i = 0; (($i -lt $CIDR.Length) -and (!$result)); $i++) { $mask = GetCIDRMask -CIDR $CIDR[$i]; $result = ($mask.Mask -band $address) -eq $mask.IP; } return $result; } } # Determine if the VM is using a promo SKU. function global:IsVMPromoSku { process { if ($Rule.TargetType -ne 'Microsoft.Compute/virtualMachines') { return $False; } return $TargetObject.Properties.hardwareProfile.vmSize -like '*_Promo'; } } |