How do I copy over all secrets from one Azure Keyvault to another using Powershell
Solution 1
this is just too triggering (no offense), here's a more "powershelly" version:
Param(
[Parameter(Mandatory)]
[string]$sourceVaultName,
[Parameter(Mandatory)]
[string]$destVaultName
)
Connect-AzAccount
$secretNames = (Get-AzKeyVaultSecret -VaultName $sourceVaultName).Name
$secretNames.foreach{
Set-AzKeyVaultSecret -VaultName $destVaultName -Name $_ `
-SecretValue (Get-AzKeyVaultSecret -VaultName $sourceVaultName -Name $_).SecretValue
}
Just to sum it up:
Parameters are mandatory with this change and you can tab complete them, so you dont have to remember which one is first.
Using foreach
is a bit cleaner than using do\while
(certainly less cognitive effort).
You dont have to cast values to text and encrypt it back, you can just use encrypted value to assign it to new secret
Solution 2
There is now!
import-module AzureRM.keyvault
$sourceVaultName = $args[0]
$destVaultName = $args[1]
Connect-AzureRmAccount
#unfortunately you can only access secret values one at a time, by name. so this gets the names first
$names = (Get-AzureKeyVaultSecret -VaultName $sourceVaultName | select Name)
$i=0
do {
$rawSecret = (Get-AzureKeyVaultSecret -VaultName $sourceVaultName -Name $names[$i].Name).SecretValueText
$AKVsecret = ConvertTo-SecureString $rawSecret -AsPlainText -Force
Set-AzureKeyVaultSecret -VaultName $destVaultName -Name $names[$i].Name -SecretValue $AKVsecret
$i++
} while($i -lt $names.length)
You can call it using
script.ps1 source-keyvault-name dest-keyvault-name
Solution 3
The script can be translated to the new coolness of az.cli
Param(
[Parameter(Mandatory)]
[string]$sourceVaultName,
[Parameter(Mandatory=$false)]
[string]$sourceSubscription,
[Parameter(Mandatory)]
[string]$destVaultName,
[Parameter(Mandatory=$false)]
[string]$descriptionSubscription
)
# az login
if($sourceSubscription){
az account set --subscription $sourceSubscription
}
Write-Host 'Reading secrets ids from' $sourceVaultName
$secretNames = az keyvault secret list --vault-name $sourceVaultName -o json --query "[].name" | ConvertFrom-Json
Write-Host 'Reading secrets values'
$secrets = $secretNames | % {
$secret = az keyvault secret show --name $_ --vault-name $sourceVaultName -o json | ConvertFrom-Json
[PSCustomObject]@{
name = $_;
value = $secret.value;
}
}
Write-Host 'writing secrets'
if($descriptionSubscription){
az account set --subscription $descriptionSubscription
}
$secrets.foreach{
az keyvault secret set --vault-name $destVaultName --name $_.name --value $_.value
}
Solution 4
This is for those who came here looking for a python solution:
from azure.keyvault.secrets import SecretClient # pip install azure-keyvault-secrets
from azure.identity import DefaultAzureCredential # pip install azure-identity
source_vault_url = "https://sourcevault.vault.azure.net"
destination_vault_url = "https://destvault.vault.azure.net/"
credential = DefaultAzureCredential(
exclude_cli_credential=False
, exclude_environment_credential=True
, exclude_managed_identity_credential=True
, exclude_visual_studio_code_credential=True
, exclude_shared_token_cache_credential=True
, exclude_interactive_browser_credential=True
)
source_client = SecretClient(vault_url=source_vault_url, credential=credential)
destination_client = SecretClient(vault_url=destination_vault_url, credential=credential)
key_list = ['key1', 'key2', 'key3']
# Get secrets from the source key vault
credentials = {}
for key in key_list :
credentials[key] = source_client.get_secret(key).value
# Set secrets in the destination key vault
for key, value in credentials.items():
print(f"Creating a secret called '{key}' with the value '{value}' ...")
destination_client.set_secret(key, value)
Solution 5
I wrote a set of powershell scripts to clone key vaults from one subscription to another. Hope it make some help.
Related videos on Youtube
Tom Warner
I like writing code and being outside. StackOverflow is great because that's where I learned how to code, and now people even pay me for it.
Updated on June 04, 2022Comments
-
Tom Warner almost 2 years
We recently found ourselves needing to copy over every single secret (name and value) from one Azure KeyVault to a newly created one. I found ways to restore the secrets from a backup, but we didn't have a backup. Is there a Powershell script that can just loop through every name/value combo in a source vault and copy it to a destination vault?
-
Tom Warner about 5 yearscool that looks way neater--i don't write a lot of powershell (if you couldn't tell) so thanks for cleaning it up!
-
Sartigan about 3 yearsCorrect me if I'm wrong, but aren't you just copying all secrets from a keyvault and rewriting them in the very same keyvault?
-
HSharma about 3 years@Sartigan No, I am making this dynamic so you can specify name of the new key vault and the script will copy it there
-
Zizzipupp almost 3 yearsTypeError: 'NoneType' object is not subscriptable
-
cody.codes almost 3 yearsScript works well for me. Ensure that you fill out the
key_list
list with the keys you'd like to transfer. Also a good note is that this is for two key vaults within the same Azure subscription! -
GavinB almost 3 yearsThis DOES not work, it fails silently as the name is not exported. The fix is reasonably simple though ``` $secretNames = az keyvault secret list --vault-name $sourceVaultName -o json --query "[].id" | ConvertFrom-Json | ForEach-Object { $_.Substring($_.LastIndexOf('/') +1 ) }