pwsh/dev/functions/processNetwork.ps1 (424 lines of code) (raw):

function processNetwork { $start = Get-Date Write-Host "Processing Network enrichment ($($arrayVNets.Count) Virtual Networks)" $htVNets = @{} foreach ($vnet in $arrayVNets) { $htVNets.($vnet.id) = $vnet } $script:htSubnets = @{} $script:arrayVirtualNetworks = [System.Collections.ArrayList]@() $script:arraySubnets = [System.Collections.ArrayList]@() foreach ($vnet in $arrayVNets) { #region peerings $vnetIdSplit = ($vnet.id -split '/') $subscriptionId = $vnetIdSplit[2] $subscriptionName = 'n/a' $MGPath = 'n/a' if ($htSubscriptionsMgPath.($subscriptionId)) { $subHelper = $htSubscriptionsMgPath.($subscriptionId) $subscriptionName = $subHelper.displayName $MGPath = $subHelper.ParentNameChainDelimited } $subnetsWithPrivateEndPointsCount = 0 if ($vnet.properties.subnets.properties.privateEndpoints.id.Count -gt 0) { $subnetsWithPrivateEndPointsCount = $vnet.properties.subnets.where({ $_.properties.privateEndpoints.id.Count -gt 0 }).Count } $subnetsWithConnectedDevicesCount = 0 if ($vnet.properties.subnets.properties.ipConfigurations.id.Count -gt 0) { $subnetsWithConnectedDevicesCount = $vnet.properties.subnets.where({ $_.properties.ipConfigurations.id.Count -gt 0 }).Count } $vnetResourceGroup = $vnetIdSplit[4] if ($vnet.properties.virtualNetworkPeerings.id.Count -gt 0) { foreach ($peering in $vnet.properties.virtualNetworkPeerings) { $remotevnetIdSplit = ($peering.properties.remoteVirtualNetwork.id -split '/') $remotesubscriptionId = $remotevnetIdSplit[2] $remotesubscriptionName = 'n/a' $remoteMGPath = 'n/a' $peeringXTenant = 'unknown' if ($htSubscriptionsMgPath.($remotesubscriptionId)) { $peeringXTenant = 'false' $remotesubHelper = $htSubscriptionsMgPath.($remotesubscriptionId) $remotesubscriptionName = $remotesubHelper.displayName $remoteMGPath = $remotesubHelper.ParentNameChainDelimited } else { if ($htUnknownTenantsForSubscription.($remotesubscriptionId)) { $remoteTenantId = $htUnknownTenantsForSubscription.($remotesubscriptionId).TenantId $remoteMGPath = $remoteTenantId if ($remoteTenantId -eq $azApiCallConf['checkcontext'].tenant.id) { $peeringXTenant = 'false' } else { $peeringXTenant = 'true' } } else { $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($remotesubscriptionId)?api-version=2020-01-01" $remoteTenantId = AzAPICall -AzAPICallConfiguration $azApiCallConf -uri $uri -listenOn 'content' -currentTask "getTenantId for subscriptionId '$($remotesubscriptionId)'" if ($remoteTenantId.id -like '/subscriptions/*') { #sub actually could be resolved but not available in htSubscriptionsMgPath Write-Host "SubscriptionId '$($remotesubscriptionId)' (tenantId: '$($remoteTenantId.tenantId)' (current context tenantId: '$($azapiCallConf['checkContext'].tenant.Id)')) was not captured by getSubscriptions/getEntities, however could be fully resolved with direct get call (ARM subscription API)" -ForegroundColor Magenta $remoteMGPath = $remoteTenantId.tenantId if ($azapiCallConf['checkContext'].tenant.Id -eq $remoteTenantId.tenantId) { $peeringXTenant = 'false' } else { $peeringXTenant = 'true' } } else { $arrayRemoteMGPath = [System.Collections.ArrayList]@() foreach ($remoteId in $remoteTenantId) { if ($remoteId -eq 'SubscriptionNotFound Tenant unknown') { $remoteMGPath = 'unknown' $peeringXTenant = 'n/a' } else { $objectGuid = [System.Guid]::empty if ([System.Guid]::TryParse($remoteId, [System.Management.Automation.PSReference]$ObjectGuid)) { if ($remoteId -in $MSTenantIds) { $null = $arrayRemoteMGPath.Add("$remoteId (MS)") } else { $null = $arrayRemoteMGPath.Add($remoteId) } if ($remoteId -eq $azApiCallConf['checkcontext'].tenant.id) { $peeringXTenant = 'false' } else { $peeringXTenant = 'true' } } $script:htUnknownTenantsForSubscription.($remotesubscriptionId) = @{ TenantId = $arrayRemoteMGPath -join ', ' } $remoteMGPath += $arrayRemoteMGPath -join ', ' } } } } } $remotevnetName = $remotevnetIdSplit[8] $remotevnetResourceGroup = $remotevnetIdSplit[4] if ($htVNets.($peering.properties.remoteVirtualNetwork.id)) { $remotevnetState = 'existent' $remoteLocation = $htVNets.($peering.properties.remoteVirtualNetwork.id).location $remotePeeringsCount = $htVNets.($peering.properties.remoteVirtualNetwork.id).properties.virtualNetworkPeerings.id.Count $remoteDhcpoptionsDnsservers = $htVNets.($peering.properties.remoteVirtualNetwork.id).properties.dhcpoptions.dnsservers $remoteSubnetsCount = $htVNets.($peering.properties.remoteVirtualNetwork.id).properties.subnets.id.Count $remoteSubnetsWithNSGCount = $htVNets.($peering.properties.remoteVirtualNetwork.id).properties.subnets.properties.networkSecurityGroup.id.Count $remoteSubnetsWithRouteTable = $htVNets.($peering.properties.remoteVirtualNetwork.id).properties.subnets.properties.routeTable.id.Count $remoteSubnetsWithDelegations = $htVNets.($peering.properties.remoteVirtualNetwork.id).properties.subnets.properties.delegations.id.Count $remotePrivateEndPoints = $htVNets.($peering.properties.remoteVirtualNetwork.id).properties.subnets.properties.privateEndpoints.id.Count $remoteSubnetsWithPrivateEndPoints = $htVNets.($peering.properties.remoteVirtualNetwork.id).properties.subnets.where({ $_.properties.privateEndpoints.id.Count -gt 0 }).Count $remoteConnectedDevices = $htVNets.($peering.properties.remoteVirtualNetwork.id).properties.subnets.properties.ipConfigurations.id.Count $remoteSubnetsWithConnectedDevices = $htVNets.($peering.properties.remoteVirtualNetwork.id).properties.subnets.where({ $_.properties.ipConfigurations.id.Count -gt 0 }).Count $remoteDdosProtection = $htVNets.($peering.properties.remoteVirtualNetwork.id).properties.enableDdosProtection $remotePeering = $htVNets.($peering.properties.remoteVirtualNetwork.id).properties.virtualNetworkPeerings.where({ $_.properties.remoteVirtualNetwork.id -eq $vnet.id }) if ($remotePeering.count -eq 1) { $remotePeeringName = $remotePeering.name $remotePeeringState = $remotePeering.Properties.peeringState $remotePeeringSyncLevel = $remotePeering.Properties.peeringSyncLevel $remoteAllowVirtualNetworkAccess = $remotePeering.properties.allowVirtualNetworkAccess $remoteAllowForwardedTraffic = $remotePeering.properties.allowForwardedTraffic $remoteAllowGatewayTransit = $remotePeering.properties.allowGatewayTransit $remoteUseRemoteGateways = $remotePeering.properties.useRemoteGateways $remoteDoNotVerifyRemoteGateways = $remotePeering.properties.doNotVerifyRemoteGateways $remotePeerCompleteVnets = $remotePeering.properties.peerCompleteVnets $remoteRouteServiceVips = $remotePeering.properties.routeServiceVips } else { $remotePeeringName = 'n/a' $remotePeeringState = 'n/a' $remotePeeringSyncLevel = 'n/a' $remoteAllowVirtualNetworkAccess = 'n/a' $remoteAllowForwardedTraffic = 'n/a' $remoteAllowGatewayTransit = 'n/a' $remoteUseRemoteGateways = 'n/a' $remoteDoNotVerifyRemoteGateways = 'n/a' $remotePeerCompleteVnets = 'n/a' $remoteRouteServiceVips = 'n/a' } } else { if ($getMgParentName -eq 'Tenant Root') { $remotevnetState = 'non-existent' } else { $remotevnetState = 'n/a' } $remoteLocation = 'n/a' $remotePeeringsCount = 'n/a' $remoteDhcpoptionsDnsservers = 'n/a' $remoteSubnetsCount = 'n/a' $remoteSubnetsWithNSGCount = 'n/a' $remoteSubnetsWithRouteTable = 'n/a' $remoteSubnetsWithDelegations = 'n/a' $remotePrivateEndPoints = 'n/a' $remoteSubnetsWithPrivateEndPoints = 'n/a' $remoteConnectedDevices = 'n/a' $remoteSubnetsWithConnectedDevices = 'n/a' $remoteDdosProtection = 'n/a' $remotePeeringName = 'n/a' $remotePeeringState = 'n/a' $remotePeeringSyncLevel = 'n/a' $remoteAllowVirtualNetworkAccess = 'n/a' $remoteAllowForwardedTraffic = 'n/a' $remoteAllowGatewayTransit = 'n/a' $remoteUseRemoteGateways = 'n/a' $remoteDoNotVerifyRemoteGateways = 'n/a' $remotePeerCompleteVnets = 'n/a' $remoteRouteServiceVips = 'n/a' } $null = $script:arrayVirtualNetworks.Add([PSCustomObject]@{ SubscriptionName = $subscriptionName Subscription = ($vnet.id -split '/')[2] MGPath = $MGPath VNet = $vnet.name VNetId = $vnet.id VNetResourceGroup = $vnetResourceGroup Location = $vnet.location AddressSpaceAddressPrefixes = ($vnet.properties.addressSpace.addressPrefixes -join "$CsvDelimiterOpposite ") DhcpoptionsDnsservers = ($vnet.properties.dhcpoptions.dnsservers -join "$CsvDelimiterOpposite ") SubnetsCount = $vnet.properties.subnets.id.Count SubnetsWithNSGCount = $vnet.properties.subnets.properties.networkSecurityGroup.id.Count SubnetsWithRouteTableCount = $vnet.properties.subnets.properties.routeTable.id.Count SubnetsWithDelegationsCount = $vnet.properties.subnets.properties.delegations.id.Count PrivateEndpointsCount = $vnet.properties.subnets.properties.privateEndpoints.id.Count SubnetsWithPrivateEndPointsCount = $subnetsWithPrivateEndPointsCount ConnectedDevices = $vnet.properties.subnets.properties.ipConfigurations.id.Count SubnetsWithConnectedDevicesCount = $subnetsWithConnectedDevicesCount DdosProtection = $vnet.properties.enableDdosProtection PeeringsCount = $vnet.properties.virtualNetworkPeerings.id.Count PeeringXTenant = $peeringXTenant PeeringName = $peering.name PeeringState = $peering.properties.peeringState PeeringSyncLevel = $peering.properties.peeringSyncLevel AllowVirtualNetworkAccess = $peering.properties.allowVirtualNetworkAccess AllowForwardedTraffic = $peering.properties.allowForwardedTraffic AllowGatewayTransit = $peering.properties.allowGatewayTransit UseRemoteGateways = $peering.properties.useRemoteGateways DoNotVerifyRemoteGateways = $peering.properties.doNotVerifyRemoteGateways PeerCompleteVnets = $peering.properties.peerCompleteVnets RouteServiceVips = $peering.properties.routeServiceVips RemotePeeringsCount = $remotePeeringsCount RemotePeeringName = $remotePeeringName RemotePeeringState = $remotePeeringState RemotePeeringSyncLevel = $remotePeeringSyncLevel RemoteAllowVirtualNetworkAccess = $RemoteAllowVirtualNetworkAccess RemoteAllowForwardedTraffic = $RemoteAllowForwardedTraffic RemoteAllowGatewayTransit = $RemoteAllowGatewayTransit RemoteUseRemoteGateways = $RemoteUseRemoteGateways RemoteDoNotVerifyRemoteGateways = $RemoteDoNotVerifyRemoteGateways RemotePeerCompleteVnets = $RemotePeerCompleteVnets RemoteRouteServiceVips = $RemoteRouteServiceVips RemoteSubscriptionName = $remotesubscriptionName RemoteSubscription = $remotesubscriptionId RemoteMGPath = $remoteMGPath -join ', ' RemoteVNet = $remotevnetName RemoteVNetId = $peering.properties.remoteVirtualNetwork.id RemoteVNetState = $remotevnetState RemoteVNetResourceGroup = $remotevnetResourceGroup RemoteVNetLocation = $remoteLocation RemoteAddressSpaceAddressPrefixes = ($peering.properties.remoteAddressSpace.addressPrefixes -join "$CsvDelimiterOpposite ") RemoteVirtualNetworkAddressSpaceAddressPrefixes = ($peering.properties.remoteVirtualNetworkAddressSpace.addressPrefixes -join "$CsvDelimiterOpposite ") RemoteDhcpoptionsDnsservers = ($remoteDhcpoptionsDnsservers -join "$CsvDelimiterOpposite ") RemoteSubnetsCount = $remoteSubnetsCount RemoteSubnetsWithNSGCount = $remoteSubnetsWithNSGCount RemoteSubnetsWithRouteTable = $remoteSubnetsWithRouteTable RemoteSubnetsWithDelegations = $remoteSubnetsWithDelegations RemotePrivateEndPoints = $remotePrivateEndPoints RemoteSubnetsWithPrivateEndPoints = $remoteSubnetsWithPrivateEndPoints RemoteConnectedDevices = $remoteConnectedDevices RemoteSubnetsWithConnectedDevices = $remoteSubnetsWithConnectedDevices RemoteDdosProtection = $remoteDdosProtection }) } } else { $null = $script:arrayVirtualNetworks.Add([PSCustomObject]@{ SubscriptionName = $subscriptionName Subscription = ($vnet.id -split '/')[2] MGPath = $MGPath VNet = $vnet.name VNetId = $vnet.id VNetResourceGroup = $vnetResourceGroup Location = $vnet.location AddressSpaceAddressPrefixes = ($vnet.properties.addressSpace.addressPrefixes -join "$CsvDelimiterOpposite ") DhcpoptionsDnsservers = ($vnet.properties.dhcpoptions.dnsservers -join "$CsvDelimiterOpposite ") SubnetsCount = $vnet.properties.subnets.id.Count SubnetsWithNSGCount = $vnet.properties.subnets.properties.networkSecurityGroup.id.Count SubnetsWithRouteTableCount = $vnet.properties.subnets.properties.routeTable.id.Count SubnetsWithDelegationsCount = $vnet.properties.subnets.properties.delegations.id.Count PrivateEndpointsCount = $vnet.properties.subnets.properties.privateEndpoints.id.Count SubnetsWithPrivateEndPointsCount = $subnetsWithPrivateEndPointsCount ConnectedDevices = $vnet.properties.subnets.properties.ipConfigurations.id.Count SubnetsWithConnectedDevicesCount = $subnetsWithConnectedDevicesCount DdosProtection = $vnet.properties.enableDdosProtection PeeringsCount = $vnet.properties.virtualNetworkPeerings.id.Count PeeringXTenant = 'n/a' PeeringName = '' PeeringState = '' PeeringSyncLevel = '' AllowVirtualNetworkAccess = '' AllowForwardedTraffic = '' AllowGatewayTransit = '' UseRemoteGateways = '' DoNotVerifyRemoteGateways = '' PeerCompleteVnets = '' RouteServiceVips = '' RemotePeeringsCount = '' RemotePeeringName = '' RemotePeeringState = '' RemotePeeringSyncLevel = '' RemoteAllowVirtualNetworkAccess = '' RemoteAllowForwardedTraffic = '' RemoteAllowGatewayTransit = '' RemoteUseRemoteGateways = '' RemoteDoNotVerifyRemoteGateways = '' RemotePeerCompleteVnets = '' RemoteRouteServiceVips = '' RemoteSubscriptionName = '' RemoteSubscription = '' RemoteMGPath = '' RemoteVNet = '' RemoteVNetId = '' RemoteVNetState = '' RemoteVNetResourceGroup = '' RemoteVNetLocation = '' RemoteAddressSpaceAddressPrefixes = '' RemoteVirtualNetworkAddressSpaceAddressPrefixes = '' RemoteDhcpoptionsDnsservers = '' RemoteSubnetsCount = '' RemoteSubnetsWithNSGCount = '' RemoteSubnetsWithRouteTable = '' RemoteSubnetsWithDelegations = '' RemotePrivateEndPoints = '' RemoteSubnetsWithPrivateEndPoints = '' RemoteConnectedDevices = '' RemoteSubnetsWithConnectedDevices = '' RemoteDdosProtection = '' }) } #endregion peerings #region subnets if ($vnet.properties.subnets.Count -gt 0) { foreach ($subnet in $vnet.properties.subnets) { $script:htSubnets.($subnet.id) = @{ SubscriptionName = $subscriptionName Subscription = ($vnet.id -split '/')[2] MGPath = $MGPath VNet = $vnet.name VNetId = $vnet.id Location = $vnet.location ResourceGroup = $vnetResourceGroup } $arrayServiceEndPoints = @() if ($subnet.properties.serviceEndpoints.service.Count -gt 0) { $arrayServiceEndPoints = foreach ($serviceEndpoint in $subnet.properties.serviceEndpoints) { "$($serviceEndpoint.service) ($(($serviceEndpoint.locations | Sort-Object) -join ', '))" } } $delegation = '' if ($subnet.properties.delegations.Count -gt 0) { $delegation = "$($subnet.properties.delegations.properties.serviceName) ($(($subnet.properties.delegations.properties.actions | Sort-Object) -join ', '))" } #region IP address usage #https://github.com/ElanShudnow/AzureCode/blob/242b923eada55fa795b930473a50dedf14bdc409/PowerShell/AzSubnetAvailability/AzSubnetAvailability.ps1 # Gets the mask from the IP configuration (I.e 10.0.0.0/24, turns to just "24") if (-not [string]::IsNullOrWhiteSpace($subnet.properties.addressPrefix)) { $AddressPrefix = $subnet.properties.addressPrefix $subnetNet = $AddressPrefix -replace '/.*' $subnetNetOutput = $subnetNet } #ignore IPv6 if (-not [string]::IsNullOrWhiteSpace($subnet.properties.addressPrefixes)) { $arr = foreach ($entry in $subnet.properties.addressPrefixes) { if ($entry -match '^(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])\/(\d{1}|[0-2]{1}\d{1}|3[0-2])$') { $AddressPrefix = $entry $AddressPrefix -replace '/.*' $subnetNet = $AddressPrefix -replace '/.*' } else { "(ignoring IPv6 $entry)" } } $subnetNetOutput = $arr } $Mask = $AddressPrefix.substring($AddressPrefix.Length - 2, 2) #Amount of available IP Addresses minus the 3 IPs that Azure consumes, minus net and broadcast #https://learn.microsoft.com/azure/virtual-network/virtual-networks-faq#are-there-any-restrictions-on-using-ip-addresses-within-these-subnets switch ($Mask) { '30' { $AvailableAddresses = [Math]::Pow(2, 2) - 5 } '29' { $AvailableAddresses = [Math]::Pow(2, 3) - 5 } '28' { $AvailableAddresses = [Math]::Pow(2, 4) - 5 } '27' { $AvailableAddresses = [Math]::Pow(2, 5) - 5 } '26' { $AvailableAddresses = [Math]::Pow(2, 6) - 5 } '25' { $AvailableAddresses = [Math]::Pow(2, 7) - 5 } '24' { $AvailableAddresses = [Math]::Pow(2, 8) - 5 } '23' { $AvailableAddresses = [Math]::Pow(2, 9) - 5 } '22' { $AvailableAddresses = [Math]::Pow(2, 10) - 5 } '21' { $AvailableAddresses = [Math]::Pow(2, 11) - 5 } '20' { $AvailableAddresses = [Math]::Pow(2, 12) - 5 } '19' { $AvailableAddresses = [Math]::Pow(2, 13) - 5 } '18' { $AvailableAddresses = [Math]::Pow(2, 14) - 5 } '17' { $AvailableAddresses = [Math]::Pow(2, 15) - 5 } '16' { $AvailableAddresses = [Math]::Pow(2, 16) - 5 } '15' { $AvailableAddresses = [Math]::Pow(2, 17) - 5 } '14' { $AvailableAddresses = [Math]::Pow(2, 18) - 5 } '13' { $AvailableAddresses = [Math]::Pow(2, 19) - 5 } '12' { $AvailableAddresses = [Math]::Pow(2, 20) - 5 } '11' { $AvailableAddresses = [Math]::Pow(2, 21) - 5 } '10' { $AvailableAddresses = [Math]::Pow(2, 22) - 5 } '9' { $AvailableAddresses = [Math]::Pow(2, 23) - 5 } '8' { $AvailableAddresses = [Math]::Pow(2, 24) - 5 } } $IPsLeft = $AvailableAddresses - $subnet.properties.ipConfigurations.Count $PercentIPsUsed = [math]::Round((($subnet.properties.ipConfigurations.Count / $AvailableAddresses) * 100), 1) $subnetIPAddressUsageCritical = $false if ($PercentIPsUsed -gt $NetworkSubnetIPAddressUsageCriticalPercentage) { $subnetIPAddressUsageCritical = $true } #endregion IP address usage $subnetPrefix = $AddressPrefix -replace '.*/' $subnetmask = ([IPAddress]"$([system.convert]::ToInt64(('1'*$subnetPrefix).PadRight(32,'0'),2))").IPAddressToString $IPBits = [int[]]$subnetNet.Split('.') $MaskBits = [int[]]$subnetmask.Split('.') $NetworkIDBits = 0..3 | ForEach-Object { $IPBits[$_] -band $MaskBits[$_] } $Broadcast = (0..3 | ForEach-Object { $NetworkIDBits[$_] + ($MaskBits[$_] -bxor 255) }) -join '.' $Range = "$subnetNet - $Broadcast" $null = $script:arraySubnets.Add([PSCustomObject]@{ SubscriptionName = $subscriptionName Subscription = ($vnet.id -split '/')[2] MGPath = $MGPath VNet = $vnet.name VNetId = $vnet.id VNetResourceGroup = $vnetResourceGroup Location = $vnet.location SubnetName = $subnet.name SubnetId = $subnet.id SubnetNet = $subnetNetOutput -join "$CsvDelimiterOpposite " SubnetPrefix = $subnetPrefix Subnetmask = $subnetmask Range = $Range ConnectedDevices = $subnet.properties.ipConfigurations.Count AvailableIPAddresses = $IPsLeft UsedIPAddressesPercent = "$PercentIPsUsed %" SubnetIPAddressUsageCritical = $subnetIPAddressUsageCritical PrivateEndpointNetworkPolicies = $subnet.properties.privateEndpointNetworkPolicies PrivateLinkServiceNetworkPolicies = $subnet.properties.privateLinkServiceNetworkPolicies ServiceEndpointsCount = $subnet.properties.serviceEndpoints.service.Count ServiceEndpoints = $arrayServiceEndPoints -join ', ' Delegation = $delegation NetworkSecurityGroup = $subnet.properties.networkSecurityGroup.id RouteTable = $subnet.properties.routeTable NatGateway = '' PrivateEndpoints = $subnet.properties.privateEndpoints.Count }) } } #endregion subnets } $end = Get-Date Write-Host " Processing Network enrichment duration: $((New-TimeSpan -Start $start -End $end).TotalSeconds) seconds" }