How Do I Copy Azure Key Vault Secrets to Another Key Vault?

Short answer

Azure Key Vault has no built-in operation that copies a vault, or even a batch of secrets, into another vault. You have two routes. Backup and restore works one secret at a time, keeps every version, and only works within the same Azure subscription and geography. Reading each secret and writing it to the destination with the CLI, PowerShell, or an SDK works across subscriptions and tenants, but you have to carry the metadata across yourself, and the values pass through whatever machine runs the script. For a new environment or customer, most teams end up scripting the second route or using a tool that does it for them.

Why would you need to copy secrets between Key Vaults?

Any time a new vault has to start out with the same secrets as an existing one. The usual reasons:

  • Creating a new staging or production environment
  • Deploying the application for a new customer
  • Creating a new franchise location
  • Deploying to a new Azure region
  • Creating a new single-tenant application instance
  • Moving an application to a different subscription
  • Splitting one overloaded vault into several
  • Standing up a disaster recovery copy

A new environment can need dozens of secrets before the application will start. Recreating them by hand is slow, and the failure is easy to miss: one mistyped or forgotten secret and the app either fails at startup or runs against the wrong resource.

Does Azure Key Vault support cloning an entire vault?

No. There's no native operation that creates a vault with the same secrets as another one. Microsoft provides backup and restore for individual objects (secrets, keys, and certificates), and a backup covers one object at a time, not a whole vault. That's useful for recovery and some migrations, but it isn't the same as saying:

"Create a new Key Vault with the same secrets as this one."

That leaves the two routes from the short answer, and they behave quite differently:

Backup and restore Read and write
Scope One secret per operation One secret per operation (you script the loop)
Versions All versions come along Current value only; the destination starts at version one
Tags, content type, expiry Carried over with the secret Only what you copy explicitly
Across subscriptions No, same subscription only Yes
Across geographies No, same geography only Yes
Name already exists in destination Restore fails Creates a new version unless you check first
Where the value travels Stays in Azure as an encrypted blob Passes through the machine running the script

Can I use Azure CLI to copy secrets?

Yes. Copying one secret takes two commands:

value=$(az keyvault secret show --vault-name myapp-customera-prod \
  --name Stripe--SecretKey --query value -o tsv)

az keyvault secret set --vault-name myapp-customerb-prod \
  --name Stripe--SecretKey --value "$value"

That copies the value and nothing else. Wrapping it in a loop over az keyvault secret list is the usual next step, and it's where the trouble starts:

  • Metadata gets dropped. Tags, content type, activation and expiry dates, and the enabled flag only travel if you read them and pass them to set yourself.
  • Values land on the command line. Arguments can show up in process listings, shell history, and pipeline logs. Fine for a one-off, not for a script you'll run for every customer.
  • Re-running creates duplicates. Setting a secret that already exists adds a new version rather than skipping it.
  • Soft-deleted names block you. If the destination once held a secret with that name and it's still in the deleted-but-recoverable state, the write fails with a 409 conflict.
  • Certificates come across as plain secrets. Every certificate has a secret behind it, and it shows up in the secrets list. Copying it gives you a secret, not a certificate you can renew or manage.
  • Only the current version moves. The destination has no history, which is usually what you want for a new environment.

Once you're past a handful of secrets, an SDK is a better tool than a shell loop, since values stay in memory and you can handle each of those cases in code. There's a full example in the section on sensitive values below.

What about backing up and restoring secrets?

A backup is an encrypted copy of one Key Vault object, including all of its versions, and a restore puts it into another vault:

az keyvault secret backup --vault-name myapp-customera-prod \
  --name Stripe--SecretKey --file stripe.backup

az keyvault secret restore --vault-name myapp-customerb-prod --file stripe.backup

Several constraints matter here:

  • Same subscription and geography. The backup blob can't be decrypted outside Azure, so Microsoft's documentation says it has to be restored into a vault in the same subscription and geography, for example North America.
  • Restore won't overwrite. If the destination already has a secret with that name, the restore fails.
  • Every version is restored. That's what you want for disaster recovery. For a new customer environment it isn't, because you'd be copying the full history of another environment's credentials into the new vault.
  • It needs elevated rights. The prerequisites in Microsoft's documentation list Contributor-level permissions or higher on the subscription.
  • Backup files are sensitive. A restored copy is independent of the original, and there's no way to revoke a backup blob or a copy that's already been restored. Store the files like the secrets themselves and delete them when you're done.

Backup and restore is a good fit for disaster recovery and for moving a secret, history included, to another vault in the same subscription and geography. For seeding a new environment it's a poor fit: it carries old versions, it can't cross subscriptions, and it's one secret per command.

What is the difference between copying and cloning?

The difference matters for deployment teams.

Copying a secret means recreating one secret in another Key Vault.

Cloning a Key Vault means using an existing vault as a template for a new environment and reproducing the appropriate set of secrets, with the right values for the new home.

Existing customer environment
        │
        ▼
Customer A Production Key Vault
        │
        │ Clone
        ▼
Customer B Production Key Vault

Copying is a mechanical operation. Cloning has decisions in it, and that's where most of the work is.

Why is cloning useful for single-tenant SaaS?

Say every customer gets an isolated deployment: an App Service, a database, storage, application configuration, and a Key Vault. The vault might hold a database connection string, storage credentials, third-party API credentials, application secrets, encryption settings, and integration credentials.

When customer #2 is onboarded, nobody wants to retype every secret from customer #1. The better starting point is a known-good vault structure where the customer-specific values get swapped out. That turns vault provisioning from a checklist someone works through by hand into a repeatable step in the deployment. It also leaves you with a vault per customer, which is its own problem the first time someone asks where a particular secret lives.

What about franchise or regional deployments?

The same pattern applies outside SaaS. A company deploying one application to 100 franchise locations ends up with:

Location 001 Key Vault
Location 002 Key Vault
Location 003 Key Vault
...
Location 100 Key Vault

The secret names are mostly identical and the values mostly differ. A standard template, used as the starting point for each new location, is the only approach that stays manageable at that count.

How should sensitive values be handled when cloning?

Not every secret in the source should end up in the destination. A useful cloning process sorts secrets into three groups: ones that can be copied, ones that must be replaced, and ones that should be generated fresh. For example:

Database--ConnectionString       → Replace
Stripe--SecretKey                → Replace
SendGrid--ApiKey                 → Replace
Application--SigningKey          → Generate
Feature--DefaultConfiguration    → Copy

As a rule of thumb, anything tied to a specific customer, environment, or external account gets replaced. Anything that should be unique per environment, like signing keys and internal API keys, gets generated. What's left is usually configuration and can be copied. The exact split depends on your application.

Direction matters too. Cloning production into development carries production credentials into an environment with weaker controls. It's safer to clone from a template vault, one whose structure is right and whose values are safe, than from a live production vault.

Here's an SDK version in C# that follows those rules. It preserves tags, content type, and dates for copied secrets, skips secrets that already exist, skips the ones behind certificates, and reports failures:

using Azure;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using System.Security.Cryptography;

var credential = new DefaultAzureCredential();
var source = new SecretClient(new Uri("https://myapp-template-prod.vault.azure.net/"), credential);
var dest   = new SecretClient(new Uri("https://myapp-customerb-prod.vault.azure.net/"), credential);

// Anything not listed here is copied as-is.
var rules = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
    ["Database--ConnectionString"] = "replace",
    ["Stripe--SecretKey"]          = "replace",
    ["SendGrid--ApiKey"]           = "replace",
    ["Application--SigningKey"]    = "generate",
};

var existing = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
await foreach (var p in dest.GetPropertiesOfSecretsAsync())
{
    existing.Add(p.Name);
}

await foreach (var props in source.GetPropertiesOfSecretsAsync())
{
    if (props.Managed)
    {
        Console.WriteLine($"SKIP     {props.Name} (backs a certificate)");
        continue;
    }

    if (existing.Contains(props.Name))
    {
        Console.WriteLine($"SKIP     {props.Name} (already in destination)");
        continue;
    }

    var rule = rules.GetValueOrDefault(props.Name, "copy");

    var value = rule switch
    {
        "copy"     => await ReadValueAsync(props.Name),
        "generate" => Convert.ToBase64String(RandomNumberGenerator.GetBytes(32)),
        _          => "REPLACE-ME"
    };

    var secret = new KeyVaultSecret(props.Name, value);
    secret.Properties.ContentType = props.ContentType;

    foreach (var tag in props.Tags)
    {
        secret.Properties.Tags[tag.Key] = tag.Value;
    }

    if (rule == "copy")
    {
        secret.Properties.ExpiresOn = props.ExpiresOn;
        secret.Properties.NotBefore = props.NotBefore;
        secret.Properties.Enabled = props.Enabled;
    }
    else if (rule == "replace")
    {
        // Placeholder stays disabled so nothing can read it by accident.
        secret.Properties.Enabled = false;
        secret.Properties.Tags["needs_value"] = "true";
    }

    try
    {
        await dest.SetSecretAsync(secret);
        Console.WriteLine($"{rule.ToUpperInvariant(),-8} {props.Name}");
    }
    catch (RequestFailedException ex) when (ex.Status == 409)
    {
        Console.Error.WriteLine($"CONFLICT {props.Name}: probably soft-deleted in the destination");
    }
    catch (RequestFailedException ex)
    {
        Console.Error.WriteLine($"FAILED   {props.Name}: HTTP {ex.Status}");
    }
}

async Task<string> ReadValueAsync(string name)
{
    KeyVaultSecret secret = await source.GetSecretAsync(name);
    return secret.Value;
}

A few choices in there are deliberate. Secrets marked "replace" are created disabled, with a placeholder value and a needs_value tag. The name exists, so the new vault has the right shape, but an application that tries to read one fails loudly instead of running on a fake value. You can also list what's left to fill in with az keyvault secret list --vault-name myapp-customerb-prod --query "[?tags.needs_value=='true'].name". Expiry dates aren't copied for replaced or generated secrets, since they described the source credential.

The identity running this needs to read secrets in the source (Key Vault Secrets User on an RBAC vault) and write them in the destination (Key Vault Secrets Officer). Reads show up in the source vault's audit logs, which is worth knowing before you point a pipeline at a production vault.

Is cloning Azure Key Vault the same as copying the vault resource?

No. Creating a new Key Vault gives you an empty vault. It doesn't reproduce the secrets from another one. Copying secrets, on the other hand, doesn't reproduce the vault's configuration:

  • Permission model and role assignments
  • Network rules and private endpoints
  • Soft delete and purge protection
  • Diagnostic settings and log destinations
  • Tags and naming

None of that is a secret, and none of it should be set up by hand for each new vault. Define it in infrastructure as code so every vault starts with the same guardrails, then populate the secrets into a vault that's already configured correctly. A useful clone process covers the contents and purpose of the environment, and leaves the Azure resource itself to your deployment templates.

What is the best way to create a pre-populated Key Vault?

For teams that create similar environments repeatedly, there are three approaches, and they often work together.

Infrastructure as code

Terraform, Bicep, or ARM templates are the right place to create the vault, its settings, its role assignments, and any secrets whose values can be generated or supplied at deploy time. Two cautions. Terraform writes secret values to its state file, so treat that state as sensitive. In Bicep, mark secret parameters @secure() so the values stay out of deployment history. IaC is awkward for one job in particular: copying values that only exist in another vault.

Custom automation

A script or small program, like the C# example above, can read from a template vault and populate the new one. Run it from a pipeline under a managed identity, give that identity the two roles it needs and nothing more, and make it report what it skipped. The maintenance cost is real, since you own the rules, the error handling, and the audit trail.

A dedicated Key Vault management tool

A management tool puts a user-facing workflow over the same operations: pick a source vault, pick a destination, and reproduce the secrets you want, without anyone working through the portal one secret at a time. KickCatch Secrets Manager takes this approach. It clones the secret names from a source vault into one or many new vaults, writing empty placeholders by default so the structure arrives without the values, and copying the values only if you deliberately turn that on. It's aimed at teams that create vaults often enough that a script has become something they maintain rather than something they run.

Most teams end up combining two of these: IaC for the vault and its settings, and either automation or a tool for the secrets inside.

Frequently asked questions

Can Azure Key Vault be cloned?

Not with a single native operation. Azure provides backup and restore for individual objects, and cloning a whole environment takes automation or a management tool.

Can I copy all secrets from one Key Vault to another?

Yes, but you have to script it. List the secrets in the source, read each value, and write it to the destination along with its tags, content type, and dates. Azure's own backup and restore works on one object at a time and doesn't give you a full-vault copy.

Can I clone a Key Vault into another Azure subscription?

With read-and-write copying, yes, as long as your identity can read the source and write to the destination. Backup and restore can't do it, because backups only restore within the same subscription and geography. Across tenants, you need a separate credential for each side, and it's worth checking your data residency requirements before moving secrets between regions.

Can I copy a secret in the Azure portal?

Not with a copy button. In the portal you can use Download Backup on a secret and Restore Backup in the destination vault, which works within the same subscription and geography. Otherwise you open the secret, view its value, and create a new secret in the other vault by hand.

Are secret versions copied?

With backup and restore, yes, all of them. With read-and-write copying, only the current value, and the destination starts with a single version. For a new environment that's usually the better result.

How do I copy certificates and keys?

Use the certificate and key backup and restore commands, which have the same subscription and geography limits, or import or re-issue them in the destination. Copying the secret behind a certificate only gives you a plain secret.

What permissions do I need to copy secrets?

On RBAC vaults, Key Vault Secrets User on the source to read values and Key Vault Secrets Officer on the destination to write them. Backup and restore needs more; Microsoft's documentation lists Contributor-level permissions on the subscription.

Why does my copy fail with a 409 conflict?

Almost always because the name is still held by a soft-deleted secret in the destination vault. Recover it with az keyvault secret recover or purge it with az keyvault secret purge. Purging is blocked while purge protection is on and the retention period hasn't ended.

How do I create a Key Vault for a new customer?

Create the vault as part of your customer provisioning process, using infrastructure as code so the settings match every other vault, then populate its secrets from a template using automation or a management tool. Microsoft's guidance for multitenant solutions covers when a vault per tenant makes sense. KickCatch Secrets Manager can clone the secret names from an existing vault into the new one, so the structure is there and only the values are left to set.

Is copying secrets manually a good deployment process?

It's fine for an occasional one-off. As the number of environments grows, manual copying gets harder to audit and easier to get wrong, and a repeatable process pays for itself quickly.

Related questions

How Do I Search Azure Key Vault Secrets?

The Azure portal has no search for Key Vault secrets, inside a single vault or across vaults. What works instead: the CLI, PowerShell, the SDKs, and cross-vault tooling.

Browse every Azure Key Vault question

Start a new vault from one you already have

KickCatch Secrets Manager clones the secret names from an existing Azure Key Vault into one or many new vaults, so a new environment starts with the right structure — and never retains your secret values.

Start Your Free Trial