azure-sdk-for-net
azure-sdk-for-net copied to clipboard
[BUG] Cannot re-create a secret in KeyVault even after purging
Library name and version
Azure.Security.KeyVault.Secrets 4.4.0
Describe the bug
I am trying to delete a secret from KeyVault and replace it with another with the same key.
The KeyVault has Soft-delete enabled and Purge protection disabled.
Despite following the steps outlined at https://learn.microsoft.com/en-us/azure/key-vault/secrets/quick-create-net?tabs=azure-cli#sample-code when I try to create the secret again, an exception is thrown.
Expected behavior
The old secret should be successfully deleted so that a new secret with the same key can be created.
Actual behavior
The following exception is thrown:
Azure.RequestFailedException: Secret mySecret is currently being deleted and cannot be re-created; retry later. Status: 409 (Conflict) ErrorCode: Conflict
Content: {"error":{"code":"Conflict","message":"Secret mySecret is currently being deleted and cannot be re-created; retry later.","innererror":{"code":"ObjectIsBeingDeleted"}}}
Headers: Cache-Control: no-cache Pragma: no-cache x-ms-keyvault-region: uksouth x-ms-client-request-id: 92f45d1f-cfcc-43bc-9367-2e64aba5e1bf x-ms-request-id: 4685a803-62b0-46e0-a35e-3d15712c3d18 x-ms-keyvault-service-version: 1.9.713.1 x-ms-keyvault-network-info: conn_type=Ipv4;addr=90.253.118.37;act_addr_fam=InterNetwork; X-Content-Type-Options: REDACTED Strict-Transport-Security: REDACTED Date: Fri, 17 Feb 2023 10:04:32 GMT Content-Length: 168 Content-Type: application/json; charset=utf-8 Expires: -1
at Azure.Security.KeyVault.KeyVaultPipeline.SendRequestAsync(Request request, CancellationToken cancellationToken) at Azure.Security.KeyVault.KeyVaultPipeline.SendRequestAsync[TContent,TResult](RequestMethod method, TContent content, Func`1 resultFactory, CancellationToken cancellationToken, String[] path) at Azure.Security.KeyVault.Secrets.SecretClient.SetSecretAsync(KeyVaultSecret secret, CancellationToken cancellationToken) at Azure.Security.KeyVault.Secrets.SecretClient.SetSecretAsync(String name, String value, CancellationToken cancellationToken) at key_vault_console_app.Program.Main(String[] args) in C:\Repos\Sandpit\ConsoleApp2\ConsoleApp2\Program.cs:line 45 at key_vault_console_app.Program.<Main>(String[] args)
Reproduction Steps
I have created a console app based on https://learn.microsoft.com/en-us/azure/key-vault/secrets/quick-create-net?tabs=azure-cli#sample-code and added a step to add the secret again:
class Program
{
static async Task Main(string[] args)
{
const string secretName = "mySecret";
var keyVaultName = "MYKEYVAULTNAME";
var kvUri = $"https://{keyVaultName}.vault.azure.net";
var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
Console.Write("Input the value of your secret > ");
var secretValue = Console.ReadLine();
Console.Write($"Creating a secret in {keyVaultName} called '{secretName}' with the value '{secretValue}' ...");
await client.SetSecretAsync(secretName, secretValue);
Console.WriteLine(" done.");
Console.WriteLine("Forgetting your secret.");
secretValue = string.Empty;
Console.WriteLine($"Your secret is '{secretValue}'.");
Console.WriteLine($"Retrieving your secret from {keyVaultName}.");
var secret = await client.GetSecretAsync(secretName);
Console.WriteLine($"Your secret is '{secret.Value.Value}'.");
Console.Write($"Deleting your secret from {keyVaultName} ...");
DeleteSecretOperation operation = await client.StartDeleteSecretAsync(secretName);
// You only need to wait for completion if you want to purge or recover the secret.
await operation.WaitForCompletionAsync();
Console.WriteLine(" done.");
Console.Write($"Purging your secret from {keyVaultName} ...");
await client.PurgeDeletedSecretAsync(secretName);
Console.WriteLine(" done.");
// Additional step:
Console.Write($"Creating a secret in {keyVaultName} called '{secretName}' with the value '{secretValue}' ...");
await client.SetSecretAsync(secretName, secretValue);
Console.WriteLine(" done.");
}
}
Environment
No response
Thank you for your feedback. Tagging and routing to the team member best able to assist.
Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @RandalliLama, @schaabs, @jlichwa.
Issue Details
Library name and version
Azure.Security.KeyVault.Secrets 4.4.0
Describe the bug
I am trying to delete a secret from KeyVault and replace it with another with the same key.
The KeyVault has Soft-delete enabled and Purge protection disabled.
Despite following the steps outlined at https://learn.microsoft.com/en-us/azure/key-vault/secrets/quick-create-net?tabs=azure-cli#sample-code when I try to create the secret again, an exception is thrown.
Expected behavior
The old secret should be successfully deleted so that a new secret with the same key can be created.
Actual behavior
The following exception is thrown:
Azure.RequestFailedException: Secret mySecret is currently being deleted and cannot be re-created; retry later. Status: 409 (Conflict) ErrorCode: Conflict
Content: {"error":{"code":"Conflict","message":"Secret mySecret is currently being deleted and cannot be re-created; retry later.","innererror":{"code":"ObjectIsBeingDeleted"}}}
Headers: Cache-Control: no-cache Pragma: no-cache x-ms-keyvault-region: uksouth x-ms-client-request-id: 92f45d1f-cfcc-43bc-9367-2e64aba5e1bf x-ms-request-id: 4685a803-62b0-46e0-a35e-3d15712c3d18 x-ms-keyvault-service-version: 1.9.713.1 x-ms-keyvault-network-info: conn_type=Ipv4;addr=90.253.118.37;act_addr_fam=InterNetwork; X-Content-Type-Options: REDACTED Strict-Transport-Security: REDACTED Date: Fri, 17 Feb 2023 10:04:32 GMT Content-Length: 168 Content-Type: application/json; charset=utf-8 Expires: -1
at Azure.Security.KeyVault.KeyVaultPipeline.SendRequestAsync(Request request, CancellationToken cancellationToken) at Azure.Security.KeyVault.KeyVaultPipeline.SendRequestAsync[TContent,TResult](RequestMethod method, TContent content, Func`1 resultFactory, CancellationToken cancellationToken, String[] path) at Azure.Security.KeyVault.Secrets.SecretClient.SetSecretAsync(KeyVaultSecret secret, CancellationToken cancellationToken) at Azure.Security.KeyVault.Secrets.SecretClient.SetSecretAsync(String name, String value, CancellationToken cancellationToken) at key_vault_console_app.Program.Main(String[] args) in C:\Repos\Sandpit\ConsoleApp2\ConsoleApp2\Program.cs:line 45 at key_vault_console_app.Program.<Main>(String[] args)
Reproduction Steps
I have created a console app based on https://learn.microsoft.com/en-us/azure/key-vault/secrets/quick-create-net?tabs=azure-cli#sample-code and added a step to add the secret again:
class Program
{
static async Task Main(string[] args)
{
const string secretName = "mySecret";
var keyVaultName = "MYKEYVAULTNAME";
var kvUri = $"https://{keyVaultName}.vault.azure.net";
var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
Console.Write("Input the value of your secret > ");
var secretValue = Console.ReadLine();
Console.Write($"Creating a secret in {keyVaultName} called '{secretName}' with the value '{secretValue}' ...");
await client.SetSecretAsync(secretName, secretValue);
Console.WriteLine(" done.");
Console.WriteLine("Forgetting your secret.");
secretValue = string.Empty;
Console.WriteLine($"Your secret is '{secretValue}'.");
Console.WriteLine($"Retrieving your secret from {keyVaultName}.");
var secret = await client.GetSecretAsync(secretName);
Console.WriteLine($"Your secret is '{secret.Value.Value}'.");
Console.Write($"Deleting your secret from {keyVaultName} ...");
DeleteSecretOperation operation = await client.StartDeleteSecretAsync(secretName);
// You only need to wait for completion if you want to purge or recover the secret.
await operation.WaitForCompletionAsync();
Console.WriteLine(" done.");
Console.Write($"Purging your secret from {keyVaultName} ...");
await client.PurgeDeletedSecretAsync(secretName);
Console.WriteLine(" done.");
// Additional step:
Console.Write($"Creating a secret in {keyVaultName} called '{secretName}' with the value '{secretValue}' ...");
await client.SetSecretAsync(secretName, secretValue);
Console.WriteLine(" done.");
}
}
Environment
No response
| Author: | MattW52 |
|---|---|
| Assignees: | heaths |
| Labels: |
|
| Milestone: | - |
Unfortunately, purging does take time and there's no way to poll for it like we do for deletions or recovery. This is a service limitation. @jlichwa for feedback. Is this something the service team might consider a change to?
@MattW52 alternatively, you can loop trying to create the key until it works, but can I ask why you're trying to purge a secret when creating a new one? You can create a new version just by calling SetSecret again. This way, old secrets are kept in case they are ever needed e.g., compare with possibly leaked credentials, make sure you don't reuse a past secret, etc.
We integrate with 3rd party systems on-behalf of our Customers and use Key Vault to store config. Some of those 3rd parties require us to delete that config should the Customer decide to revoke our access. Some actually require us to demonstrate this behaviour before they will allow us to access live data.
Key Vault seemed like a good fit, I just need to get the purging to work.
Thanks.
Purging does work, though. You just can't expect to turn around and create a new key/secret/cert for ~30s in many cases. That seems like an impractical scenario. There is, unfortunately, no wait to monitor when a purge is complete. See #6514 from years back where this was discussed with the service team.
It is async operation without ability to monitor completion. 30seconds sleep should be enough for demonstration purposes. It is not possible to introduce without changing service behavior, which would be a breaking change.
Key Vault Team
Ok, thanks. I really meant "wait for the purging to work" rather than "get the purging to work".