manifests/collectors/Networking/NetworkSecurityGroup.psd1
|
# # GENERATED by scripts/ConvertTo-ScoutCollectorDefinition.ps1 from Modules/Public/InventoryModules/Networking/NetworkSecurityGroup.ps1 (AB#5660). # Field expressions are copied verbatim from the original collector and evaluate in an # equivalent scope -- see docs/design/decisions/declarative-collectors.md. # Review before trusting; regenerate rather than hand-patch if the source collector changes. # @{ ResourceTypes = @( 'microsoft.network/networksecuritygroups' ) ResourceTypeMatching = 'Grouped' AdditionalFilter = $null FilterPreamble = '' RowLoopVariable = '1' SetupPreamble = @' $NSGs = $Resources | Where-Object { $_.TYPE -eq 'microsoft.network/networksecuritygroups' } $nic = $Resources | Where-Object {$_.TYPE -eq 'microsoft.network/networkinterfaces'} $vmss = $Resources | Where-Object {$_.TYPE -eq 'microsoft.compute/virtualmachinescalesets'} $flowlogs = $Resources | Where-Object {$_.TYPE -eq 'microsoft.network/networkwatchers/flowlogs'} '@ SetupVariables = @( 'NSGs' 'nic' 'vmss' 'flowlogs' ) Preamble = @' $ResUCount = 1 $sub1 = $SUB | Where-Object { $_.Id -eq $1.subscriptionId } $data = $1.PROPERTIES $Retired = $Retirements | Where-Object { $_.id -eq $1.id } if ($Retired) { $RetiredFeature = foreach ($Retire in $Retired) { $RetiredServiceID = $Unsupported | Where-Object {$_.Id -eq $Retired.ServiceID} $tmp0 = [pscustomobject]@{ 'RetiredFeature' = $RetiredServiceID.RetiringFeature 'RetiredDate' = $RetiredServiceID.RetirementDate } $tmp0 } $RetiringFeature = if (@($RetiredFeature.RetiredFeature).count -gt 1) { $RetiredFeature.RetiredFeature | ForEach-Object { $_ + ' ,' } }else { $RetiredFeature.RetiredFeature} $RetiringFeature = [string]$RetiringFeature $RetiringFeature = if ($RetiringFeature -like '* ,*') { $RetiringFeature -replace ".$" }else { $RetiringFeature } $RetiringDate = if (@($RetiredFeature.RetiredDate).count -gt 1) { $RetiredFeature.RetiredDate | ForEach-Object { $_ + ' ,' } }else { $RetiredFeature.RetiredDate} $RetiringDate = [string]$RetiringDate $RetiringDate = if ($RetiringDate -like '* ,*') { $RetiringDate -replace ".$" }else { $RetiringDate } } else { $RetiringFeature = $null $RetiringDate = $null } $NSGFlows = foreach ($flow in $flowlogs) { if ((Get-AZSCSafeProperty -InputObject $flow -Path 'properties.targetResourceId') -eq $1.id) { $flow } } $FlowLogsEnabled = if ((Get-AZSCSafeProperty -InputObject $NSGFlows -Path 'properties.enabled') -eq 'true') { $true }else { $false } $FlowLogRetentionDays = Get-AZSCSafeProperty -InputObject $NSGFlows -Path 'properties.retentionPolicy.days' $FlowLogsRetention = if (![string]::IsNullOrEmpty($FlowLogRetentionDays)) { $FlowLogRetentionDays }else { 'Not Enabled' } $FlowLogStorageId = Get-AZSCSafeProperty -InputObject $NSGFlows -Path 'properties.storageId' $FlowLogsStorage = if (![string]::IsNullOrEmpty($FlowLogStorageId)) { (Get-AZSCIdSegment -Id $FlowLogStorageId -Index 8) }else { 'Not Enabled' } $Tags = if ($null -ne $1.PSObject.Properties['tags'] -and $1.tags -and @($1.tags.PSObject.Properties).Count -gt 0) { $1.tags.PSObject.Properties }else { '0' } $NetworkInterfaceIds = Get-AZSCSafeProperty -InputObject $data -Path 'networkInterfaces.id' -Enumerate $SubnetIds = Get-AZSCSafeProperty -InputObject $data -Path 'subnets.id' -Enumerate $RelatedNics = @() $RelatedSubs = @() # AB#6844: $FinalNICs and $FinalSubs are assigned only INSIDE the two `if # (![string]::IsNullOrEmpty(...))` blocks below. An NSG associated with neither a NIC # nor a subnet -- a freshly created one, or one left behind after a teardown -- reached # the field expressions with the variables never set, and StrictMode's # uninitialised-variable check took the whole worksheet down. Declaring them here is # the fix; the branches still overwrite them whenever there is something to report. $FinalNICs = '' $FinalSubs = '' if (![string]::IsNullOrEmpty($NetworkInterfaceIds)) { foreach ($NICID in $NetworkInterfaceIds) { $NICDetails = $nic | Where-Object {$_.id -eq $NICID} if (![string]::IsNullOrEmpty($NICDetails)) { $NicPrivateIp = Get-AZSCSafeProperty -InputObject $NICDetails -Path 'properties.ipconfigurations.properties.privateipaddress' -Enumerate $RelatedNics += ($NICDetails.name + ' ('+$NicPrivateIp+')') } elseif ($NICID -like '*microsoft.compute/virtualmachinescalesets*') { $RelatedNics += (Get-AZSCIdSegment -Id $NICID -Index 12) } } $FinalNICs = if ($RelatedNics.count -gt 1) { $RelatedNics | ForEach-Object { $_ + ' ,' } }else { $RelatedNics } $FinalNICs = [string]$FinalNICs $FinalNICs = if ($FinalNICs -like '* ,*') { $FinalNICs -replace ".$" }else { $FinalNICs } } if (![string]::IsNullOrEmpty($SubnetIds)) { foreach ($SUBID in $SubnetIds) { $RelatedSubs += ((Get-AZSCIdSegment -Id $SUBID -Index 8) + ' ('+ (Get-AZSCIdSegment -Id $SUBID -Index 10) + ')') } $FinalSUBs = if ($RelatedSubs.count -gt 1) { $RelatedSubs | ForEach-Object { $_ + ' ,' } }else { $RelatedSubs } $FinalSUBs = [string]$FinalSUBs $FinalSUBs = if ($FinalSUBs -like '* ,*') { $FinalSUBs -replace ".$" }else { $FinalSUBs } } elseif ([string]::IsNullOrEmpty($SubnetIds) -and $NetworkInterfaceIds -like '*microsoft.compute/virtualmachinescalesets*') { $VMSSs = $vmss | Where-Object {$_.properties.virtualmachineprofile.networkprofile.networkinterfaceconfigurations.properties.networksecuritygroup.id -eq $1.id} foreach ($VM in $VMSSs) { $SUBID = Get-AZSCSafeProperty -InputObject $VM -Path 'properties.virtualmachineprofile.networkprofile.networkinterfaceconfigurations.properties.ipconfigurations.properties.subnet.id' -Enumerate $RelatedSubs += ((Get-AZSCIdSegment -Id $SUBID -Index 8) + ' ('+ (Get-AZSCIdSegment -Id $SUBID -Index 10) + ')') } $FinalSUBs = if ($RelatedSubs.count -gt 1) { $RelatedSubs | ForEach-Object { $_ + ' ,' } }else { $RelatedSubs } $FinalSUBs = [string]$FinalSUBs $FinalSUBs = if ($FinalSUBs -like '* ,*') { $FinalSUBs -replace ".$" }else { $FinalSUBs } } $SecurityRules = $data.securityRules $SecurityRules = if (![string]::IsNullOrEmpty($SecurityRules)) { $SecurityRules }else { '0' } '@ AdditionalRowLoops = @( @{ Variable = '2' # AB#6845 decision ($2): NO EmitNullWhenEmpty, deliberately. $SecurityRules falls back # to '0', so an NSG carrying no custom security rules keeps its row. # # An NSG with only default rules is both common and worth reporting -- it is the one # attached to a subnet while permitting everything the platform defaults permit. The # sentinel already holds it, and Collector.SparsePayload.Tests.ps1 asserts it on a # hand-built sparse payload. Source = '$SecurityRules' Preamble = '' } ) TagLoop = @{ Variable = 'Tag' Source = '$Tags' Preamble = @' if (![string]::IsNullOrEmpty($2.properties.sourceAddressPrefixes)) { $Source = if (@($2.properties.sourceAddressPrefixes).count -gt 1) { $2.properties.sourceAddressPrefixes | ForEach-Object { $_ + ' ,' } }else { $2.properties.sourceAddressPrefixes } $Source = [string]$Source $Source = if ($Source -like '* ,*') { $Source -replace ".$" }else { $Source } } elseif(![string]::IsNullOrEmpty($2.properties.sourceAddressPrefix)) { $Source = if (@($2.properties.sourceAddressPrefix).count -gt 1) { $2.properties.sourceAddressPrefix | ForEach-Object { $_ + ' ,' } }else { $2.properties.sourceAddressPrefix } $Source = [string]$Source $Source = if ($Source -like '* ,*') { $Source -replace ".$" }else { $Source } } else { $Source = '' } if (![string]::IsNullOrEmpty($2.properties.sourcePortRanges)) { $SourcePort = if (@($2.properties.sourcePortRanges).count -gt 1) { $2.properties.sourcePortRanges | ForEach-Object { $_ + ' ,' } }else { $2.properties.sourcePortRanges } $SourcePort = [string]$SourcePort $SourcePort = if ($SourcePort -like '* ,*') { $SourcePort -replace ".$" }else { $SourcePort } } elseif(![string]::IsNullOrEmpty($2.properties.sourcePortRange)) { $SourcePort = if (@($2.properties.sourcePortRange).count -gt 1) { $2.properties.sourcePortRange | ForEach-Object { $_ + ' ,' } }else { $2.properties.sourcePortRange } $SourcePort = [string]$SourcePort $SourcePort = if ($SourcePort -like '* ,*') { $SourcePort -replace ".$" }else { $SourcePort } } else { $SourcePort = '' } if (![string]::IsNullOrEmpty($2.properties.destinationAddressPrefixes)) { $Destination = if (@($2.properties.destinationAddressPrefixes).count -gt 1) { $2.properties.destinationAddressPrefixes | ForEach-Object { $_ + ' ,' } }else { $2.properties.destinationAddressPrefixes } $Destination = [string]$Destination $Destination = if ($Destination -like '* ,*') { $Destination -replace ".$" }else { $Destination } } elseif(![string]::IsNullOrEmpty($2.properties.destinationAddressPrefix)) { $Destination = if (@($2.properties.destinationAddressPrefix).count -gt 1) { $2.properties.destinationAddressPrefix | ForEach-Object { $_ + ' ,' } }else { $2.properties.destinationAddressPrefix } $Destination = [string]$Destination $Destination = if ($Destination -like '* ,*') { $Destination -replace ".$" }else { $Destination } } else { $Destination = '' } if (![string]::IsNullOrEmpty($2.properties.destinationPortRanges)) { $DestinationPort = if (@($2.properties.destinationPortRanges).count -gt 1) { $2.properties.destinationPortRanges | ForEach-Object { $_ + ' ,' } }else { $2.properties.destinationPortRanges } $DestinationPort = [string]$DestinationPort $DestinationPort = if ($DestinationPort -like '* ,*') { $DestinationPort -replace ".$" }else { $DestinationPort } } elseif(![string]::IsNullOrEmpty($2.properties.destinationPortRange)) { $DestinationPort = if (@($2.properties.destinationPortRange).count -gt 1) { $2.properties.destinationPortRange | ForEach-Object { $_ + ' ,' } }else { $2.properties.destinationPortRange } $DestinationPort = [string]$DestinationPort $DestinationPort = if ($DestinationPort -like '* ,*') { $DestinationPort -replace ".$" }else { $DestinationPort } } else { $DestinationPort = '' } if (@($NetworkInterfaceIds).count -eq 0 -and @($SubnetIds).count -eq 0) { $Orphaned = $true; } else { $Orphaned = $false; } '@ } Fields = @( @{ Name = 'ID' Expression = '$1.id' } @{ Name = 'Subscription' Expression = '$sub1.Name' } @{ Name = 'Resource Group' Expression = '$1.RESOURCEGROUP' } @{ Name = 'Name' Expression = '$1.NAME' } @{ Name = 'Location' Expression = '$1.LOCATION' } @{ Name = 'Retiring Feature' Expression = '$RetiringFeature' } @{ Name = 'Retiring Date' Expression = '$RetiringDate' } @{ Name = 'Orphaned' Expression = '$Orphaned' } @{ Name = 'Security Rules' Expression = '$2.name' } @{ Name = 'Direction' Expression = '$2.properties.direction' } @{ Name = 'Action' Expression = '$2.properties.Access' } @{ Name = 'Priority' Expression = '[string]$2.properties.priority' } @{ Name = 'Protocol' Expression = '[string]$2.properties.protocol' } @{ Name = 'Source' Expression = '$Source' } @{ Name = 'Source Port' Expression = '$SourcePort' } @{ Name = 'Destination' Expression = '$Destination' } @{ Name = 'Destination Port' Expression = '$DestinationPort' } @{ Name = 'Related NICs' Expression = '$FinalNICs' } @{ Name = 'Related VNETs and Subnets' Expression = '$FinalSUBs' } @{ Name = 'Flow Logs Enabled' Expression = '$FlowLogsEnabled' } @{ Name = 'Flow Logs Retention Days' Expression = '$FlowLogsRetention' } @{ Name = 'Flow Logs Storage Account' Expression = '$FlowLogsStorage' } @{ Name = 'Resource U' Expression = '$ResUCount' } @{ Name = 'Tag Name' Expression = '[string]$Tag.Name' } @{ Name = 'Tag Value' Expression = '[string]$Tag.Value' } ) Export = @{ WorksheetName = 'Network Security Groups' TableNamePrefix = 'NSGTable_' Columns = @( 'Subscription' 'Resource Group' 'Name' 'Location' 'Retiring Feature' 'Retiring Date' 'Orphaned' 'Security Rules' 'Direction' 'Action' 'Priority' 'Protocol' 'Source' 'Source Port' 'Destination' 'Destination Port' 'Related NICs' 'Related VNETs and Subnets' 'Flow Logs Enabled' 'Flow Logs Retention Days' 'Flow Logs Storage Account' 'Resource U' ) TagColumns = @( 'Tag Name' 'Tag Value' ) TagColumnsBefore = 'Resource U' NumberFormat = '0' ConditionalText = @( 'New-ConditionalText TRUE -Range G:G' 'New-ConditionalText FALSE -Range R:R' 'New-ConditionalText -Range E2:E100 -ConditionalType ContainsText' ) } SourceCollector = 'Modules/Public/InventoryModules/Networking/NetworkSecurityGroup.ps1' } |