Merged PR 51902: updated keyvaults rbac column

updated keyvaults rbac column
added scripts to detected unused resources

Related work items: #103196
This commit is contained in:
Jurjen Ladenius
2024-07-17 09:40:19 +00:00
parent 6957def272
commit 579ba243bd
4 changed files with 1643 additions and 36 deletions

View File

@@ -72,7 +72,7 @@ foreach ($managementGroup in $managementGroups)
$resourceCheck.ManagementGroupId = $managementGroup.Id $resourceCheck.ManagementGroupId = $managementGroup.Id
$resourceCheck.ManagementGroupName = $managementGroup.DisplayName $resourceCheck.ManagementGroupName = $managementGroup.DisplayName
$resourceCheck.SubscriptionId = $subscription.Id $resourceCheck.SubscriptionId = $subscription.Id
$resourceCheck.SubscriptionName = $subscription.Name $resourceCheck.SubscriptionName = $subscription.DisplayName
$resourceCheck.ResourceGroup = $vaultWithAllProps.ResourceGroupName $resourceCheck.ResourceGroup = $vaultWithAllProps.ResourceGroupName
$resourceCheck.ResourceId = $vaultWithAllProps.ResourceId $resourceCheck.ResourceId = $vaultWithAllProps.ResourceId
$resourceCheck.Location = $vaultWithAllProps.Location $resourceCheck.Location = $vaultWithAllProps.Location

View File

@@ -2,11 +2,13 @@
class ResourceCheck { class ResourceCheck {
[string] $ResourceId = "" [string] $ResourceId = ""
[string] $Location = "" [string] $ManagementGroupId = ""
[string] $ResourceName = "" [string] $ManagementGroupName = ""
[string] $ResourceGroup = ""
[string] $SubscriptionId = "" [string] $SubscriptionId = ""
[string] $SubscriptionName = "" [string] $SubscriptionName = ""
[string] $ResourceGroup = ""
[string] $ResourceName = ""
[string] $Location = ""
[string] $Tag_Team = "" [string] $Tag_Team = ""
[string] $Tag_Product = "" [string] $Tag_Product = ""
[string] $Tag_Environment = "" [string] $Tag_Environment = ""
@@ -30,53 +32,67 @@ Write-Host "====================================================================
[string] $date = Get-Date -Format "yyyy-MM-dd HHmm" [string] $date = Get-Date -Format "yyyy-MM-dd HHmm"
$fileName = ".\$date azure_key_vaults.csv" $fileName = ".\$date azure_key_vaults.csv"
foreach ($subscription in $subscriptions) $managementGroups = Get-AzManagementGroup
foreach ($managementGroup in $managementGroups)
{ {
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------------------------" Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------------------------"
Write-Host "Management group [$($managementGroup.Name)]"
Set-AzContext -SubscriptionId $subscription.Id $subscriptions = Get-AzManagementGroupSubscription -Group $managementGroup.Name | Where-Object State -eq "Active"
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------------------------" foreach ($subscription in $subscriptions)
{
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------------------------"
$scope = $subscription.Id.Substring($subscription.Parent.Length, $subscription.Id.Length - $subscription.Parent.Length)
$subscriptionId = $scope.Replace("/subscriptions/", "")
Write-Host "Subscription [$($subscription.DisplayName) - $subscriptionId]"
Set-AzContext -SubscriptionId $subscriptionId | Out-Null
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------------------------"
$allResourceGroups = Get-AzResourceGroup $allResourceGroups = Get-AzResourceGroup
[ResourceCheck[]]$Result = @() [ResourceCheck[]]$Result = @()
foreach ($group in $allResourceGroups) { foreach ($group in $allResourceGroups) {
Write-Host $group.ResourceGroupName Write-Host $group.ResourceGroupName
$allVaults = Get-AzKeyVault -ResourceGroupName $group.ResourceGroupName $allVaults = Get-AzKeyVault -ResourceGroupName $group.ResourceGroupName
foreach ($vault in $allVaults) { foreach ($vault in $allVaults) {
$vaultWithAllProps = Get-AzKeyVault -ResourceGroupName $group.ResourceGroupName -Name $vault.VaultName $vaultWithAllProps = Get-AzKeyVault -ResourceGroupName $group.ResourceGroupName -Name $vault.VaultName
[ResourceCheck] $resourceCheck = [ResourceCheck]::new() $enabledRBAC = $vaultWithAllProps.EnableRbacAuthorization -eq "TRUE"
$resourceCheck.ResourceId = $vaultWithAllProps.ResourceId
$resourceCheck.Location = $vaultWithAllProps.Location
$resourceCheck.ResourceName = $vaultWithAllProps.VaultName
$resourceCheck.ResourceGroup = $vaultWithAllProps.ResourceGroupName
$resourceCheck.SubscriptionId = $subscription.Id
$resourceCheck.SubscriptionName = $subscription.Name
$resourceCheck.Tag_Team = $vaultWithAllProps.Tags.team
$resourceCheck.Tag_Product = $vaultWithAllProps.Tags.product
$resourceCheck.Tag_Environment = $vaultWithAllProps.Tags.environment
$resourceCheck.Tag_Data = $vaultWithAllProps.Tags.data
$resourceCheck.Tag_CreatedOnDate = $vaultWithAllProps.Tags.CreatedOnDate
$resourceCheck.Tag_Deployment = $vaultWithAllProps.Tags.drp_deployment
$resourceCheck.Prop_EnablePurgeProtection = $vaultWithAllProps.EnablePurgeProtection
$resourceCheck.Prop_EnableRbacAuthorization = $vaultWithAllProps.EnableRbacAuthorization
$resourceCheck.Prop_EnableSoftDelete = $vaultWithAllProps.EnableSoftDelete
$resourceCheck.Prop_PublicNetworkAccess = $vaultWithAllProps.PublicNetworkAccess
$Result += $resourceCheck [ResourceCheck] $resourceCheck = [ResourceCheck]::new()
$resourceCheck.ManagementGroupId = $managementGroup.Id
$resourceCheck.ManagementGroupName = $managementGroup.DisplayName
$resourceCheck.ResourceId = $vaultWithAllProps.ResourceId
$resourceCheck.Location = $vaultWithAllProps.Location
$resourceCheck.ResourceName = $vaultWithAllProps.VaultName
$resourceCheck.ResourceGroup = $vaultWithAllProps.ResourceGroupName
$resourceCheck.SubscriptionId = $subscription.Id
$resourceCheck.SubscriptionName = $subscription.DisplayName
$resourceCheck.Tag_Team = $vaultWithAllProps.Tags.team
$resourceCheck.Tag_Product = $vaultWithAllProps.Tags.product
$resourceCheck.Tag_Environment = $vaultWithAllProps.Tags.environment
$resourceCheck.Tag_Data = $vaultWithAllProps.Tags.data
$resourceCheck.Tag_CreatedOnDate = $vaultWithAllProps.Tags.CreatedOnDate
$resourceCheck.Tag_Deployment = $vaultWithAllProps.Tags.drp_deployment
$resourceCheck.Prop_EnablePurgeProtection = $vaultWithAllProps.EnablePurgeProtection
$resourceCheck.Prop_EnableRbacAuthorization = $enabledRBAC
$resourceCheck.Prop_EnableSoftDelete = $vaultWithAllProps.EnableSoftDelete
$resourceCheck.Prop_PublicNetworkAccess = $vaultWithAllProps.PublicNetworkAccess
$Result += $resourceCheck
}
} }
$Result | Export-Csv -Path $fileName -Append -NoTypeInformation
} }
$Result | Export-Csv -Path $fileName -Append -NoTypeInformation
} }
Write-Host "======================================================================================================================================================================" Write-Host "======================================================================================================================================================================"
Write-Host "Done." Write-Host "Done."

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,248 @@
<#
.SYNOPSIS
This script removes all specified tags from all specified resources and resource
groups.
.DESCRIPTION
This script removes all specified tags from all specified resources and resource
groups.
The default values for some parameters can be specified in a config file named
'Defaults.json'.
Project Link: https://github.com/thgossler/AzSaveMoney
Copyright (c) 2022 Thomas Gossler
License: MIT
.INPUTS
Azure resources/groups across all (or specified) subscriptions.
.NOTES
Warnings are suppressed by $WarningPreference='SilentlyContinue'.
#>
#Requires -Version 7
#Requires -Modules Az.Accounts
#Requires -Modules Az.ResourceGraph
#Requires -Modules Az.Resources
#Requires -Modules PowerShellGet
######################################################################
# Configuration Settings
######################################################################
[CmdletBinding(SupportsShouldProcess)]
param (
# The ID of the Azure AD tenant. Can be set in defaults config file. Can be
# set in defaults config file.
[string]$DirectoryId,
# The Azure environment name (default: AzureCloud, for options call
# "(Get-AzEnvironment).Name"). Can be set in defaults config file.
[string]$AzEnvironment,
# The list of Azure subscription IDs to process. If empty all subscriptions
# will be processed (default: all). Can be set in defaults config file.
[System.Array]$SubscriptionIdsToProcess = @(),
# The list of names of the tags to be removed (default: all
# 'SubjectForDeletion...' tags). Can be set in defaults config file.
[System.Array]$TagNamesToRemove = @(
"SubjectForDeletion"
"SubjectForDeletion-FindingDate"
"SubjectForDeletion-Reason"
"SubjectForDeletion-Hint"
),
# Don't remove the tags from resources.
[switch]$DontRemoveFromResources = $false,
# Don't remove the tags from resource groups.
[switch]$DontRemoveFromResourceGroups = $false
)
# Get configured defaults from config file
$defaultsConfig = (Test-Path -Path $PSScriptRoot/Defaults.json -PathType Leaf) ? (Get-Content -Path $PSScriptRoot/Defaults.json -Raw | ConvertFrom-Json) : @{}
if ([string]::IsNullOrWhiteSpace($DirectoryId) -and ![string]::IsNullOrWhiteSpace($defaultsConfig.DirectoryId)) {
$DirectoryId = $defaultsConfig.DirectoryId
}
if ([string]::IsNullOrWhiteSpace($AzEnvironment)) {
if (![string]::IsNullOrWhiteSpace($defaultsConfig.AzEnvironment)) {
$AzEnvironment = $defaultsConfig.AzEnvironment
}
else {
$AzEnvironment = 'AzureCloud'
}
}
if ($SubscriptionIdsToProcess.Count -lt 1 -and $defaultsConfig.SubscriptionIdsToProcess -and
($defaultsConfig.SubscriptionIdsToProcess -is [System.Array]) -and $defaultsConfig.SubscriptionIdsToProcess.Count -gt 0)
{
$SubscriptionIdsToProcess = $defaultsConfig.SubscriptionIdsToProcess
}
$tab = ' '
######################################################################
# Execution
######################################################################
$WarningPreference = 'SilentlyContinue'
Clear-Host
$WhatIfHint = ""
$IsWhatIfMode = !$PSCmdlet.ShouldProcess("WhatIf mode", "Enable")
if ($IsWhatIfMode) {
Write-Host ""
Write-Host " *** WhatIf mode (no changes are made) *** " -BackgroundColor DarkBlue -ForegroundColor White
$WhatIfHint = "What if: "
}
if (!((Get-AzEnvironment).Name -contains $AzEnvironment)) {
Write-Error "Invalid Azure environment name '$AzEnvironment'"
return
}
$loggedIn = $false
if (![string]::IsNullOrWhiteSpace($DirectoryId)) {
$loggedIn = Connect-AzAccount -Environment $AzEnvironment -TenantId $DirectoryId -WhatIf:$false
}
else {
$loggedIn = Connect-AzAccount -Environment $AzEnvironment -WhatIf:$false
$DirectoryId = (Get-AzContext).Tenant.Id
}
if (!$loggedIn) {
Write-Error "Sign-in failed"
return
}
Write-Host "$([Environment]::NewLine)Subscriptions to process:"
if ($null -ne $SubscriptionIdsToProcess -and $SubscriptionIdsToProcess.Count -gt 0) {
foreach ($s in $SubscriptionIdsToProcess) {
Write-Host "$($tab)$s"
}
}
else {
Write-Host "all"
}
Write-Host "$([System.Environment]::NewLine)Tags to remove:"
$TagNamesToRemove | ForEach-Object { Write-Host "$($tab)$_" }
$choice = Read-Host -Prompt "$([Environment]::NewLine)Remove all these tags? 'y' = yes, <Any> = no "
if ($choice -ine "y") {
Write-Host "Cancelled by user."
return
}
if (!$DontRemoveFromResources) {
Write-Host "$([Environment]::NewLine)Searching matching resources..."
$query = "Resources | where "
if ($null -ne $SubscriptionIdsToProcess -and $SubscriptionIdsToProcess.Count -gt 0) {
$query += "("
$op = ""
foreach ($subscriptionId in $SubscriptionIdsToProcess) {
$query += "$op subscriptionId =~ '$subscriptionId'"
$op = " or "
}
$query += " ) and "
}
$op = ""
foreach ($tagName in $TagNamesToRemove) {
$query += "$op tags['$tagName'] != ''"
$op = " or "
}
if ($VerbosePreference -eq $true) {
Write-Host "Query: $query" -ForegroundColor DarkGray
}
$resources = [System.Collections.ArrayList]@()
$skipToken = $null;
$queryResult = $null;
do {
if ($null -eq $skipToken) {
$queryResult = Search-AzGraph -Query $query
}
else {
$queryResult = Search-AzGraph -Query $query -SkipToken $skipToken
}
$skipToken = $queryResult.SkipToken;
$resources.AddRange($queryResult.Data) | Out-Null
} while ($null -ne $skipToken)
if ($resources.Count -gt 0) {
Write-Host "$($WhatIfHint)Removing tags from resources (subscriptionId / resourceGroupName / resourceName):"
$i = 0; $count = $resources.Count
foreach ($resource in $resources) {
$i += 1
Write-Host "$($tab)$($WhatIfHint)($i/$count) $($resource.subscriptionId) / $($resource.resourceGroup) / $($resource.name)..."
$tags = Get-AzTag -ResourceId $resource.id
if (!$tags.Properties.TagsProperty) { continue }
$tagsToRemove = [hashtable]@{}
foreach ($tagName in $TagNamesToRemove) {
$tagValue = $tags.Properties.TagsProperty[$tagName]
if (![string]::IsNullOrWhiteSpace($tagValue)) {
$tagsToRemove.Add($tagName, $tags.Properties.TagsProperty[$tagName]) | Out-Null
}
}
if ($tagsToRemove.Keys.Count -gt 0 -and !$IsWhatIfMode) {
Update-AzTag -ResourceId $resource.id -Tag $tagsToRemove -Operation Delete -WhatIf:$WhatIfPreference | Out-Null
}
}
}
else {
Write-Host "No matching resources found."
}
}
if (!$DontRemoveFromResourceGroups) {
Write-Host "$([Environment]::NewLine)Processing resource groups..."
$subscriptions = @(Get-AzSubscription -TenantId $DirectoryId -ErrorAction Stop | Where-Object -Property State -ne 'Disabled')
$s_i = 0; $s_count = $subscriptions.Count
foreach ($sub in $subscriptions) {
if ($null -ne $SubscriptionIdsToProcess -and $SubscriptionIdsToProcess.Count -gt 0 -and `
!$SubscriptionIdsToProcess.Contains($sub.Id))
{
continue
}
$s_i += 1
Write-Host "$([Environment]::NewLine)($s_i/$s_count) Subscription '$($sub.Name)' ($($sub.SubscriptionId))..."
Set-AzContext -TenantId $DirectoryId -Subscription $sub.SubscriptionId -WhatIf:$false | Out-Null
$resourceGroups = [hashtable]@{}
foreach ($tagName in $TagNamesToRemove) {
Get-AzResourceGroup | Where-Object { $_.Tags.Keys -icontains $tagName } | ForEach-Object {
$rgName = $_.ResourceGroupName
$resourceGroups.$rgName = $_
}
}
if ($resourceGroups.Count -eq 0) { continue }
Write-Host "$($WhatIfHint)Removing tags from resource groups (subscriptionId / resourceGroupName):"
$r_i = 0; $r_count = $resourceGroups.Keys.Count
foreach ($rgName in $resourceGroups.Keys) {
$r_i += 1
$rg = $resourceGroups[$rgName]
Write-Host "$($tab)$($WhatIfHint)($r_i/$r_count) $($sub.SubscriptionId) / $($rg.ResourceGroupName)..."
$tags = Get-AzTag -ResourceId $rg.ResourceId
if (!$tags.Properties.TagsProperty) { continue }
$tagsToRemove = [hashtable]@{}
foreach ($tagName in $TagNamesToRemove) {
$tagValue = $tags.Properties.TagsProperty[$tagName]
if ($null -ne $tagValue) {
$tagsToRemove.Add($tagName, $tags.Properties.TagsProperty[$tagName]) | Out-Null
}
}
if ($tagsToRemove.Keys.Count -gt 0 -and !$IsWhatIfMode) {
Update-AzTag -ResourceId $rg.ResourceId -Tag $tagsToRemove -Operation Delete -WhatIf:$WhatIfPreference | Out-Null
}
}
}
}
Write-Host "$([Environment]::NewLine)Finished."