pwsh/dev/functions/dataCollection/dataCollectionFunctions.ps1 (3,889 lines of code) (raw):

#region functions4DataCollection function dataCollectionMGSecureScore { [CmdletBinding()]Param( [string]$Id ) $mgAscSecureScoreResult = '' if ($azAPICallConf['htParameters'].NoMDfCSecureScore -eq $false) { if ($htMgASCSecureScore.($Id)) { $mgAscSecureScoreResult = $htMgASCSecureScore.($Id).SecureScore } else { $mgAscSecureScoreResult = 'isNullOrEmpty' } } return $mgAscSecureScoreResult } $funcDataCollectionMGSecureScore = $function:dataCollectionMGSecureScore.ToString() function dataCollectionDefenderPlans { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $ChildMgMgPath, $SubscriptionQuotaId ) $currentTask = "Getting Microsoft Defender for Cloud plans for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$SubscriptionQuotaId']" #https://learn.microsoft.com/rest/api/defenderforcloud/pricings $securitypricingsAPIVersion = $azAPICallConf['htParameters'].APIMappingCloudEnvironment.securityPricings.($azAPICallConf['htParameters'].azureCloudEnvironment) $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Security/pricings?api-version=$($securitypricingsAPIVersion)" $method = 'GET' $defenderPlansResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' if ($defenderPlansResult -eq 'SubScriptionNotRegistered' -or $defenderPlansResult -eq 'DisallowedProvider') { #Subscription skipped for MDfC $null = $script:arrayDefenderPlansSubscriptionsSkipped.Add([PSCustomObject]@{ subscriptionId = $scopeId subscriptionName = $scopeDisplayName subscriptionQuotaId = $subscriptionQuotaId subscriptionMgPath = $childMgMgPath reason = $defenderPlansResult }) } else { if ($defenderPlansResult.Count -gt 0) { foreach ($defenderPlanResult in $defenderPlansResult) { $null = $script:arrayDefenderPlans.Add([PSCustomObject]@{ subscriptionId = $scopeId subscriptionName = $scopeDisplayName subscriptionMgPath = $childMgMgPath defenderPlan = $defenderPlanResult.name defenderPlanTier = $defenderPlanResult.properties.pricingTier defenderPlanFull = $defenderPlanResult }) } } } $currentTask = "Getting Microsoft Defender for Cloud settings for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$SubscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Security/settings?api-version=2022-05-01" $method = 'GET' $securitySettingsResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask if ($securitySettingsResult -eq 'SubScriptionNotRegistered' -or $securitySettingsResult -eq 'DisallowedProvider') { Write-Host "Subscription $scopeId skipped for SecuritySettings ($securitySettingsResult)" } else { foreach ($setting in $securitySettingsResult) { if (-not $htSecuritySettings.$scopeId) { $script:htSecuritySettings.$scopeId = @{} } $script:htSecuritySettings.($scopeId).($setting.name) = $setting } } } $funcDataCollectionDefenderPlans = $function:dataCollectionDefenderPlans.ToString() function dataCollectionAdvisorScores { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $ChildMgMgPath, $SubscriptionQuotaId ) $currentTask = "Getting Advisor Scores for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$SubscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Advisor/advisorScore?api-version=2020-07-01-preview" $method = 'GET' $advisorScoreResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' -skipOnErrorCode 404 if ($advisorScoreResult -eq 'SubScriptionNotRegistered' -or $advisorScoreResult -eq 'DisallowedProvider') { } else { if ($advisorScoreResult -like 'azgvzerrorMessage_*') { } else { if ($advisorScoreResult.Count -gt 0) { foreach ($entry in $advisorScoreResult) { #Write-Host ($entry | ConvertTo-Json -Depth 99) if ($entry.Name) { $objectGuid = [System.Guid]::empty if ([System.Guid]::TryParse($entry.Name, [System.Management.Automation.PSReference]$ObjectGuid)) { } else { $null = $script:arrayAdvisorScores.Add([PSCustomObject]@{ subscriptionId = $scopeId subscriptionName = $scopeDisplayName subscriptionQuotaId = $SubscriptionQuotaId subscriptionMgPath = $childMgMgPath category = $entry.Name score = $entry.properties.lastRefreshedScore.score }) } } } } } } } $funcDataCollectionAdvisorScores = $function:dataCollectionAdvisorScores.ToString() function dataCollectionDefenderEmailContacts { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $SubscriptionQuotaId ) $currentTask = "Getting Microsoft Defender for Cloud Email contacts for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$SubscriptionQuotaId']" #https://learn.microsoft.com/rest/api/defenderforcloud/security-contacts $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Security/securityContacts?api-version=2020-01-01-preview" $method = 'GET' $defenderSecurityContactsResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -listenOn 'Content' -currentTask $currentTask -caller 'CustomDataCollection' if ($defenderSecurityContactsResult -eq 'SubScriptionNotRegistered' -or $defenderSecurityContactsResult -eq 'DisallowedProvider') { } else { if ($defenderSecurityContactsResult -like 'azgvzerrorMessage_*') { $errorInfo = $defenderSecurityContactsResult -replace 'azgvzerrorMessage_' $script:htDefenderEmailContacts.($scopeId) = @{ subscriptionId = $scopeId subscriptionName = $scopeDisplayName emails = $errorInfo roles = $errorInfo alertNotificationsState = $errorInfo alertNotificationsminimalSeverity = $errorInfo } } else { if ($defenderSecurityContactsResult.Count -gt 0) { foreach ($entry in $defenderSecurityContactsResult) { if ($entry.properties) { if ($entry.properties.notificationsByRole.roles.count -gt 0) { $roles = ($entry.properties.notificationsByRole.roles | Sort-Object) -join "$CsvDelimiterOpposite " } else { $roles = 'none' } if ($entry.properties.emails) { if (-not [string]::IsNullOrWhiteSpace($entry.properties.emails)) { $emailsSplitted = $entry.properties.emails -split ';' $arrayEmails = @() foreach ($email in $emailsSplitted) { $arrayEmails += "'$email'" } $emails = ($arrayEmails | Sort-Object) -join "$CsvDelimiterOpposite " } else { $emails = $entry.properties.emails } } else { $emails = 'none' } if ($entry.properties.alertNotifications.state) { $alertNotificationsState = $entry.properties.alertNotifications.state } if ($entry.properties.alertNotifications.minimalSeverity) { $alertNotificationsminimalSeverity = $entry.properties.alertNotifications.minimalSeverity } } else { $roles = 'n/a' $emails = 'n/a' $alertNotificationsState = 'n/a' $alertNotificationsminimalSeverity = 'n/a' } $script:htDefenderEmailContacts.($scopeId) = @{ subscriptionId = $scopeId subscriptionName = $scopeDisplayName emails = $emails roles = $roles alertNotificationsState = $alertNotificationsState alertNotificationsminimalSeverity = $alertNotificationsminimalSeverity } } } else { $script:htDefenderEmailContacts.($scopeId) = @{ subscriptionId = $scopeId subscriptionName = $scopeDisplayName emails = 'n/a' roles = 'n/a' alertNotificationsState = 'n/a' alertNotificationsminimalSeverity = 'n/a' } } } } } $funcDataCollectionDefenderEmailContacts = $function:dataCollectionDefenderEmailContacts.ToString() function dataCollectionVNets { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $SubscriptionQuotaId ) $currentTask = "Getting Virtual Networks for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$SubscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Network/virtualNetworks?api-version=2022-05-01" $method = 'GET' $networkResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' if ($networkResult -eq 'someError') { } else { if ($networkResult.Count -gt 0) { if ($networkResult -ne 'DisallowedProvider') { foreach ($vnet in $networkResult) { $null = $script:arrayVNets.Add($vnet) } } } } } $funcDataCollectionVNets = $function:dataCollectionVNets.ToString() function dataCollectionPrivateEndpoints { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $SubscriptionQuotaId ) $currentTask = "Getting Private Endpoints for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$SubscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Network/privateEndpoints?api-version=2022-05-01" $method = 'GET' $privateEndpointsResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' -unhandledErrorAction Continue if ($privateEndpointsResult.Count -gt 0) { if ($privateEndpointsResult -ne 'DisallowedProvider') { foreach ($pe in $privateEndpointsResult) { $null = $script:arrayPrivateEndPoints.Add($pe) } } } } $funcDataCollectionPrivateEndpoints = $function:dataCollectionPrivateEndpoints.ToString() function dataCollectionDiagnosticsSub { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $ChildMgMgPath, $ChildMgId, $subscriptionQuotaId ) $currentTask = "Getting Diagnostic Settings for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/microsoft.insights/diagnosticSettings?api-version=2021-05-01-preview" $method = 'GET' $getDiagnosticSettingsSub = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask if ($getDiagnosticSettingsSub.Count -eq 0) { $null = $script:arrayDiagnosticSettingsMgSub.Add([PSCustomObject]@{ Scope = 'Sub' ScopeName = $scopeDisplayName ScopeId = $scopeId ScopeMgPath = $childMgMgPath SubMgParent = $childMgId DiagnosticsPresent = 'false' }) } else { foreach ($diagnosticSetting in $getDiagnosticSettingsSub) { $arrayLogs = [System.Collections.ArrayList]@() if ($diagnosticSetting.Properties.logs) { foreach ($logCategory in $diagnosticSetting.properties.logs) { $null = $arrayLogs.Add([PSCustomObject]@{ Category = $logCategory.category Enabled = $logCategory.enabled }) } } $htLogs = @{} if ($diagnosticSetting.Properties.logs) { foreach ($logCategory in $diagnosticSetting.properties.logs) { if ($logCategory.enabled) { $htLogs.($logCategory.category) = 'true' } else { $htLogs.($logCategory.category) = 'false' } } } if ($diagnosticSetting.Properties.workspaceId) { $null = $script:arrayDiagnosticSettingsMgSub.Add([PSCustomObject]@{ Scope = 'Sub' ScopeName = $scopeDisplayName ScopeId = $scopeId ScopeMgPath = $childMgMgPath SubMgParent = $childMgId DiagnosticsPresent = 'true' DiagnosticSettingName = $diagnosticSetting.name DiagnosticTargetType = 'LA' DiagnosticTargetId = $diagnosticSetting.Properties.workspaceId DiagnosticCategories = $arrayLogs DiagnosticCategoriesHt = $htLogs }) } if ($diagnosticSetting.Properties.storageAccountId) { $null = $script:arrayDiagnosticSettingsMgSub.Add([PSCustomObject]@{ Scope = 'Sub' ScopeName = $scopeDisplayName ScopeId = $scopeId ScopeMgPath = $childMgMgPath SubMgParent = $childMgId DiagnosticsPresent = 'true' DiagnosticSettingName = $diagnosticSetting.name DiagnosticTargetType = 'SA' DiagnosticTargetId = $diagnosticSetting.Properties.storageAccountId DiagnosticCategories = $arrayLogs DiagnosticCategoriesHt = $htLogs }) } if ($diagnosticSetting.Properties.eventHubAuthorizationRuleId) { $null = $script:arrayDiagnosticSettingsMgSub.Add([PSCustomObject]@{ Scope = 'Sub' ScopeName = $scopeDisplayName ScopeId = $scopeId ScopeMgPath = $childMgMgPath SubMgParent = $childMgId DiagnosticsPresent = 'true' DiagnosticSettingName = $diagnosticSetting.name DiagnosticTargetType = 'EH' DiagnosticTargetId = $diagnosticSetting.Properties.eventHubAuthorizationRuleId DiagnosticCategories = $arrayLogs DiagnosticCategoriesHt = $htLogs }) } } } } $funcDataCollectionDiagnosticsSub = $function:dataCollectionDiagnosticsSub.ToString() function dataCollectionDiagnosticsMG { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName ) $mgPath = $htManagementGroupsMgPath.($scopeId).pathDelimited $currentTask = "Getting Diagnostic Settings for Management Group: '$($scopeDisplayName)' ('$($scopeId)')" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/providers/Microsoft.Management/managementGroups/$($mgdetail.Name)/providers/microsoft.insights/diagnosticSettings?api-version=2020-01-01-preview" $method = 'GET' $getDiagnosticSettingsMg = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask if ($getDiagnosticSettingsMg -eq 'InvalidResourceType') { #skipping until supported } else { if ($getDiagnosticSettingsMg.Count -eq 0) { $null = $script:arrayDiagnosticSettingsMgSub.Add([PSCustomObject]@{ Scope = 'Mg' ScopeName = $scopeDisplayName ScopeId = $scopeId ScopeMgPath = $mgPath DiagnosticsPresent = 'false' DiagnosticsInheritedOrnot = $false DiagnosticsInheritedFrom = 'none' }) } else { foreach ($diagnosticSetting in $getDiagnosticSettingsMg) { $arrayLogs = [System.Collections.ArrayList]@() if ($diagnosticSetting.Properties.logs) { foreach ($logCategory in $diagnosticSetting.properties.logs) { $null = $arrayLogs.Add([PSCustomObject]@{ Category = $logCategory.category Enabled = $logCategory.enabled }) } } $htLogs = @{} if ($diagnosticSetting.Properties.logs) { foreach ($logCategory in $diagnosticSetting.properties.logs) { if ($logCategory.enabled) { $htLogs.($logCategory.category) = 'true' } else { $htLogs.($logCategory.category) = 'false' } } } if ($diagnosticSetting.Properties.workspaceId) { $null = $script:arrayDiagnosticSettingsMgSub.Add([PSCustomObject]@{ Scope = 'Mg' ScopeName = $scopeDisplayName ScopeId = $scopeId ScopeMgPath = $mgPath DiagnosticsPresent = 'true' DiagnosticsInheritedOrnot = $false DiagnosticsInheritedFrom = 'none' DiagnosticSettingName = $diagnosticSetting.name DiagnosticTargetType = 'LA' DiagnosticTargetId = $diagnosticSetting.Properties.workspaceId DiagnosticCategories = $arrayLogs DiagnosticCategoriesHt = $htLogs }) } if ($diagnosticSetting.Properties.storageAccountId) { $null = $script:arrayDiagnosticSettingsMgSub.Add([PSCustomObject]@{ Scope = 'Mg' ScopeName = $scopeDisplayName ScopeId = $scopeId ScopeMgPath = $mgPath DiagnosticsPresent = 'true' DiagnosticsInheritedOrnot = $false DiagnosticsInheritedFrom = 'none' DiagnosticSettingName = $diagnosticSetting.name DiagnosticTargetType = 'SA' DiagnosticTargetId = $diagnosticSetting.Properties.storageAccountId DiagnosticCategories = $arrayLogs DiagnosticCategoriesHt = $htLogs }) } if ($diagnosticSetting.Properties.eventHubAuthorizationRuleId) { $null = $script:arrayDiagnosticSettingsMgSub.Add([PSCustomObject]@{ Scope = 'Mg' ScopeName = $scopeDisplayName ScopeId = $scopeId ScopeMgPath = $mgPath DiagnosticsPresent = 'true' DiagnosticsInheritedOrnot = $false DiagnosticsInheritedFrom = 'none' DiagnosticSettingName = $diagnosticSetting.name DiagnosticTargetType = 'EH' DiagnosticTargetId = $diagnosticSetting.Properties.eventHubAuthorizationRuleId DiagnosticCategories = $arrayLogs DiagnosticCategoriesHt = $htLogs }) } } } } } $funcDataCollectionDiagnosticsMG = $function:dataCollectionDiagnosticsMG.ToString() function dataCollectionStorageAccounts { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $ChildMgMgPath, $ChildMgParentNameChainDelimited, $subscriptionQuotaId ) $currentTask = "Getting Storage Accounts for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Storage/storageAccounts?api-version=2021-09-01" $method = 'GET' $storageAccountsSubscriptionResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' if ($storageAccountsSubscriptionResult -ne 'DisallowedProvider') { foreach ($storageAccount in $storageAccountsSubscriptionResult) { $dtisostart = Get-Date (Get-Date).AddHours(-1).ToUniversalTime() -UFormat '+%Y-%m-%dT%H:%M:%S.000Z' $dtisoend = Get-Date (Get-Date).ToUniversalTime() -UFormat '+%Y-%m-%dT%H:%M:%S.000Z' $currentTask = "Getting Storage Account '$($storageAccount.name)' UsedCapacity ('$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId'])" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)$($storageAccount.id)/providers/Microsoft.Insights/metrics?timespan=$($dtisostart)/$($dtisoend)&metricnames=UsedCapacity&aggregation=Average&api-version=2021-05-01" $method = 'GET' $storageAccountUsedCapacity = $null $storageAccountUsedCapacity = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' -unhandledErrorAction Continue $usedCapacity = 'n/a' if ($storageAccountUsedCapacity.Count -gt 0) { if (-not [string]::IsNullOrWhiteSpace($storageAccountUsedCapacity.timeseries.data.average)) { $usedCapacity = [decimal]$storageAccountUsedCapacity.timeseries.data.average / 1024 / 1024 / 1024 } } $obj = [System.Collections.ArrayList]@() $null = $obj.Add([PSCustomObject]@{ SA = $storageAccount SAUsedCapacity = $usedCapacity }) $null = $script:storageAccounts.Add($obj) } } } $funcDataCollectionStorageAccounts = $function:dataCollectionStorageAccounts.ToString() function dataCollectionResources { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $ChildMgMgPath, $ChildMgParentNameChainDelimited, $subscriptionQuotaId ) #region resources LIST $currentTask = "Getting Resources for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/resources?`$expand=createdTime,changedTime,properties&api-version=2024-03-01" $method = 'GET' $resourcesSubscriptionResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' #endregion resources LIST #region resources GET if ($resourcesSubscriptionResult.Count -gt 0) { $arrayResourcesWithProperties = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList)) $batchSize = [math]::ceiling($resourcesSubscriptionResult.Count / $azAPICallConf['htParameters'].ThrottleLimit) #Write-Host "Optimal batch size: $($batchSize)" $counterBatch = [PSCustomObject] @{ Value = 0 } $resourcesSubscriptionResultBatch = ($resourcesSubscriptionResult) | Group-Object -Property { [math]::Floor($counterBatch.Value++ / $batchSize) } #Write-Host "Processing data in $($resourcesSubscriptionResultBatch.Count) batches" $resourcesSubscriptionResultBatch | ForEach-Object -Parallel { #region using $arrayResourcesWithProperties = $using:arrayResourcesWithProperties $htResourceProvidersRef = $using:htResourceProvidersRef $arrayPrivateEndPointsFromResourceProperties = $using:arrayPrivateEndPointsFromResourceProperties $htAvailablePrivateEndpointTypes = $using:htAvailablePrivateEndpointTypes $htResourcePropertiesConvertfromJSONFailed = $using:htResourcePropertiesConvertfromJSONFailed $scopeId = $using:scopeId $scopeDisplayName = $using:scopeDisplayName $ChildMgParentNameChainDelimited = $using:ChildMgParentNameChainDelimited $azAPICallConf = $using:azAPICallConf #$htResourcesWithProperties = $using:htResourcesWithProperties #endregion using foreach ($resource in $_.Group) { if ($htAvailablePrivateEndpointTypes.(($resource.type).ToLower())) { if ($htResourceProvidersRef.($resource.type)) { if ($htResourceProvidersRef.($resource.type).APIDefault) { $apiVersionToUse = $htResourceProvidersRef.($resource.type).APIDefault $apiRef = 'default' } else { $apiVersionToUse = $htResourceProvidersRef.($resource.type).APILatest $apiRef = 'latest' } $currentTask = "Getting Resource Properties API-version: '$apiVersionToUse' ($apiRef); ResourceType: '$($resource.type)'; ResourceId: '$($resource.id)'" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)$($resource.id)?api-version=$apiVersionToUse" $method = 'GET' $resourceResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' -listenOn Content -unhandledErrorAction Continue if ($resourceResult -ne 'ResourceOrResourcegroupNotFound' -and $resourceResult -ne 'convertfromJSONError') { $null = $script:arrayResourcesWithProperties.Add($resourceResult) #$script:htResourcesWithProperties.($resourceResult.id) = $resourceResult if ($resourceResult.properties.privateEndpointConnections.Count -gt 0) { foreach ($privateEndpointConnection in $resourceResult.properties.privateEndpointConnections) { $resourceResultIdSplit = $resourceResult.id -split '/' $null = $script:arrayPrivateEndPointsFromResourceProperties.Add([PSCustomObject]@{ ResourceName = $resourceResult.name ResourceType = $resourceResult.type ResourceId = $resourceResult.id ResourceResourceGroup = $resourceResultIdSplit[4] ResourceSubscriptionId = $scopeId ResourceSubscriptionName = $scopeDisplayName ResourceMGPath = $ChildMgParentNameChainDelimited privateEndpointConnection = $privateEndpointConnection }) } } } else { if ($resourceResult -eq 'convertfromJSONError') { $script:htResourcePropertiesConvertfromJSONFailed.($resource.id) = @{} } } } else { Write-Host "[Azure Governance Visualizer] Please file an issue at the Azure Governance Visualizer GitHub repository (aka.ms/AzGovViz) and provide this information (scrub subscription Id and company identifyable names): No API-version matches! ResourceType: '$($resource.type)'; ResourceId: '$($resource.id)' - Thank you!" -ForegroundColor DarkRed } } else { #Write-Host "$($resource.type) not in `$htAvailablePrivateEndpointTypes" } } } -ThrottleLimit $azAPICallConf['htParameters'].ThrottleLimit } #endregion resources GET #region PSRule if ($azAPICallConf['htParameters'].DoPSRule -eq $true) { if ($resourcesSubscriptionResult.Count -gt 0) { $startPSRule = Get-Date try { <# $path = (Get-Module PSRule.Rules.Azure -ListAvailable | Sort-Object Version -Descending -Top 1).ModuleBase Write-Host "Import-Module (Join-Path $path -ChildPath 'PSRule.Rules.Azure-nodeps.psd1')" Import-Module (Join-Path $path -ChildPath 'PSRule.Rules.Azure-nodeps.psd1') #> if ($azAPICallConf['htParameters'].PSRuleFailedOnly -eq $true) { $psruleResults = $arrayResourcesWithProperties | Invoke-PSRule -Module psrule.rules.Azure -As Detail -Culture en-us -WarningAction Ignore -ErrorAction SilentlyContinue -Outcome Fail, Error } else { $psruleResults = $arrayResourcesWithProperties | Invoke-PSRule -Module psrule.rules.Azure -As Detail -Culture en-us -WarningAction Ignore -ErrorAction SilentlyContinue } } catch { Write-Host " Please report 'PSRule for Azure' error '$($scopeDisplayName)' ('$scopeId'): $_" } $endPSRule = Get-Date $durationPSRule = $((New-TimeSpan -Start $startPSRule -End $endPSRule).TotalSeconds) $null = $script:arrayPSRuleTracking.Add([PSCustomObject]@{ subscriptionId = $scopeId duration = $durationPSRule }) if ($psruleResults.Count -gt 0) { foreach ($psRuleResult in $psRuleResults) { $null = $script:arrayPSRule.Add([PSCustomObject]@{ resourceType = $psRuleResult.TargetType subscriptionId = $scopeId mgPath = $ChildMgParentNameChainDelimited resourceId = $psRuleResult.TargetObject.id pillar = $psRuleResult.Info.Annotations.pillar category = $psRuleResult.Info.Annotations.category severity = $psRuleResult.Info.Annotations.severity rule = $psRuleResult.Info.DisplayName description = $psRuleResult.Info.Description recommendation = $psRuleResult.Info.Recommendation link = $psRuleResult.Info.Annotations.'online version' result = $psRuleResult.Outcome errorMsg = $psRuleResult.Error.Message }) } } } } #endregion PSRule foreach ($resourceTypeLocation in ($resourcesSubscriptionResult | Group-Object -Property type, location)) { $null = $script:resourcesAll.Add([PSCustomObject]@{ subscriptionId = $scopeId type = ($resourceTypeLocation.values[0]).ToLower() location = ($resourceTypeLocation.values[1]).ToLower() count_ = $resourceTypeLocation.Count }) } foreach ($resourceType in ($resourcesSubscriptionResult | Group-Object -Property type)) { if (-not $htResourceTypesUniqueResource.(($resourceType.name).ToLower())) { $script:htResourceTypesUniqueResource.(($resourceType.name).ToLower()) = @{ resourceId = $resourceType.Group.Id | Select-Object -First 1 } } } $startSubResourceIdsThis = Get-Date <# Build the $JSONcafResourceNaming #pending PR https://github.com/MicrosoftDocs/cloud-adoption-framework/pull/916 $arrayCAFNamingConvention = [System.Collections.ArrayList]@() $htCAFNamingConvention = @{} #$cafNamingFromFile = Get-Content -Path .\cafNaming.md -Encoding utf8 $CAFFileName = 'resource-abbreviations.md' Invoke-webrequest -OutFile .\$($CAFFileName) -URI "https://raw.githubusercontent.com/MicrosoftDocs/cloud-adoption-framework/main/docs/ready/azure-best-practices/resource-abbreviations.md" $cafNamingFromFile = Get-Content -Path .\$($CAFFileName) -Encoding utf8 $cafNamingFromFile.count foreach ($line in $cafNamingFromFile) { #$line if ($line -match "microsoft.") { $tranformed = $line -replace '`' -split " \| " $friendlyName = $($tranformed[0] -replace "\| ") $resourceType = $($tranformed[1]) $namingConvention = $($tranformed[2] -replace " \|" -replace "\|") $null = $arrayCAFNamingConvention.Add([PSCustomObject]@{ resourceType = $resourceType friendlyName = $friendlyName namingConvention = $namingConvention }) } } $htCAFNamingConvention = [ordered]@{} $arrayCAFNamingConventionGroupedByType = $arrayCAFNamingConvention | Sort-Object -Property resourceType | Group-Object -Property resourceType foreach ($entry in $arrayCAFNamingConventionGroupedByType){ $htCAFNamingConvention.($entry.name) = @{} $htCAFNamingConvention.($entry.name).friendlyName = $entry.group.friendlyName $htCAFNamingConvention.($entry.name).namingConvention = $entry.group.namingConvention } $htCAFNamingConvention | ConvertTo-Json #> $JSONcafResourceNaming = @' { "Microsoft.AnalysisServices/servers": { "friendlyName": "Azure Analysis Services server", "namingConvention": "as" }, "Microsoft.ApiManagement/service": { "friendlyName": "API management service instance", "namingConvention": "apim-" }, "Microsoft.AppConfiguration/configurationStores": { "friendlyName": "App Configuration store", "namingConvention": "appcs-" }, "Microsoft.Authorization/policyDefinitions": { "friendlyName": "Policy definition", "namingConvention": "policy-" }, "Microsoft.Automation/automationAccounts": { "friendlyName": "Automation account", "namingConvention": "aa-" }, "Microsoft.Blueprint/blueprints": { "friendlyName": "Blueprint", "namingConvention": "bp-" }, "Microsoft.Blueprint/blueprints/artifacts": { "friendlyName": "Blueprint assignment", "namingConvention": "bpa-" }, "Microsoft.Cache/Redis": { "friendlyName": "Azure Cache for Redis instance", "namingConvention": "redis-" }, "Microsoft.Cdn/profiles": { "friendlyName": "CDN profile", "namingConvention": "cdnp-" }, "Microsoft.Cdn/profiles/endpoints": { "friendlyName": "CDN endpoint", "namingConvention": "cdne-" }, "Microsoft.CognitiveServices/accounts": { "friendlyName": "Azure Cognitive Services", "namingConvention": "cog-" }, "Microsoft.Compute/availabilitySets": { "friendlyName": "Availability set", "namingConvention": "avail-" }, "Microsoft.Compute/cloudServices": { "friendlyName": "Cloud service", "namingConvention": "cld-" }, "Microsoft.Compute/diskEncryptionSets": { "friendlyName": "Disk encryption set", "namingConvention": "des" }, "Microsoft.Compute/disks": { "friendlyName": [ "Managed disk (data)", "Managed disk (OS)" ], "namingConvention": [ "disk", "osdisk" ] }, "Microsoft.Compute/galleries": { "friendlyName": "Gallery", "namingConvention": "gal" }, "Microsoft.Compute/snapshots": { "friendlyName": "Snapshot", "namingConvention": "snap-" }, "Microsoft.Compute/virtualMachines": { "friendlyName": "Virtual machine", "namingConvention": "vm" }, "Microsoft.Compute/virtualMachineScaleSets": { "friendlyName": "Virtual machine scale set", "namingConvention": "vmss-" }, "Microsoft.ContainerInstance/containerGroups": { "friendlyName": "Container instance", "namingConvention": "ci" }, "Microsoft.ContainerRegistry/registries": { "friendlyName": "Container registry", "namingConvention": "cr" }, "Microsoft.ContainerService/managedClusters": { "friendlyName": "AKS cluster", "namingConvention": "aks-" }, "Microsoft.Databricks/workspaces": { "friendlyName": "Azure Databricks workspace", "namingConvention": "dbw-" }, "Microsoft.DataFactory/factories": { "friendlyName": "Azure Data Factory", "namingConvention": "adf-" }, "Microsoft.DataLakeAnalytics/accounts": { "friendlyName": "Data Lake Analytics account", "namingConvention": "dla" }, "Microsoft.DataLakeStore/accounts": { "friendlyName": "Data Lake Store account", "namingConvention": "dls" }, "Microsoft.DataMigration/services": { "friendlyName": "Database Migration Service instance", "namingConvention": "dms-" }, "Microsoft.DataProtection/BackupVaults": { "friendlyName": "Backup vault", "namingConvention": "bv-" }, "Microsoft.DBforMySQL/servers": { "friendlyName": "MySQL database", "namingConvention": "mysql-" }, "Microsoft.DBforPostgreSQL/servers": { "friendlyName": "PostgreSQL database", "namingConvention": "psql-" }, "Microsoft.Devices/IotHubs": { "friendlyName": "IoT hub", "namingConvention": "iot-" }, "Microsoft.Devices/provisioningServices": { "friendlyName": "Provisioning services", "namingConvention": "provs-" }, "Microsoft.Devices/provisioningServices/certificates": { "friendlyName": "Provisioning services certificate", "namingConvention": "pcert-" }, "Microsoft.DocumentDB/databaseAccounts/sqlDatabases": { "friendlyName": "Azure Cosmos DB database", "namingConvention": "cosmos-" }, "Microsoft.EventGrid/domains": { "friendlyName": "Event Grid domain", "namingConvention": "evgd-" }, "Microsoft.EventGrid/domains/topics": { "friendlyName": "Event Grid topic", "namingConvention": "evgt-" }, "Microsoft.EventGrid/eventSubscriptions": { "friendlyName": "Event Grid subscriptions", "namingConvention": "evgs-" }, "Microsoft.EventHub/namespaces": { "friendlyName": "Event Hubs namespace", "namingConvention": "evhns-" }, "Microsoft.EventHub/namespaces/eventHubs": { "friendlyName": "Event hub", "namingConvention": "evh-" }, "Microsoft.HDInsight/clusters": { "friendlyName": [ "HDInsight - Hadoop cluster", "HDInsight - Kafka cluster", "HDInsight - Spark cluster", "HDInsight - Storm cluster", "HDInsight - ML Services cluster", "HDInsight - HBase cluster" ], "namingConvention": [ "hadoop-", "kafka-", "spark-", "storm-", "mls-", "hbase-" ] }, "Microsoft.HybridCompute/machines": { "friendlyName": "Azure Arc enabled server", "namingConvention": "arcs-" }, "Microsoft.Insights/actionGroups": { "friendlyName": "Azure Monitor action group", "namingConvention": "ag-" }, "Microsoft.Insights/components": { "friendlyName": "Application Insights", "namingConvention": "appi-" }, "Microsoft.KeyVault/vaults": { "friendlyName": "Key vault", "namingConvention": "kv-" }, "Microsoft.Kubernetes/connectedClusters": { "friendlyName": "Azure Arc enabled Kubernetes cluster", "namingConvention": "arck" }, "Microsoft.Kusto/clusters": { "friendlyName": "Azure Data Explorer cluster", "namingConvention": "dec" }, "Microsoft.Kusto/clusters/databases": { "friendlyName": "Azure Data Explorer cluster database", "namingConvention": "dedb" }, "Microsoft.Logic/integrationAccounts": { "friendlyName": "Integration account", "namingConvention": "ia-" }, "Microsoft.Logic/workflows": { "friendlyName": "Logic apps", "namingConvention": "logic-" }, "Microsoft.MachineLearningServices/workspaces": { "friendlyName": "Azure Machine Learning workspace", "namingConvention": "mlw-" }, "Microsoft.ManagedIdentity/userAssignedIdentities": { "friendlyName": "Managed Identity", "namingConvention": "id-" }, "Microsoft.Management/managementGroups": { "friendlyName": "Management group", "namingConvention": "mg-" }, "Microsoft.Migrate/assessmentProjects": { "friendlyName": "Azure Migrate project", "namingConvention": "migr-" }, "Microsoft.Network/applicationGateways": { "friendlyName": "Application gateway", "namingConvention": "agw-" }, "Microsoft.Network/applicationSecurityGroups": { "friendlyName": "Application security group (ASG)", "namingConvention": "asg-" }, "Microsoft.Network/azureFirewalls": { "friendlyName": "Firewall", "namingConvention": "afw-" }, "Microsoft.Network/bastionHosts": { "friendlyName": "Bastion", "namingConvention": "bas-" }, "Microsoft.Network/connections": { "friendlyName": "Connections", "namingConvention": "con-" }, "Microsoft.Network/dnsZones": { "friendlyName": "DNS", "namingConvention": "dnsz-" }, "Microsoft.Network/expressRouteCircuits": { "friendlyName": "ExpressRoute circuit", "namingConvention": "erc-" }, "Microsoft.Network/firewallPolicies": { "friendlyName": [ "Web Application Firewall (WAF) policy", "Firewall policy" ], "namingConvention": [ "waf", "afwp-" ] }, "Microsoft.Network/firewallPolicies/ruleGroups": { "friendlyName": "Web Application Firewall (WAF) policy rule group", "namingConvention": "wafrg" }, "Microsoft.Network/frontDoors": { "friendlyName": "Front Door instance", "namingConvention": "fd-" }, "Microsoft.Network/frontdoorWebApplicationFirewallPolicies": { "friendlyName": "Front Door firewall policy", "namingConvention": "fdfp-" }, "Microsoft.Network/loadBalancers": { "friendlyName": [ "Load balancer (external)", "Load balancer (internal)" ], "namingConvention": [ "lbe-", "lbi-" ] }, "Microsoft.Network/loadBalancers/inboundNatRules": { "friendlyName": "Load balancer rule", "namingConvention": "rule-" }, "Microsoft.Network/localNetworkGateways": { "friendlyName": "Local network gateway", "namingConvention": "lgw-" }, "Microsoft.Network/natGateways": { "friendlyName": "NAT gateway", "namingConvention": "ng-" }, "Microsoft.Network/networkInterfaces": { "friendlyName": "Network interface (NIC)", "namingConvention": "nic-" }, "Microsoft.Network/networkSecurityGroups": { "friendlyName": "Network security group (NSG)", "namingConvention": "nsg-" }, "Microsoft.Network/networkSecurityGroups/securityRules": { "friendlyName": "Network security group (NSG) security rules", "namingConvention": "nsgsr-" }, "Microsoft.Network/networkWatchers": { "friendlyName": "Network Watcher", "namingConvention": "nw-" }, "Microsoft.Network/privateDnsZones": { "friendlyName": "DNS zone", "namingConvention": "pdnsz-" }, "Microsoft.Network/privateLinkServices": { "friendlyName": "Private Link", "namingConvention": "pl-" }, "Microsoft.Network/publicIPAddresses": { "friendlyName": "Public IP address", "namingConvention": "pip-" }, "Microsoft.Network/publicIPPrefixes": { "friendlyName": "Public IP address prefix", "namingConvention": "ippre-" }, "Microsoft.Network/routeFilters": { "friendlyName": "Route filter", "namingConvention": "rf-" }, "Microsoft.Network/routeTables": { "friendlyName": "Route table", "namingConvention": "rt-" }, "Microsoft.Network/routeTables/routes": { "friendlyName": "User defined route (UDR)", "namingConvention": "udr-" }, "Microsoft.Network/trafficManagerProfiles": { "friendlyName": "Traffic Manager profile", "namingConvention": "traf-" }, "Microsoft.Network/virtualNetworkGateways": { "friendlyName": "Virtual network gateway", "namingConvention": "vgw-" }, "Microsoft.Network/virtualNetworks": { "friendlyName": "Virtual network", "namingConvention": "vnet-" }, "Microsoft.Network/virtualNetworks/subnets": { "friendlyName": "Virtual network subnet", "namingConvention": "snet-" }, "Microsoft.Network/virtualNetworks/virtualNetworkPeerings": { "friendlyName": "Virtual network peering", "namingConvention": "peer-" }, "Microsoft.Network/virtualWans": { "friendlyName": "Virtual WAN", "namingConvention": "vwan-" }, "Microsoft.Network/vpnGateways": { "friendlyName": "VPN Gateway", "namingConvention": "vpng-" }, "Microsoft.Network/vpnGateways/vpnConnections": { "friendlyName": "VPN connection", "namingConvention": "vcn-" }, "Microsoft.Network/vpnGateways/vpnSites": { "friendlyName": "VPN site", "namingConvention": "vst-" }, "Microsoft.NotificationHubs/namespaces": { "friendlyName": "Notification Hubs namespace", "namingConvention": "ntfns-" }, "Microsoft.NotificationHubs/namespaces/notificationHubs": { "friendlyName": "Notification Hubs", "namingConvention": "ntf-" }, "Microsoft.OperationalInsights/workspaces": { "friendlyName": "Log Analytics workspace", "namingConvention": "log-" }, "Microsoft.PowerBIDedicated/capacities": { "friendlyName": "Power BI Embedded", "namingConvention": "pbi-" }, "Microsoft.Purview/accounts": { "friendlyName": "Azure Purview instance", "namingConvention": "pview-" }, "Microsoft.RecoveryServices/vaults": { "friendlyName": "Recovery Services vault", "namingConvention": "rsv-" }, "Microsoft.RecoveryServices/vaults/backupPolicies": { "friendlyName": "Recovery Services vault backup policy", "namingConvention": "rsvbp-" }, "Microsoft.Resources/resourceGroups": { "friendlyName": "Resource group", "namingConvention": "rg-" }, "Microsoft.Search/searchServices": { "friendlyName": "Azure Cognitive Search", "namingConvention": "srch-" }, "Microsoft.ServiceBus/namespaces": { "friendlyName": "Service Bus", "namingConvention": "sb-" }, "Microsoft.ServiceBus/namespaces/queues": { "friendlyName": "Service Bus queue", "namingConvention": "sbq-" }, "Microsoft.ServiceBus/namespaces/topics": { "friendlyName": "Service Bus topic", "namingConvention": "sbt-" }, "Microsoft.serviceEndPointPolicies": { "friendlyName": "Service endpoint", "namingConvention": "se-" }, "Microsoft.ServiceFabric/clusters": { "friendlyName": "Service Fabric cluster", "namingConvention": "sf-" }, "Microsoft.SignalRService/SignalR": { "friendlyName": "SignalR", "namingConvention": "sigr" }, "Microsoft.Sql/managedInstances": { "friendlyName": "SQL Managed Instance", "namingConvention": "sqlmi-" }, "Microsoft.Sql/servers": { "friendlyName": [ "Azure SQL Data Warehouse", "Azure SQL Database server" ], "namingConvention": [ "sqldw-", "sql-" ] }, "Microsoft.Sql/servers/databases": { "friendlyName": [ "SQL Server Stretch Database", "Azure SQL database" ], "namingConvention": [ "sqlstrdb-", "sqldb-" ] }, "Microsoft.Storage/storageAccounts": { "friendlyName": [ "Storage account", "VM storage account" ], "namingConvention": [ "st", "stvm" ] }, "Microsoft.StorSimple/managers": { "friendlyName": "Azure StorSimple", "namingConvention": "ssimp" }, "Microsoft.StreamAnalytics/cluster": { "friendlyName": "Azure Stream Analytics", "namingConvention": "asa-" }, "Microsoft.Synapse/workspaces": { "friendlyName": [ "Azure Synapse Analytics Workspaces", "Azure Synapse Analytics" ], "namingConvention": [ "synw", "syn" ] }, "Microsoft.Synapse/workspaces/sqlPools": { "friendlyName": [ "Azure Synapse Analytics Spark Pool", "Azure Synapse Analytics SQL Dedicated Pool" ], "namingConvention": [ "synsp", "syndp" ] }, "Microsoft.TimeSeriesInsights/environments": { "friendlyName": "Time Series Insights environment", "namingConvention": "tsi-" }, "Microsoft.Web/serverFarms": { "friendlyName": "App Service plan", "namingConvention": "plan-" }, "Microsoft.Web/sites": { "friendlyName": [ "Web app", "Function app", "App Service environment" ], "namingConvention": [ "app-", "func-", "ase-" ] }, "Microsoft.Web/staticSites": { "friendlyName": "Static web app", "namingConvention": "stapp-" } } '@ $htCAFNamingConvention = $JSONcafResourceNaming | ConvertFrom-Json $resourcesSubscriptionResultGroupedByType = $resourcesSubscriptionResult | Group-Object -Property type foreach ($entry in $resourcesSubscriptionResultGroupedByType) { if ($htCAFNamingConvention.($entry.Name)) { $doCAFResourceNamingCheck = $true $namingConvention = $htCAFNamingConvention.($entry.Name).namingConvention $namingConventionFriendlyName = $htCAFNamingConvention.($entry.Name).friendlyName } else { $doCAFResourceNamingCheck = $false $namingConvention = 'n/a' $namingConventionFriendlyName = 'n/a' } foreach ($resource in ($entry.Group)) { if ($doCAFResourceNamingCheck) { $cafResourceNamingCheck = 'failed' $applicableNaming = $namingConvention -join "$CsvDelimiterOpposite " foreach ($naming in $namingConvention) { if (($resource.name).StartsWith($naming, 'CurrentCultureIgnoreCase')) { $cafResourceNamingCheck = 'passed' } } } else { $cafResourceNamingCheck = 'n/a' $applicableNaming = 'n/a' } $sku = $null if ($resource.sku) { $sku = $resource.sku } $kind = $null if ($resource.kind) { $kind = $resource.kind } $null = $script:resourcesIdsAll.Add([PSCustomObject]@{ subscriptionId = $scopeId subscriptionName = $scopeDisplayName mgPath = $childMgMgPath type = ($resource.type).ToLower() sku = $sku kind = $kind id = ($resource.Id).ToLower() name = ($resource.name).ToLower() location = ($resource.location).ToLower() tags = ($resource.tags) createdTime = ($resource.createdTime) changedTime = ($resource.changedTime) cafResourceNamingResult = $cafResourceNamingCheck cafResourceNaming = $applicableNaming cafResourceNamingFriendlyName = $namingConventionFriendlyName -join "$CSVDelimiterOpposite " }) if ($resource.identity.userAssignedIdentities) { $resource.identity.userAssignedIdentities.psobject.properties | ForEach-Object { if ((-not [string]::IsNullOrEmpty($resource.Id)) -and (-not [string]::IsNullOrEmpty($_.Value.principalId))) { $hlp = ($_.Name.split('/')) $hlpMiSubId = $hlp[2] if ($scopeId -eq $hlpMiSubId) { $miCrossSubscription = $false } else { $miCrossSubscription = $true } $null = $script:arrayUserAssignedIdentities4Resources.Add([PSCustomObject]@{ resourceId = $resource.Id resourceName = $resource.name resourceMgPath = $childMgMgPath resourceSubscriptionName = $scopeDisplayName resourceSubscriptionId = $scopeId resourceResourceGroupName = ($resource.Id -split ('/'))[4] resourceType = $resource.type resourceLocation = $resource.location miPrincipalId = $_.Value.principalId miClientId = $_.Value.clientId miMgPath = $htSubscriptionsMgPath.($hlpMiSubId).pathDelimited miSubscriptionName = $htSubscriptionsMgPath.($hlpMiSubId).DisplayName miSubscriptionId = $hlpMiSubId miResourceGroupName = $hlp[4] miResourceId = $_.Name miResourceName = $_.Name -replace '.*/' miCrossSubscription = $miCrossSubscription }) } } } } } $endSubResourceIdsThis = Get-Date $null = $script:arraySubResourcesAddArrayDuration.Add([PSCustomObject]@{ sub = $scopeId DurationSec = (New-TimeSpan -Start $startSubResourceIdsThis -End $endSubResourceIdsThis).TotalSeconds }) #resourceTags $script:htSubscriptionTagList.($scopeId) = @{ Resource = @{} } foreach ($tags in ($resourcesSubscriptionResult.where( { $_.Tags -and -not [String]::IsNullOrWhiteSpace($_.Tags) } )).Tags) { foreach ($tagName in $tags.PSObject.Properties.Name) { #resource if ($htSubscriptionTagList.($scopeId).Resource.ContainsKey($tagName)) { $script:htSubscriptionTagList.($scopeId).Resource."$tagName" += 1 } else { $script:htSubscriptionTagList.($scopeId).Resource."$tagName" = 1 } #resourceAll if ($htAllTagList.Resource.ContainsKey($tagName)) { $script:htAllTagList.Resource."$tagName" += 1 } else { $script:htAllTagList.Resource."$tagName" = 1 } #all if ($htAllTagList.AllScopes.ContainsKey($tagName)) { $script:htAllTagList.AllScopes."$tagName" += 1 } else { $script:htAllTagList.AllScopes."$tagName" = 1 } } } } $funcDataCollectionResources = $function:dataCollectionResources.ToString() function dataCollectionResourceGroups { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $subscriptionQuotaId ) $currentTask = "Getting ResourceGroups for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/resourcegroups?api-version=2021-04-01" $method = 'GET' $resourceGroupsSubscriptionResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' $null = $script:resourceGroupsAll.Add([PSCustomObject]@{ subscriptionId = $scopeId count_ = ($resourceGroupsSubscriptionResult).count }) #resourceGroupTags if ($azAPICallConf['htParameters'].NoResources -eq $true) { $script:htSubscriptionTagList.($scopeId) = @{} } $script:htSubscriptionTagList.($scopeId).ResourceGroup = @{} foreach ($tags in ($resourceGroupsSubscriptionResult.where( { $_.Tags -and -not [String]::IsNullOrWhiteSpace($_.Tags) } )).Tags) { foreach ($tagName in $tags.PSObject.Properties.Name) { #resource if ($htSubscriptionTagList.($scopeId).ResourceGroup.ContainsKey($tagName)) { $script:htSubscriptionTagList.($scopeId).ResourceGroup."$tagName" += 1 } else { $script:htSubscriptionTagList.($scopeId).ResourceGroup."$tagName" = 1 } #resourceAll if ($htAllTagList.ResourceGroup.ContainsKey($tagName)) { $script:htAllTagList.ResourceGroup."$tagName" += 1 } else { $script:htAllTagList.ResourceGroup."$tagName" = 1 } #all if ($htAllTagList.AllScopes.ContainsKey($tagName)) { $script:htAllTagList.AllScopes."$tagName" += 1 } else { $script:htAllTagList.AllScopes."$tagName" = 1 } } } } $funcDataCollectionResourceGroups = $function:dataCollectionResourceGroups.ToString() function dataCollectionResourceProviders { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayname, $subscriptionQuotaId ) ($script:htResourceProvidersAll).($scopeId) = @{} $currentTask = "Getting ResourceProviders for Subscription: '$($scopeDisplayname)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers?api-version=2019-10-01" $method = 'GET' $resProvResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' ($script:htResourceProvidersAll).($scopeId).Providers = $resProvResult | Select-Object namespace, registrationState } $funcDataCollectionResourceProviders = $function:dataCollectionResourceProviders.ToString() function dataCollectionFeatures { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayname, [object]$MgParentNameChain, $subscriptionQuotaId ) $currentTask = "Getting Features for Subscription: '$($scopeDisplayname)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Features/features?api-version=2021-07-01" $method = 'GET' $featuresResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' $featuresResultRegistered = $featuresResult.where({ $_.properties.state -eq 'Registered' }) if ($featuresResultRegistered.Count -gt 0) { foreach ($registeredFeature in $featuresResultRegistered) { $null = $script:arrayFeaturesAll.Add([PSCustomObject]@{ subscriptionId = $registeredFeature.id.split('/')[2] mgPathArray = $MgParentNameChain mgPath = ($MgParentNameChain -join ',') feature = $registeredFeature.name }) } } } $funcDataCollectionFeatures = $function:dataCollectionFeatures.ToString() function dataCollectionResourceLocks { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayname, $subscriptionQuotaId ) $currentTask = "Getting ResourceLocks for Subscription: '$($scopeDisplayname)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Authorization/locks?api-version=2016-09-01" $method = 'GET' $requestSubscriptionResourceLocks = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' $requestSubscriptionResourceLocksCount = ($requestSubscriptionResourceLocks).Count if ($requestSubscriptionResourceLocksCount -gt 0) { $htTemp = @{} $locksAnyLockSubscriptionCount = 0 $locksCannotDeleteSubscriptionCount = 0 $locksReadOnlySubscriptionCount = 0 $arrayResourceGroupsAnyLock = [System.Collections.ArrayList]@() $arrayResourceGroupsCannotDeleteLock = [System.Collections.ArrayList]@() $arrayResourceGroupsReadOnlyLock = [System.Collections.ArrayList]@() $arrayResourcesAnyLock = [System.Collections.ArrayList]@() $arrayResourcesCannotDeleteLock = [System.Collections.ArrayList]@() $arrayResourcesReadOnlyLock = [System.Collections.ArrayList]@() foreach ($requestSubscriptionResourceLock in $requestSubscriptionResourceLocks) { $splitRequestSubscriptionResourceLockId = ($requestSubscriptionResourceLock.Id).Split('/') switch (($splitRequestSubscriptionResourceLockId).Count - 1) { #subLock 6 { $locksAnyLockSubscriptionCount++ if ($requestSubscriptionResourceLock.properties.level -eq 'CanNotDelete') { $locksCannotDeleteSubscriptionCount++ } if ($requestSubscriptionResourceLock.properties.level -eq 'ReadOnly') { $locksReadOnlySubscriptionCount++ } } #rgLock 8 { $resourceGroupName = $splitRequestSubscriptionResourceLockId[0..4] -join '/' $null = $arrayResourceGroupsAnyLock.Add([PSCustomObject]@{ rg = $resourceGroupName }) if ($requestSubscriptionResourceLock.properties.level -eq 'CanNotDelete') { $null = $arrayResourceGroupsCannotDeleteLock.Add([PSCustomObject]@{ rg = $resourceGroupName }) } if ($requestSubscriptionResourceLock.properties.level -eq 'ReadOnly') { $null = $arrayResourceGroupsReadOnlyLock.Add([PSCustomObject]@{ rg = $resourceGroupName }) } } #resLock 12 { $resourceId = $splitRequestSubscriptionResourceLockId[0..8] -join '/' $null = $arrayResourcesAnyLock.Add([PSCustomObject]@{ res = $resourceId }) if ($requestSubscriptionResourceLock.properties.level -eq 'CanNotDelete') { $null = $arrayResourcesCannotDeleteLock.Add([PSCustomObject]@{ res = $resourceId }) } if ($requestSubscriptionResourceLock.properties.level -eq 'ReadOnly') { $null = $arrayResourcesReadOnlyLock.Add([PSCustomObject]@{ res = $resourceId }) } } } } $htTemp.SubscriptionLocksCannotDeleteCount = $locksCannotDeleteSubscriptionCount $htTemp.SubscriptionLocksReadOnlyCount = $locksReadOnlySubscriptionCount #resourceGroups $htTemp.ResourceGroupsLocksCannotDeleteCount = $arrayResourceGroupsCannotDeleteLock.Count $htTemp.ResourceGroupsLocksCannotDelete = $arrayResourceGroupsCannotDeleteLock $htTemp.ResourceGroupsLocksReadOnlyCount = $arrayResourceGroupsReadOnlyLock.Count $htTemp.ResourceGroupsLocksReadOnly = $arrayResourceGroupsReadOnlyLock #resources $htTemp.ResourcesLocksCannotDeleteCount = $arrayResourcesCannotDeleteLock.Count $htTemp.ResourcesLocksCannotDelete = $arrayResourcesCannotDeleteLock $htTemp.ResourcesLocksReadOnlyCount = $arrayResourcesReadOnlyLock.Count $htTemp.ResourcesLocksReadOnly = $arrayResourcesReadOnlyLock $script:htResourceLocks.($scopeId) = $htTemp } } $funcDataCollectionResourceLocks = $function:dataCollectionResourceLocks.ToString() function dataCollectionTags { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $subscriptionQuotaId ) $currentTask = "Getting Tags for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Resources/tags/default?api-version=2020-06-01" $method = 'GET' $requestSubscriptionTags = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -listenOn 'Content' -caller 'CustomDataCollection' $script:htSubscriptionTagList.($scopeId).Subscription = @{} if ($requestSubscriptionTags.properties.tags) { $subscriptionTags = @() ($script:htSubscriptionTags).($scopeId) = @{} foreach ($tag in ($requestSubscriptionTags.properties.tags).PSObject.Properties) { $subscriptionTags += "$($tag.Name)/$($tag.Value)" ($script:htSubscriptionTags).($scopeId).($tag.Name) = $tag.Value $tagName = $tag.Name #subscription if ($htSubscriptionTagList.($scopeId).Subscription.ContainsKey($tagName)) { $script:htSubscriptionTagList.($scopeId).Subscription."$tagName" += 1 } else { $script:htSubscriptionTagList.($scopeId).Subscription."$tagName" = 1 } #subscriptionAll if ($htAllTagList.Subscription.ContainsKey($tagName)) { $script:htAllTagList.Subscription."$tagName" += 1 } else { $script:htAllTagList.Subscription."$tagName" = 1 } #all if ($htAllTagList.AllScopes.ContainsKey($tagName)) { $script:htAllTagList.AllScopes."$tagName" += 1 } else { $script:htAllTagList.AllScopes."$tagName" = 1 } } $subscriptionTagsCount = ($subscriptionTags).Count $subscriptionTags = $subscriptionTags -join "$CsvDelimiterOpposite " } else { $subscriptionTagsCount = 0 $subscriptionTags = 'none' } $htSubscriptionTagsReturn = @{ subscriptionTagsCount = $subscriptionTagsCount subscriptionTags = $subscriptionTags } return $htSubscriptionTagsReturn } $funcDataCollectionTags = $function:dataCollectionTags.ToString() function dataCollectionPolicyComplianceStates { [CmdletBinding()]Param( [string]$TargetMgOrSub, [string]$scopeId, [string]$scopeDisplayName, $subscriptionQuotaId ) if ($TargetMgOrSub -eq 'Sub') { $currentTask = "Getting Policy Compliance for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.PolicyInsights/policyStates/latest/summarize?api-version=2019-10-01" } if ($TargetMgOrSub -eq 'MG') { $currentTask = "Getting Policy Compliance for Management Group: '$($scopeDisplayName)' ('$scopeId')" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/providers/Microsoft.Management/managementGroups/$($scopeId)/providers/Microsoft.PolicyInsights/policyStates/latest/summarize?api-version=2019-10-01" } $method = 'POST' $policyComplianceResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' if ($policyComplianceResult -eq 'ResponseTooLarge') { if ($TargetMgOrSub -eq 'Sub') { $script:htCachePolicyComplianceResponseTooLargeSUB.($scopeId) = @{} } if ($TargetMgOrSub -eq 'MG') { $script:htCachePolicyComplianceResponseTooLargeMG.($scopeId) = @{} } } elseif ($policyComplianceResult -eq 'DisallowedProvider') { #nothing to do } else { if ($TargetMgOrSub -eq 'Sub') { ($script:htCachePolicyComplianceSUB).($scopeId) = @{} } if ($TargetMgOrSub -eq 'MG') { ($script:htCachePolicyComplianceMG).($scopeId) = @{} } foreach ($policyAssignment in $policyComplianceResult.policyassignments | Sort-Object -Property policyAssignmentId) { $policyAssignmentIdToLower = ($policyAssignment.policyAssignmentId).ToLower() if ($TargetMgOrSub -eq 'Sub') { ($script:htCachePolicyComplianceSUB).($scopeId).($policyAssignmentIdToLower) = @{} } if ($TargetMgOrSub -eq 'MG') { ($script:htCachePolicyComplianceMG).($scopeId).($policyAssignmentIdToLower) = @{} } foreach ($policyComplianceState in $policyAssignment.results.policydetails) { if ($policyComplianceState.ComplianceState -eq 'compliant') { if ($TargetMgOrSub -eq 'Sub') { ($script:htCachePolicyComplianceSUB).($scopeId).($policyAssignmentIdToLower).CompliantPolicies = $policyComplianceState.count } if ($TargetMgOrSub -eq 'MG') { ($script:htCachePolicyComplianceMG).($scopeId).($policyAssignmentIdToLower).CompliantPolicies = $policyComplianceState.count } } if ($policyComplianceState.ComplianceState -eq 'noncompliant') { if ($TargetMgOrSub -eq 'Sub') { ($script:htCachePolicyComplianceSUB).($scopeId).($policyAssignmentIdToLower).NonCompliantPolicies = $policyComplianceState.count } if ($TargetMgOrSub -eq 'MG') { ($script:htCachePolicyComplianceMG).($scopeId).($policyAssignmentIdToLower).NonCompliantPolicies = $policyComplianceState.count } } } foreach ($resourceComplianceState in $policyAssignment.results.resourcedetails) { if ($resourceComplianceState.ComplianceState -eq 'compliant') { if ($TargetMgOrSub -eq 'Sub') { ($script:htCachePolicyComplianceSUB).($scopeId).($policyAssignmentIdToLower).CompliantResources = $resourceComplianceState.count } if ($TargetMgOrSub -eq 'MG') { ($script:htCachePolicyComplianceMG).($scopeId).($policyAssignmentIdToLower).CompliantResources = $resourceComplianceState.count } } if ($resourceComplianceState.ComplianceState -eq 'nonCompliant') { if ($TargetMgOrSub -eq 'Sub') { ($script:htCachePolicyComplianceSUB).($scopeId).($policyAssignmentIdToLower).NonCompliantResources = $resourceComplianceState.count } if ($TargetMgOrSub -eq 'MG') { ($script:htCachePolicyComplianceMG).($scopeId).($policyAssignmentIdToLower).NonCompliantResources = $resourceComplianceState.count } } if ($resourceComplianceState.ComplianceState -eq 'conflict') { if ($TargetMgOrSub -eq 'Sub') { ($script:htCachePolicyComplianceSUB).($scopeId).($policyAssignmentIdToLower).ConflictingResources = $resourceComplianceState.count } if ($TargetMgOrSub -eq 'MG') { ($script:htCachePolicyComplianceMG).($scopeId).($policyAssignmentIdToLower).ConflictingResources = $resourceComplianceState.count } } } } } } $funcDataCollectionPolicyComplianceStates = $function:dataCollectionPolicyComplianceStates.ToString() function dataCollectionASCSecureScoreSub { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $subscriptionQuotaId ) if ($azAPICallConf['htParameters'].NoMDfCSecureScore -eq $false) { $currentTask = "Getting Microsoft Defender for Cloud Secure Score for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Security/securescores?api-version=2020-01-01" $method = 'GET' $subASCSecureScoreResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' if ($subASCSecureScoreResult -ne 'DisallowedProvider') { $subASCSecureScoreResultASCScore = ($subASCSecureScoreResult.where({ $_.name -eq 'ascScore' })) if ($subASCSecureScoreResultASCScore.count -gt 0) { $secureScorePercentageRounded = [math]::Round(($subASCSecureScoreResultASCScore.properties.score.current / $subASCSecureScoreResultASCScore.properties.score.max * 100), 2) $subscriptionASCSecureScore = "$($secureScorePercentageRounded)% ($($subASCSecureScoreResultASCScore.properties.score.current) of $($subASCSecureScoreResultASCScore.properties.score.max) points)" } else { $subscriptionASCSecureScore = 'n/a' } } else { $subscriptionASCSecureScore = 'n/a' } } else { $subscriptionASCSecureScore = "excluded (-NoMDfCSecureScore $($azAPICallConf['htParameters'].NoMDfCSecureScore))" } return $subscriptionASCSecureScore } $funcDataCollectionASCSecureScoreSub = $function:dataCollectionASCSecureScoreSub.ToString() function dataCollectionBluePrintDefinitionsMG { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $hierarchyLevel, $mgParentId, $mgParentName, $mgAscSecureScoreResult ) $currentTask = "Getting Blueprint definitions for Management Group: '$($scopeDisplayName)' ('$scopeId')" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/providers/Microsoft.Management/managementGroups/$($scopeId)/providers/Microsoft.Blueprint/blueprints?api-version=2018-11-01-preview" $method = 'GET' $scopeBlueprintDefinitionResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' $addRowToTableDone = $false if (($scopeBlueprintDefinitionResult).count -gt 0) { foreach ($blueprint in $scopeBlueprintDefinitionResult) { if (-not $($htCacheDefinitionsBlueprint).($blueprint.Id)) { ($script:htCacheDefinitionsBlueprint).($blueprint.Id) = @{} } $blueprintName = $blueprint.name $blueprintId = $blueprint.Id $blueprintDisplayName = $blueprint.properties.displayName $blueprintDescription = $blueprint.properties.description $blueprintScoped = "/providers/Microsoft.Management/managementGroups/$($scopeId)" $addRowToTableDone = $true addRowToTable ` -level $hierarchyLevel ` -mgName $scopeDisplayName ` -mgId $scopeId ` -mgParentId $mgParentId ` -mgParentName $mgParentName ` -mgASCSecureScore $mgAscSecureScoreResult ` -BlueprintName $blueprintName ` -BlueprintId $blueprintId ` -BlueprintDisplayName $blueprintDisplayName ` -BlueprintDescription $blueprintDescription ` -BlueprintScoped $blueprintScoped } } $returnObject = @{} if ($addRowToTableDone) { $returnObject.'addRowToTableDone' = @{} } return $returnObject } $funcDataCollectionBluePrintDefinitionsMG = $function:dataCollectionBluePrintDefinitionsMG.ToString() function dataCollectionBluePrintDefinitionsSub { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $hierarchyLevel, $childMgDisplayName, $childMgId, $childMgParentId, $childMgParentName, $mgAscSecureScoreResult, $subscriptionQuotaId, $subscriptionState, $subscriptionASCSecureScore, $subscriptionTags, $subscriptionTagsCount ) $currentTask = "Getting Blueprint definitions for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Blueprint/blueprints?api-version=2018-11-01-preview" $method = 'GET' $scopeBlueprintDefinitionResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' $addRowToTableDone = $false if ($scopeBlueprintDefinitionResult -ne 'DisallowedProvider') { if (($scopeBlueprintDefinitionResult).count -gt 0) { foreach ($blueprint in $scopeBlueprintDefinitionResult) { if (-not $($htCacheDefinitionsBlueprint).($blueprint.Id)) { ($script:htCacheDefinitionsBlueprint).($blueprint.Id) = @{} } $blueprintName = $blueprint.name $blueprintId = $blueprint.Id $blueprintDisplayName = $blueprint.properties.displayName $blueprintDescription = $blueprint.properties.description $blueprintScoped = "/subscriptions/$($scopeId)" $addRowToTableDone = $true addRowToTable ` -level $hierarchyLevel ` -mgName $childMgDisplayName ` -mgId $childMgId ` -mgParentId $childMgParentId ` -mgParentName $childMgParentName ` -mgASCSecureScore $mgAscSecureScoreResult ` -Subscription $scopeDisplayName ` -SubscriptionId $scopeId ` -SubscriptionQuotaId $subscriptionQuotaId ` -SubscriptionState $subscriptionState ` -SubscriptionASCSecureScore $subscriptionASCSecureScore ` -SubscriptionTags $subscriptionTags ` -SubscriptionTagsCount $subscriptionTagsCount ` -BlueprintName $blueprintName ` -BlueprintId $blueprintId ` -BlueprintDisplayName $blueprintDisplayName ` -BlueprintDescription $blueprintDescription ` -BlueprintScoped $blueprintScoped } } } $returnObject = @{} if ($addRowToTableDone) { $returnObject.'addRowToTableDone' = @{} } return $returnObject } $funcDataCollectionBluePrintDefinitionsSub = $function:dataCollectionBluePrintDefinitionsSub.ToString() function dataCollectionBluePrintAssignmentsSub { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $hierarchyLevel, $childMgDisplayName, $childMgId, $childMgParentId, $childMgParentName, $mgAscSecureScoreResult, $subscriptionQuotaId, $subscriptionState, $subscriptionASCSecureScore, $subscriptionTags, $subscriptionTagsCount ) $currentTask = "Getting Blueprint assignments for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Blueprint/blueprintAssignments?api-version=2018-11-01-preview" $method = 'GET' $subscriptionBlueprintAssignmentsResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' $addRowToTableDone = $false if ($subscriptionBlueprintAssignmentsResult -ne 'DisallowedProvider') { if (($subscriptionBlueprintAssignmentsResult).count -gt 0) { foreach ($subscriptionBlueprintAssignment in $subscriptionBlueprintAssignmentsResult) { if (-not ($htCacheAssignmentsBlueprint).($subscriptionBlueprintAssignment.Id)) { #($script:htCacheAssignmentsBlueprint).($subscriptionBlueprintAssignment.Id) = @{} ($script:htCacheAssignmentsBlueprint).($subscriptionBlueprintAssignment.Id) = $subscriptionBlueprintAssignment } if (($subscriptionBlueprintAssignment.properties.blueprintId) -like '/subscriptions/*') { $blueprintScope = $subscriptionBlueprintAssignment.properties.blueprintId -replace '/providers/Microsoft.Blueprint/blueprints/.*', '' $blueprintName = $subscriptionBlueprintAssignment.properties.blueprintId -replace '.*/blueprints/', '' -replace '/versions/.*', '' } if (($subscriptionBlueprintAssignment.properties.blueprintId) -like '/providers/Microsoft.Management/managementGroups/*') { $blueprintScope = $subscriptionBlueprintAssignment.properties.blueprintId -replace '/providers/Microsoft.Blueprint/blueprints/.*', '' $blueprintName = $subscriptionBlueprintAssignment.properties.blueprintId -replace '.*/blueprints/', '' -replace '/versions/.*', '' } $currentTask = "Getting Blueprint definitions related to Blueprint assignments for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/$($blueprintScope)/providers/Microsoft.Blueprint/blueprints/$($blueprintName)?api-version=2018-11-01-preview" $method = 'GET' $subscriptionBlueprintDefinitionResult = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -listenOn 'Content' -caller 'CustomDataCollection' if ($subscriptionBlueprintDefinitionResult -eq 'BlueprintNotFound') { $blueprintName = 'BlueprintNotFound' $blueprintId = 'BlueprintNotFound' $blueprintAssignmentVersion = $subscriptionBlueprintAssignment.properties.blueprintId -replace '.*/' $blueprintDisplayName = 'BlueprintNotFound' $blueprintDescription = 'BlueprintNotFound' $blueprintScoped = $blueprintScope $blueprintAssignmentId = $subscriptionBlueprintAssignmentsResult.Id } else { $blueprintName = $subscriptionBlueprintDefinitionResult.name $blueprintId = $subscriptionBlueprintDefinitionResult.Id $blueprintAssignmentVersion = $subscriptionBlueprintAssignment.properties.blueprintId -replace '.*/' $blueprintDisplayName = $subscriptionBlueprintDefinitionResult.properties.displayName $blueprintDescription = $subscriptionBlueprintDefinitionResult.properties.description $blueprintScoped = $blueprintScope $blueprintAssignmentId = $subscriptionBlueprintAssignmentsResult.Id } $addRowToTableDone = $true addRowToTable ` -level $hierarchyLevel ` -mgName $childMgDisplayName ` -mgId $childMgId ` -mgParentId $childMgParentId ` -mgParentName $childMgParentName ` -mgASCSecureScore $mgAscSecureScoreResult ` -Subscription $scopeDisplayName ` -SubscriptionId $scopeId ` -SubscriptionQuotaId $subscriptionQuotaId ` -SubscriptionState $subscriptionState ` -SubscriptionASCSecureScore $subscriptionASCSecureScore ` -SubscriptionTags $subscriptionTags ` -SubscriptionTagsCount $subscriptionTagsCount ` -BlueprintName $blueprintName ` -BlueprintId $blueprintId ` -BlueprintDisplayName $blueprintDisplayName ` -BlueprintDescription $blueprintDescription ` -BlueprintScoped $blueprintScoped ` -BlueprintAssignmentVersion $blueprintAssignmentVersion ` -BlueprintAssignmentId $blueprintAssignmentId } } } $returnObject = @{} if ($addRowToTableDone) { $returnObject.'addRowToTableDone' = @{} } return $returnObject } $funcDataCollectionBluePrintAssignmentsSub = $function:dataCollectionBluePrintAssignmentsSub.ToString() function dataCollectionPolicyExemptions { [CmdletBinding()]Param( [string]$TargetMgOrSub, [string]$scopeId, [string]$scopeDisplayName, $subscriptionQuotaId ) if ($TargetMgOrSub -eq 'Sub') { $currentTask = "Getting Policy exemptions for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Authorization/policyExemptions?api-version=2020-07-01-preview" } if ($TargetMgOrSub -eq 'MG') { $currentTask = "Getting Policy exemptions for Management Group: '$($scopeDisplayName)' ('$scopeId')" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/providers/Microsoft.Management/managementGroups/$($scopeId)/providers/Microsoft.Authorization/policyExemptions?api-version=2020-07-01-preview&`$filter=atScope()" } $method = 'GET' $requestPolicyExemptionAPI = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' $requestPolicyExemptionAPICount = ($requestPolicyExemptionAPI).Count if ($requestPolicyExemptionAPICount -gt 0) { foreach ($exemption in $requestPolicyExemptionAPI) { if (-not $htPolicyAssignmentExemptions.($exemption.Id)) { $script:htPolicyAssignmentExemptions.($exemption.Id) = @{} $script:htPolicyAssignmentExemptions.($exemption.Id).exemption = $exemption } } } } $funcDataCollectionPolicyExemptions = $function:dataCollectionPolicyExemptions.ToString() function dataCollectionPolicyDefinitions { [CmdletBinding()]Param( [string]$TargetMgOrSub, [string]$scopeId, [string]$scopeDisplayName, $subscriptionQuotaId ) if ($TargetMgOrSub -eq 'Sub') { $currentTask = "Getting Policy definitions for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Authorization/policyDefinitions?api-version=2021-06-01&`$filter=policyType eq 'Custom'" } if ($TargetMgOrSub -eq 'MG') { $currentTask = "Getting Policy definitions for Management Group: '$($scopeDisplayName)' ('$scopeId')" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/providers/Microsoft.Management/managementgroups/$($scopeId)/providers/Microsoft.Authorization/policyDefinitions?api-version=2021-06-01&`$filter=policyType eq 'Custom'" } $method = 'GET' $requestPolicyDefinitionAPI = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' $scopePolicyDefinitions = $requestPolicyDefinitionAPI.where( { $_.properties.policyType -eq 'custom' } ) if ($TargetMgOrSub -eq 'Sub') { $PolicyDefinitionsScopedCount = (($scopePolicyDefinitions.where( { ($_.id) -like "/subscriptions/$($scopeId)/*" } ))).count } if ($TargetMgOrSub -eq 'MG') { $PolicyDefinitionsScopedCount = (($scopePolicyDefinitions.where( { ($_.id) -like "/providers/Microsoft.Management/managementGroups/$($scopeId)/*" } ))).count } foreach ($scopePolicyDefinition in $scopePolicyDefinitions) { $hlpPolicyDefinitionId = ($scopePolicyDefinition.id).ToLower() $doIt = $true if ($TargetMgOrSub -eq 'MG') { $doIt = $false if ($hlpPolicyDefinitionId -like "/providers/Microsoft.Management/managementGroups/$($scopeId)/*" -and $hlpPolicyDefinitionId -notlike "/providers/Microsoft.Management/managementGroups/$($ManagementGroupId)/*") { $doIt = $true } if ($scopeId -eq $ManagementGroupId) { $doIt = $true } } if ($doIt) { if (-not $script:htCacheDefinitionsPolicy.($hlpPolicyDefinitionId)) { if (($scopePolicyDefinition.Properties.description).length -eq 0) { $policyDefinitionDescription = 'no description given' } else { $policyDefinitionDescription = $scopePolicyDefinition.Properties.description } $htTemp = @{} $htTemp.Id = $hlpPolicyDefinitionId if ($hlpPolicyDefinitionId -like '/providers/Microsoft.Management/managementGroups/*') { $htTemp.Scope = (($hlpPolicyDefinitionId).split('/'))[0..4] -join '/' $htTemp.ScopeMgSub = 'Mg' $htTemp.ScopeId = (($hlpPolicyDefinitionId).split('/'))[4] $htTemp.ScopeMGLevel = $htManagementGroupsMgPath.((($hlpPolicyDefinitionId).split('/'))[4]).ParentNameChainCount } if ($hlpPolicyDefinitionId -like '/subscriptions/*') { $htTemp.Scope = (($hlpPolicyDefinitionId).split('/'))[0..2] -join '/' $htTemp.ScopeMgSub = 'Sub' $htTemp.ScopeId = (($hlpPolicyDefinitionId).split('/'))[2] $htTemp.ScopeMGLevel = $htSubscriptionsMgPath.((($hlpPolicyDefinitionId).split('/'))[2]).level } if ($azAPICallConf['htParameters'].NoALZPolicyVersionChecker -eq $false) { $policyJsonRule = $scopePolicyDefinition.properties.policyRule | ConvertTo-Json -Depth 99 $hash = [System.Security.Cryptography.HashAlgorithm]::Create('sha256').ComputeHash([System.Text.Encoding]::UTF8.GetBytes($policyJsonRule)) $stringHash = [System.BitConverter]::ToString($hash) if ($alzPolicies.($scopePolicyDefinition.name) -or $alzPolicyHashes.($stringHash) -or $scopePolicyDefinition.properties.metadata.source -eq 'https://github.com/Azure/Enterprise-Scale/') { $policyHashMatch = $false if ($alzPolicyHashes.($stringHash)) { $policyHashMatch = $true $htTemp.ALZ = 'true' if ($alzPolicyHashes.($stringHash).metadataSource -eq 'https://github.com/Azure/Enterprise-Scale/' -and $alzPolicyHashes.($stringHash).metadataSource -eq $scopePolicyDefinition.properties.metadata.source -and $alzPolicyHashes.($stringHash).policyName -eq $scopePolicyDefinition.name) { $htTemp.ALZIdentificationLevel = 'PolicyRule Hash, Policy Name, MetaData Tag' } elseif ($alzPolicyHashes.($stringHash).policyName -eq $scopePolicyDefinition.name) { $htTemp.ALZIdentificationLevel = 'PolicyRule Hash, Policy Name' } else { $htTemp.ALZIdentificationLevel = 'PolicyRule Hash' } $htTemp.ALZPolicyName = $alzPolicyHashes.($stringHash).policyName $htTemp.hash = $stringHash if ($alzpolicies.($alzPolicyHashes.($stringHash).policyName).status -eq 'obsolete') { $htTemp.ALZState = 'obsolete' $htTemp.ALZLatestVer = '' } else { if ($scopePolicyDefinition.Properties.metadata.version) { if ($alzpolicies.($alzPolicyHashes.($stringHash).policyName).latestVersion -eq $scopePolicyDefinition.Properties.metadata.version) { $htTemp.ALZState = 'upToDate' } else { if ($alzpolicies.($alzPolicyHashes.($stringHash).policyName).latestVersion -like '*-deprecated') { $htTemp.ALZState = 'deprecated' } else { $htTemp.ALZState = 'outDated' } } } else { $htTemp.ALZState = 'potentiallyOutDated (no ver)' } $htTemp.ALZLatestVer = $alzpolicies.($alzPolicyHashes.($stringHash).policyName).latestVersion } } $policyNameMatch = $false if ($alzPolicies.($scopePolicyDefinition.name) -and -not $policyHashMatch) { $policyNameMatch = $true $htTemp.ALZ = 'true' if ($alzPolicies.($scopePolicyDefinition.name).metadataSource -eq 'https://github.com/Azure/Enterprise-Scale/' -and $alzPolicies.($scopePolicyDefinition.name).metadataSource -eq $scopePolicyDefinition.properties.metadata.source) { $htTemp.ALZIdentificationLevel = 'Policy Name, MetaData Tag' } else { $htTemp.ALZIdentificationLevel = 'Policy Name' } $htTemp.ALZPolicyName = $alzPolicies.($scopePolicyDefinition.name).policyName $htTemp.hash = $stringHash if ($alzPolicies.($scopePolicyDefinition.name).status -eq 'obsolete') { $htTemp.ALZState = 'obsolete' $htTemp.ALZLatestVer = '' } else { if ($scopePolicyDefinition.Properties.metadata.version) { if ($alzPolicies.($scopePolicyDefinition.name).latestVersion -eq $scopePolicyDefinition.Properties.metadata.version) { $htTemp.ALZState = 'upToDate' } else { if ($alzPolicies.($scopePolicyDefinition.name).latestVersion -like '*-deprecated') { $htTemp.ALZState = 'deprecated' } else { $htTemp.ALZState = 'outDated' } } } else { $htTemp.ALZState = 'potentiallyOutDated (no ver)' } $htTemp.ALZLatestVer = $alzPolicies.($scopePolicyDefinition.name).latestVersion } } if ($scopePolicyDefinition.properties.metadata.source -eq 'https://github.com/Azure/Enterprise-Scale/' -and -not $policyHashMatch -and -not $policyNameMatch) { $htTemp.ALZ = 'true' $htTemp.ALZState = 'unknown' $htTemp.ALZLatestVer = '' $htTemp.ALZIdentificationLevel = 'MetaData Tag' $htTemp.ALZPolicyName = '' $htTemp.hash = $stringHash } } else { $htTemp.ALZ = 'false' $htTemp.ALZState = '' $htTemp.ALZLatestVer = '' $htTemp.ALZIdentificationLevel = '' $htTemp.ALZPolicyName = '' $htTemp.hash = $stringHash } } else { $htTemp.ALZ = 'n/a' $htTemp.ALZState = '' $htTemp.ALZLatestVer = '' $htTemp.ALZIdentificationLevel = '' $htTemp.ALZPolicyName = '' $htTemp.hash = '' } $htTemp.DisplayName = $($scopePolicyDefinition.Properties.displayname) $htTemp.Name = $scopePolicyDefinition.Name $htTemp.Description = $($policyDefinitionDescription) $htTemp.Type = $($scopePolicyDefinition.Properties.policyType) $htTemp.Category = $($scopePolicyDefinition.Properties.metadata.category) if ($scopePolicyDefinition.Properties.metadata.version) { $htTemp.Version = $($scopePolicyDefinition.Properties.metadata.version) } else { $htTemp.Version = 'n/a' } $htTemp.PolicyDefinitionId = $hlpPolicyDefinitionId if ($scopePolicyDefinition.Properties.metadata.deprecated -eq $true -or $scopePolicyDefinition.Properties.displayname -like "``[Deprecated``]*") { $htTemp.Deprecated = $scopePolicyDefinition.Properties.metadata.deprecated } else { $htTemp.Deprecated = $false } if ($scopePolicyDefinition.Properties.metadata.preview -eq $true -or $scopePolicyDefinition.Properties.displayname -like "``[*Preview``]*") { $htTemp.Preview = $scopePolicyDefinition.Properties.metadata.preview } else { $htTemp.Preview = $false } #region effect $htEffectDetected = detectPolicyEffect -policyDefinition $scopePolicyDefinition $htTemp.effectDefaultValue = $htEffectDetected.defaultValue $htTemp.effectAllowedValue = $htEffectDetected.allowedValues $htTemp.effectFixedValue = $htEffectDetected.fixedValue #endregion effect $htTemp.Json = $scopePolicyDefinition $script:htCacheDefinitionsPolicy.($hlpPolicyDefinitionId) = $htTemp } if (-not [string]::IsNullOrWhiteSpace($scopePolicyDefinition.properties.policyRule.then.details.roleDefinitionIds)) { $script:htCacheDefinitionsPolicy.($hlpPolicyDefinitionId).RoleDefinitionIds = $scopePolicyDefinition.properties.policyRule.then.details.roleDefinitionIds } else { $script:htCacheDefinitionsPolicy.($hlpPolicyDefinitionId).RoleDefinitionIds = 'n/a' } #region namingValidation if (-not [string]::IsNullOrEmpty($scopePolicyDefinition.Properties.displayname)) { $namingValidationResult = NamingValidation -toCheck $scopePolicyDefinition.Properties.displayname if ($namingValidationResult.Count -gt 0) { if (-not $script:htNamingValidation.Policy.($hlpPolicyDefinitionId)) { $script:htNamingValidation.Policy.($hlpPolicyDefinitionId) = @{} } $script:htNamingValidation.Policy.($hlpPolicyDefinitionId).displayNameInvalidChars = ($namingValidationResult -join '') $script:htNamingValidation.Policy.($hlpPolicyDefinitionId).displayName = $scopePolicyDefinition.Properties.displayname } } if (-not [string]::IsNullOrEmpty($scopePolicyDefinition.Name)) { $namingValidationResult = NamingValidation -toCheck $scopePolicyDefinition.Name if ($namingValidationResult.Count -gt 0) { if (-not $script:htNamingValidation.Policy.($hlpPolicyDefinitionId)) { $script:htNamingValidation.Policy.($hlpPolicyDefinitionId) = @{} } $script:htNamingValidation.Policy.($hlpPolicyDefinitionId).nameInvalidChars = ($namingValidationResult -join '') $script:htNamingValidation.Policy.($hlpPolicyDefinitionId).name = $scopePolicyDefinition.Name } } #endregion namingValidation } } $returnObject = @{} $returnObject.'PolicyDefinitionsScopedCount' = $PolicyDefinitionsScopedCount return $returnObject } $funcDataCollectionPolicyDefinitions = $function:dataCollectionPolicyDefinitions.ToString() function dataCollectionPolicySetDefinitions { [CmdletBinding()]Param( [string]$TargetMgOrSub, [string]$scopeId, [string]$scopeDisplayName, $subscriptionQuotaId ) if ($TargetMgOrSub -eq 'Sub') { $currentTask = "Getting PolicySet definitions for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Authorization/policySetDefinitions?api-version=2021-06-01&`$filter=policyType eq 'Custom'" } if ($TargetMgOrSub -eq 'MG') { $currentTask = "Getting PolicySet definitions for Management Group: '$($scopeDisplayName)' ('$scopeId')" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/providers/Microsoft.Management/managementgroups/$($scopeId)/providers/Microsoft.Authorization/policySetDefinitions?api-version=2021-06-01&`$filter=policyType eq 'Custom'" } $method = 'GET' $requestPolicySetDefinitionAPI = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' $scopePolicySetDefinitions = $requestPolicySetDefinitionAPI.where( { $_.properties.policyType -eq 'custom' } ) if ($TargetMgOrSub -eq 'Sub') { $PolicySetDefinitionsScopedCount = ($scopePolicySetDefinitions.where( { ($_.Id) -like "/subscriptions/$($scopeId)/*" } )).count } if ($TargetMgOrSub -eq 'MG') { $PolicySetDefinitionsScopedCount = (($scopePolicySetDefinitions.where( { ($_.Id) -like "/providers/Microsoft.Management/managementGroups/$($scopeId)/*" } ))).count } foreach ($scopePolicySetDefinition in $scopePolicySetDefinitions) { $hlpPolicySetDefinitionId = ($scopePolicySetDefinition.id).ToLower() $doIt = $true if ($TargetMgOrSub -eq 'MG') { $doIt = $false if ($hlpPolicySetDefinitionId -like "/providers/Microsoft.Management/managementGroups/$($scopeId)/*" -and $hlpPolicySetDefinitionId -notlike "/providers/Microsoft.Management/managementGroups/$($ManagementGroupId)/*") { $doIt = $true } if ($scopeId -eq $ManagementGroupId) { $doIt = $true } } if ($doIt) { if (-not $script:htCacheDefinitionsPolicySet.($hlpPolicySetDefinitionId)) { if (($scopePolicySetDefinition.Properties.description).length -eq 0) { $policySetDefinitionDescription = 'no description given' } else { $policySetDefinitionDescription = $scopePolicySetDefinition.Properties.description } $htTemp = @{} $htTemp.Id = $hlpPolicySetDefinitionId if ($scopePolicySetDefinition.Id -like '/providers/Microsoft.Management/managementGroups/*') { $htTemp.Scope = (($scopePolicySetDefinition.Id).split('/'))[0..4] -join '/' $htTemp.ScopeMgSub = 'Mg' $htTemp.ScopeId = (($scopePolicySetDefinition.Id).split('/'))[4] $htTemp.ScopeMGLevel = $htManagementGroupsMgPath.((($scopePolicySetDefinition.Id).split('/'))[4]).ParentNameChainCount } if ($scopePolicySetDefinition.Id -like '/subscriptions/*') { $htTemp.Scope = (($scopePolicySetDefinition.Id).split('/'))[0..2] -join '/' $htTemp.ScopeMgSub = 'Sub' $htTemp.ScopeId = (($scopePolicySetDefinition.Id).split('/'))[2] $htTemp.ScopeMGLevel = $htSubscriptionsMgPath.((($scopePolicySetDefinition.Id).split('/'))[2]).level } if ($azAPICallConf['htParameters'].NoALZPolicyVersionChecker -eq $false) { $policyJsonParameters = $scopePolicySetDefinition.properties.parameters | ConvertTo-Json -Depth 99 $policyJsonPolicyDefinitions = $scopePolicySetDefinition.properties.policyDefinitions | ConvertTo-Json -Depth 99 $hashParameters = [System.Security.Cryptography.HashAlgorithm]::Create('sha256').ComputeHash([System.Text.Encoding]::UTF8.GetBytes($policyJsonParameters)) $stringHashParameters = [System.BitConverter]::ToString($hashParameters) $hashPolicyDefinitions = [System.Security.Cryptography.HashAlgorithm]::Create('sha256').ComputeHash([System.Text.Encoding]::UTF8.GetBytes($policyJsonPolicyDefinitions)) $stringHashPolicyDefinitions = [System.BitConverter]::ToString($hashPolicyDefinitions) $stringHash = "$($stringHashParameters)_$($stringHashPolicyDefinitions)" if ($alzPolicySets.($scopePolicySetDefinition.name) -or $allESLZPolicySetHashes.($stringHash) -or $scopePolicySetDefinition.properties.metadata.source -eq 'https://github.com/Azure/Enterprise-Scale/') { $policySetHashMatch = $false if ($alzPolicySetHashes.($stringHash)) { $policySetHashMatch = $true $htTemp.ALZ = 'true' if ($allESLZPolicySetHashes.($stringHash).metadataSource -eq 'https://github.com/Azure/Enterprise-Scale/' -and $allESLZPolicySetHashes.($stringHash).metadataSource -eq $scopePolicySetDefinition.properties.metadata.source -and $allESLZPolicySetHashes.($stringHash).policySetName -eq $scopePolicySetDefinition.name) { $htTemp.ALZIdentificationLevel = 'PolicySet Hash, PolicySet Name, MetaData Tag' } elseif ($allESLZPolicySetHashes.($stringHash).policySetName -eq $scopePolicySetDefinition.name) { $htTemp.ALZIdentificationLevel = 'PolicySet Hash, PolicySet Name' } else { $htTemp.ALZIdentificationLevel = 'PolicySet Hash' } $htTemp.ALZPolicySetName = $alzPolicySetHashes.($stringHash).policySetName if ($alzPolicySetHashes.($stringHash).status -eq 'obsolete') { $htTemp.ALZState = 'obsolete' $htTemp.ALZLatestVer = '' } else { if ($alzPolicySetHashes.($stringHash).latestVersion -eq $scopePolicySetDefinition.Properties.metadata.version) { $htTemp.ALZState = 'upToDate' } else { if ($alzPolicySetHashes.($stringHash).latestVersion -like '*-deprecated') { $htTemp.ALZState = 'deprecated' } else { $htTemp.ALZState = 'outDated' } } $htTemp.ALZLatestVer = $alzPolicySetHashes.($stringHash).latestVersion } } $policySetNameMatch = $false if ($alzPolicySets.($scopePolicySetDefinition.name) -and -not $policySetHashMatch) { $policySetNameMatch = $true $htTemp.ALZ = 'true' if ($alzPolicySets.($scopePolicySetDefinition.name).metadataSource -eq 'https://github.com/Azure/Enterprise-Scale/' -and $alzPolicySets.($scopePolicySetDefinition.name).metadataSource -eq $scopePolicySetDefinition.properties.metadata.source) { $htTemp.ALZIdentificationLevel = 'PolicySet Name, MetaData Tag' } else { $htTemp.ALZIdentificationLevel = 'PolicySet Name' } $htTemp.ALZPolicySetName = $alzPolicySets.($scopePolicySetDefinition.name).policySetName if ($alzPolicySets.($scopePolicySetDefinition.name).status -eq 'obsolete') { $htTemp.ALZState = 'obsolete' $htTemp.ALZLatestVer = '' } else { if ($alzPolicySets.($scopePolicySetDefinition.name).latestVersion -eq $scopePolicySetDefinition.Properties.metadata.version) { $htTemp.ALZState = 'upToDate' } else { if ($alzPolicySets.($scopePolicySetDefinition.name).latestVersion -like '*-deprecated') { $htTemp.ALZState = 'deprecated' } else { $htTemp.ALZState = 'outDated' } } $htTemp.ALZLatestVer = $alzPolicySets.($scopePolicySetDefinition.name).latestVersion } } if ($scopePolicySetDefinition.properties.metadata.source -eq 'https://github.com/Azure/Enterprise-Scale/' -and -not $policySetHashMatch -and -not $policySetNameMatch) { $htTemp.ALZ = 'true' $htTemp.ALZState = 'unknown' $htTemp.ALZLatestVer = '' $htTemp.ALZIdentificationLevel = 'MetaData Tag' $htTemp.ALZPolicyName = '' $htTemp.hash = $stringHash } } else { $htTemp.ALZ = 'false' $htTemp.ALZState = '' $htTemp.ALZLatestVer = '' $htTemp.ALZIdentificationLevel = '' $htTemp.ALZPolicySetName = '' } } else { $htTemp.ALZ = 'n/a' $htTemp.ALZState = '' $htTemp.ALZLatestVer = '' $htTemp.ALZIdentificationLevel = '' $htTemp.ALZPolicySetName = '' } $htTemp.DisplayName = $($scopePolicySetDefinition.Properties.displayname) $htTemp.Name = $scopePolicySetDefinition.Name $htTemp.Description = $($policySetDefinitionDescription) $htTemp.Type = $($scopePolicySetDefinition.Properties.policyType) $htTemp.Category = $($scopePolicySetDefinition.Properties.metadata.category) if ($scopePolicySetDefinition.Properties.metadata.version) { $htTemp.Version = $($scopePolicySetDefinition.Properties.metadata.version) } else { $htTemp.Version = 'n/a' } $htTemp.PolicyDefinitionId = $hlpPolicySetDefinitionId $arrayPolicySetPolicyIdsToLower = @() $htPolicySetPolicyRefIds = @{} $arrayPolicySetPolicyIdsToLower = foreach ($policySetPolicy in $scopePolicySetDefinition.properties.policydefinitions) { $($policySetPolicy.policyDefinitionId).ToLower() $htPolicySetPolicyRefIds.($policySetPolicy.policyDefinitionReferenceId) = ($policySetPolicy.policyDefinitionId) } $htTemp.PolicySetPolicyIds = $arrayPolicySetPolicyIdsToLower $htTemp.PolicySetPolicyRefIds = $htPolicySetPolicyRefIds $htTemp.Json = $scopePolicySetDefinition if ($scopePolicySetDefinition.Properties.metadata.deprecated -eq $true -or $scopePolicySetDefinition.Properties.displayname -like "``[Deprecated``]*") { $htTemp.Deprecated = $scopePolicySetDefinition.Properties.metadata.deprecated } else { $htTemp.Deprecated = $false } if ($scopePolicySetDefinition.Properties.metadata.preview -eq $true -or $scopePolicySetDefinition.Properties.displayname -like "``[*Preview``]*") { $htTemp.Preview = $scopePolicySetDefinition.Properties.metadata.preview } else { $htTemp.Preview = $false } ($script:htCacheDefinitionsPolicySet).($hlpPolicySetDefinitionId) = $htTemp } #namingValidation if (-not [string]::IsNullOrEmpty($scopePolicySetDefinition.Properties.displayname)) { $namingValidationResult = NamingValidation -toCheck $scopePolicySetDefinition.Properties.displayname if ($namingValidationResult.Count -gt 0) { if (-not $script:htNamingValidation.PolicySet.($scopePolicySetDefinition.Id)) { $script:htNamingValidation.PolicySet.($scopePolicySetDefinition.Id) = @{} } $script:htNamingValidation.PolicySet.($scopePolicySetDefinition.Id).displayNameInvalidChars = ($namingValidationResult -join '') $script:htNamingValidation.PolicySet.($scopePolicySetDefinition.Id).displayName = $scopePolicySetDefinition.Properties.displayname } } if (-not [string]::IsNullOrEmpty($scopePolicySetDefinition.Name)) { $namingValidationResult = NamingValidation -toCheck $scopePolicySetDefinition.Name if ($namingValidationResult.Count -gt 0) { if (-not $script:htNamingValidation.PolicySet.($scopePolicySetDefinition.Id)) { $script:htNamingValidation.PolicySet.($scopePolicySetDefinition.Id) = @{} } $script:htNamingValidation.PolicySet.($scopePolicySetDefinition.Id).nameInvalidChars = ($namingValidationResult -join '') $script:htNamingValidation.PolicySet.($scopePolicySetDefinition.Id).name = $scopePolicySetDefinition.Name } } } } $returnObject = @{} $returnObject.'PolicySetDefinitionsScopedCount' = $PolicySetDefinitionsScopedCount return $returnObject } $funcDataCollectionPolicySetDefinitions = $function:dataCollectionPolicySetDefinitions.ToString() function dataCollectionPolicyAssignmentsMG { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $hierarchyLevel, $mgParentId, $mgParentName, $mgAscSecureScoreResult, $PolicyDefinitionsScopedCount, $PolicySetDefinitionsScopedCount ) $addRowToTableDone = $false $currentTask = "Getting Policy assignments for Management Group: '$($scopeDisplayName)' ('$($scopeId)')" if ($azAPICallConf['htParameters'].LargeTenant -eq $false -or $azAPICallConf['htParameters'].PolicyAtScopeOnly -eq $false) { $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/providers/Microsoft.Management/managementgroups/$($scopeId)/providers/Microsoft.Authorization/policyAssignments?`$filter=atscope()&api-version=2021-06-01" } else { $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/providers/Microsoft.Management/managementgroups/$($scopeId)/providers/Microsoft.Authorization/policyAssignments?`$filter=atExactScope()&api-version=2021-06-01" } $method = 'GET' $L0mgmtGroupPolicyAssignments = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' $L0mgmtGroupPolicyAssignmentsPolicyCount = (($L0mgmtGroupPolicyAssignments.where( { $_.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policyDefinitions/' } ))).count $L0mgmtGroupPolicyAssignmentsPolicySetCount = (($L0mgmtGroupPolicyAssignments.where( { $_.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policySetDefinitions/' } ))).count $L0mgmtGroupPolicyAssignmentsPolicyAtScopeCount = (($L0mgmtGroupPolicyAssignments.where( { $_.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policyDefinitions/' -and $_.Id -match "/providers/Microsoft.Management/managementGroups/$($scopeId)" } ))).count $L0mgmtGroupPolicyAssignmentsPolicySetAtScopeCount = (($L0mgmtGroupPolicyAssignments.where( { $_.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policySetDefinitions/' -and $_.Id -match "/providers/Microsoft.Management/managementGroups/$($scopeId)" } ))).count $L0mgmtGroupPolicyAssignmentsPolicyAndPolicySetAtScopeCount = ($L0mgmtGroupPolicyAssignmentsPolicyAtScopeCount + $L0mgmtGroupPolicyAssignmentsPolicySetAtScopeCount) if (-not $htMgAtScopePolicyAssignments.($scopeId)) { $script:htMgAtScopePolicyAssignments.($scopeId) = @{} $script:htMgAtScopePolicyAssignments.($scopeId).AssignmentsCount = $L0mgmtGroupPolicyAssignmentsPolicyAndPolicySetAtScopeCount } foreach ($L0mgmtGroupPolicyAssignment in $L0mgmtGroupPolicyAssignments) { $doIt = $false if ($L0mgmtGroupPolicyAssignment.properties.scope -eq "/providers/Microsoft.Management/managementGroups/$($scopeId)" -and $L0mgmtGroupPolicyAssignment.properties.scope -ne "/providers/Microsoft.Management/managementGroups/$($ManagementGroupId)") { $doIt = $true } if ($scopeId -eq $ManagementGroupId) { $doIt = $true } if ($doIt) { $htTemp = @{} $htTemp.Assignment = $L0mgmtGroupPolicyAssignment $htTemp.AssignmentScopeMgSubRg = 'Mg' $splitAssignment = (($L0mgmtGroupPolicyAssignment.Id).ToLower()).Split('/') $htTemp.AssignmentScopeId = [string]($splitAssignment[4]) $script:htCacheAssignmentsPolicy.(($L0mgmtGroupPolicyAssignment.Id).ToLower()) = $htTemp } #region namingValidation if (-not [string]::IsNullOrEmpty($L0mgmtGroupPolicyAssignment.Properties.DisplayName)) { $namingValidationResult = NamingValidation -toCheck $L0mgmtGroupPolicyAssignment.Properties.DisplayName if ($namingValidationResult.Count -gt 0) { if (-not $script:htNamingValidation.PolicyAssignment.($L0mgmtGroupPolicyAssignment.Id)) { $script:htNamingValidation.PolicyAssignment.($L0mgmtGroupPolicyAssignment.Id) = @{} } $script:htNamingValidation.PolicyAssignment.($L0mgmtGroupPolicyAssignment.Id).displayNameInvalidChars = ($namingValidationResult -join '') $script:htNamingValidation.PolicyAssignment.($L0mgmtGroupPolicyAssignment.Id).displayName = $L0mgmtGroupPolicyAssignment.Properties.DisplayName } } if (-not [string]::IsNullOrEmpty($L0mgmtGroupPolicyAssignment.Name)) { $namingValidationResult = NamingValidation -toCheck $L0mgmtGroupPolicyAssignment.Name if ($namingValidationResult.Count -gt 0) { if (-not $script:htNamingValidation.PolicyAssignment.($L0mgmtGroupPolicyAssignment.Id)) { $script:htNamingValidation.PolicyAssignment.($L0mgmtGroupPolicyAssignment.Id) = @{} } $script:htNamingValidation.PolicyAssignment.($L0mgmtGroupPolicyAssignment.Id).nameInvalidChars = ($namingValidationResult -join '') $script:htNamingValidation.PolicyAssignment.($L0mgmtGroupPolicyAssignment.Id).name = $L0mgmtGroupPolicyAssignment.Name } } #endregion namingValidation if ($L0mgmtGroupPolicyAssignment.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policyDefinitions/' -OR $L0mgmtGroupPolicyAssignment.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policySetDefinitions/') { #policy if ($L0mgmtGroupPolicyAssignment.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policyDefinitions/') { $policyVariant = 'Policy' $policyDefinitionId = ($L0mgmtGroupPolicyAssignment.properties.policydefinitionid).ToLower() $policyDefinitionSplitted = $policyDefinitionId.split('/') $hlpPolicyDefinitionScope = $policyDefinitionSplitted[4] if ( ($policyDefinitionId -like '/providers/microsoft.management/managementgroups/*' -and $htManagementGroupsMgPath.($scopeId).path -contains ($hlpPolicyDefinitionScope)) -or $policyDefinitionId -like '/providers/microsoft.authorization/policydefinitions/*' ) { $tryCounter = 0 do { $tryCounter++ if (($htCacheDefinitionsPolicy).($policyDefinitionId)) { $policyReturnedFromHt = $true $policyDefinition = ($htCacheDefinitionsPolicy).($policyDefinitionId) if ([string]::IsnullOrEmpty($policyDefinition.PolicyDefinitionId)) { Write-Host "check: $policyDefinitionId" $policyDefinition } if ($policyDefinition.Type -eq 'Custom') { $policyDefintionScope = $policyDefinition.Scope $policyDefintionScopeMgSub = $policyDefinition.ScopeMgSub $policyDefintionScopeId = $policyDefinition.ScopeId } else { $policyDefintionScope = 'n/a' $policyDefintionScopeMgSub = 'n/a' $policyDefintionScopeId = 'n/a' } $policyAvailability = '' $policyDisplayName = ($policyDefinition).DisplayName $policyDescription = ($policyDefinition).Description $policyDefinitionType = ($policyDefinition).Type $policyDefinitionIsALZ = ($policyDefinition).ALZ $policyCategory = ($policyDefinition).Category $policyDefinitionEffectDefault = ($policyDefinition).effectDefaultValue $policyDefinitionEffectFixed = ($policyDefinition).effectFixedValue } else { #test Write-Host " attention! $scopeDisplayName ($scopeId); policyAssignment '$($L0mgmtGroupPolicyAssignment.Id)' policyDefinition (Policy) could not be found: '$($policyDefinitionId)' -retry" Start-Sleep -Seconds 1 } } until ($policyReturnedFromHt -or $tryCounter -gt 2) if (-not $policyReturnedFromHt) { Write-Host " attention! $scopeDisplayName ($scopeId); policyAssignment '$($L0mgmtGroupPolicyAssignment.Id)' policyDefinition (Policy) could not be found: '$($policyDefinitionId)'" Write-Host " scope: $($scopeId) Policy / Custom:$($mgPolicyDefinitions.Count) CustomAtScope:$($PolicyDefinitionsScopedCount)" Write-Host " built-in PolicyDefinitions: $($($htCacheDefinitionsPolicy).Values.where({$_.Type -eq 'BuiltIn'}).Count)" Write-Host " custom PolicyDefinitions: $($($htCacheDefinitionsPolicy).Values.where({$_.Type -eq 'Custom'}).Count)" Write-Host ' Listing all PolicyDefinitions:' foreach ($tmpPolicyDefinitionId in ($($htCacheDefinitionsPolicy).Keys | Sort-Object)) { Write-Host $tmpPolicyDefinitionId } Throw 'Error - Azure Governance Visualizer: check the last console output for details' } } #policyDefinition Scope does not exist else { if ($htManagementGroupsMgPath.Keys -contains $hlpPolicyDefinitionScope) { Write-Host " $scopeDisplayName ($scopeId); policyAssignment '$($L0mgmtGroupPolicyAssignment.Id)' policyDefinition (Policy) could not be found: '$($policyDefinitionId)' - the scope '$($hlpPolicyDefinitionScope)' is not contained in the '$scopeId' Management Group chain. The Policy definition scope '$hlpPolicyDefinitionScope' has MGPath: '$($htManagementGroupsMgPath.($hlpPolicyDefinitionScope).pathDelimited)'" } else { Write-Host " $scopeDisplayName ($scopeId); policyAssignment '$($L0mgmtGroupPolicyAssignment.Id)' policyDefinition (Policy) could not be found: '$($policyDefinitionId)' - the scope '$($hlpPolicyDefinitionScope)' could not be found" } $policyAvailability = 'na' $policyDefintionScope = "/$($policyDefinitionSplitted[1])/$($policyDefinitionSplitted[2])/$($policyDefinitionSplitted[3])/$($hlpPolicyDefinitionScope)" $policyDefintionScopeMgSub = 'Mg' $policyDefintionScopeId = $hlpPolicyDefinitionScope $policyDisplayName = 'unknown' $policyDescription = 'unknown' $policyDefinitionType = 'likely Custom' $policyDefinitionIsALZ = 'unknown' $policyCategory = 'unknown' $policyDefinitionEffectDefault = 'unknown' $policyDefinitionEffectFixed = 'unknown' } $policyAssignmentScope = $L0mgmtGroupPolicyAssignment.Properties.Scope $policyAssignmentId = ($L0mgmtGroupPolicyAssignment.Id).ToLower() $policyAssignmentName = $L0mgmtGroupPolicyAssignment.Name $policyAssignmentDisplayName = $L0mgmtGroupPolicyAssignment.Properties.DisplayName if (($L0mgmtGroupPolicyAssignment.Properties.Description).length -eq 0) { $policyAssignmentDescription = 'no description given' } else { $policyAssignmentDescription = $L0mgmtGroupPolicyAssignment.Properties.Description } if ($L0mgmtGroupPolicyAssignment.identity) { $policyAssignmentIdentity = $L0mgmtGroupPolicyAssignment.identity.principalId } else { $policyAssignmentIdentity = 'n/a' } $assignedBy = 'n/a' $createdBy = '' $createdOn = '' $updatedBy = '' $updatedOn = '' if ($L0mgmtGroupPolicyAssignment.properties.metadata) { if ($L0mgmtGroupPolicyAssignment.properties.metadata.assignedBy) { $assignedBy = $L0mgmtGroupPolicyAssignment.properties.metadata.assignedBy } if ($L0mgmtGroupPolicyAssignment.properties.metadata.createdBy) { $createdBy = $L0mgmtGroupPolicyAssignment.properties.metadata.createdBy } if ($L0mgmtGroupPolicyAssignment.properties.metadata.createdOn) { $createdOn = $L0mgmtGroupPolicyAssignment.properties.metadata.createdOn } if ($L0mgmtGroupPolicyAssignment.properties.metadata.updatedBy) { $updatedBy = $L0mgmtGroupPolicyAssignment.properties.metadata.updatedBy } if ($L0mgmtGroupPolicyAssignment.properties.metadata.updatedOn) { $updatedOn = $L0mgmtGroupPolicyAssignment.properties.metadata.updatedOn } } if ($L0mgmtGroupPolicyAssignment.Properties.nonComplianceMessages.Message) { $nonComplianceMessage = $L0mgmtGroupPolicyAssignment.Properties.nonComplianceMessages.Message } else { $nonComplianceMessage = '' } $formatedPolicyAssignmentParameters = '' $hlp = $L0mgmtGroupPolicyAssignment.Properties.Parameters if (-not [string]::IsNullOrEmpty($hlp)) { $arrayPolicyAssignmentParameters = @() $arrayPolicyAssignmentParameters = foreach ($parameterName in $hlp.PSObject.Properties.Name | Sort-Object) { "$($parameterName)=$($hlp.($parameterName).Value -join "$($CsvDelimiter) ")" } $formatedPolicyAssignmentParameters = $arrayPolicyAssignmentParameters -join "$($CsvDelimiterOpposite) " } $addRowToTableDone = $true addRowToTable ` -level $hierarchyLevel ` -mgName $scopeDisplayName ` -mgId $scopeId ` -mgParentId $mgParentId ` -mgParentName $mgParentName ` -mgASCSecureScore $mgAscSecureScoreResult ` -Policy $policyDisplayName ` -PolicyAvailability $policyAvailability ` -PolicyDescription $policyDescription ` -PolicyVariant $policyVariant ` -PolicyType $policyDefinitionType ` -PolicyIsALZ $policyDefinitionIsALZ ` -PolicyCategory $policyCategory ` -PolicyDefinitionIdGuid ($policyDefinitionId -replace '.*/') ` -PolicyDefinitionId $policyDefinitionId ` -PolicyDefintionScope $policyDefintionScope ` -PolicyDefintionScopeMgSub $policyDefintionScopeMgSub ` -PolicyDefintionScopeId $policyDefintionScopeId ` -PolicyDefinitionsScopedLimit $LimitPOLICYPolicyDefinitionsScopedManagementGroup ` -PolicyDefinitionsScopedCount $policyDefinitionsScopedCount ` -PolicySetDefinitionsScopedLimit $LimitPOLICYPolicySetDefinitionsScopedManagementGroup ` -PolicySetDefinitionsScopedCount $policySetDefinitionsScopedCount ` -PolicyDefinitionEffectDefault $policyDefinitionEffectDefault ` -PolicyDefinitionEffectFixed $policyDefinitionEffectFixed ` -PolicyAssignmentScope $policyAssignmentScope ` -PolicyAssignmentScopeMgSubRg 'Mg' ` -PolicyAssignmentScopeName ($policyAssignmentScope -replace '.*/', '') ` -PolicyAssignmentNotScopes $L0mgmtGroupPolicyAssignment.Properties.NotScopes ` -PolicyAssignmentId $policyAssignmentId ` -PolicyAssignmentName $policyAssignmentName ` -PolicyAssignmentDisplayName $policyAssignmentDisplayName ` -PolicyAssignmentDescription $policyAssignmentDescription ` -PolicyAssignmentEnforcementMode $L0mgmtGroupPolicyAssignment.Properties.EnforcementMode ` -PolicyAssignmentNonComplianceMessages $nonComplianceMessage ` -PolicyAssignmentIdentity $policyAssignmentIdentity ` -PolicyAssignmentLimit $LimitPOLICYPolicyAssignmentsManagementGroup ` -PolicyAssignmentCount $L0mgmtGroupPolicyAssignmentsPolicyCount ` -PolicyAssignmentAtScopeCount $L0mgmtGroupPolicyAssignmentsPolicyAtScopeCount ` -PolicyAssignmentParameters $L0mgmtGroupPolicyAssignment.Properties.Parameters ` -PolicyAssignmentParametersFormated $formatedPolicyAssignmentParameters ` -PolicyAssignmentAssignedBy $assignedBy ` -PolicyAssignmentCreatedBy $createdBy ` -PolicyAssignmentCreatedOn $createdOn ` -PolicyAssignmentUpdatedBy $updatedBy ` -PolicyAssignmentUpdatedOn $updatedOn ` -PolicySetAssignmentLimit $LimitPOLICYPolicySetAssignmentsManagementGroup ` -PolicySetAssignmentCount $L0mgmtGroupPolicyAssignmentsPolicySetCount ` -PolicySetAssignmentAtScopeCount $L0mgmtGroupPolicyAssignmentsPolicySetAtScopeCount ` -PolicyAndPolicySetAssignmentAtScopeCount $L0mgmtGroupPolicyAssignmentsPolicyAndPolicySetAtScopeCount } #policySet if ($L0mgmtGroupPolicyAssignment.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policySetDefinitions/') { $policyVariant = 'PolicySet' $policySetDefinitionId = ($L0mgmtGroupPolicyAssignment.properties.policydefinitionid).ToLower() $policySetDefinitionSplitted = $policySetDefinitionId.split('/') $hlpPolicySetDefinitionScope = $policySetDefinitionSplitted[4] $tryCounter = 0 do { $tryCounter++ if (($htCacheDefinitionsPolicySet).($policySetDefinitionId)) { $policySetReturnedFromHt = $true $policySetDefinition = ($htCacheDefinitionsPolicySet).($policySetDefinitionId) if ($policySetDefinition.Type -eq 'Custom') { $policySetDefintionScope = $policySetDefinition.Scope $policySetDefintionScopeMgSub = $policySetDefinition.ScopeMgSub $policySetDefintionScopeId = $policySetDefinition.ScopeId } else { $policySetDefintionScope = 'n/a' $policySetDefintionScopeMgSub = 'n/a' $policySetDefintionScopeId = 'n/a' } $policySetDisplayName = $policySetDefinition.DisplayName $policySetDescription = $policySetDefinition.Description $policySetDefinitionType = $policySetDefinition.Type $policySetDefinitionIsALZ = $policySetDefinition.ALZ $policySetCategory = $policySetDefinition.Category } else { #Write-Host "pa '($L0mgmtGroupPolicyAssignment.Id)' scope: '$($scopeId)' - policySetDefinition not available: $policySetDefinitionId" Start-Sleep -Seconds 1 } } until ($policySetReturnedFromHt -or $tryCounter -gt 2) if (-not $policySetReturnedFromHt) { Write-Host " $scopeDisplayName ($scopeId); policyAssignment '$($L0mgmtGroupPolicyAssignment.Id)' policyDefinition (PolicySet) could not be found: '$($policySetDefinitionId)'" $policySetDefintionScope = "/$($policySetDefinitionSplitted[1])/$($policySetDefinitionSplitted[2])/$($policySetDefinitionSplitted[3])/$($hlpPolicySetDefinitionScope)" $policySetDefintionScopeMgSub = 'Mg' $policySetDefintionScopeId = $hlpPolicySetDefinitionScope $policySetDisplayName = 'unknown' $policySetDescription = 'unknown' $policySetDefinitionType = 'likely Custom' $policySetDefinitionIsALZ = 'unknown' $policySetCategory = 'unknown' } $policyAssignmentScope = $L0mgmtGroupPolicyAssignment.Properties.Scope $policyAssignmentId = ($L0mgmtGroupPolicyAssignment.Id).ToLower() $policyAssignmentName = $L0mgmtGroupPolicyAssignment.Name $policyAssignmentDisplayName = $L0mgmtGroupPolicyAssignment.Properties.DisplayName if (($L0mgmtGroupPolicyAssignment.Properties.Description).length -eq 0) { $policyAssignmentDescription = 'no description given' } else { $policyAssignmentDescription = $L0mgmtGroupPolicyAssignment.Properties.Description } if ($L0mgmtGroupPolicyAssignment.identity) { $policyAssignmentIdentity = $L0mgmtGroupPolicyAssignment.identity.principalId } else { $policyAssignmentIdentity = 'n/a' } $assignedBy = 'n/a' $createdBy = '' $createdOn = '' $updatedBy = '' $updatedOn = '' if ($L0mgmtGroupPolicyAssignment.properties.metadata) { if ($L0mgmtGroupPolicyAssignment.properties.metadata.assignedBy) { $assignedBy = $L0mgmtGroupPolicyAssignment.properties.metadata.assignedBy } if ($L0mgmtGroupPolicyAssignment.properties.metadata.createdBy) { $createdBy = $L0mgmtGroupPolicyAssignment.properties.metadata.createdBy } if ($L0mgmtGroupPolicyAssignment.properties.metadata.createdOn) { $createdOn = $L0mgmtGroupPolicyAssignment.properties.metadata.createdOn } if ($L0mgmtGroupPolicyAssignment.properties.metadata.updatedBy) { $updatedBy = $L0mgmtGroupPolicyAssignment.properties.metadata.updatedBy } if ($L0mgmtGroupPolicyAssignment.properties.metadata.updatedOn) { $updatedOn = $L0mgmtGroupPolicyAssignment.properties.metadata.updatedOn } } if (($L0mgmtGroupPolicyAssignment.Properties.nonComplianceMessages.where( { -not $_.policyDefinitionReferenceId } )).Message) { $nonComplianceMessage = ($L0mgmtGroupPolicyAssignment.Properties.nonComplianceMessages.where( { -not $_.policyDefinitionReferenceId } )).Message } else { $nonComplianceMessage = '' } $formatedPolicyAssignmentParameters = '' $hlp = $L0mgmtGroupPolicyAssignment.Properties.Parameters if (-not [string]::IsNullOrEmpty($hlp)) { $arrayPolicyAssignmentParameters = @() $arrayPolicyAssignmentParameters = foreach ($parameterName in $hlp.PSObject.Properties.Name | Sort-Object) { "$($parameterName)=$($hlp.($parameterName).Value -join "$($CsvDelimiter) ")" } $formatedPolicyAssignmentParameters = $arrayPolicyAssignmentParameters -join "$($CsvDelimiterOpposite) " } $addRowToTableDone = $true addRowToTable ` -level $hierarchyLevel ` -mgName $scopeDisplayName ` -mgId $scopeId ` -mgParentId $mgParentId ` -mgParentName $mgParentName ` -mgASCSecureScore $mgAscSecureScoreResult ` -Policy $policySetDisplayName ` -PolicyDescription $policySetDescription ` -PolicyVariant $policyVariant ` -PolicyType $policySetDefinitionType ` -PolicyIsALZ $policySetDefinitionIsALZ ` -PolicyCategory $policySetCategory ` -PolicyDefinitionIdGuid ($policySetDefinitionId -replace '.*/') ` -PolicyDefinitionId $policySetDefinitionId ` -PolicyDefintionScope $policySetDefintionScope ` -PolicyDefintionScopeMgSub $policySetDefintionScopeMgSub ` -PolicyDefintionScopeId $policySetDefintionScopeId ` -PolicyDefinitionsScopedLimit $LimitPOLICYPolicyDefinitionsScopedManagementGroup ` -PolicyDefinitionsScopedCount $policyDefinitionsScopedCount ` -PolicySetDefinitionsScopedLimit $LimitPOLICYPolicySetDefinitionsScopedManagementGroup ` -PolicySetDefinitionsScopedCount $policySetDefinitionsScopedCount ` -PolicyAssignmentScope $policyAssignmentScope ` -PolicyAssignmentScopeMgSubRg 'Mg' ` -PolicyAssignmentScopeName ($policyAssignmentScope -replace '.*/', '') ` -PolicyAssignmentNotScopes $L0mgmtGroupPolicyAssignment.Properties.NotScopes ` -PolicyAssignmentId $policyAssignmentId ` -PolicyAssignmentName $policyAssignmentName ` -PolicyAssignmentDisplayName $policyAssignmentDisplayName ` -PolicyAssignmentDescription $policyAssignmentDescription ` -PolicyAssignmentEnforcementMode $L0mgmtGroupPolicyAssignment.Properties.EnforcementMode ` -PolicyAssignmentNonComplianceMessages $nonComplianceMessage ` -PolicyAssignmentIdentity $policyAssignmentIdentity ` -PolicyAssignmentLimit $LimitPOLICYPolicyAssignmentsManagementGroup ` -PolicyAssignmentCount $L0mgmtGroupPolicyAssignmentsPolicyCount ` -PolicyAssignmentAtScopeCount $L0mgmtGroupPolicyAssignmentsPolicyAtScopeCount ` -PolicyAssignmentParameters $L0mgmtGroupPolicyAssignment.Properties.Parameters ` -PolicyAssignmentParametersFormated $formatedPolicyAssignmentParameters ` -PolicyAssignmentAssignedBy $assignedBy ` -PolicyAssignmentCreatedBy $createdBy ` -PolicyAssignmentCreatedOn $createdOn ` -PolicyAssignmentUpdatedBy $updatedBy ` -PolicyAssignmentUpdatedOn $updatedOn ` -PolicySetAssignmentLimit $LimitPOLICYPolicySetAssignmentsManagementGroup ` -PolicySetAssignmentCount $L0mgmtGroupPolicyAssignmentsPolicySetCount ` -PolicySetAssignmentAtScopeCount $L0mgmtGroupPolicyAssignmentsPolicySetAtScopeCount ` -PolicyAndPolicySetAssignmentAtScopeCount $L0mgmtGroupPolicyAssignmentsPolicyAndPolicySetAtScopeCount } } } $returnObject = @{} if ($addRowToTableDone) { $returnObject.'addRowToTableDone' = @{} } return $returnObject } $funcDataCollectionPolicyAssignmentsMG = $function:dataCollectionPolicyAssignmentsMG.ToString() function dataCollectionPolicyAssignmentsSub { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $hierarchyLevel, $childMgDisplayName, $childMgId, $childMgParentId, $childMgParentName, $mgAscSecureScoreResult, $subscriptionQuotaId, $subscriptionState, $subscriptionASCSecureScore, $subscriptionTags, $subscriptionTagsCount, $PolicyDefinitionsScopedCount, $PolicySetDefinitionsScopedCount ) $currentTask = "Getting Policy assignments for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Authorization/policyAssignments?api-version=2021-06-01" $method = 'GET' $addRowToTableDone = $false if ($azAPICallConf['htParameters'].DoNotIncludeResourceGroupsOnPolicy -eq $false) { $L1mgmtGroupSubPolicyAssignments = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' $L1mgmtGroupSubPolicyAssignmentsPolicyCount = ($L1mgmtGroupSubPolicyAssignments.where( { $_.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policyDefinitions/' } )).count $L1mgmtGroupSubPolicyAssignmentsPolicySetCount = ($L1mgmtGroupSubPolicyAssignments.where( { $_.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policySetDefinitions/' } )).count $L1mgmtGroupSubPolicyAssignmentsPolicyAtScopeCount = ($L1mgmtGroupSubPolicyAssignments.where( { $_.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policyDefinitions/' -and $_.Id -match "/subscriptions/$($scopeId)" } )).count $L1mgmtGroupSubPolicyAssignmentsPolicySetAtScopeCount = ($L1mgmtGroupSubPolicyAssignments.where( { $_.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policySetDefinitions/' -and $_.Id -match "/subscriptions/$($scopeId)" } )).count $L1mgmtGroupSubPolicyAssignmentsQuery = $L1mgmtGroupSubPolicyAssignments } else { $L1mgmtGroupSubPolicyAssignments = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' $L1mgmtGroupSubPolicyAssignmentsPolicyCount = ($L1mgmtGroupSubPolicyAssignments.where( { $_.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policyDefinitions/' -and $_.Id -notmatch "/subscriptions/$($scopeId)/resourceGroups" } )).count $L1mgmtGroupSubPolicyAssignmentsPolicySetCount = ($L1mgmtGroupSubPolicyAssignments.where( { $_.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policySetDefinitions/' -and $_.Id -notmatch "/subscriptions/$($scopeId)/resourceGroups" } )).count $L1mgmtGroupSubPolicyAssignmentsPolicyAtScopeCount = ($L1mgmtGroupSubPolicyAssignments.where( { $_.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policyDefinitions/' -and $_.Id -match "/subscriptions/$($scopeId)" -and $_.Id -notmatch "/subscriptions/$($scopeId)/resourceGroups" } )).count $L1mgmtGroupSubPolicyAssignmentsPolicySetAtScopeCount = ($L1mgmtGroupSubPolicyAssignments.where( { $_.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policySetDefinitions/' -and $_.Id -match "/subscriptions/$($scopeId)" -and $_.Id -notmatch "/subscriptions/$($scopeId)/resourceGroups" } )).count foreach ($L1mgmtGroupSubPolicyAssignment in $L1mgmtGroupSubPolicyAssignments.where( { $_.Id -match "/subscriptions/$($scopeId)/resourceGroups" } )) { ($script:htCacheAssignmentsPolicyOnResourceGroupsAndResources).(($L1mgmtGroupSubPolicyAssignment.Id).ToLower()) = $L1mgmtGroupSubPolicyAssignment } $L1mgmtGroupSubPolicyAssignmentsQuery = $L1mgmtGroupSubPolicyAssignments.where( { $_.Id -notmatch "/subscriptions/$($scopeId)/resourceGroups" } ) } $L1mgmtGroupSubPolicyAssignmentsPolicyAndPolicySetAtScopeCount = ($L1mgmtGroupSubPolicyAssignmentsPolicyAtScopeCount + $L1mgmtGroupSubPolicyAssignmentsPolicySetAtScopeCount) foreach ($L1mgmtGroupSubPolicyAssignment in $L1mgmtGroupSubPolicyAssignmentsQuery ) { if ($L1mgmtGroupSubPolicyAssignment.Id -like "/subscriptions/$($scopeId)/*") { $htTemp = @{} $htTemp.Assignment = $L1mgmtGroupSubPolicyAssignment $splitAssignment = (($L1mgmtGroupSubPolicyAssignment.Id).ToLower()).Split('/') if (($L1mgmtGroupSubPolicyAssignment.Id).ToLower() -like "/subscriptions/$($scopeId)/resourceGroups*") { $htTemp.AssignmentScopeMgSubRg = 'Rg' $htTemp.AssignmentScopeId = "$($splitAssignment[2])/$($splitAssignment[4])" } else { $htTemp.AssignmentScopeMgSubRg = 'Sub' $htTemp.AssignmentScopeId = [string]$splitAssignment[2] } $script:htCacheAssignmentsPolicy.(($L1mgmtGroupSubPolicyAssignment.Id).ToLower()) = $htTemp } #region namingValidation if (-not [string]::IsNullOrEmpty($L1mgmtGroupSubPolicyAssignment.Properties.DisplayName)) { $namingValidationResult = NamingValidation -toCheck $L1mgmtGroupSubPolicyAssignment.Properties.DisplayName if ($namingValidationResult.Count -gt 0) { if (-not $script:htNamingValidation.PolicyAssignment.($L1mgmtGroupSubPolicyAssignment.Id)) { $script:htNamingValidation.PolicyAssignment.($L1mgmtGroupSubPolicyAssignment.Id) = @{} } $script:htNamingValidation.PolicyAssignment.($L1mgmtGroupSubPolicyAssignment.Id).displayNameInvalidChars = ($namingValidationResult -join '') $script:htNamingValidation.PolicyAssignment.($L1mgmtGroupSubPolicyAssignment.Id).displayName = $L1mgmtGroupSubPolicyAssignment.Properties.DisplayName } } if (-not [string]::IsNullOrEmpty($L1mgmtGroupSubPolicyAssignment.Name)) { $namingValidationResult = NamingValidation -toCheck $L1mgmtGroupSubPolicyAssignment.Name if ($namingValidationResult.Count -gt 0) { if (-not $script:htNamingValidation.PolicyAssignment.($L1mgmtGroupSubPolicyAssignment.Id)) { $script:htNamingValidation.PolicyAssignment.($L1mgmtGroupSubPolicyAssignment.Id) = @{} } $script:htNamingValidation.PolicyAssignment.($L1mgmtGroupSubPolicyAssignment.Id).nameInvalidChars = ($namingValidationResult -join '') $script:htNamingValidation.PolicyAssignment.($L1mgmtGroupSubPolicyAssignment.Id).name = $L1mgmtGroupSubPolicyAssignment.Name } } #endregion namingValidation if ($L1mgmtGroupSubPolicyAssignment.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policyDefinitions/' -OR $L1mgmtGroupSubPolicyAssignment.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policySetDefinitions/') { #policy if ($L1mgmtGroupSubPolicyAssignment.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policyDefinitions/') { $policyVariant = 'Policy' $policyDefinitionId = ($L1mgmtGroupSubPolicyAssignment.properties.policydefinitionid).ToLower() if (($htCacheDefinitionsPolicy).($policyDefinitionId)) { $policyAvailability = '' #handling some strange scenario where the synchronized hashTable responds fragments?! $tryCounter = 0 do { $tryCounter++ $policyAssignmentsPolicyDefinition = ($htCacheDefinitionsPolicy).($policyDefinitionId) if (($policyAssignmentsPolicyDefinition).Type -eq 'Custom' -or ($policyAssignmentsPolicyDefinition).Type -eq 'Builtin') { $policyReturnedFromHt = $true $policyDisplayName = ($policyAssignmentsPolicyDefinition).DisplayName $policyDescription = ($policyAssignmentsPolicyDefinition).Description $policyDefinitionType = ($policyAssignmentsPolicyDefinition).Type $policyDefinitionIsALZ = ($policyAssignmentsPolicyDefinition).ALZ $policyCategory = ($policyAssignmentsPolicyDefinition).Category $policyDefinitionEffectDefault = ($policyAssignmentsPolicyDefinition).effectDefaultValue $policyDefinitionEffectFixed = ($policyAssignmentsPolicyDefinition).effectFixedValue if (($policyAssignmentsPolicyDefinition).Type -ne $policyDefinitionType) { Write-Host "$scopeDisplayName ($scopeId) $policyVariant was processing: $policyDefinitionId" Write-Host "'$(($policyAssignmentsPolicyDefinition).Type)' ne '$policyDefinitionType'" Write-Host "!Please report this error: $($azAPICallConf['htParameters'].GithubRepository)" -ForegroundColor Yellow throw } if ($policyDefinitionType -eq 'Custom') { $policyDefintionScope = ($policyAssignmentsPolicyDefinition).Scope $policyDefintionScopeMgSub = ($policyAssignmentsPolicyDefinition).ScopeMgSub $policyDefintionScopeId = ($policyAssignmentsPolicyDefinition).ScopeId } if ($policyDefinitionType -eq 'Builtin') { $policyDefintionScope = 'n/a' $policyDefintionScopeMgSub = 'n/a' $policyDefintionScopeId = 'n/a' } } else { Write-Host " **INCONSISTENCY! processing policyId:'$policyDefinitionId'; policyAss:'$($L1mgmtGroupSubPolicyAssignment.Id)'; policyAssignmentsPolicyDefinition.Type: '$($policyAssignmentsPolicyDefinition.Type)'" Start-Sleep -Seconds 1 } } until($policyReturnedFromHt -or $tryCounter -gt 5) if (-not $policyReturnedFromHt) { Write-Host "FinalHandler - $scopeDisplayName ($scopeId) $policyVariant was processing: policyId:'$policyDefinitionId'; policyAss:'$($L1mgmtGroupSubPolicyAssignment.Id)'; policyAssignmentsPolicyDefinition.Type: '$($policyAssignmentsPolicyDefinition.Type)'" Write-Host ($policyAssignmentsPolicyDefinition | ConvertTo-Json -Depth 99) Write-Host "!Please report this error: $($azAPICallConf['htParameters'].GithubRepository)" -ForegroundColor Yellow throw } } #policyDefinition not exists! else { $policyDefinitionSplitted = $policyDefinitionId.split('/') if ($policyDefinitionId -like '/providers/microsoft.management/managementgroups/*') { $hlpPolicyDefinitionScope = $policyDefinitionSplitted[4] if ($htSubscriptionsMgPath.($scopeId).path -contains $hlpPolicyDefinitionScope) { Write-Host " ATTENTION: $scopeDisplayName ($scopeId); policyAssignment '$($L1mgmtGroupSubPolicyAssignment.Id)' policyDefinition (Policy) could not be found: '$($policyDefinitionId)' - the scope '$($hlpPolicyDefinitionScope)' HOWEVER IS CONTAINED in the '$scopeId' Management Group chain. The Policy definition scope '$hlpPolicyDefinitionScope' has MGPath: '$($htManagementGroupsMgPath.($hlpPolicyDefinitionScope).pathDelimited)'" } else { if ($htManagementGroupsMgPath.($hlpPolicyDefinitionScope)) { Write-Host " $scopeDisplayName ($scopeId); policyAssignment '$($L1mgmtGroupSubPolicyAssignment.Id)' policyDefinition (Policy) could not be found: '$($policyDefinitionId)' - the scope '$($hlpPolicyDefinitionScope)' IS NOT CONTAINED in the '$scopeId' Management Group chain. The Policy definition scope '$hlpPolicyDefinitionScope' has MGPath: '$($htManagementGroupsMgPath.($hlpPolicyDefinitionScope).pathDelimited)'" } else { Write-Host " $scopeDisplayName ($scopeId); policyAssignment '$($L1mgmtGroupSubPolicyAssignment.Id)' policyDefinition (Policy) could not be found: '$($policyDefinitionId)' - the scope '$($hlpPolicyDefinitionScope)' IS NOT CONTAINED in the '$scopeId' Management Group chain. The Policy definition scope '$hlpPolicyDefinitionScope' could not be found" } } $policyDefintionScope = "/$($policyDefinitionSplitted[1])/$($policyDefinitionSplitted[2])/$($policyDefinitionSplitted[3])/$($hlpPolicyDefinitionScope)" $policyDefintionScopeMgSub = 'Mg' $policyDefintionScopeId = $hlpPolicyDefinitionScope } else { $hlpPolicyDefinitionScope = $policyDefinitionSplitted[2] Write-Host " $scopeDisplayName ($scopeId); policyAssignment '$($L1mgmtGroupSubPolicyAssignment.Id)' policyDefinition (Policy) could not be found: '$($policyDefinitionId)'" $policyDefintionScope = "/$($policyDefinitionSplitted[1])/$($hlpPolicyDefinitionScope)" $policyDefintionScopeMgSub = 'Sub' $policyDefintionScopeId = $hlpPolicyDefinitionScope } $policyAvailability = 'na' $policyDisplayName = 'unknown' $policyDescription = 'unknown' $policyDefinitionType = 'likely Custom' $policyDefinitionIsALZ = 'unknown' $policyCategory = 'unknown' $policyDefinitionEffectDefault = 'unknown' $policyDefinitionEffectFixed = 'unknown' } $PolicyAssignmentScope = $L1mgmtGroupSubPolicyAssignment.Properties.Scope if ($PolicyAssignmentScope -like '/providers/Microsoft.Management/managementGroups/*') { $PolicyAssignmentScopeMgSubRg = 'Mg' } else { $splitPolicyAssignmentScope = ($PolicyAssignmentScope).Split('/') switch (($splitPolicyAssignmentScope).Count - 1) { #sub 2 { $PolicyAssignmentScopeMgSubRg = 'Sub' } 4 { $PolicyAssignmentScopeMgSubRg = 'Rg' } Default { $PolicyAssignmentScopeMgSubRg = 'unknown' } } } $PolicyAssignmentId = ($L1mgmtGroupSubPolicyAssignment.Id).ToLower() $PolicyAssignmentName = $L1mgmtGroupSubPolicyAssignment.Name $PolicyAssignmentDisplayName = $L1mgmtGroupSubPolicyAssignment.Properties.DisplayName if (($L1mgmtGroupSubPolicyAssignment.Properties.Description).length -eq 0) { $PolicyAssignmentDescription = 'no description given' } else { $PolicyAssignmentDescription = $L1mgmtGroupSubPolicyAssignment.Properties.Description } if ($L1mgmtGroupSubPolicyAssignment.identity) { $PolicyAssignmentIdentity = $L1mgmtGroupSubPolicyAssignment.identity.principalId } else { $PolicyAssignmentIdentity = 'n/a' } $assignedBy = 'n/a' $createdBy = '' $createdOn = '' $updatedBy = '' $updatedOn = '' if ($L1mgmtGroupSubPolicyAssignment.properties.metadata) { if ($L1mgmtGroupSubPolicyAssignment.properties.metadata.assignedBy) { $assignedBy = $L1mgmtGroupSubPolicyAssignment.properties.metadata.assignedBy } if ($L1mgmtGroupSubPolicyAssignment.properties.metadata.createdBy) { $createdBy = $L1mgmtGroupSubPolicyAssignment.properties.metadata.createdBy } if ($L1mgmtGroupSubPolicyAssignment.properties.metadata.createdOn) { $createdOn = $L1mgmtGroupSubPolicyAssignment.properties.metadata.createdOn } if ($L1mgmtGroupSubPolicyAssignment.properties.metadata.updatedBy) { $updatedBy = $L1mgmtGroupSubPolicyAssignment.properties.metadata.updatedBy } if ($L1mgmtGroupSubPolicyAssignment.properties.metadata.updatedOn) { $updatedOn = $L1mgmtGroupSubPolicyAssignment.properties.metadata.updatedOn } } if ($L1mgmtGroupSubPolicyAssignment.Properties.nonComplianceMessages.Message) { $nonComplianceMessage = $L1mgmtGroupSubPolicyAssignment.Properties.nonComplianceMessages.Message } else { $nonComplianceMessage = '' } $formatedPolicyAssignmentParameters = '' $hlp = $L1mgmtGroupSubPolicyAssignment.Properties.Parameters if (-not [string]::IsNullOrEmpty($hlp)) { $arrayPolicyAssignmentParameters = @() $arrayPolicyAssignmentParameters = foreach ($parameterName in $hlp.PSObject.Properties.Name | Sort-Object) { "$($parameterName)=$($hlp.($parameterName).Value -join "$($CsvDelimiter) ")" } $formatedPolicyAssignmentParameters = $arrayPolicyAssignmentParameters -join "$($CsvDelimiterOpposite) " } $addRowToTableDone = $true addRowToTable ` -level $hierarchyLevel ` -mgName $childMgDisplayName ` -mgId $childMgId ` -mgParentId $childMgParentId ` -mgParentName $childMgParentName ` -mgASCSecureScore $mgAscSecureScoreResult ` -Subscription $scopeDisplayName ` -SubscriptionId $scopeId ` -SubscriptionQuotaId $subscriptionQuotaId ` -SubscriptionState $subscriptionState ` -SubscriptionASCSecureScore $subscriptionASCSecureScore ` -SubscriptionTags $subscriptionTags ` -SubscriptionTagsCount $subscriptionTagsCount ` -Policy $policyDisplayName ` -PolicyAvailability $policyAvailability ` -PolicyDescription $policyDescription ` -PolicyVariant $policyVariant ` -PolicyType $policyDefinitionType ` -PolicyIsALZ $policyDefinitionIsALZ ` -PolicyCategory $policyCategory ` -PolicyDefinitionIdGuid ($policyDefinitionId -replace '.*/') ` -PolicyDefinitionId $policyDefinitionId ` -PolicyDefintionScope $policyDefintionScope ` -PolicyDefintionScopeMgSub $policyDefintionScopeMgSub ` -PolicyDefintionScopeId $policyDefintionScopeId ` -PolicyDefinitionsScopedLimit $LimitPOLICYPolicyDefinitionsScopedSubscription ` -PolicyDefinitionsScopedCount $PolicyDefinitionsScopedCount ` -PolicySetDefinitionsScopedLimit $LimitPOLICYPolicySetDefinitionsScopedSubscription ` -PolicySetDefinitionsScopedCount $PolicySetDefinitionsScopedCount ` -PolicyDefinitionEffectDefault $policyDefinitionEffectDefault ` -PolicyDefinitionEffectFixed $policyDefinitionEffectFixed ` -PolicyAssignmentScope $PolicyAssignmentScope ` -PolicyAssignmentScopeMgSubRg $PolicyAssignmentScopeMgSubRg ` -PolicyAssignmentScopeName ($PolicyAssignmentScope -replace '.*/', '') ` -PolicyAssignmentNotScopes $L1mgmtGroupSubPolicyAssignment.Properties.NotScopes ` -PolicyAssignmentId $PolicyAssignmentId ` -PolicyAssignmentName $PolicyAssignmentName ` -PolicyAssignmentDisplayName $PolicyAssignmentDisplayName ` -PolicyAssignmentDescription $PolicyAssignmentDescription ` -PolicyAssignmentEnforcementMode $L1mgmtGroupSubPolicyAssignment.Properties.EnforcementMode ` -PolicyAssignmentNonComplianceMessages $nonComplianceMessage ` -PolicyAssignmentIdentity $PolicyAssignmentIdentity ` -PolicyAssignmentLimit $LimitPOLICYPolicyAssignmentsSubscription ` -PolicyAssignmentCount $L1mgmtGroupSubPolicyAssignmentsPolicyCount ` -PolicyAssignmentAtScopeCount $L1mgmtGroupSubPolicyAssignmentsPolicyAtScopeCount ` -PolicyAssignmentParameters $L1mgmtGroupSubPolicyAssignment.Properties.Parameters ` -PolicyAssignmentParametersFormated $formatedPolicyAssignmentParameters ` -PolicyAssignmentAssignedBy $assignedBy ` -PolicyAssignmentCreatedBy $createdBy ` -PolicyAssignmentCreatedOn $createdOn ` -PolicyAssignmentUpdatedBy $updatedBy ` -PolicyAssignmentUpdatedOn $updatedOn ` -PolicySetAssignmentLimit $LimitPOLICYPolicySetAssignmentsSubscription ` -PolicySetAssignmentCount $L1mgmtGroupSubPolicyAssignmentsPolicySetCount ` -PolicySetAssignmentAtScopeCount $L1mgmtGroupSubPolicyAssignmentsPolicySetAtScopeCount ` -PolicyAndPolicySetAssignmentAtScopeCount $L1mgmtGroupSubPolicyAssignmentsPolicyAndPolicySetAtScopeCount } #policySet if ($L1mgmtGroupSubPolicyAssignment.properties.policyDefinitionId -match '/providers/Microsoft.Authorization/policySetDefinitions/') { $policyVariant = 'PolicySet' $policySetDefinitionId = ($L1mgmtGroupSubPolicyAssignment.properties.policydefinitionid).ToLower() $policySetDefinitionSplitted = $policySetDefinitionId.split('/') if (($htCacheDefinitionsPolicySet).($policySetDefinitionId)) { $policyAvailability = '' #handling some strange behavior where the synchronized hashTable responds fragments?! $tryCounter = 0 do { $tryCounter++ $policyAssignmentsPolicySetDefinition = ($htCacheDefinitionsPolicySet).($policySetDefinitionId) if (($policyAssignmentsPolicySetDefinition).Type -eq 'Custom' -or ($policyAssignmentsPolicySetDefinition).Type -eq 'Builtin') { $policySetReturnedFromHt = $true $policySetDisplayName = ($policyAssignmentsPolicySetDefinition).DisplayName $policySetDescription = ($policyAssignmentsPolicySetDefinition).Description $policySetDefinitionType = ($policyAssignmentsPolicySetDefinition).Type $policySetDefinitionIsALZ = ($policyAssignmentsPolicySetDefinition).ALZ $policySetCategory = ($policyAssignmentsPolicySetDefinition).Category if (($policyAssignmentsPolicySetDefinition).Type -ne $policySetDefinitionType) { Write-Host "$scopeDisplayName ($scopeId) $policyVariant was processing: $policySetDefinitionId" Write-Host "'$(($policyAssignmentsPolicySetDefinition).Type)' ne '$policySetDefinitionType'" Write-Host "!Please report this error: $($azAPICallConf['htParameters'].GithubRepository)" -ForegroundColor Yellow throw } if ($policySetDefinitionType -eq 'Custom') { $policySetDefintionScope = ($policyAssignmentsPolicySetDefinition).Scope $policySetDefintionScopeMgSub = ($policyAssignmentsPolicySetDefinition).ScopeMgSub $policySetDefintionScopeId = ($policyAssignmentsPolicySetDefinition).ScopeId } if ($policySetDefinitionType -eq 'Builtin') { $policySetDefintionScope = 'n/a' $policySetDefintionScopeMgSub = 'n/a' $policySetDefintionScopeId = 'n/a' } } else { #Write-Host "TryHandler - $scopeDisplayName ($scopeId) $policyVariant was processing: policySetId:'$policySetDefinitionId'; policyAss:'$($L1mgmtGroupSubPolicyAssignment.Id)'; type:'$(($policyAssignmentsPolicySetDefinition).Type)' - sleeping '$tryCounter' seconds" Start-Sleep -Seconds 1 } } until($policySetReturnedFromHt -or $tryCounter -gt 5) if (-not $policySetReturnedFromHt) { Write-Host "FinalHandler - $scopeDisplayName ($scopeId) $policyVariant was processing: policySetId:'$policySetDefinitionId'; policyAss:'$($L1mgmtGroupSubPolicyAssignment.Id)'" Write-Host "!Please report this error: $($azAPICallConf['htParameters'].GithubRepository)" -ForegroundColor Yellow throw } } #policySetDefinition not exists! else { $policyAvailability = 'na' $policySetDisplayName = 'unknown' $policySetDescription = 'unknown' $policySetDefinitionType = 'likely Custom' $policySetDefinitionIsALZ = 'unknown' $policySetCategory = 'unknown' if ($policySetDefinitionId -like '/providers/microsoft.management/managementgroups/*') { $hlpPolicySetDefinitionScope = $policySetDefinitionSplitted[4] $policySetDefintionScope = "/$($policySetDefinitionSplitted[1])/$($policySetDefinitionSplitted[2])/$($policySetDefinitionSplitted[3])/$($hlpPolicySetDefinitionScope)" $policySetDefintionScopeMgSub = 'Mg' $policySetDefintionScopeId = $hlpPolicySetDefinitionScope } else { $hlpPolicySetDefinitionScope = $policySetDefinitionSplitted[2] $policySetDefintionScope = "/$($policySetDefinitionSplitted[1])/$($hlpPolicySetDefinitionScope)" $policySetDefintionScopeMgSub = 'Sub' $policySetDefintionScopeId = $hlpPolicySetDefinitionScope } Write-Host " $scopeDisplayName ($scopeId); policyAssignment '$($L1mgmtGroupSubPolicyAssignment.Id)' policyDefinition (PolicySet) could not be found: '$($policySetDefinitionId)'" } $PolicyAssignmentScope = $L1mgmtGroupSubPolicyAssignment.Properties.Scope if ($PolicyAssignmentScope -like '/providers/Microsoft.Management/managementGroups/*') { $PolicyAssignmentScopeMgSubRg = 'Mg' } else { $splitPolicyAssignmentScope = ($PolicyAssignmentScope).Split('/') switch (($splitPolicyAssignmentScope).Count - 1) { #sub 2 { $PolicyAssignmentScopeMgSubRg = 'Sub' } 4 { $PolicyAssignmentScopeMgSubRg = 'Rg' } Default { $PolicyAssignmentScopeMgSubRg = 'unknown' } } } $PolicyAssignmentId = ($L1mgmtGroupSubPolicyAssignment.Id).ToLower() $PolicyAssignmentName = $L1mgmtGroupSubPolicyAssignment.Name $PolicyAssignmentDisplayName = $L1mgmtGroupSubPolicyAssignment.Properties.DisplayName if (($L1mgmtGroupSubPolicyAssignment.Properties.Description).length -eq 0) { $PolicyAssignmentDescription = 'no description given' } else { $PolicyAssignmentDescription = $L1mgmtGroupSubPolicyAssignment.Properties.Description } if ($L1mgmtGroupSubPolicyAssignment.identity) { $PolicyAssignmentIdentity = $L1mgmtGroupSubPolicyAssignment.identity.principalId } else { $PolicyAssignmentIdentity = 'n/a' } $assignedBy = 'n/a' $createdBy = '' $createdOn = '' $updatedBy = '' $updatedOn = '' if ($L1mgmtGroupSubPolicyAssignment.properties.metadata) { if ($L1mgmtGroupSubPolicyAssignment.properties.metadata.assignedBy) { $assignedBy = $L1mgmtGroupSubPolicyAssignment.properties.metadata.assignedBy } if ($L1mgmtGroupSubPolicyAssignment.properties.metadata.createdBy) { $createdBy = $L1mgmtGroupSubPolicyAssignment.properties.metadata.createdBy } if ($L1mgmtGroupSubPolicyAssignment.properties.metadata.createdOn) { $createdOn = $L1mgmtGroupSubPolicyAssignment.properties.metadata.createdOn } if ($L1mgmtGroupSubPolicyAssignment.properties.metadata.updatedBy) { $updatedBy = $L1mgmtGroupSubPolicyAssignment.properties.metadata.updatedBy } if ($L1mgmtGroupSubPolicyAssignment.properties.metadata.updatedOn) { $updatedOn = $L1mgmtGroupSubPolicyAssignment.properties.metadata.updatedOn } } if (($L1mgmtGroupSubPolicyAssignment.Properties.nonComplianceMessages.where( { -not $_.policyDefinitionReferenceId })).Message) { $nonComplianceMessage = ($L1mgmtGroupSubPolicyAssignment.Properties.nonComplianceMessages.where( { -not $_.policyDefinitionReferenceId })).Message } else { $nonComplianceMessage = '' } $formatedPolicyAssignmentParameters = '' $hlp = $L1mgmtGroupSubPolicyAssignment.Properties.Parameters if (-not [string]::IsNullOrEmpty($hlp)) { $arrayPolicyAssignmentParameters = @() $arrayPolicyAssignmentParameters = foreach ($parameterName in $hlp.PSObject.Properties.Name | Sort-Object) { "$($parameterName)=$($hlp.($parameterName).Value -join "$($CsvDelimiter) ")" } $formatedPolicyAssignmentParameters = $arrayPolicyAssignmentParameters -join "$($CsvDelimiterOpposite) " } $addRowToTableDone = $true addRowToTable ` -level $hierarchyLevel ` -mgName $childMgDisplayName ` -mgId $childMgId ` -mgParentId $childMgParentId ` -mgParentName $childMgParentName ` -mgASCSecureScore $mgAscSecureScoreResult ` -Subscription $scopeDisplayName ` -SubscriptionId $scopeId ` -SubscriptionQuotaId $subscriptionQuotaId ` -SubscriptionState $subscriptionState ` -SubscriptionASCSecureScore $subscriptionASCSecureScore ` -SubscriptionTags $subscriptionTags ` -SubscriptionTagsCount $subscriptionTagsCount ` -Policy $policySetDisplayName ` -PolicyAvailability $policyAvailability ` -PolicyDescription $policySetDescription ` -PolicyVariant $policyVariant ` -PolicyType $policySetDefinitionType ` -PolicyIsALZ $policySetDefinitionIsALZ ` -PolicyCategory $policySetCategory ` -PolicyDefinitionIdGuid (($policySetDefinitionId) -replace '.*/') ` -PolicyDefinitionId $policySetDefinitionId ` -PolicyDefintionScope $policySetDefintionScope ` -PolicyDefintionScopeMgSub $policySetDefintionScopeMgSub ` -PolicyDefintionScopeId $policySetDefintionScopeId ` -PolicyDefinitionsScopedLimit $LimitPOLICYPolicyDefinitionsScopedSubscription ` -PolicyDefinitionsScopedCount $PolicyDefinitionsScopedCount ` -PolicySetDefinitionsScopedLimit $LimitPOLICYPolicySetDefinitionsScopedSubscription ` -PolicySetDefinitionsScopedCount $PolicySetDefinitionsScopedCount ` -PolicyAssignmentScope $PolicyAssignmentScope ` -PolicyAssignmentScopeMgSubRg $PolicyAssignmentScopeMgSubRg ` -PolicyAssignmentScopeName ($PolicyAssignmentScope -replace '.*/', '') ` -PolicyAssignmentNotScopes $L1mgmtGroupSubPolicyAssignment.Properties.NotScopes ` -PolicyAssignmentId $PolicyAssignmentId ` -PolicyAssignmentName $PolicyAssignmentName ` -PolicyAssignmentDisplayName $PolicyAssignmentDisplayName ` -PolicyAssignmentDescription $PolicyAssignmentDescription ` -PolicyAssignmentEnforcementMode $L1mgmtGroupSubPolicyAssignment.Properties.EnforcementMode ` -PolicyAssignmentNonComplianceMessages $nonComplianceMessage ` -PolicyAssignmentIdentity $PolicyAssignmentIdentity ` -PolicyAssignmentLimit $LimitPOLICYPolicyAssignmentsSubscription ` -PolicyAssignmentCount $L1mgmtGroupSubPolicyAssignmentsPolicyCount ` -PolicyAssignmentAtScopeCount $L1mgmtGroupSubPolicyAssignmentsPolicyAtScopeCount ` -PolicyAssignmentParameters $L1mgmtGroupSubPolicyAssignment.Properties.Parameters ` -PolicyAssignmentParametersFormated $formatedPolicyAssignmentParameters ` -PolicyAssignmentAssignedBy $assignedBy ` -PolicyAssignmentCreatedBy $createdBy ` -PolicyAssignmentCreatedOn $createdOn ` -PolicyAssignmentUpdatedBy $updatedBy ` -PolicyAssignmentUpdatedOn $updatedOn ` -PolicySetAssignmentLimit $LimitPOLICYPolicySetAssignmentsSubscription ` -PolicySetAssignmentCount $L1mgmtGroupSubPolicyAssignmentsPolicySetCount ` -PolicySetAssignmentAtScopeCount $L1mgmtGroupSubPolicyAssignmentsPolicySetAtScopeCount ` -PolicyAndPolicySetAssignmentAtScopeCount $L1mgmtGroupSubPolicyAssignmentsPolicyAndPolicySetAtScopeCount } } } $returnObject = @{} if ($addRowToTableDone) { $returnObject.'addRowToTableDone' = @{} } return $returnObject } $funcDataCollectionPolicyAssignmentsSub = $function:dataCollectionPolicyAssignmentsSub.ToString() function dataCollectionRoleDefinitions { [CmdletBinding()]Param( [string]$TargetMgOrSub, [string]$scopeId, [string]$scopeDisplayName, $subscriptionQuotaId ) $roledefinitionsAPIVersion = $azAPICallConf['htParameters'].APIMappingCloudEnvironment.roledefinitions.($azAPICallConf['htParameters'].azureCloudEnvironment) if ($TargetMgOrSub -eq 'Sub') { $currentTask = "Getting Custom Role definitions for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Authorization/roleDefinitions?api-version=$($roledefinitionsAPIVersion)&`$filter=type eq 'CustomRole'" } if ($TargetMgOrSub -eq 'MG') { $currentTask = "Getting Custom Role definitions for Management Group: '$($scopeDisplayName)' ('$scopeId')" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/providers/Microsoft.Management/managementGroups/$($scopeId)/providers/Microsoft.Authorization/roleDefinitions?api-version=$($roledefinitionsAPIVersion)&`$filter=type eq 'CustomRole'" } $method = 'GET' $scopeCustomRoleDefinitions = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' foreach ($scopeCustomRoleDefinition in $scopeCustomRoleDefinitions) { if (-not $($htCacheDefinitionsRole).($scopeCustomRoleDefinition.name)) { if ( ( $scopeCustomRoleDefinition.properties.permissions.Actions -contains 'Microsoft.Authorization/roleassignments/write' -or $scopeCustomRoleDefinition.properties.permissions.Actions -contains 'Microsoft.Authorization/roleassignments/*' -or $scopeCustomRoleDefinition.properties.permissions.Actions -contains 'Microsoft.Authorization/*/write' -or $scopeCustomRoleDefinition.properties.permissions.Actions -contains 'Microsoft.Authorization/*' -or $scopeCustomRoleDefinition.properties.permissions.Actions -contains '*/write' -or $scopeCustomRoleDefinition.properties.permissions.Actions -contains '*' ) -and ( $scopeCustomRoleDefinition.properties.permissions.NotActions -notcontains 'Microsoft.Authorization/roleassignments/write' -and $scopeCustomRoleDefinition.properties.permissions.NotActions -notcontains 'Microsoft.Authorization/roleassignments/*' -and $scopeCustomRoleDefinition.properties.permissions.NotActions -notcontains 'Microsoft.Authorization/*/write' -and $scopeCustomRoleDefinition.properties.permissions.NotActions -notcontains 'Microsoft.Authorization/*' -and $scopeCustomRoleDefinition.properties.permissions.NotActions -notcontains '*/write' -and $scopeCustomRoleDefinition.properties.permissions.NotActions -notcontains '*' ) ) { $roleCapable4RoleAssignmentsWrite = $true } else { $roleCapable4RoleAssignmentsWrite = $false } $htTemp = @{ Id = $($scopeCustomRoleDefinition.name) Name = $($scopeCustomRoleDefinition.properties.roleName) IsCustom = $true AssignableScopes = $($scopeCustomRoleDefinition.properties.AssignableScopes) Actions = $($scopeCustomRoleDefinition.properties.permissions.Actions) NotActions = $($scopeCustomRoleDefinition.properties.permissions.NotActions) DataActions = $($scopeCustomRoleDefinition.properties.permissions.DataActions) NotDataActions = $($scopeCustomRoleDefinition.properties.permissions.NotDataActions) Json = $scopeCustomRoleDefinition RoleCanDoRoleAssignments = $roleCapable4RoleAssignmentsWrite } ($script:htCacheDefinitionsRole).($scopeCustomRoleDefinition.name) = $htTemp #namingValidation if (-not [string]::IsNullOrEmpty($scopeCustomRoleDefinition.properties.roleName)) { $namingValidationResult = NamingValidation -toCheck $scopeCustomRoleDefinition.properties.roleName if ($namingValidationResult.Count -gt 0) { $script:htNamingValidation.Role.($scopeCustomRoleDefinition.name) = @{ roleNameInvalidChars = ($namingValidationResult -join '') roleName = $scopeCustomRoleDefinition.properties.roleName } } } } } } $funcDataCollectionRoleDefinitions = $function:dataCollectionRoleDefinitions.ToString() function dataCollectionRoleAssignmentsMG { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $hierarchyLevel, $mgParentId, $mgParentName, $mgAscSecureScoreResult ) $addRowToTableDone = $false #PIM MGRoleAssignmentScheduleInstances if ($htDoARMRoleAssignmentScheduleInstances.Do -eq $true) { $currentTask = "Getting ARM RoleAssignment ScheduleInstances for Management Group: '$($scopeDisplayName)' ('$($scopeId)')" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/providers/Microsoft.Management/managementGroups/$($scopeId)/providers/Microsoft.Authorization/roleAssignmentScheduleInstances?api-version=2020-10-01" $method = 'GET' $roleAssignmentScheduleInstancesFromAPI = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' if ($roleAssignmentScheduleInstancesFromAPI -eq 'RoleAssignmentScheduleInstancesError' -or $roleAssignmentScheduleInstancesFromAPI -eq 'AadPremiumLicenseRequired') { if ($roleAssignmentScheduleInstancesFromAPI -eq 'AadPremiumLicenseRequired') { Write-Host " -> Setting 'htDoARMRoleAssignmentScheduleInstances.Do' to false (AadPremiumLicenseRequired)" $script:htDoARMRoleAssignmentScheduleInstances.Do = $false } } else { $roleAssignmentScheduleInstances = ($roleAssignmentScheduleInstancesFromAPI.where( { ($_.properties.roleAssignmentScheduleId -replace '.*/') -ne ($_.properties.originRoleAssignmentId -replace '.*/') })) $roleAssignmentScheduleInstancesCount = $roleAssignmentScheduleInstances.Count if ($roleAssignmentScheduleInstancesCount -gt 0) { foreach ($roleAssignmentScheduleInstance in $roleAssignmentScheduleInstances) { $script:htRoleAssignmentsPIM.($roleAssignmentScheduleInstance.properties.originRoleAssignmentId.tolower()) = $roleAssignmentScheduleInstance.properties } } } } #RoleAssignment API MG $currentTask = "Getting Role assignments API for Management Group: '$($scopeDisplayName)' ('$($scopeId)')" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/providers/Microsoft.Management/managementGroups/$($scopeId)/providers/Microsoft.Authorization/roleAssignments?api-version=2015-07-01" $method = 'GET' $roleAssignmentsFromAPI = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' if ($roleAssignmentsFromAPI.Count -gt 0) { $principalsToResolve = @() $principalsToResolve = foreach ($ra in $roleAssignmentsFromAPI.properties | Sort-Object -Property principalId -Unique) { if (-not $htPrincipals.($ra.principalId)) { $ra.principalId } } if ($principalsToResolve.Count -gt 0) { ResolveObjectIds -objectIds $principalsToResolve } } $L0mgmtGroupRoleAssignments = $roleAssignmentsFromAPI $L0mgmtGroupRoleAssignmentsLimitUtilization = (($L0mgmtGroupRoleAssignments.properties.where( { $_.scope -eq "/providers/Microsoft.Management/managementGroups/$($scopeId)" } ))).count if (-not $htMgAtScopeRoleAssignments.($scopeId)) { $script:htMgAtScopeRoleAssignments.($scopeId) = @{ AssignmentsCount = $L0mgmtGroupRoleAssignmentsLimitUtilization } } if ($azAPICallConf['htParameters'].LargeTenant -eq $true -or $azAPICallConf['htParameters'].RBACAtScopeOnly -eq $true) { $L0mgmtGroupRoleAssignments = $L0mgmtGroupRoleAssignments.where( { $_.properties.scope -eq "/providers/Microsoft.Management/managementGroups/$($scopeId)" } ) } else { #tenantLevelRoleAssignments if (-not $htMgAtScopeRoleAssignments.'tenantLevelRoleAssignments') { $tenantLevelRoleAssignmentsCount = (($L0mgmtGroupRoleAssignments.where( { $_.id -like '/providers/Microsoft.Authorization/roleAssignments/*' } ))).count $script:htMgAtScopeRoleAssignments.'tenantLevelRoleAssignments' = @{ AssignmentsCount = $tenantLevelRoleAssignmentsCount } } } foreach ($L0mgmtGroupRoleAssignment in $L0mgmtGroupRoleAssignments) { $roleAssignmentId = ($L0mgmtGroupRoleAssignment.id).ToLower() if ($htRoleAssignmentsPIM.($roleAssignmentId)) { $hlperPim = $htRoleAssignmentsPIM.($roleAssignmentId) $pim = 'true' $pimAssignmentType = $hlperPim.assignmentType $pimSlotStart = $($hlperPim.startDateTime) if ($hlperPim.endDateTime) { $pimSlotEnd = $($hlperPim.endDateTime) } else { $pimSlotEnd = 'eternity' } } else { $pim = 'false' $pimAssignmentType = '' $pimSlotStart = '' $pimSlotEnd = '' } $roleAssignmentIdGuid = $roleAssignmentId -replace '.*/' if (-not $htRoleAssignmentsFromAPIInheritancePrevention.($roleAssignmentIdGuid)) { $script:htRoleAssignmentsFromAPIInheritancePrevention.($roleAssignmentIdGuid) = @{ assignment = $L0mgmtGroupRoleAssignment } } $roleDefinitionId = $L0mgmtGroupRoleAssignment.properties.roleDefinitionId $roleDefinitionIdGuid = $roleDefinitionId -replace '.*/' if (-not ($htCacheDefinitionsRole).($roleDefinitionIdGuid)) { $roleAssignmentsRoleDefinition = '' $roleDefinitionName = "'This roleDefinition likely was deleted although a roleAssignment existed'" } else { $roleAssignmentsRoleDefinition = ($htCacheDefinitionsRole).($roleDefinitionIdGuid) $roleDefinitionName = $roleAssignmentsRoleDefinition.Name } $doIt = $false if ($L0mgmtGroupRoleAssignment.properties.scope -eq "/providers/Microsoft.Management/managementGroups/$($scopeId)" -and $L0mgmtGroupRoleAssignment.properties.scope -ne "/providers/Microsoft.Management/managementGroups/$($ManagementGroupId)") { $doIt = $true } if ($scopeId -eq $ManagementGroupId) { $doIt = $true } if ($doIt) { #assignment $splitAssignment = ($roleAssignmentId).Split('/') $arrayRoleAssignment = [System.Collections.ArrayList]@() $null = $arrayRoleAssignment.Add([PSCustomObject]@{ RoleAssignmentId = $roleAssignmentId Scope = $L0mgmtGroupRoleAssignment.properties.scope DisplayName = $htPrincipals.($L0mgmtGroupRoleAssignment.properties.principalId).displayName SignInName = $htPrincipals.($L0mgmtGroupRoleAssignment.properties.principalId).signInName RoleDefinitionName = $roleDefinitionName RoleDefinitionId = $L0mgmtGroupRoleAssignment.properties.roleDefinitionId -replace '.*/' ObjectId = $L0mgmtGroupRoleAssignment.properties.principalId ObjectType = $htPrincipals.($L0mgmtGroupRoleAssignment.properties.principalId).type PIM = $pim }) $htTemp = @{} $htTemp.Assignment = $arrayRoleAssignment if ($roleAssignmentId -like '/providers/Microsoft.Authorization/roleAssignments/*') { $htTemp.AssignmentScopeTenMgSubRgRes = 'Tenant' $htTemp.AssignmentScopeId = 'Tenant' } else { $htTemp.AssignmentScopeTenMgSubRgRes = 'Mg' $htTemp.AssignmentScopeId = [string]$splitAssignment[4] } ($script:htCacheAssignmentsRole).($roleAssignmentId) = $htTemp } if (($htPrincipals.($L0mgmtGroupRoleAssignment.properties.principalId).displayName).length -eq 0) { $roleAssignmentIdentityDisplayname = 'n/a' } else { if ($htPrincipals.($L0mgmtGroupRoleAssignment.properties.principalId).type -eq 'User') { if ($azAPICallConf['htParameters'].DoNotShowRoleAssignmentsUserData -eq $false) { $roleAssignmentIdentityDisplayname = $htPrincipals.($L0mgmtGroupRoleAssignment.properties.principalId).displayName } else { $roleAssignmentIdentityDisplayname = 'scrubbed' } } else { $roleAssignmentIdentityDisplayname = $htPrincipals.($L0mgmtGroupRoleAssignment.properties.principalId).displayName } } if (-not $htPrincipals.($L0mgmtGroupRoleAssignment.properties.principalId).signInName) { $roleAssignmentIdentitySignInName = 'n/a' } else { if ($htPrincipals.($L0mgmtGroupRoleAssignment.properties.principalId).type -eq 'User') { if ($azAPICallConf['htParameters'].DoNotShowRoleAssignmentsUserData -eq $false) { $roleAssignmentIdentitySignInName = $htPrincipals.($L0mgmtGroupRoleAssignment.properties.principalId).signInName } else { $roleAssignmentIdentitySignInName = 'scrubbed' } } else { $roleAssignmentIdentitySignInName = $htPrincipals.($L0mgmtGroupRoleAssignment.properties.principalId).signInName } } $roleAssignmentIdentityObjectId = $L0mgmtGroupRoleAssignment.properties.principalId $roleAssignmentIdentityObjectType = $htPrincipals.($L0mgmtGroupRoleAssignment.properties.principalId).type $roleAssignmentScope = $L0mgmtGroupRoleAssignment.properties.scope $roleAssignmentScopeName = $roleAssignmentScope -replace '.*/' $roleAssignmentScopeType = 'MG' $roleSecurityCustomRoleOwner = 0 if ($roleAssignmentsRoleDefinition.Actions -eq '*' -and (($roleAssignmentsRoleDefinition.NotActions)).length -eq 0 -and $roleAssignmentsRoleDefinition.IsCustom -eq $True) { $roleSecurityCustomRoleOwner = 1 } $roleSecurityOwnerAssignmentSP = 0 if (($roleAssignmentsRoleDefinition.Id -eq '8e3af657-a8ff-443c-a75c-2fe8c4bcb635' -and $roleAssignmentIdentityObjectType -eq 'ServicePrincipal') -or ($roleAssignmentsRoleDefinition.Actions -eq '*' -and (($roleAssignmentsRoleDefinition.NotActions)).length -eq 0 -and $roleAssignmentsRoleDefinition.IsCustom -eq $True -and $roleAssignmentIdentityObjectType -eq 'ServicePrincipal')) { $roleSecurityOwnerAssignmentSP = 1 } $createdBy = '' $createdOn = '' $createdOnUnformatted = $null $updatedBy = '' $updatedOn = '' if ($L0mgmtGroupRoleAssignment.properties.createdBy) { $createdBy = $L0mgmtGroupRoleAssignment.properties.createdBy } if ($L0mgmtGroupRoleAssignment.properties.createdOn) { $createdOn = $L0mgmtGroupRoleAssignment.properties.createdOn } if ($L0mgmtGroupRoleAssignment.properties.updatedBy) { $updatedBy = $L0mgmtGroupRoleAssignment.properties.updatedBy } if ($L0mgmtGroupRoleAssignment.properties.updatedOn) { $updatedOn = $L0mgmtGroupRoleAssignment.properties.updatedOn } $createdOnUnformatted = $L0mgmtGroupRoleAssignment.properties.createdOn $addRowToTableDone = $true addRowToTable ` -level $hierarchyLevel ` -mgName $scopeDisplayName ` -mgId $scopeId ` -mgParentId $mgParentId ` -mgParentName $mgParentName ` -mgASCSecureScore $mgAscSecureScoreResult ` -RoleDefinitionId $roleDefinitionIdGuid ` -RoleDefinitionName $roleDefinitionName ` -RoleIsCustom $roleAssignmentsRoleDefinition.IsCustom ` -RoleAssignableScopes ($roleAssignmentsRoleDefinition.AssignableScopes -join "$CsvDelimiterOpposite ") ` -RoleActions ($roleAssignmentsRoleDefinition.Actions -join "$CsvDelimiterOpposite ") ` -RoleNotActions ($roleAssignmentsRoleDefinition.NotActions -join "$CsvDelimiterOpposite ") ` -RoleDataActions ($roleAssignmentsRoleDefinition.DataActions -join "$CsvDelimiterOpposite ") ` -RoleNotDataActions ($roleAssignmentsRoleDefinition.NotDataActions -join "$CsvDelimiterOpposite ") ` -RoleCanDoRoleAssignments $roleAssignmentsRoleDefinition.RoleCanDoRoleAssignments ` -RoleAssignmentIdentityDisplayname $roleAssignmentIdentityDisplayname ` -RoleAssignmentIdentitySignInName $roleAssignmentIdentitySignInName ` -RoleAssignmentIdentityObjectId $roleAssignmentIdentityObjectId ` -RoleAssignmentIdentityObjectType $roleAssignmentIdentityObjectType ` -RoleAssignmentId $roleAssignmentId ` -RoleAssignmentScope $roleAssignmentScope ` -RoleAssignmentScopeName $roleAssignmentScopeName ` -RoleAssignmentScopeType $roleAssignmentScopeType ` -RoleAssignmentCreatedBy $createdBy ` -RoleAssignmentCreatedOn $createdOn ` -RoleAssignmentCreatedOnUnformatted $createdOnUnformatted ` -RoleAssignmentUpdatedBy $updatedBy ` -RoleAssignmentUpdatedOn $updatedOn ` -RoleAssignmentsLimit $LimitRBACRoleAssignmentsManagementGroup ` -RoleAssignmentsCount $L0mgmtGroupRoleAssignmentsLimitUtilization ` -RoleSecurityCustomRoleOwner $roleSecurityCustomRoleOwner ` -RoleSecurityOwnerAssignmentSP $roleSecurityOwnerAssignmentSP ` -RoleAssignmentPIM $pim ` -RoleAssignmentPIMAssignmentType $pimAssignmentType ` -RoleAssignmentPIMSlotStart $pimSlotStart ` -RoleAssignmentPIMSlotEnd $pimSlotEnd } $returnObject = @{} if ($addRowToTableDone) { $returnObject.'addRowToTableDone' = @{} } return $returnObject } $funcDataCollectionRoleAssignmentsMG = $function:dataCollectionRoleAssignmentsMG.ToString() function dataCollectionRoleAssignmentsSub { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, $hierarchyLevel, $childMgDisplayName, $childMgId, $childMgParentId, $childMgParentName, $mgAscSecureScoreResult, $subscriptionQuotaId, $subscriptionState, $subscriptionASCSecureScore, $subscriptionTags, $subscriptionTagsCount ) $addRowToTableDone = $false #Usage $currentTask = "Getting Role assignments usage metrics for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Authorization/roleAssignmentsUsageMetrics?api-version=2019-08-01-preview" $method = 'GET' $roleAssignmentsUsage = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -listenOn 'Content' -caller 'CustomDataCollection' $script:htSubscriptionsRoleAssignmentLimit.($scopeId) = $roleAssignmentsUsage.roleAssignmentsLimit #PIM SubscriptionRoleAssignmentScheduleInstances if ($htDoARMRoleAssignmentScheduleInstances.Do -eq $true) { $currentTask = "Getting ARM RoleAssignment ScheduleInstances for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Authorization/roleAssignmentScheduleInstances?api-version=2020-10-01" $method = 'GET' $roleAssignmentScheduleInstancesFromAPI = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' if ($roleAssignmentScheduleInstancesFromAPI -eq 'RoleAssignmentScheduleInstancesError' -or $roleAssignmentScheduleInstancesFromAPI -eq 'AadPremiumLicenseRequired') { # this should not be required at sub level as the error would already have occured at mg level # if ($roleAssignmentScheduleInstancesFromAPI -eq 'AadPremiumLicenseRequired') { # Write-Host " Setting 'htDoARMRoleAssignmentScheduleInstances.Do' to false (AadPremiumLicenseRequired)" # $script:htDoARMRoleAssignmentScheduleInstances.Do = $false # } } else { $roleAssignmentScheduleInstances = ($roleAssignmentScheduleInstancesFromAPI.where( { ($_.properties.roleAssignmentScheduleId -replace '.*/') -ne ($_.properties.originRoleAssignmentId -replace '.*/') })) $roleAssignmentScheduleInstancesCount = $roleAssignmentScheduleInstances.Count if ($roleAssignmentScheduleInstancesCount -gt 0) { foreach ($roleAssignmentScheduleInstance in $roleAssignmentScheduleInstances) { $script:htRoleAssignmentsPIM.($roleAssignmentScheduleInstance.properties.originRoleAssignmentId.tolower()) = $roleAssignmentScheduleInstance.properties } } } } #RoleAssignment API Sub $currentTask = "Getting Role assignments API for Subscription: '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" $uri = "$($azAPICallConf['azAPIEndpointUrls'].ARM)/subscriptions/$($scopeId)/providers/Microsoft.Authorization/roleAssignments?api-version=2015-07-01" $method = 'GET' $roleAssignmentsFromAPI = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask $currentTask -caller 'CustomDataCollection' $baseRoleAssignments = [System.Collections.ArrayList]@() if ($roleAssignmentsFromAPI.Count -gt 0) { foreach ($roleAssignmentFromAPI in $roleAssignmentsFromAPI) { if ($roleAssignmentFromAPI.id -match "/subscriptions/$($scopeId)/") { $roleAssignmentIdGuid = $roleAssignmentFromAPI.id -replace '.*/' if (-not $htRoleAssignmentsFromAPIInheritancePrevention.($roleAssignmentIdGuid)) { $null = $baseRoleAssignments.Add($roleAssignmentFromAPI) } else { $null = $baseRoleAssignments.Add($htRoleAssignmentsFromAPIInheritancePrevention.($roleAssignmentIdGuid).assignment) } } else { $null = $baseRoleAssignments.Add($roleAssignmentFromAPI) } } } if ($azAPICallConf['htParameters'].DoNotIncludeResourceGroupsAndResourcesOnRBAC -eq $true) { $relevantRAs = $baseRoleAssignments.where( { $_.id -notmatch "/subscriptions/$($scopeId)/resourcegroups/" } ) } else { $relevantRAs = $baseRoleAssignments } if ($relevantRAs.Count -gt 0) { $principalsToResolve = @() $principalsToResolve = foreach ($ra in $relevantRAs.properties | Sort-Object -Property principalId -Unique) { if (-not $htPrincipals.($ra.principalId)) { $ra.principalId } } if ($principalsToResolve.Count -gt 0) { ResolveObjectIds -objectIds $principalsToResolve } } $L1mgmtGroupSubRoleAssignments = $baseRoleAssignments if ($azAPICallConf['htParameters'].DoNotIncludeResourceGroupsAndResourcesOnRBAC -eq $true) { foreach ($L1mgmtGroupSubRoleAssignmentOnRg in $L1mgmtGroupSubRoleAssignments.where( { $_.id -match "/subscriptions/$($scopeId)/resourcegroups/" } )) { if (-not ($htCacheAssignmentsRBACOnResourceGroupsAndResources).($L1mgmtGroupSubRoleAssignmentOnRg.id)) { $roleDefinitionId = $L1mgmtGroupSubRoleAssignmentOnRg.properties.roleDefinitionId $roleDefinitionIdGuid = $roleDefinitionId -replace '.*/' if (-not ($htCacheDefinitionsRole).($roleDefinitionIdGuid)) { $roleAssignmentsRoleDefinition = '' $roleDefinitionName = "'This roleDefinition likely was deleted although a roleAssignment existed'" } else { $roleAssignmentsRoleDefinition = ($htCacheDefinitionsRole).($roleDefinitionIdGuid) $roleDefinitionName = $roleAssignmentsRoleDefinition.Name } #assignment $arrayRoleAssignment = [System.Collections.ArrayList]@() $null = $arrayRoleAssignment.Add([PSCustomObject]@{ RoleAssignmentId = $L1mgmtGroupSubRoleAssignmentOnRg.id Scope = $L1mgmtGroupSubRoleAssignmentOnRg.properties.scope RoleDefinitionName = $roleDefinitionName RoleDefinitionId = $L1mgmtGroupSubRoleAssignmentOnRg.properties.roleDefinitionId -replace '.*/' ObjectId = $L1mgmtGroupSubRoleAssignmentOnRg.properties.principalId }) ($script:htCacheAssignmentsRBACOnResourceGroupsAndResources).($L1mgmtGroupSubRoleAssignmentOnRg.id) = $arrayRoleAssignment } } } if ($azAPICallConf['htParameters'].LargeTenant -eq $true -or $azAPICallConf['htParameters'].RBACAtScopeOnly -eq $true) { if ($azAPICallConf['htParameters'].DoNotIncludeResourceGroupsAndResourcesOnRBAC -eq $false) { $assignmentsScope = $L1mgmtGroupSubRoleAssignments } else { $assignmentsScope = $L1mgmtGroupSubRoleAssignments.where( { $_.properties.Scope -eq "/subscriptions/$($scopeId)" } ) } } else { if ($azAPICallConf['htParameters'].DoNotIncludeResourceGroupsAndResourcesOnRBAC -eq $false) { $assignmentsScope = $L1mgmtGroupSubRoleAssignments } else { $assignmentsScope = $L1mgmtGroupSubRoleAssignments.where( { $_.id -notmatch "/subscriptions/$($scopeId)/resourcegroups/" } ) } } foreach ($L1mgmtGroupSubRoleAssignment in $assignmentsScope) { $roleAssignmentId = ($L1mgmtGroupSubRoleAssignment.id).ToLower() $roleDefinitionId = $L1mgmtGroupSubRoleAssignment.properties.roleDefinitionId $roleDefinitionIdGuid = $roleDefinitionId -replace '.*/' if (-not ($htCacheDefinitionsRole).($roleDefinitionIdGuid)) { $roleAssignmentsRoleDefinition = '' $roleDefinitionName = "'This roleDefinition likely was deleted although a roleAssignment existed'" } else { $roleAssignmentsRoleDefinition = ($htCacheDefinitionsRole).($roleDefinitionIdGuid) $roleDefinitionName = $roleAssignmentsRoleDefinition.Name } $roleAssignmentIdentityObjectId = $L1mgmtGroupSubRoleAssignment.properties.principalId $roleAssignmentIdentityObjectType = $htPrincipals.($L1mgmtGroupSubRoleAssignment.properties.principalId).type $roleAssignmentScope = $L1mgmtGroupSubRoleAssignment.properties.scope $roleAssignmentScopeName = $roleAssignmentScope -replace '.*/' if ($roleAssignmentScope -like '/subscriptions/*' -and $roleAssignmentScope -notlike '/subscriptions/*/resourcegroups/*') { $roleAssignmentScopeType = 'Sub' $roleAssignmentScopeRG = '' $roleAssignmentScopeRes = '' } if ($roleAssignmentScope -like '/subscriptions/*/resourcegroups/*' -and $roleAssignmentScope -notlike '/subscriptions/*/resourcegroups/*/providers*') { $roleAssignmentScopeType = 'RG' $roleAssignmentScopeSplit = $roleAssignmentScope.Split('/') $roleAssignmentScopeRG = $roleAssignmentScopeSplit[4] $roleAssignmentScopeRes = '' } if ($roleAssignmentScope -like '/subscriptions/*/resourcegroups/*/providers*') { $roleAssignmentScopeType = 'Res' $roleAssignmentScopeSplit = $roleAssignmentScope.Split('/') $roleAssignmentScopeRG = $roleAssignmentScopeSplit[4] $roleAssignmentScopeRes = $roleAssignmentScopeSplit[8] } if ($htRoleAssignmentsPIM.($roleAssignmentId)) { $hlperPim = $htRoleAssignmentsPIM.($roleAssignmentId) $pim = 'true' $pimAssignmentType = $hlperPim.assignmentType $pimSlotStart = $($hlperPim.startDateTime) if ($hlperPim.endDateTime) { $pimSlotEnd = $($hlperPim.endDateTime) } else { $pimSlotEnd = 'eternity' } } else { $pim = 'false' $pimAssignmentType = '' $pimSlotStart = '' $pimSlotEnd = '' } if ($roleAssignmentId -like "/subscriptions/$($scopeId)/*") { #assignment $splitAssignment = ($roleAssignmentId).Split('/') $arrayRoleAssignment = [System.Collections.ArrayList]@() $null = $arrayRoleAssignment.Add([PSCustomObject]@{ RoleAssignmentId = $roleAssignmentId Scope = $L1mgmtGroupSubRoleAssignment.properties.scope DisplayName = $htPrincipals.($L1mgmtGroupSubRoleAssignment.properties.principalId).displayName SignInName = $htPrincipals.($L1mgmtGroupSubRoleAssignment.properties.principalId).signInName RoleDefinitionName = $roleDefinitionName RoleDefinitionId = $L1mgmtGroupSubRoleAssignment.properties.roleDefinitionId -replace '.*/' ObjectId = $L1mgmtGroupSubRoleAssignment.properties.principalId ObjectType = $htPrincipals.($L1mgmtGroupSubRoleAssignment.properties.principalId).type PIM = $pim }) $htTemp = @{} $htTemp.Assignment = $arrayRoleAssignment $htTemp.AssignmentScopeTenMgSubRgRes = $roleAssignmentScopeType if ($roleAssignmentScopeType -eq 'Sub') { $htTemp.AssignmentScopeId = [string]$splitAssignment[2] } if ($roleAssignmentScopeType -eq 'RG') { $htTemp.AssignmentScopeId = "$($splitAssignment[2])/$($splitAssignment[4])" } if ($roleAssignmentScopeType -eq 'Res') { $htTemp.AssignmentScopeId = "$($splitAssignment[2])/$($splitAssignment[4])/$($splitAssignment[8])" $htTemp.ResourceType = "$($splitAssignment[6])-$($splitAssignment[7])" } ($script:htCacheAssignmentsRole).($roleAssignmentId) = $htTemp } if (($htPrincipals.($L1mgmtGroupSubRoleAssignment.properties.principalId).displayName).length -eq 0) { $roleAssignmentIdentityDisplayname = 'n/a' } else { if ($htPrincipals.($L1mgmtGroupSubRoleAssignment.properties.principalId).type -eq 'User') { if ($azAPICallConf['htParameters'].DoNotShowRoleAssignmentsUserData -eq $false) { $roleAssignmentIdentityDisplayname = $htPrincipals.($L1mgmtGroupSubRoleAssignment.properties.principalId).displayName } else { $roleAssignmentIdentityDisplayname = 'scrubbed' } } else { $roleAssignmentIdentityDisplayname = $htPrincipals.($L1mgmtGroupSubRoleAssignment.properties.principalId).displayName } } if (-not $htPrincipals.($L1mgmtGroupSubRoleAssignment.properties.principalId).signInName) { $roleAssignmentIdentitySignInName = 'n/a' } else { if ($htPrincipals.($L1mgmtGroupSubRoleAssignment.properties.principalId).type -eq 'User') { if ($azAPICallConf['htParameters'].DoNotShowRoleAssignmentsUserData -eq $false) { $roleAssignmentIdentitySignInName = $htPrincipals.($L1mgmtGroupSubRoleAssignment.properties.principalId).signInName } else { $roleAssignmentIdentitySignInName = 'scrubbed' } } else { $roleAssignmentIdentitySignInName = $htPrincipals.($L1mgmtGroupSubRoleAssignment.properties.principalId).signInName } } $roleSecurityCustomRoleOwner = 0 if (($htCacheDefinitionsRole).$($roleDefinitionIdGuid).Actions -eq '*' -and ((($htCacheDefinitionsRole).$($roleDefinitionIdGuid).NotActions)).length -eq 0 -and ($htCacheDefinitionsRole).$($roleDefinitionIdGuid).IsCustom -eq $True) { $roleSecurityCustomRoleOwner = 1 } $roleSecurityOwnerAssignmentSP = 0 if ((($htCacheDefinitionsRole).$($roleDefinitionIdGuid).Id -eq '8e3af657-a8ff-443c-a75c-2fe8c4bcb635' -and $roleAssignmentIdentityObjectType -eq 'ServicePrincipal') -or (($htCacheDefinitionsRole).$($roleDefinitionIdGuid).Actions -eq '*' -and ((($htCacheDefinitionsRole).$($roleDefinitionIdGuid).NotActions)).length -eq 0 -and ($htCacheDefinitionsRole).$($roleDefinitionIdGuid).IsCustom -eq $True -and $roleAssignmentIdentityObjectType -eq 'ServicePrincipal')) { $roleSecurityOwnerAssignmentSP = 1 } $createdBy = '' $createdOn = '' $createdOnUnformatted = $null $updatedBy = '' $updatedOn = '' if ($L1mgmtGroupSubRoleAssignment.properties.createdBy) { $createdBy = $L1mgmtGroupSubRoleAssignment.properties.createdBy } if ($L1mgmtGroupSubRoleAssignment.properties.createdOn) { $createdOn = $L1mgmtGroupSubRoleAssignment.properties.createdOn } if ($L1mgmtGroupSubRoleAssignment.properties.updatedBy) { $updatedBy = $L1mgmtGroupSubRoleAssignment.properties.updatedBy } if ($L1mgmtGroupSubRoleAssignment.properties.updatedOn) { $updatedOn = $L1mgmtGroupSubRoleAssignment.properties.updatedOn } $createdOnUnformatted = $L1mgmtGroupSubRoleAssignment.properties.createdOn $addRowToTableDone = $true addRowToTable ` -level $hierarchyLevel ` -mgName $childMgDisplayName ` -mgId $childMgId ` -mgParentId $childMgParentId ` -mgParentName $childMgParentName ` -mgASCSecureScore $mgAscSecureScoreResult ` -Subscription $scopeDisplayName ` -SubscriptionId $scopeId ` -SubscriptionQuotaId $subscriptionQuotaId ` -SubscriptionState $subscriptionState ` -SubscriptionASCSecureScore $subscriptionASCSecureScore ` -SubscriptionTags $subscriptionTags ` -SubscriptionTagsCount $subscriptionTagsCount ` -RoleDefinitionId $roleDefinitionIdGuid ` -RoleDefinitionName $roleDefinitionName ` -RoleIsCustom $roleAssignmentsRoleDefinition.IsCustom ` -RoleAssignableScopes ($roleAssignmentsRoleDefinition.AssignableScopes -join "$CsvDelimiterOpposite ") ` -RoleActions ($roleAssignmentsRoleDefinition.Actions -join "$CsvDelimiterOpposite ") ` -RoleNotActions ($roleAssignmentsRoleDefinition.NotActions -join "$CsvDelimiterOpposite ") ` -RoleDataActions ($roleAssignmentsRoleDefinition.DataActions -join "$CsvDelimiterOpposite ") ` -RoleNotDataActions ($roleAssignmentsRoleDefinition.NotDataActions -join "$CsvDelimiterOpposite ") ` -RoleCanDoRoleAssignments $roleAssignmentsRoleDefinition.RoleCanDoRoleAssignments ` -RoleAssignmentIdentityDisplayname $roleAssignmentIdentityDisplayname ` -RoleAssignmentIdentitySignInName $roleAssignmentIdentitySignInName ` -RoleAssignmentIdentityObjectId $roleAssignmentIdentityObjectId ` -RoleAssignmentIdentityObjectType $roleAssignmentIdentityObjectType ` -RoleAssignmentId $roleAssignmentId ` -RoleAssignmentScope $roleAssignmentScope ` -RoleAssignmentScopeName $roleAssignmentScopeName ` -RoleAssignmentScopeRG $roleAssignmentScopeRG ` -RoleAssignmentScopeRes $roleAssignmentScopeRes ` -RoleAssignmentScopeType $roleAssignmentScopeType ` -RoleAssignmentCreatedBy $createdBy ` -RoleAssignmentCreatedOn $createdOn ` -RoleAssignmentCreatedOnUnformatted $createdOnUnformatted ` -RoleAssignmentUpdatedBy $updatedBy ` -RoleAssignmentUpdatedOn $updatedOn ` -RoleAssignmentsLimit $roleAssignmentsUsage.roleAssignmentsLimit ` -RoleAssignmentsCount $roleAssignmentsUsage.roleAssignmentsCurrentCount ` -RoleSecurityCustomRoleOwner $roleSecurityCustomRoleOwner ` -RoleSecurityOwnerAssignmentSP $roleSecurityOwnerAssignmentSP ` -RoleAssignmentPIM $pim ` -RoleAssignmentPIMAssignmentType $pimAssignmentType ` -RoleAssignmentPIMSlotStart $pimSlotStart ` -RoleAssignmentPIMSlotEnd $pimSlotEnd } $returnObject = @{} if ($addRowToTableDone) { $returnObject.'addRowToTableDone' = @{} } return $returnObject } $funcDataCollectionRoleAssignmentsSub = $function:dataCollectionRoleAssignmentsSub.ToString() function dataCollectionClassicAdministratorsSub { [CmdletBinding()]Param( [string]$scopeId, [string]$scopeDisplayName, [string]$subscriptionMgPath, $subscriptionQuotaId ) $apiEndPoint = $azAPICallConf['azAPIEndpointUrls'].ARM $api = "/subscriptions/$($scopeId)/providers/Microsoft.Authorization/classicAdministrators" $apiVersion = '?api-version=2015-07-01' $uri = $apiEndPoint + $api + $apiVersion $azAPICallPayload = @{ uri = $uri method = 'GET' currentTask = "classicAdministrators '$($scopeDisplayName)' ('$scopeId') [quotaId:'$subscriptionQuotaId']" AzAPICallConfiguration = $azAPICallConf } $AzApiCallResult = AzAPICall @azAPICallPayload if ($AzApiCallResult -ne 'ClassicAdministratorListFailed') { $arrayClassicAdministrators = [System.Collections.ArrayList]@() foreach ($roleAll in $AzApiCallResult) { $splitPropertiesRole = $roleAll.properties.role.Split(';') foreach ($role in $splitPropertiesRole) { $null = $arrayClassicAdministrators.Add([PSCustomObject]@{ Subscription = $scopeDisplayName SubscriptionId = $scopeId SubscriptionMgPath = $subscriptionMgPath Identity = $roleAll.properties.emailAddress Role = $role Id = $roleAll.id }) } } $script:htClassicAdministrators.($scopeId) = @{ ClassicAdministrators = $arrayClassicAdministrators } } } $funcDataCollectionClassicAdministratorsSub = $function:dataCollectionClassicAdministratorsSub.ToString() #endregion functions4DataCollection