How do I copy over all secrets from one Azure Keyvault to another using Powershell

16,652

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.

Share:
16,652

Related videos on Youtube

Tom Warner
Author by

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, 2022

Comments

  • Tom Warner
    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
    Tom Warner about 5 years
    cool that looks way neater--i don't write a lot of powershell (if you couldn't tell) so thanks for cleaning it up!
  • Sartigan
    Sartigan about 3 years
    Correct 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
    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
    Zizzipupp almost 3 years
    TypeError: 'NoneType' object is not subscriptable
  • cody.codes
    cody.codes almost 3 years
    Script 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
    GavinB almost 3 years
    This 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 ) }