To check key vaults for soft delete and purge protection, query each vault's settings in Azure Resource Graph, which lists every vault in the subscriptions you can read. Soft delete is on by default and cannot be turned off once on, but purge protection is optional and stays off until someone turns it on. Resource Graph can lag a recent change, so confirm a vault in Azure before you act on a result.
| Method | Best fit |
|---|---|
| PowerShell | A repeatable, sortable CSV of every vault across selected subscriptions. |
| Admin centre | A quick review in Azure Resource Graph Explorer, or a look at 1 vault, without installing tools. |
| Altivane | Recommended for recurring reviews across readable subscriptions, with the weak points of each vault in a workbook. |
Before you start
Use an Azure account with read access to the subscriptions you want to check. The built-in Reader role is enough, assigned at the subscription or a parent scope. It reads the settings of every Azure resource and gives no access to the secrets, keys or certificates inside a vault. The PowerShell example uses Az.Accounts and Az.ResourceGraph, and no separate product licence is needed.
Soft delete keeps a deleted vault or vault item recoverable for 7 to 90 days, a period set when the vault is created. Purge protection stops anyone purging a deleted vault or item until that period ends, and once enabled it cannot be turned off. The query treats soft delete as on unless Azure says it is off. It covers key vaults, not Managed HSM pools, which are a separate resource type. The script reads Azure and exports a CSV without changing anything. Its finally block disconnects the account and clears its local Azure contexts, so you may need to sign in again.
Option 1
Check key vault soft delete and purge protection with PowerShell
Install the modules once and connect to Azure. The query reads each vault's soft delete, purge protection and retention, and the script writes 1 row per vault with the weakest vaults first.
Install-Module -Name Az.Accounts, Az.ResourceGraph -Repository PSGallery -Scope CurrentUser$ErrorActionPreference = 'Stop'
Connect-AzAccount -ErrorAction Stop
try {
$subscriptionIds = @(
Get-AzSubscription |
Where-Object State -eq 'Enabled' |
Select-Object -ExpandProperty Id
)
if ($subscriptionIds.Count -eq 0) {
Write-Output 'No enabled subscriptions are available to this account.'
return
}
$query = @(
'Resources'
'| where type =~ "microsoft.keyvault/vaults"'
'| extend softDelete = coalesce(tobool(properties.enableSoftDelete), true)'
'| extend purgeProtection = coalesce(tobool(properties.enablePurgeProtection), false)'
'| extend retentionDays = toint(properties.softDeleteRetentionInDays)'
'| project id, name, subscriptionId, resourceGroup, location,'
' softDelete, purgeProtection, retentionDays'
'| order by purgeProtection asc, softDelete asc, id asc'
) -join ' '
function Get-AzGraphRows {
param([string]$Query, [string[]]$SubscriptionIds)
$results = [System.Collections.Generic.List[object]]::new()
$skipToken = $null
do {
$arguments = @{
Query = $Query
Subscription = $SubscriptionIds
First = 1000
}
if ($skipToken) { $arguments.SkipToken = $skipToken }
$page = Search-AzGraph @arguments
foreach ($record in $page.Data) { $results.Add($record) }
$skipToken = $page.SkipToken
} while ($skipToken)
return $results.ToArray()
}
$rows = @(Get-AzGraphRows -Query $query -SubscriptionIds $subscriptionIds)
if ($rows.Count -eq 0) {
Write-Output 'No key vaults were found in the readable subscriptions.'
} else {
$rows |
Select-Object name, subscriptionId, resourceGroup, location, softDelete,
purgeProtection, retentionDays, id |
Export-Csv -Path './key-vault-protection.csv' -NoTypeInformation -Encoding utf8
$weak = @($rows | Where-Object { -not $_.purgeProtection -or -not $_.softDelete })
Write-Output "$($rows.Count) key vaults saved to key-vault-protection.csv."
Write-Output "$($weak.Count) vaults lack purge protection or soft delete."
}
} finally {
Disconnect-AzAccount | Out-Null
}The export has each vault's name, subscription ID, resource group, location, soft delete, purge protection, retention in days and resource ID. Retention is empty when Azure returns no value. An empty result writes a message, not an empty CSV.
To narrow the search, keep only the subscription IDs you want in $subscriptionIds. To list only the weak vaults, add | where purgeProtection == false or softDelete == false after the extend lines. Keep id in the output, because Azure's continuation token needs it.
Option 2
Review key vault protection in Azure Resource Graph Explorer
- Sign in to the Azure portal with read access to the subscriptions.
- Search for resource graph > choose Resource Graph Explorer.
- To change its scope, choose Directory, then choose the directory, management group or subscription to query.
- Paste this query in Query 1 and choose Run query:
Resources | where type =~ 'microsoft.keyvault/vaults' | extend softDelete = coalesce(tobool(properties.enableSoftDelete), true) | extend purgeProtection = coalesce(tobool(properties.enablePurgeProtection), false) | extend retentionDays = toint(properties.softDeleteRetentionInDays) | project id, name, subscriptionId, resourceGroup, location, softDelete, purgeProtection, retentionDays | order by purgeProtection asc, softDelete asc, id asc - Review the vaults in Results. Vaults with purge protection off come first.
- To check 1 vault directly, search for Key vaults, choose the vault, then choose Properties and read its soft delete and purge protection settings.
Explorer suits an occasional review or a check of 1 vault. Use PowerShell when you need a repeatable CSV across several subscriptions.
Option 3 ยท Recommended for recurring reviews
Check key vault protection with Altivane
- Open Altivane and choose the tenant.
- Run the Azure Key Vaults report.
- Open the Excel workbook and read the Azure key vaults table, where each vault has its soft delete, purge protection and retention in days.
- Read the findings column for what is weak in each vault.
Altivane reads every subscription the connected account can read in 1 run and writes an Excel workbook to keep. The findings name what is weak, such as no purge protection, soft delete off, open to every network, or access policies in place of Azure roles, and the table also shows each vault's permission model and public network access. If the account can read no subscription, the table is empty and says how to give Altivane its Azure role.
Contact usCommon questions
Can I turn purge protection off again?
No. Once purge protection is on, nobody can disable it, including Microsoft, so a deleted vault's name cannot be reused until the vault is recovered or its retention period ends. Soft delete is the same: once on, it stays on.
Why does a vault show soft delete on but purge protection off?
A new vault has soft delete on by default, but purge protection is optional and off unless someone enables it. Microsoft recommends it when keys encrypt data, and most Azure services that use Key Vault, such as Storage, require it.
What else should I review in these subscriptions?
For addresses nothing uses, see how to find unused public IP addresses in Azure, which needs the same read access.
Microsoft references
Technical references checked on 7 October 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.
- Azure Key Vault soft-delete overview
- Azure Key Vault recovery management with soft delete and purge protection
- Microsoft.KeyVault vaults resource reference
- Run a Resource Graph query using Azure PowerShell
- Connect-AzAccount cmdlet reference
- Get-AzSubscription cmdlet reference
- Disconnect-AzAccount cmdlet reference
- Search-AzGraph cmdlet reference
- Run a Resource Graph query in the Azure portal
- Azure Resource Graph overview
- Azure Resource Graph table and resource type reference
- Azure built-in roles: Reader