After my previous article on the basic Powershell cmdlets for Azure Key Vault, I thought it would be interesting to provide to all users, who are already familiar with it, a method to export all keys, certs, and secrets stored in it once via Powershell.
Understanding Azure Key Vault Service
One of the prerequisites for getting the most out of this script is understanding or reading carefully Azure Key Vault official documentation first.
It seems obvious, but there are “details” like Identity and Access Management (IAM) and access policies which determine the scope and access your user has to the object (secret, key, certificate) in the Key Vault you want to access/backup. Important features of Azure Key Vault Service that my script solution cannot replace are soft-delete, retention period, and purge protection.
Why Backing-up an Azure Key Vault?
Why not?! Seriously. If you care about your data, it’s your responsibility and choice to decide if you need to export it or not.
Depending on your use of Azure Key Vault and how you want to follow the recommendations/best practices of the vendor is common to have multiple Azure Key Vaults for different reasons like isolating apps, projects, departments, environments, locations, etc… just to name a few.
I can guarantee that even if you don’t need it right now or in the near future, understanding how to do it can be useful.
How to backup objects from the Vault with AZ CLI
The official documentation shows how to use AZ CLI to backup a single object from Key Vault:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
## Log in to Azure az login ## Set your subscription az account set --subscription {AZURE SUBSCRIPTION ID} ## Register Key Vault as a provider az provider register -n Microsoft.KeyVault ## Back up a certificate in Key Vault az keyvault certificate backup --file {File Path} --name {Certificate Name} --vault-name {Key Vault Name} --subscription {SUBSCRIPTION ID} ## Back up a key in Key Vault az keyvault key backup --file {File Path} --name {Key Name} --vault-name {Key Vault Name} --subscription {SUBSCRIPTION ID} ## Back up a secret in Key Vault az keyvault secret backup --file {File Path} --name {Secret Name} --vault-name {Key Vault Name} --subscription {SUBSCRIPTION ID} ## Restore a certificate in Key Vault az keyvault certificate restore --file {File Path} --vault-name {Key Vault Name} --subscription {SUBSCRIPTION ID} ## Restore a key in Key Vault az keyvault key restore --file {File Path} --vault-name {Key Vault Name} --subscription {SUBSCRIPTION ID} ## Restore a secret in Key Vault az keyvault secret restore --file {File Path} --vault-name {Key Vault Name} --subscription {SUBSCRIPTION ID} |
I like Azure CLI, but the documentation was also including an example with Powershell, so I’ve written my own script/solution to do what I need.
Backup-MyKeyVault Powershell script
This is my script which I wrote and stored on my cloud shell (https://shell.azure.com) so whenever I need to export it I can simply run the script and download it from the browser.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
#Paolo Frigo, https://scriptinglibrary.com Function Backup-MyKeyVault { <# .SYNOPSIS Backup Azure Key Vault keys, certs and secrets .DESCRIPTION This funciton creates a ZIP archive containing all keys, secrets and certificates stored in your Azure Key Vault. .PARAMETER VaultName thi parameter is required to specify which Vault Name you want to backup .EXAMPLE Backup-MyKeyVault -KeyVault "mykeyvaultname1", "mykeyvaultname2" Specify one or more Azure Key Voults to backup .EXAMPLE get-azkeyvault | Backup-MyKeyVault Oneliner to enumerate all Azure Key Vault and create individual archive for each one. #> [CmdletBinding()] param ( [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName =$true)] [string[]] $VaultName ) process { foreach ($MyVaultName in $VaultName) { if (($(Get-AzKeyVaultKey $MyVaultName).count + $(Get-AzKeyVaultSecret $MyVaultName).count ) -gt 0) { #Creates temporary folders New-Item -ItemType Directory "$($MyVaultName)" | Out-Null Set-Location $MyVaultName New-Item -ItemType Directory -name "Certs" | Out-Null New-Item -ItemType Directory -name "Secrets" | Out-Null New-Item -ItemType Directory -name "Keys" | Out-Null #Stats counters $CertCounter=0 $KeyCounter=0 $SecretCounter=0 Foreach ($item in $(Get-AzKeyVaultSecret -VaultName $MyVaultName)){ if ($item.ContentType -eq "application/x-pkcs12"){ $cert = Get-AzureKeyVaultCertificate -VaultName $MyVaultName -Name "$(($item).name)" Backup-AzureKeyVaultCertificate -Certificate $cert -OutputFile "Certs\\$(($item).name).blob" -Force | Out-Null $CertCounter+=1 } else{ Backup-AzureKeyVaultSecret -VaultName $MyVaultName -Name $($item).name -OutputFile "Secrets\\$(($item).name).blob" | Out-Null $SecretCounter+=1 } } Foreach ($keyitem in $(Get-AzKeyVaultKey -VaultName $MyVaultName)){ try{ Backup-AzKeyVaultKey -VaultName $MyVaultName -Name $($keyitem.name) -Output "Keys\\$($keyitem.name).blob" -ErrorAction SilentlyContinue |Out-Null $KeyCounter+=1 } catch { Write-Error "$($keyitem.name) was not exported" } } Set-Location .. $datetime = Get-Date -format "yyyyMMdd-hhmmss" $Filename = "$($MyVaultName)-$($datetime).zip" Compress-Archive -Path "$($MyVaultName)/*" -DestinationPath "$Filename" Remove-Item -Recurse -Force $MyVaultName Write-output "EXPORTED from `"$MyVaultName`" to `"$Filename`": `n $KeyCounter keys `n $CertCounter certificates `n $SecretCounter secrets " } else{ Write-Output "NO ACTION for $($MyVaultName): `nThere are no Keys,Certificates or Secrets to backup!" } } } } #Backup all Azure Key Vaults get-azkeyvault | Backup-MyKeyVault |
I upload this script on my cloud shell
And download the ZIP files which has a folder structure to properly organise:
- Secrets
- Key
- Certificates
Additional Notes
Please note that each Azure Key Vault will be saved with this naming convention “KEYVAULTNAME-DATE-TIME.ZIP”.
If the Key Vault is empty, in other words, there are no keys, certificates, or secrets, there will be no zip archive generated.
Wrap-Up
As with many other scripts, this one was something I quickly wrote for pure necessity having to deal with different projects, and sometimes these projects or PoC were designed to be short-lived.
I hope you will find it useful and, as usual, you can find it on my GitHub repository.
What is line 72 doing?
I can’t see why that deletion is required?
Remove-Item -Recurse -Force ./azkeyvscriptinglib14521
Hi Stefan,
Thanks for your comment. What you have found at line 72 is an error. At the beginning of the script few folders are created and at line 72 there is the housekeeping of removing all created files and folders. I fixed that line now, please have a look now, and should make more sense to you.
Regards
Hi Paolo,
That makes sense. Thanks for the clarification! 😀