I've been trying to tweak and make a basic simple script just a bit more clean and overall to improve it. Basically the initial script was iterating and doing a backup for each secret,certificate and key from each keyvault in a subscription. I am trying to make it better by creating a function and trying to use it as such, unfortunately I'm still missing some thigns and I would like someone to help me sort this out:
function Get-Backup{
[CmdletBinding()]
param (
[Parameter()]
$Item,
[Parameter()]
$VaultName
)
$Items = az keyvault $Item list --vault-name $VaultName | ConvertFrom-Json
foreach ($Item in $Items) {
az keyvault $Item backup --vault-name $VaultName --name $Item.Name --file $Item/$Name.txt
}
}
$Vaults = az keyvault list | ConvertFrom-Json
foreach ($VaultName in $Vaults) {
Get-Backup("secret",$VaultName)
Get-Backup("certificate",$VaultName)
Get-Backup("key",$VaultName)
}
This doesn't work, and I don't understand really what I'm missing or doing wrong. the whole point of this would be to do a script that would automatically pick all the secrets all the keys and all the certificates in a vault, and do this for each vault.
I am trying to compile a function so I could reduce the main code and rely more on functions.
Unfortunatetly I can not post the error as it contains lots of identifiable information of my subscription name resource group etc. Starts with " ERROR: '' is misspelled or not recognized by the system. "
I am looking to do this myself but being stuck for a couple of days, I'd really appreaciate some hints and help.
Could you try solution given here. But please note that here you have
risk of having in-memory variables
Param(
[parameter(mandatory)] [string] $originVault,
[parameter(mandatory)] [string] $originSubscriptionId,
[parameter(mandatory)] [string] $destinationVault,
[parameter(mandatory)] [string] $destinationSubscriptionId,
[string] $disableDestinationSecrets = $true
)
# 1. Set the source subscription id.
Write-Host "Setting origin subscription to: $($originSubscriptionId)..."
az account set -s $originSubscriptionId
# 1.1 Get all secrets
Write-Host "Listing all origin secrets from vault: $($originVault)"
$originSecretKeys = az keyvault secret list --vault-name $originVault -o json --query "[].name" | ConvertFrom-Json
# 1.3 Loop secrets into PSCustomObjects, making it easy to work with later.
$secretObjects = $originSecretKeys | ForEach-Object {
Write-Host " - Getting secret value for '$($_)'"
$secret = az keyvault secret show --name $_ --vault-name $originVault -o json | ConvertFrom-Json
[PSCustomObject]@{
secretName = $_;
secretValue = $secret.value;
}#endcustomobject.
}#endforeach.
Write-Host "Done fetching secrets..."
# 2. Set the destination subscription id.
Write-Host "Setting destination subscription to: $($destinationSubscriptionId)..."
az account set -s $destinationSubscriptionId
# 2.2 Loop secrets objects, and set secrets in destination vault
Write-Host "Writing all destination secrets to vault: $($destinationVault)"
$secretObjects | ForEach-Object {
Write-Host " - Setting secret value for '$($_.secretName)'"
az keyvault secret set --vault-name $destinationVault --name "$($_.secretName)" --value "$($_.secretValue)" --disabled $disableDestinationSecrets -o none
}
# 3. Clean up
Write-Host "Cleaning up and exiting."
Remove-Variable secretObjects
Remove-Variable originSecretKeys
Write-Host "Finished."
or this one which uses powershell instead of azure cli.
$storageAccountTemplateFile = "https://raw.githubusercontent.com/srozemuller/Azure/main/AzureStorageAccount/azuredeploy.json"
$storageAccountTemplateParameters = "https://raw.githubusercontent.com/srozemuller/Azure/main/AzureStorageAccount/azuredeploy.parameters.json"
$backupFolder = "$env:Temp\KeyVaultBackup"
$location = "West Europe"
$backupLocationTag = "BackupLocation"
$backupContainerTag = "BackupContainer"
$global:parameters = @{
resourceGroupName = "RG-PRD-Backups-001"
location = $location
}
function backup-keyVaultItems($keyvaultName) {
#######Parameters
#######Setup backup directory
If ((test-path $backupFolder)) {
Remove-Item $backupFolder -Recurse -Force
}
####### Backup items
New-Item -ItemType Directory -Force -Path "$($backupFolder)\$($keyvaultName)" | Out-Null
Write-Output "Starting backup of KeyVault to a local directory."
###Certificates
$certificates = Get-AzKeyVaultCertificate -VaultName $keyvaultName
foreach ($cert in $certificates) {
Backup-AzKeyVaultCertificate -Name $cert.name -VaultName $keyvaultName -OutputFile "$backupFolder\$keyvaultName\certificate-$($cert.name)" | Out-Null
}
###Secrets
$secrets = Get-AzKeyVaultSecret -VaultName $keyvaultName
foreach ($secret in $secrets) {
#Exclude any secrets automatically generated when creating a cert, as these cannot be backed up
if (! ($certificates.Name -contains $secret.name)) {
Backup-AzKeyVaultSecret -Name $secret.name -VaultName $keyvaultName -OutputFile "$backupFolder\$keyvaultName\secret-$($secret.name)" | Out-Null
}
}
#keys
$keys = Get-AzKeyVaultKey -VaultName $keyvaultName
foreach ($kvkey in $keys) {
#Exclude any keys automatically generated when creating a cert, as these cannot be backed up
if (! ($certificates.Name -contains $kvkey.name)) {
Backup-AzKeyVaultKey -Name $kvkey.name -VaultName $keyvaultName -OutputFile "$backupFolder\$keyvaultName\key-$($kvkey.name)" | Out-Null
}
}
}
$keyvaults = Get-AzKeyVault
if ($keyvaults) {
if ($null -eq (get-AzResourceGroup $global:parameters.resourceGroupName -ErrorAction SilentlyContinue)) {
New-AzResourceGroup @global:parameters
}
if ($null -eq ($keyvaults | ? { $_.Tags.Keys -match $BackupLocationTag })) {
# if no backuplocation tags is available at any of the keyVaults we will create one first
$deployment = New-AzResourceGroupDeployment -ResourceGroupName $global:parameters.resourceGroupName -TemplateUri $storageAccountTemplateFile -TemplateParameterUri $storageAccountTemplateParameters
$backupLocation = $deployment.outputs.Get_Item("storageAccount").value
if ($deployment.ProvisioningState -eq "Succeeded") {
foreach ($keyvault in $keyvaults) {
$containerName = $keyvault.VaultName.Replace("-", $null).ToLower()
if (!(Get-aztag -ResourceId $keyvault.ResourceId | ? { $_.Tags.Keys -match $BackupLocationTag } )) {
Update-AzTag $keyvault.ResourceId -operation Merge -Tag @{BackupLocation = $backupLocation; BackupContainer = $containerName }
}
}
}
}
else {
foreach ($keyvault in $keyvaults) {
$backupLocation = (get-azkeyvault -VaultName $keyvault.vaultname | ? { $_.Tags.Keys -match $BackupLocationTag}).tags.Get_Item($BackupLocationTag)
$storageAccount = get-AzStorageAccount | ? { $_.StorageAccountName -eq $backupLocation }
if ($null -eq (Get-aztag -ResourceId $keyvault.ResourceId | ? { $_.Tags.Keys -match $BackupContainerTag } )) {
$containerName = $keyvault.VaultName.Replace("-", $null).ToLower()
Update-AzTag $keyvault.ResourceId -operation Merge -Tag @{BackupContainer = $containerName }
}
$containerName = (get-azkeyvault -VaultName $keyvault.vaultname | ? { $_.Tags.Keys -match $backupContainerTag }).tags.Get_Item($backupContainerTag)
if ($null -eq (Get-AzStorageContainer -Name $containerName -Context $storageAccount.context)) {
New-AzStorageContainer -Name $containerName -Context $storageAccount.context
}
backup-keyVaultItems -keyvaultName $keyvault.VaultName
foreach ($file in (get-childitem "$($backupFolder)\$($keyvault.VaultName)")) {
Set-AzStorageBlobContent -File $file.FullName -Container $containerName -Blob $file.name -Context $storageAccount.context -Force
}
}
}
}