diff --git a/README.md b/README.md index f1d0e08..30f00fb 100644 --- a/README.md +++ b/README.md @@ -86,11 +86,24 @@ Azure Architecture Center (Landing zones): [Azure Governance Visualizer deployme ## Release history +**Changes** (2026-May-18 / 6.7.3 Patch) + +- fix issue 294; retirement Classic Administrators + +**Changes** (2025-May-21 / 6.7.2 Patch) + +- use [AzAPICall](https://aka.ms/AzAPICall) PowerShell module version 1.4.1 (previous 1.4.0). Handle token refresh for OIDC in Azure Devops and GitHub Actions fix + +**Changes** (2025-May-20 / 6.7.1 Patch) + +- use [AzAPICall](https://aka.ms/AzAPICall) PowerShell module version 1.4.0 (previous 1.2.4). Handle token refresh for OIDC in Azure Devops and GitHub Actions + **Changes** (2025-May-19 / 6.7.0 Minor) - New feature "ALZ Policy Assignments Checker" - This new view, will compare the current deployed ALZ hierarchy with the ALZ archetypes definitions and point out the missing policy assignments. It will also reference the missing policy assignments' payloads and [AzAdvertizer](https://www.azadvertizer.net/) links. - New switch-parameter `-ALZPolicyAssignmentsChecker` - Execute the ALZPolicyAssignmentsChecker feature - New Parameter `-ALZManagementGroupsIds` - Provide the Management Group Ids of the deployed ALZ hierarchy (more details: [Parameters](#parameters)) + - [techcommunity blog post](https://techcommunity.microsoft.com/blog/azuregovernanceandmanagementblog/keep-your-azure-landing-zones-policy-assignments-up-to-date-with-azure-governanc/4292789) [Full release history](history.md) @@ -108,6 +121,7 @@ More [demo output](https://github.com/JulianHayward/AzGovViz) - Microsoft Dev Radio (YouTube) [Get visibility into your environment with Azure Governance Visualizer](https://www.youtube.com/watch?v=hZXvF5oypLE) - Jack Tracey (Cloud Solution Architect Microsoft) [Azure Governance Visualizer With Azure DevOps](https://jacktracey.co.uk/azgovviz-with-azure-devops/) - SCHUTTEN.CLOUD [Automate Pertinent Governance Insight with Azure Governance Visualizer](https://schutten.cloud/post/azure-governance-visualizer/) +- DEVOPS masterminds [Indispensable Azure Tools: Azure Governance Visualizer (AzGovViz) for Governance Excellence](https://devopsmasterminds.com/technical-blog-posts-devops-masterminds/indispensable-azure-tools-azure-governance-visualizer-azgovviz-for-governance-excellence/) ### Presentations @@ -185,7 +199,6 @@ Short presentation on Azure Governance Visualizer: [download](slides/AzGovViz_in - PIM (Privileged Identity Management) eligibility for role assignments - Get a full report of all PIM eligible role assignments for Management Groups and subscriptions, including resolved user members of Microsoft Entra ID groups that have assigned eligibility - 💡 Note: this feature requires you to execute as service principal with `Application` API permission `PrivilegedAccess.Read.AzureResources` - - Role assignments ClassicAdministrators - Security & best practice analysis - Existence of custom role definition that reflect 'Owner' permissions - Report all role definitions that are capable to write role assignments, list all role assignments for those role definitions @@ -547,7 +560,7 @@ Screenshot of Microsoft Graph permissions in the Microsoft Entra admin center - `-NoNetwork` - Do not execute Network analysis / Virtual Network and Virtual Network Peerings - `-NetworkSubnetIPAddressUsageCriticalPercentage` - Warning level when certain percentage of IP addresses is used (default = 90%) - `-TenantId4AzContext` - Define the Tenant Id to use for AzContext (default is to use the Tenant Id from the current context) -- `-ALZPolicyAssignmentsChecker` - Execute the 'Azure Landing Zones (ALZ) Policy Assignments Checker' feature +- `-ALZPolicyAssignmentsChecker` - Execute the 'Azure Landing Zones (ALZ) Policy Assignments Checker' feature. [techcommunity blog post](https://techcommunity.microsoft.com/blog/azuregovernanceandmanagementblog/keep-your-azure-landing-zones-policy-assignments-up-to-date-with-azure-governanc/4292789) - `-ALZManagementGroupsIds` - if your Management Group (MG) structure deviates from the ALZ defaults, then you will need to map your MG structure to the default ALZ structure. If your MG structure does not deviate from the ALZ defaults then you do not need to define this parameter _example:_ @@ -561,7 +574,7 @@ _example:_ landing_zones = '' corp = '' online = '' - sandboxes = '' + sandbox = '' decommissioned = '' } ``` @@ -768,7 +781,7 @@ git config --system core.longpaths true ## Facts -Disabled Azure subscriptions and subscriptions where Quota ID starts with with "AAD\_" are being skipped, all others are queried. More information on Subscription Quota ID / Offer numbers: [Supported Microsoft Azure offers](https://learn.microsoft.com/azure/cost-management-billing/costs/understand-cost-mgt-data#supported-microsoft-azure-offers). +Disabled Azure subscriptions and subscriptions where Quota ID starts with "AAD\_" are being skipped, all others are queried. More information on Subscription Quota ID / Offer numbers: [Supported Microsoft Azure offers](https://learn.microsoft.com/azure/cost-management-billing/costs/understand-cost-mgt-data#supported-microsoft-azure-offers). ARM Limits are not acquired programmatically, these are hardcoded. The links used to check related limits are commented in the param section of the script. diff --git a/history.md b/history.md index 16310b7..7f74853 100644 --- a/history.md +++ b/history.md @@ -4,6 +4,18 @@ ### Azure Governance Visualizer version 6 +**Changes** (2026-May-18 / 6.7.3 Patch) + +- fix issue 294; retirement Classic Administrators + +**Changes** (2025-May-21 / 6.7.2 Patch) + +- use [AzAPICall](https://aka.ms/AzAPICall) PowerShell module version 1.4.1 (previous 1.4.0). Handle token refresh for OIDC in Azure Devops and GitHub Actions fix + +**Changes** (2025-May-20 / 6.7.1 Patch) + +- use [AzAPICall](https://aka.ms/AzAPICall) PowerShell module version 1.4.0 (previous 1.2.4). Handle token refresh for OIDC in Azure Devops and GitHub Actions + **Changes** (2025-May-19 / 6.7.0 Minor) - New feature "ALZ Policy Assignments Checker" - This new view, will compare the current deployed ALZ hierarchy with the ALZ archetypes definitions and point out the missing policy assignments. It will also reference the missing policy assignments' payloads and [AzAdvertizer](https://www.azadvertizer.net/) links. diff --git a/pwsh/AzGovVizParallel.ps1 b/pwsh/AzGovVizParallel.ps1 index 3eaa0b2..b2b419b 100644 --- a/pwsh/AzGovVizParallel.ps1 +++ b/pwsh/AzGovVizParallel.ps1 @@ -170,7 +170,7 @@ .Parameter ALZPolicyAssignmentsChecker 'Azure Landing Zones (ALZ) Policy Assignments Checker' for Policy and Set assignments. Azure Governance Visualizer will clone the ALZ Library GitHub repository and collect the standard ALZ policy and set assignments. The ALZ data will be compared with the data from your tenant so that you can get an inventory for ALZ policy and set assignments that already exist in your tenant and compare with the standard assignments of ALZ. The 'Azure Landing Zones (ALZ) Policy Assignments Checker' results will be displayed in the TenantSummary. If you do want to execute the 'Azure Landing Zones (ALZ) Policy Version Checker' feature then use this parameter - PS C:\>.\AzGovVizParallel.ps1 -ManagementGroupId -NoALZPolicyVersionChecker + PS C:\>.\AzGovVizParallel.ps1 -ManagementGroupId -ALZPolicyAssignmentsChecker .Parameter ALZManagementGroupsIds 'Azure Landing Zones (ALZ) Management groups Ids'. This is the list of Ids of the ALZ management groups hierarchy. @@ -184,7 +184,7 @@ landing_zones = '' corp = '' online = '' - sandboxes = '' + sandbox = '' decommissioned = '' } @@ -372,7 +372,7 @@ landing_zones = '' corp = '' online = '' - sandboxes = '' + sandbox = '' decommissioned = '' } @@ -406,7 +406,7 @@ Param $Product = 'AzGovViz', [string] - $ProductVersion = '6.7.0', + $ProductVersion = '6.7.3', [string] $GithubRepository = 'aka.ms/AzGovViz', @@ -416,7 +416,7 @@ Param [ValidateSet('AzAPICall', 'AzAPICallBeta')]$AzAPICallModuleName = 'AzAPICall', [string] - $AzAPICallVersion = '1.2.4', + $AzAPICallVersion = '1.4.1', [switch] $DebugAzAPICall, @@ -617,7 +617,7 @@ Param landing_zones = '' corp = '' online = '' - sandboxes = '' + sandbox = '' decommissioned = '' }#>, @@ -6984,7 +6984,6 @@ function processDataCollection { $htSubscriptionsRoleAssignmentLimit = $using:htSubscriptionsRoleAssignmentLimit $arrayPsRule = $using:arrayPsRule $arrayPSRuleTracking = $using:arrayPSRuleTracking - $htClassicAdministrators = $using:htClassicAdministrators $htRoleAssignmentsPIM = $using:htRoleAssignmentsPIM $alzPolicies = $using:alzPolicies $alzPolicySets = $using:alzPolicySets @@ -7026,7 +7025,6 @@ function processDataCollection { $function:dataCollectionPolicyAssignmentsSub = $using:funcDataCollectionPolicyAssignmentsSub $function:dataCollectionRoleDefinitions = $using:funcDataCollectionRoleDefinitions $function:dataCollectionRoleAssignmentsSub = $using:funcDataCollectionRoleAssignmentsSub - $function:dataCollectionClassicAdministratorsSub = $using:funcDataCollectionClassicAdministratorsSub $function:dataCollectionDefenderEmailContacts = $using:funcDataCollectionDefenderEmailContacts $function:dataCollectionVNets = $using:funcDataCollectionVNets $function:dataCollectionPrivateEndpoints = $using:funcDataCollectionPrivateEndpoints @@ -7210,9 +7208,6 @@ function processDataCollection { if ($functionReturn.'addRowToTableDone') { $addRowToTableDone = $true } - - #SubscriptionClassicAdministrators - dataCollectionClassicAdministratorsSub @baseParameters -SubscriptionMgPath $childMgMgPath } if ($addRowToTableDone -ne $true) { @@ -13736,94 +13731,6 @@ extensions: [{ name: 'sort' }] '@) #endregion ScopeInsightsBlueprintsScoped - if ($mgOrSub -eq 'sub') { - #region ScopeInsightsClassicAdministrators - if ($htClassicAdministrators.($subscriptionId).ClassicAdministrators.Count -gt 0) { - $tfCount = $htClassicAdministrators.($subscriptionId).ClassicAdministrators.Count - $htmlTableId = "ScopeInsights_ClassicAdministrators_$($subscriptionId -replace '\(','_' -replace '\)','_' -replace '-','_' -replace '\.','_')" - $randomFunctionName = "func_$htmlTableId" - [void]$htmlScopeInsights.AppendLine(@" - -
-   Download CSV semicolon | comma - - - - - - - - -"@) - $htmlScopeInsightsClassicAdministrators = $null - $htmlScopeInsightsClassicAdministrators = foreach ($classicAdministrator in $htClassicAdministrators.($subscriptionId).ClassicAdministrators | Sort-Object -Property Role, Identity) { - @" - - - - -"@ - } - [void]$htmlScopeInsights.AppendLine($htmlScopeInsightsClassicAdministrators) - [void]$htmlScopeInsights.AppendLine(@" - -
RoleIdentity
$($classicAdministrator.Role)$($classicAdministrator.Identity)
-
- -"@) - } - else { - [void]$htmlScopeInsights.AppendLine(@' - No Classic Administrators -'@) - } - [void]$htmlScopeInsights.AppendLine(@' - - -'@) - #endregion ScopeInsightsClassicAdministrators - } - #RoleAssignments #region ScopeInsightsRoleAssignments if ($mgOrSub -eq 'mg') { @@ -19712,106 +19619,6 @@ extensions: [{ name: 'sort' }] } #endregion SUMMARYOrphanedRoleAssignments - #region SUMMARYClassicAdministrators - Write-Host ' processing TenantSummary ClassicAdministrators' - - if ($htClassicAdministrators.Keys.Count -gt 0) { - $tfCount = $htClassicAdministrators.Values.ClassicAdministrators.Count - $htmlTableId = 'TenantSummary_ClassicAdministrators' - [void]$htmlTenantSummary.AppendLine(@" - -
- Download CSV semicolon | comma - - - - - - - - - - - -"@) - $htmlSUMMARYClassicAdministrators = $null - $classicAdministrators = $htClassicAdministrators.Values.ClassicAdministrators | Sort-Object -Property Subscription, Role, Identity - if (-not $NoCsvExport) { - $csvFilename = "$($filename)_ClassicAdministrators" - Write-Host " Exporting ClassicAdministrators CSV '$($outputPath)$($DirectorySeparatorChar)$($csvFilename).csv'" - $classicAdministrators | Select-Object -ExcludeProperty Id | Sort-Object -Property Subscription, SubscriptionId, Role | Export-Csv -Encoding utf8 -Path "$($outputPath)$($DirectorySeparatorChar)$($csvFilename).csv" -Delimiter $csvDelimiter -NoTypeInformation - } - $htmlSUMMARYClassicAdministrators = foreach ($classicAdministrator in $classicAdministrators) { - @" - - - - - - - -"@ - } - [void]$htmlTenantSummary.AppendLine($htmlSUMMARYClassicAdministrators) - [void]$htmlTenantSummary.AppendLine(@" - -
SubscriptionSubscriptionIdMgPathRoleIdentity
$($classicAdministrator.Subscription)$($classicAdministrator.SubscriptionId)$($classicAdministrator.SubscriptionMgPath)$($classicAdministrator.Role)$($classicAdministrator.Identity)
-
- -"@) - } - else { - [void]$htmlTenantSummary.AppendLine(@' -

No ClassicAdministrators

-'@) - } - #endregion SUMMARYClassicAdministrators - #region SUMMARYRoleAssignmentsAll $startRoleAssignmentsAll = Get-Date Write-Host ' processing TenantSummary RoleAssignments' @@ -35783,49 +35590,6 @@ function dataCollectionRoleAssignmentsSub { 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 #endregion Functions @@ -36129,7 +35893,6 @@ if (-not $HierarchyMapOnly) { } $arrayPsRule = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList)) $arrayPSRuleTracking = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList)) - $htClassicAdministrators = [System.Collections.Hashtable]::Synchronized(@{}) $arrayOrphanedResources = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList)) $arrayPIMEligible = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList)) $alzPolicies = @{} diff --git a/pwsh/dev/devAzGovVizParallel.ps1 b/pwsh/dev/devAzGovVizParallel.ps1 index a4ff9e2..dbfdd75 100644 --- a/pwsh/dev/devAzGovVizParallel.ps1 +++ b/pwsh/dev/devAzGovVizParallel.ps1 @@ -170,7 +170,7 @@ .Parameter ALZPolicyAssignmentsChecker 'Azure Landing Zones (ALZ) Policy Assignments Checker' for Policy and Set assignments. Azure Governance Visualizer will clone the ALZ Library GitHub repository and collect the standard ALZ policy and set assignments. The ALZ data will be compared with the data from your tenant so that you can get an inventory for ALZ policy and set assignments that already exist in your tenant and compare with the standard assignments of ALZ. The 'Azure Landing Zones (ALZ) Policy Assignments Checker' results will be displayed in the TenantSummary. If you do want to execute the 'Azure Landing Zones (ALZ) Policy Version Checker' feature then use this parameter - PS C:\>.\AzGovVizParallel.ps1 -ManagementGroupId -NoALZPolicyVersionChecker + PS C:\>.\AzGovVizParallel.ps1 -ManagementGroupId -ALZPolicyAssignmentsChecker .Parameter ALZManagementGroupsIds 'Azure Landing Zones (ALZ) Management groups Ids'. This is the list of Ids of the ALZ management groups hierarchy. @@ -184,7 +184,7 @@ landing_zones = '' corp = '' online = '' - sandboxes = '' + sandbox = '' decommissioned = '' } @@ -372,7 +372,7 @@ landing_zones = '' corp = '' online = '' - sandboxes = '' + sandbox = '' decommissioned = '' } @@ -406,7 +406,7 @@ Param $Product = 'AzGovViz', [string] - $ProductVersion = '6.7.0', + $ProductVersion = '6.7.3', [string] $GithubRepository = 'aka.ms/AzGovViz', @@ -416,7 +416,7 @@ Param [ValidateSet('AzAPICall', 'AzAPICallBeta')]$AzAPICallModuleName = 'AzAPICall', [string] - $AzAPICallVersion = '1.2.4', + $AzAPICallVersion = '1.4.1', [switch] $DebugAzAPICall, @@ -617,7 +617,7 @@ Param landing_zones = '' corp = '' online = '' - sandboxes = '' + sandbox = '' decommissioned = '' }#>, @@ -1103,7 +1103,6 @@ if (-not $HierarchyMapOnly) { } $arrayPsRule = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList)) $arrayPSRuleTracking = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList)) - $htClassicAdministrators = [System.Collections.Hashtable]::Synchronized(@{}) $arrayOrphanedResources = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList)) $arrayPIMEligible = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList)) $alzPolicies = @{} diff --git a/pwsh/dev/functions/dataCollection/dataCollectionFunctions.ps1 b/pwsh/dev/functions/dataCollection/dataCollectionFunctions.ps1 index b070447..9538c91 100644 --- a/pwsh/dev/functions/dataCollection/dataCollectionFunctions.ps1 +++ b/pwsh/dev/functions/dataCollection/dataCollectionFunctions.ps1 @@ -4186,47 +4186,4 @@ function dataCollectionRoleAssignmentsSub { 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 \ No newline at end of file diff --git a/pwsh/dev/functions/processDataCollection.ps1 b/pwsh/dev/functions/processDataCollection.ps1 index ae1c250..a838131 100644 --- a/pwsh/dev/functions/processDataCollection.ps1 +++ b/pwsh/dev/functions/processDataCollection.ps1 @@ -350,7 +350,6 @@ $htSubscriptionsRoleAssignmentLimit = $using:htSubscriptionsRoleAssignmentLimit $arrayPsRule = $using:arrayPsRule $arrayPSRuleTracking = $using:arrayPSRuleTracking - $htClassicAdministrators = $using:htClassicAdministrators $htRoleAssignmentsPIM = $using:htRoleAssignmentsPIM $alzPolicies = $using:alzPolicies $alzPolicySets = $using:alzPolicySets @@ -392,7 +391,6 @@ $function:dataCollectionPolicyAssignmentsSub = $using:funcDataCollectionPolicyAssignmentsSub $function:dataCollectionRoleDefinitions = $using:funcDataCollectionRoleDefinitions $function:dataCollectionRoleAssignmentsSub = $using:funcDataCollectionRoleAssignmentsSub - $function:dataCollectionClassicAdministratorsSub = $using:funcDataCollectionClassicAdministratorsSub $function:dataCollectionDefenderEmailContacts = $using:funcDataCollectionDefenderEmailContacts $function:dataCollectionVNets = $using:funcDataCollectionVNets $function:dataCollectionPrivateEndpoints = $using:funcDataCollectionPrivateEndpoints @@ -576,9 +574,6 @@ if ($functionReturn.'addRowToTableDone') { $addRowToTableDone = $true } - - #SubscriptionClassicAdministrators - dataCollectionClassicAdministratorsSub @baseParameters -SubscriptionMgPath $childMgMgPath } if ($addRowToTableDone -ne $true) { diff --git a/pwsh/dev/functions/processScopeInsightsMgOrSub.ps1 b/pwsh/dev/functions/processScopeInsightsMgOrSub.ps1 index 8fa57ed..04947dd 100644 --- a/pwsh/dev/functions/processScopeInsightsMgOrSub.ps1 +++ b/pwsh/dev/functions/processScopeInsightsMgOrSub.ps1 @@ -3586,94 +3586,6 @@ extensions: [{ name: 'sort' }] '@) #endregion ScopeInsightsBlueprintsScoped - if ($mgOrSub -eq 'sub') { - #region ScopeInsightsClassicAdministrators - if ($htClassicAdministrators.($subscriptionId).ClassicAdministrators.Count -gt 0) { - $tfCount = $htClassicAdministrators.($subscriptionId).ClassicAdministrators.Count - $htmlTableId = "ScopeInsights_ClassicAdministrators_$($subscriptionId -replace '\(','_' -replace '\)','_' -replace '-','_' -replace '\.','_')" - $randomFunctionName = "func_$htmlTableId" - [void]$htmlScopeInsights.AppendLine(@" - -
-   Download CSV semicolon | comma - - - - - - - - -"@) - $htmlScopeInsightsClassicAdministrators = $null - $htmlScopeInsightsClassicAdministrators = foreach ($classicAdministrator in $htClassicAdministrators.($subscriptionId).ClassicAdministrators | Sort-Object -Property Role, Identity) { - @" - - - - -"@ - } - [void]$htmlScopeInsights.AppendLine($htmlScopeInsightsClassicAdministrators) - [void]$htmlScopeInsights.AppendLine(@" - -
RoleIdentity
$($classicAdministrator.Role)$($classicAdministrator.Identity)
-
- -"@) - } - else { - [void]$htmlScopeInsights.AppendLine(@' - No Classic Administrators -'@) - } - [void]$htmlScopeInsights.AppendLine(@' - - -'@) - #endregion ScopeInsightsClassicAdministrators - } - #RoleAssignments #region ScopeInsightsRoleAssignments if ($mgOrSub -eq 'mg') { diff --git a/pwsh/dev/functions/processTenantSummary.ps1 b/pwsh/dev/functions/processTenantSummary.ps1 index 6eb0d4d..027802c 100644 --- a/pwsh/dev/functions/processTenantSummary.ps1 +++ b/pwsh/dev/functions/processTenantSummary.ps1 @@ -5253,106 +5253,6 @@ extensions: [{ name: 'sort' }] } #endregion SUMMARYOrphanedRoleAssignments - #region SUMMARYClassicAdministrators - Write-Host ' processing TenantSummary ClassicAdministrators' - - if ($htClassicAdministrators.Keys.Count -gt 0) { - $tfCount = $htClassicAdministrators.Values.ClassicAdministrators.Count - $htmlTableId = 'TenantSummary_ClassicAdministrators' - [void]$htmlTenantSummary.AppendLine(@" - -
- Download CSV semicolon | comma - - - - - - - - - - - -"@) - $htmlSUMMARYClassicAdministrators = $null - $classicAdministrators = $htClassicAdministrators.Values.ClassicAdministrators | Sort-Object -Property Subscription, Role, Identity - if (-not $NoCsvExport) { - $csvFilename = "$($filename)_ClassicAdministrators" - Write-Host " Exporting ClassicAdministrators CSV '$($outputPath)$($DirectorySeparatorChar)$($csvFilename).csv'" - $classicAdministrators | Select-Object -ExcludeProperty Id | Sort-Object -Property Subscription, SubscriptionId, Role | Export-Csv -Encoding utf8 -Path "$($outputPath)$($DirectorySeparatorChar)$($csvFilename).csv" -Delimiter $csvDelimiter -NoTypeInformation - } - $htmlSUMMARYClassicAdministrators = foreach ($classicAdministrator in $classicAdministrators) { - @" - - - - - - - -"@ - } - [void]$htmlTenantSummary.AppendLine($htmlSUMMARYClassicAdministrators) - [void]$htmlTenantSummary.AppendLine(@" - -
SubscriptionSubscriptionIdMgPathRoleIdentity
$($classicAdministrator.Subscription)$($classicAdministrator.SubscriptionId)$($classicAdministrator.SubscriptionMgPath)$($classicAdministrator.Role)$($classicAdministrator.Identity)
-
- -"@) - } - else { - [void]$htmlTenantSummary.AppendLine(@' -

No ClassicAdministrators

-'@) - } - #endregion SUMMARYClassicAdministrators - #region SUMMARYRoleAssignmentsAll $startRoleAssignmentsAll = Get-Date Write-Host ' processing TenantSummary RoleAssignments' diff --git a/version.json b/version.json index 563ebe6..8e71aca 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "ProductVersion": "6.7.0" + "ProductVersion": "6.7.3" } \ No newline at end of file