Skip to main content

KeyVault Name Migration

The platform operator supports two strategies for naming Azure Key Vaults:

StrategyVault name formatDefault?
Legacy{namespace_prefix}{cluster_hash}Yes (current)
Collision-resistant{app_abbreviation}{content_hash}Yes (future)

The legacy strategy derives the vault name from the namespace, which means two applications in the same namespace generate the same vault name. Both applications then attempt to own and manage that vault through Crossplane, causing permission conflicts and other breakages. Collision-resistant naming incorporates the app name, namespace, and cluster name into a hash, guaranteeing uniqueness.

Collision-resistant naming will eventually become the only supported strategy. All existing applications must migrate.


Before You Begin

You will need:

  • Azure Key Vault Officer role on the old vault (to read secrets) and the new vault (to write secrets)
  • az CLI authenticated to the correct Azure subscription

Record the old vault name before making any changes. Find it in ArgoCD by locating the AzureKeyVault resource for your application — the field status.values.resourceId contains the exact vault name.


Step 1 — Add the Annotation

Add the annotation to your PlatformApplication manifest and deploy it. This triggers the operator to reconcile with a new vault name. Crossplane will provision the new vault while the old one remains intact in Azure.

metadata:
annotations:
feature.p6m.dev/use-keyvault-collision-resistant-name: "true"

Once deployed, wait for the new AzureKeyVault resource to show as healthy in ArgoCD, then note the new vault name from status.values.resourceId.


Step 2 — Copy Secrets to the New Vault

Copy all secrets from the old vault to the new one, preserving key names and values exactly.

OLD_VAULT="<old-vault-name>"
NEW_VAULT="<new-vault-name>"

for SECRET_NAME in $(az keyvault secret list \
--vault-name "$OLD_VAULT" \
--query "[].name" \
--output tsv); do
SECRET_VALUE=$(az keyvault secret show \
--vault-name "$OLD_VAULT" \
--name "$SECRET_NAME" \
--query "value" \
--output tsv)
az keyvault secret set \
--vault-name "$NEW_VAULT" \
--name "$SECRET_NAME" \
--value "$SECRET_VALUE"
echo "Copied: $SECRET_NAME"
done
warning

If any secrets are rotated between this step and Step 4, copy the updated values to the new vault before deleting the old one.

Forgot to record the old vault name?

Use the Azure tags to find it. Both vaults are tagged with app (the application name) and cluster (the cluster name):

az keyvault list \
--query "[?tags.app=='<app-name>' && tags.cluster=='<cluster-name>'].name" \
--output tsv

This will return both vault names. The old one follows the format {namespace_prefix}{cluster_hash}.


Step 3 — Verify

In ArgoCD, confirm that:

  • The PlatformApplication is healthy
  • All ExternalSecret resources are healthy and have synced recently
  • The Secret resources they manage contain the expected keys
Force a resync if needed

Click the three-dot menu on the ExternalSecret resource in ArgoCD and select Refresh.


Step 4 — Delete the Old Vault

Once the application is verified, delete the old vault to clean up Azure resources.

danger

Deleting the vault is irreversible. Confirm Step 3 is fully complete before proceeding.

RESOURCE_GROUP=$(az keyvault show \
--name "$OLD_VAULT" \
--query "resourceGroup" \
--output tsv)

az keyvault delete \
--name "$OLD_VAULT" \
--resource-group "$RESOURCE_GROUP"

# Purge to release the name (required when soft-delete is enabled)
az keyvault purge \
--name "$OLD_VAULT"