Files
Cloud-20Engineering/Powershell/Lists/Azure/KeyVaults.ps1
Jurjen Ladenius a226ca97ac added documetation
2025-11-03 08:12:01 +01:00

326 lines
17 KiB
PowerShell
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<#
.SYNOPSIS
Generates a comprehensive inventory of Azure Key Vaults across all management groups and subscriptions.
.DESCRIPTION
This script enumerates all Azure Key Vaults within enabled subscriptions across the entire Azure tenant,
collecting detailed configuration properties, security settings, and governance tags. The results are
exported to a timestamped CSV file for analysis, compliance reporting, and security auditing.
Key capabilities:
- Multi-tenant Key Vault discovery across all management groups
- Configuration analysis including RBAC, purge protection, and soft delete settings
- Governance tag extraction for team ownership and compliance tracking
- Public network access configuration reporting
- Timestamped CSV export for audit trails and trend analysis
.PARAMETER None
This script does not accept parameters and will process all accessible Key Vaults.
.OUTPUTS
CSV File: "<date> azure_key_vaults.csv"
Contains columns for:
- Resource identification (ID, name, resource group, location)
- Management hierarchy (management group, subscription)
- Governance tags (team, product, environment, data classification)
- Security configuration (RBAC, purge protection, soft delete, network access)
.EXAMPLE
.\KeyVaults.ps1
Discovers all Key Vaults and generates: "2024-10-30 1435 azure_key_vaults.csv"
.NOTES
File Name : KeyVaults.ps1
Author : Cloud Engineering Team
Prerequisite : Azure PowerShell module (Az.KeyVault, Az.Resources, Az.Accounts)
Copyright : (c) 2024 Effectory. All rights reserved.
Version History:
1.0 - Initial release with comprehensive Key Vault inventory functionality
.LINK
https://docs.microsoft.com/en-us/azure/key-vault/
https://docs.microsoft.com/en-us/powershell/module/az.keyvault/
.COMPONENT
Requires Azure PowerShell modules:
- Az.KeyVault (for Key Vault enumeration and property retrieval)
- Az.Resources (for resource group and management group access)
- Az.Accounts (for authentication and subscription management)
.ROLE
Required Azure permissions:
- Key Vault Reader or higher on all subscriptions
- Management Group Reader for organizational hierarchy access
.FUNCTIONALITY
- Multi-subscription Key Vault discovery
- Security configuration analysis and reporting
- Governance tag extraction and compliance tracking
- CSV export with comprehensive audit trail
#>
#Requires -Modules Az.KeyVault, Az.Resources, Az.Accounts
#Requires -Version 5.1
[CmdletBinding()]
param()
# Uncomment the following line if authentication is required
#Connect-AzAccount
class ResourceCheck {
[string] $ResourceId = ""
[string] $ManagementGroupId = ""
[string] $ManagementGroupName = ""
[string] $SubscriptionId = ""
[string] $SubscriptionName = ""
[string] $ResourceGroup = ""
[string] $ResourceName = ""
[string] $Location = ""
[string] $Tag_Team = ""
[string] $Tag_Product = ""
[string] $Tag_Environment = ""
[string] $Tag_Data = ""
[string] $Tag_Deployment = ""
[string] $Tag_CreatedOnDate = ""
[string] $Prop_EnablePurgeProtection = ""
[string] $Prop_EnableRbacAuthorization = ""
[string] $Prop_EnableSoftDelete = ""
[string] $Prop_PublicNetworkAccess = ""
}
# Initialize script execution
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
$startTime = Get-Date
Write-Host "======================================================================================================================================================================"
Write-Host "🔐 AZURE KEY VAULT INVENTORY GENERATOR" -ForegroundColor Cyan
Write-Host "======================================================================================================================================================================"
Write-Host "⏰ Started: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Green
Write-Host ""
try {
# Validate Azure authentication
$context = Get-AzContext
if (-not $context) {
throw "No Azure context found. Please run Connect-AzAccount first."
}
Write-Host "🔐 Authenticated as: $($context.Account.Id)" -ForegroundColor Green
Write-Host "🏢 Tenant: $($context.Tenant.Id)" -ForegroundColor Green
Write-Host ""
# Initialize output file
[string] $date = Get-Date -Format "yyyy-MM-dd HHmm"
$fileName = ".\$date azure_key_vaults.csv"
Write-Host "📄 Output file: $fileName" -ForegroundColor Yellow
Write-Host ""
# Get management groups for organizational structure
Write-Host "🏗️ Discovering management group structure..." -ForegroundColor Cyan
$managementGroups = Get-AzManagementGroup
Write-Host "✅ Found $($managementGroups.Count) management groups" -ForegroundColor Green
Write-Host ""
# Initialize counters for progress tracking
$totalKeyVaults = 0
$processedManagementGroups = 0
$processedSubscriptions = 0
$securityIssues = @()
# Process each management group
foreach ($managementGroup in $managementGroups) {
$processedManagementGroups++
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------------------------"
Write-Host "🏗️ Management Group [$($managementGroup.DisplayName)]" -ForegroundColor Cyan
Write-Host " ID: $($managementGroup.Id)" -ForegroundColor DarkGray
try {
# Get active subscriptions in this management group
$subscriptions = Get-AzManagementGroupSubscription -Group $managementGroup.Name | Where-Object State -eq "Active"
Write-Host " 📋 Found $($subscriptions.Count) active subscriptions" -ForegroundColor Green
foreach ($subscription in $subscriptions) {
$processedSubscriptions++
Write-Host ""
Write-Host " 🔄 Processing Subscription: $($subscription.DisplayName)" -ForegroundColor Yellow
try {
# Extract subscription ID and set context
$scope = $subscription.Id.Substring($subscription.Parent.Length, $subscription.Id.Length - $subscription.Parent.Length)
$subscriptionId = $scope.Replace("/subscriptions/", "")
Write-Host " ID: $subscriptionId" -ForegroundColor DarkGray
Set-AzContext -SubscriptionId $subscriptionId | Out-Null
# Get all resource groups in the subscription
$allResourceGroups = Get-AzResourceGroup
[ResourceCheck[]]$Result = @()
$subscriptionKeyVaults = 0
foreach ($group in $allResourceGroups) {
Write-Host " 📁 Resource Group: $($group.ResourceGroupName)" -ForegroundColor DarkCyan -NoNewline
try {
# Get Key Vaults in this resource group
$allVaults = Get-AzKeyVault -ResourceGroupName $group.ResourceGroupName -ErrorAction SilentlyContinue
if ($allVaults.Count -gt 0) {
Write-Host " - Found $($allVaults.Count) Key Vaults" -ForegroundColor Green
$subscriptionKeyVaults += $allVaults.Count
} else {
Write-Host " - No Key Vaults" -ForegroundColor DarkGray
}
foreach ($vault in $allVaults) {
try {
# Get detailed Key Vault properties
$vaultWithAllProps = Get-AzKeyVault -ResourceGroupName $group.ResourceGroupName -Name $vault.VaultName
# Analyze security configuration
$enabledRBAC = $vaultWithAllProps.EnableRbacAuthorization -eq "TRUE"
# Check for security concerns
if (-not $vaultWithAllProps.EnablePurgeProtection) {
$securityIssues += "⚠️ Purge protection disabled: $($vaultWithAllProps.VaultName) in $($group.ResourceGroupName)"
}
if (-not $vaultWithAllProps.EnableSoftDelete) {
$securityIssues += "⚠️ Soft delete disabled: $($vaultWithAllProps.VaultName) in $($group.ResourceGroupName)"
}
if ($vaultWithAllProps.PublicNetworkAccess -eq "Enabled") {
$securityIssues += "🌐 Public network access enabled: $($vaultWithAllProps.VaultName) in $($group.ResourceGroupName)"
}
# Create resource check object
[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
$totalKeyVaults++
} catch {
Write-Host " ❌ Error processing vault $($vault.VaultName): $($_.Exception.Message)" -ForegroundColor Red
}
}
} catch {
Write-Host " - ❌ Error accessing resource group: $($_.Exception.Message)" -ForegroundColor Red
}
}
# Export results for this subscription
if ($Result.Count -gt 0) {
$Result | Export-Csv -Path $fileName -Append -NoTypeInformation
Write-Host " ✅ Exported $($Result.Count) Key Vaults from subscription" -ForegroundColor Green
} else {
Write-Host " No Key Vaults found in subscription" -ForegroundColor DarkYellow
}
} catch {
Write-Host " ❌ Error processing subscription: $($_.Exception.Message)" -ForegroundColor Red
}
}
} catch {
Write-Host " ❌ Error accessing management group: $($_.Exception.Message)" -ForegroundColor Red
}
Write-Host ""
}
# Calculate execution time and generate summary report
$endTime = Get-Date
$executionTime = $endTime - $startTime
Write-Host "======================================================================================================================================================================"
Write-Host "📊 AZURE KEY VAULT INVENTORY SUMMARY" -ForegroundColor Cyan
Write-Host "======================================================================================================================================================================"
Write-Host "⏰ Execution Time: $($executionTime.ToString('hh\:mm\:ss'))" -ForegroundColor Green
Write-Host "🏗️ Management Groups Processed: $processedManagementGroups" -ForegroundColor Green
Write-Host "📋 Subscriptions Processed: $processedSubscriptions" -ForegroundColor Green
Write-Host "🔐 Total Key Vaults Discovered: $totalKeyVaults" -ForegroundColor Green
Write-Host "📄 Results Exported To: $fileName" -ForegroundColor Yellow
if (Test-Path $fileName) {
$fileSize = (Get-Item $fileName).Length
Write-Host "💾 File Size: $([math]::Round($fileSize/1KB, 2)) KB" -ForegroundColor Green
}
# Display security analysis summary
if ($securityIssues.Count -gt 0) {
Write-Host ""
Write-Host "🚨 SECURITY ANALYSIS SUMMARY" -ForegroundColor Red
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------------------------"
Write-Host "Found $($securityIssues.Count) potential security concerns:" -ForegroundColor Yellow
foreach ($issue in $securityIssues | Select-Object -First 10) {
Write-Host " $issue" -ForegroundColor Yellow
}
if ($securityIssues.Count -gt 10) {
Write-Host " ... and $($securityIssues.Count - 10) more issues (see CSV for complete details)" -ForegroundColor DarkYellow
}
Write-Host ""
Write-Host "📋 Recommendations:" -ForegroundColor Cyan
Write-Host " • Enable purge protection on production Key Vaults" -ForegroundColor White
Write-Host " • Ensure soft delete is enabled for data recovery capabilities" -ForegroundColor White
Write-Host " • Consider disabling public network access where possible" -ForegroundColor White
Write-Host " • Implement RBAC authorization for enhanced security" -ForegroundColor White
} else {
Write-Host ""
Write-Host "✅ SECURITY ANALYSIS: No major security concerns detected" -ForegroundColor Green
}
Write-Host ""
Write-Host "📈 NEXT STEPS:" -ForegroundColor Cyan
Write-Host " 1. Review the generated CSV file for detailed Key Vault configurations" -ForegroundColor White
Write-Host " 2. Analyze governance tags for compliance with organizational standards" -ForegroundColor White
Write-Host " 3. Address any security recommendations identified above" -ForegroundColor White
Write-Host " 4. Consider implementing automated monitoring for Key Vault configurations" -ForegroundColor White
Write-Host ""
Write-Host "✅ Azure Key Vault inventory completed successfully!" -ForegroundColor Green
Write-Host "======================================================================================================================================================================"
} catch {
Write-Host ""
Write-Host "❌ CRITICAL ERROR OCCURRED" -ForegroundColor Red
Write-Host "======================================================================================================================================================================"
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
Write-Host "Line: $($_.InvocationInfo.ScriptLineNumber)" -ForegroundColor Red
Write-Host "Position: $($_.InvocationInfo.OffsetInLine)" -ForegroundColor Red
Write-Host ""
Write-Host "🔧 TROUBLESHOOTING STEPS:" -ForegroundColor Yellow
Write-Host " 1. Verify you are authenticated to Azure (Connect-AzAccount)" -ForegroundColor White
Write-Host " 2. Ensure you have Key Vault Reader permissions on target subscriptions" -ForegroundColor White
Write-Host " 3. Check that the Management Group Reader role is assigned" -ForegroundColor White
Write-Host " 4. Verify Azure PowerShell modules are installed and up to date" -ForegroundColor White
Write-Host " 5. Try running the script with -Verbose for additional diagnostic information" -ForegroundColor White
Write-Host ""
Write-Host "📞 For additional support, contact the Cloud Engineering team" -ForegroundColor Cyan
Write-Host "======================================================================================================================================================================"
# Ensure we exit with error code for automation scenarios
exit 1
} finally {
# Reset progress preference
$ProgressPreference = "Continue"
}