Framework/Listeners/AzResourceInventoryListener.ps1
class AzResourceInventoryListener: ListenerBase { [Microsoft.ApplicationInsights.TelemetryClient] $TelemetryClient; hidden static [AzResourceInventoryListener] $Instance = $null; AzResourceInventoryListener():Base() { $this.TelemetryClient = [Microsoft.ApplicationInsights.TelemetryClient]::new() } static [AzResourceInventoryListener] GetInstance() { if( $null -eq [AzResourceInventoryListener]::Instance ) { [AzResourceInventoryListener]::Instance = [AzResourceInventoryListener]::new(); } return [AzResourceInventoryListener]::Instance } [void] RegisterEvents() { $this.UnregisterEvents(); $this.RegisterEvent([AzSKRootEvent]::GenerateRunIdentifier, { $currentInstance = [SecurityRecommendationReport]::GetInstance(); try { $currentInstance.SetRunIdentifier([AzSKRootEventArgument] ($Event.SourceArgs | Select-Object -First 1)); } catch { $currentInstance.PublishException($_); } }); $this.RegisterEvent([SVTEvent]::CommandStarted, { $currentInstance = [AzResourceInventoryListener]::GetInstance(); try { $scanSource = [RemoteReportHelper]::GetScanSource(); if($scanSource -ne [ScanSource]::Runbook -or $event.Sender.InvocationContext.MyCommand.Name -ne 'Get-AzSKAzureServicesSecurityStatus') { return; } $SubscriptionId = ([ContextHelper]::GetCurrentRMContext()).Subscription.Id; [ResourceInventory]::FetchResources(); [AzResourceInventoryListener]::PostAzResourceInventory(); $resources= [ResourceInventory]::RawResources $controlSettings = [ConfigurationManager]::LoadServerConfigFile("ControlSettings.json"); $maxResourceCount = $controlSettings.MaxResourceInventoryObjectsCount if($resources.Count -gt $maxResourceCount) { $resources= [ResourceInventory]::FilteredResources [AIOrgTelemetryHelper]::PublishEvent( "Raw Resource Inventory Aborted",@{"TotalResources"= $([ResourceInventory]::RawResources |Measure-Object).Count;"AzSKScanableResources"=$(([ResourceInventory]::FilteredResources| Measure-Object).Count); "SubscriptionId"=$SubscriptionId;"PartialScanIdentifier"=$this.PartialScanIdentifier;}, $null) } $resourceGroups = Get-AzResourceGroup $resourceDetails = @(); $telemetryEvents = [System.Collections.ArrayList]::new() foreach($res in $resources){ $rgTags = ($resourceGroups | where-object {$_.ResourceGroupName -eq $res.ResourceGroupName}).Tags; $resourceProperties = @{ "Name" = $res.Name; "ResourceId" = $res.ResourceId; "ResourceName" = $res.Name; "ResourceType" = $res.ResourceType; "ResourceGroupName" = $res.ResourceGroupName; "Location" = $res.Location; "SubscriptionId" = $SubscriptionId; "Tags" = [Helpers]::FetchTagsString($res.Tags); "Sku" = $res.Sku "Env" = $res.Tags.Env; "ComponentID" = $res.Tags.ComponentID; "RGComponentID" = $rgTags.ComponentID; "RGEnv" = $rgTags.Env; } $telemetryEvent = "" | Select-Object Name, Properties, Metrics $telemetryEvent.Name = "Resource Inventory" $telemetryEvent.Properties = $resourceProperties $telemetryEvents.Add($telemetryEvent) | Out-Null $resourceDetails+=$resourceProperties; } [AIOrgTelemetryHelper]::TrackEvents($telemetryEvents); [RemoteApiHelper]::PostResourceFlatInventory($resourceDetails) [ResourceInventory]::SetResourceToTagMapping($resourceDetails) } catch{ $currentInstance.PublishException($_); } }); } static [void] PostAzResourceInventory() { $currentInstance = [AzResourceInventoryListener]::GetInstance(); try { $scanSource = [RemoteReportHelper]::GetScanSource(); if($scanSource -ne [ScanSource]::Runbook) { return; } $SubscriptionId = ([ContextHelper]::GetCurrentRMContext()).Subscription.Id; if(-not $SubscriptionId) {return;} $resources = "" | Select-Object "SubscriptionId", "ResourceGroups" $resources.SubscriptionId = $SubscriptionId $resources.ResourceGroups = [System.Collections.ArrayList]::new() $supportedResourceTypes = [SVTMapping]::GetSupportedResourceMap() # Not considering nested resources to reduce complexity $filteredResources = [ResourceInventory]::FilteredResources $grouped = $filteredResources | Group-Object {$_.ResourceGroupName} | Select-Object Name, Group foreach($group in $grouped){ $resourceGroup = "" | Select-Object Name, Resources $resourceGroup.Name = $group.Name $resourceGroup.Resources = [System.Collections.ArrayList]::new() foreach($item in $group.Group){ $resource = "" | Select-Object Name, ResourceId, Feature if($item.Name.Contains("/")){ $splitName = $item.Name.Split("/") $resource.Name = $splitName[$splitName.Length - 1] } else{ $resource.Name = $item.Name; } $resource.ResourceId = $item.ResourceId $resource.Feature = $supportedResourceTypes[$item.ResourceType.ToLower()] $resourceGroup.Resources.Add($resource) | Out-Null } $resources.ResourceGroups.Add($resourceGroup) | Out-Null } [RemoteApiHelper]::PostResourceInventory($resources) } catch { $currentInstance.PublishException($_); } } } |