KeyVault Name Migration
The platform operator supports two strategies for naming Azure Key Vaults:
| Strategy | Vault name format | Default? |
|---|---|---|
| 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)
azCLI 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.
- Bash
- PowerShell
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
$OLD_VAULT = "<old-vault-name>"
$NEW_VAULT = "<new-vault-name>"
$SECRET_NAMES = az keyvault secret list `
--vault-name $OLD_VAULT `
--query "[].name" `
--output tsv
foreach ($SECRET_NAME in $SECRET_NAMES) {
$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
Write-Host "Copied: $SECRET_NAME"
}
If any secrets are rotated between this step and Step 4, copy the updated values to the new vault before deleting the old one.
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
PlatformApplicationis healthy - All
ExternalSecretresources are healthy and have synced recently - The
Secretresources they manage contain the expected keys
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.
Deleting the vault is irreversible. Confirm Step 3 is fully complete before proceeding.
- Bash
- PowerShell
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"
$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