After two articles doing some fun with Azure Key Vault REST API and HttpClient, I’ve got some requests to add more things to work with vault, for example listing all existing vaults under a given subscription, or deleting a vault.
In this article, let’s explore all the operations which you can work through Azure Key Vault REST API for Vault.
Keep track of the series:
- Some fun with Azure Key Vault REST API and HttpClient – Part 1
- Some fun with Azure Key Vault REST API and HttpClient – Part 2
- Some fun with Azure Key Vault REST API and HttpClient – Part 3
- Some fun with Azure Key Vault REST API and HttpClient – Part 4
- Some fun with Azure Key Vault REST API and HttpClient – Part 4.1
- Some fun with Azure Key Vault REST API and HttpClient – Part 5
Prerequisites
For the sake of quick overview, there are some prerequisites you need before moving to the main method. First, you need to get access token before making a request to resource.There are two main resource endpoints depending on vault operation:
- Azure Resource Management REST API endpoint: it is https://management.azure.com. This is the REST API endpoint if you want to perform operation against Azure resource, for example creating a new Azure Key Vault resource.
- Vault REST API endpoint: it is https://vault.azure.net. It is used when you want to work against components (secret, key) under a specific vault.
- Base Azure AD variable: this includes tenant ID, client, ID and client secret. Note that client secret is not necessary today. It’d be good to subscribe my blog for further articles using other approaches.
- Subscription variable: this includes subscription ID of the subscription you want to play with, and other variables such as location, resource group name or so on.
- Vault variable: along with environment variables, this contains vault name and other components for the use with REST API.
- API version: this is very important. If you specify wrong API version, chances are you will get Bad Request 400. The API version for Azure Key Vault REST API can be found here. If you target to Azure Resource REST API, don’t rely on Azure Key Vault REST API. See the below error in List operation to get more information.
- Acces policy: your service principal must have permission depending on operation you want to perform.
For configuration management, you can use System.Configuration.ConfigurationManager Nuget package. Since we use Azure, it’d be better to go with Microsoft.WindowsAzure.ConfigurationManager.
List all vaults in a subscription
Azure allows you to list all vaults in a specified subscription with GET method. There is not any request body required for the call. There are the following parameters to be directly passed along with URI:
- subscriptionId: your subscription ID
- $filter: used to query Key Vault resource only.
- $top: specify number of results to return. This is optional.
- api-version: because we make a request against Azure Resource Management REST API, don’t use the 2016-10-01 specified in this article.
Here is the sample code:
static string Subscription = CloudConfigurationManager.GetSetting("AzureSubscriptionId"); ... public static async Task ListVault(HttpClient client) { string url = $"/subscriptions/{Subscription}/resources?$filter=resourceType eq 'Microsoft.KeyVault/vaults'&api-version=2018-01-01"; using (var response = await client.GetAsync(url)) { response.EnsureSuccessStatusCode(); Console.WriteLine(JObject.Parse(await response.Content.ReadAsStringAsync())); } }
The response body returns as follows:
{ "value": [{ "id": "/subscriptions/2dd8cb59-ed12-4755-a2bc-356c212fbafc/resourceGroups/s15digital-rg/providers/Microsoft.KeyVault/vaults/keyvaultreader", "name": "keyvaultreader", "type": "Microsoft.KeyVault/vaults", "location": "southeastasia", "tags": {} }, { "id": "/subscriptions/2dd8cb59-ed12-4755-a2bc-356c212fbafc/resourceGroups/webapp-rg/providers/Microsoft.KeyVault/vaults/keyvault20180221", "name": "keyvault20180221", "type": "Microsoft.KeyVault/vaults", "location": "southeastasia", "tags": {} } ] }
Note: as said, do not rely on the API version described in this article. It would be invalid to use with Azure Resource REST API. Unless, you will receive Bad Request when calling. Below is the error message
"Response: 400 Bad Request {"error":{"code":"InvalidApiVersionParameter","message":"The api-version '2016-10-01' is invalid. The supported versions are '2018-01-01, 2017-08-01,2017-06-01,2017-05-10,2017-05-01,2017-03-01,2016-09-01,2016-07-01,2016-06-01,2016-02-01,2015-11-01,2015-01-01,2014-04-01-preview,2014-04-01,2014-01-01,2013-03-01,2014-02-26,2014-04'."}
Getting a vault
Getting a vault means that you retrieve specifications of a specific vault under your subscription using GET method. There are the following parameters to be directly passed along with URI:
- subscriptionId: your subscription ID
- resourceGroupName: the resource group name to which the given vault belongs
- vaultName: name of the vault you want to check
- api-version: use 2016-10-01 as latest version.
Here is sample code
const string resourceGroup = "s15digital-rg"; static string Subscription = CloudConfigurationManager.GetSetting("AzureSubscriptionId"); static string vaultName = CloudConfigurationManager.GetSetting("vaultName"); ... public static async Task GetVault (HttpClient client) { string url = $"/subscriptions/{Subscription}/resourceGroups/{resourceGroup}/providers/Microsoft.KeyVault/vaults/{vaultName}?api-version=2016-10-01"; using (var response = await client.GetAsync(url)) { response.EnsureSuccessStatusCode(); Console.WriteLine(JObject.Parse(await response.Content.ReadAsStringAsync())); } }
Interestingly, the API version for the the provider type of vault is 2016-10-01 as latest. Below is the return of response body which contains parameters you set in Part 1.
{ "id": "/subscriptions/2dd8cb59-ed12-4755-a2bc-356c212fbafc/resourceGroups/s15digital-rg/providers/Microsoft.KeyVault/vaults/keyvaultreader", "name": "keyvaultreader", "type": "Microsoft.KeyVault/vaults", "location": "southeastasia", "tags": {}, "properties": { "sku": { "family": "A", "name": "Standard" }, "tenantId": "03987603-0fc0-4103-bd94-cdffbefb2226", "accessPolicies": [ { "tenantId": "03987603-0fc0-4103-bd94-cdffbefb2226", "objectId": "8ce8ceb9-b0b6-42f9-9f2b-b9a954232e4a", "permissions": { "keys": [ "Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore" ], "secrets": [ "Get", "List", "Set", "Delete", "Recover", "Backup", "Restore" ], "certificates": [ "Get", "List", "Update", "Create", "Import", "Delete", "Recover", "ManageContacts", "ManageIssuers", "GetIssuers", "ListIssuers", "SetIssuers", "DeleteIssuers" ] } }, { "tenantId": "03987603-0fc0-4103-bd94-cdffbefb2226", "objectId": "d4ff23b7-9c40-4702-9e91-1522afd97e23", "permissions": { "keys": [ "Get", "List", "Update", "Create", "Import", "Delete", "Recover", "Backup", "Restore" ], "secrets": [ "Get", "List", "Set", "Delete", "Recover", "Backup", "Restore" ], "certificates": [ "Get", "List", "Update", "Create", "Import", "Delete", "Recover", "ManageContacts", "ManageIssuers", "GetIssuers", "ListIssuers", "SetIssuers", "DeleteIssuers" ] } } ], "enabledForDeployment": false, "enabledForDiskEncryption": false, "enabledForTemplateDeployment": false, "vaultUri": "https://keyvaultreader.vault.azure.net/", "provisioningState": "Succeeded" } }
Deleting a vault
Deleting a vault is similar to getting a vault. The only difference is the method which is DELETE. Thus, we use DeleteAsync()
public static async Task DeleteVault(HttpClient client) { string url = $"/subscriptions/{Subscription}/resourceGroups/{resourceGroup}/providers/Microsoft.KeyVault/vaults/{vaultName}?api-version=2016-10-01"; using (var response = await client.DeleteAsync(url)) { response.EnsureSuccessStatusCode(); } }
The response body only returns status code 200 when a DELETE request is made successfully.
Listing deleted vaults
For investigation, you would need to retrieve the list of vaults you have deleted. Azure allows you to do so with GET method. But you cannot get all deleted vault resources without soft-delete enabled. Azure Key Vault uses a feature named soft-delete that aims to recovery scenario for vault. When you perform DELETE request, you are no longer have an access to that vault if this vault has no soft-delete feature enabled. If you don’t set it before a vault is deleted, the return of List deleted vaults operation always be null.
More information about Azure Key Vault soft-delete feature, read here
Soft-delete feature can be enabled via REST during the provisioning of your vault which was full documented in Part 1. In the request body, just simply set:
var requestBody = new { enableSoftDelete = true, }
One of the other ways to set this property is PowerShell:
$vaultName = "kv2018" ($resource = Get-AzureRmResource -ResourceId (Get-AzureRmKeyVault -VaultName $vaultName).ResourceId).Properties | Add-Member -MemberType "NoteProperty" -Name "enableSoftDelete" -Value "true" Set-AzureRmResource -resourceid $resource.ResourceId -Properties $resource.Properties

Here is the sample code to retrieve deleted vaults:
public static async Task ListDeletedVault(HttpClient client) { string url = $"/subscriptions/{Subscription}/providers/Microsoft.KeyVault/deletedVaults?api-version=2016-10-01"; using (var response = await client.GetAsync(url)) { response.EnsureSuccessStatusCode(); Console.WriteLine(JObject.Parse(await response.Content.ReadAsStringAsync())); } }
And the response body returns as follows:
{ "value": [ { "id": "/subscriptions/2dd8cb59-ed12-4755-a2bc-356c212fbafc/providers/Microsoft.KeyVault/locations/southeastasia/deletedVaults/kv2018", "name": "kv2018", "type": "Microsoft.KeyVault/deletedVaults", "properties": { "vaultId": "/subscriptions/2dd8cb59-ed12-4755-a2bc-356c212fbafc/resourceGroups/webapp-rg/providers/Microsoft.KeyVault/vaults/kv2018", "location": "southeastasia", "tags": {}, "deletionDate": "2018-02-21T07:54:15Z", "scheduledPurgeDate": "2018-05-22T07:54:15Z" } } ], "nextLink": "https://management.azure.com/subscriptions/2dd8cb59-ed12-4755-a2bc-356c212fbafc/[....]" }
There are a couple of notes:
- A vault which has soft-delete enabled is not really deleted. This means this still exists and you cannot create a new vault with the same name.
- You cannot enable soft-delete feature via Azure Portal.
Getting a deleted vault
You can get a specific deleted vault in a specified location and vault name. The required parameters include location and vault name
const string Location = "southeastasia"; static string Subscription = CloudConfigurationManager.GetSetting("AzureSubscriptionId"); static string vaultName = CloudConfigurationManager.GetSetting("vaultName"); ... public static async Task GetDeletedVault(HttpClient client) { string url = $"/subscriptions/{Subscription}/providers/Microsoft.KeyVault/locations/{Location}/deletedVaults/{vaultName}?api-version=2016-10-01"; using (var response = await client.GetAsync(url)) { response.EnsureSuccessStatusCode(); Console.WriteLine(JObject.Parse(await response.Content.ReadAsStringAsync())); } }
The request body is similar to the one when listing deleted vaults, but contains one vault object.
Updating a vault
Update is needed if you want to re-configure access policy, or enable soft-delete feature for example, which you cannot complete via Azure Portal. There are two ways according Microsoft guidance on Azure Key Vault REST API to update a vault: PUT and PATCH. PATCH (PathAsync() ) is not a built-in method in HttpClient, you have to write a dedicated extension method.
Remember PUT can be used to create a new vault, we can still use it to update. You just simple prepare the request body which contains all the specifications, including the existing one.
Updating access policy
Although access policy can be updated by PUT method we discussed earlier, Azure allows you to only update access policy. Along with request body containing access policy, you need the following URI parameters:
- subscriptionId: your subscription ID
- resourceGroupName: resource group name which the target vault belongs to
- vaultName: name of the vault you want to update its access policy
- operationKind: specify name of the operation: add, remove or replace.
- api-version: uses 2016-10-01
Here is the sample code
public static async Task UpdateVaultPolicy(HttpClient client) { string url = $"/subscriptions/{Subscription}/resourceGroups/{resourceGroup}/providers/Microsoft.KeyVault/vaults/{vaultName}/accessPolicies/replace?api-version=2016-10-01"; var requestBody = new { properties = new { accessPolicies = new object[] { new { tenantId = tenantId, objectId = clientId, permissions = new { keys = new string[] { "encrypt", "decrypt" }, secrets = new string[] { "get", "list", "delete" } }, } }, } }; using (var httpResponse = await client.PutAsJsonAsync(url, requestBody)) { httpResponse.EnsureSuccessStatusCode(); JObject responseContent = JObject.Parse(await httpResponse.Content.ReadAsStringAsync()); string ms = responseContent.ToString(); } }
Make sure you understand each operation to not make the application downtime. Add can be used to append new access policy which is considered a safe approach.
Purging deleted vault
A retention period of a deleted vault which has soft-delete feature enabled is 90 days. The scheduledPurgeDate property in response body tells you the retention. After 90 days from deletion date, Azure will permanently delete the vault and you will no longer have an access to the vault and its components.
In some cases, you don’t want to keep your deleted vault within the retention period, you can purge it. When purging, that deleted vault will be immediately removed out of Azure store.
Along with request body containing access policy, you need the following URI parameters:
- subscriptionId: your subscription ID
- location: the location of the deleted vault.
- vaultName: name of the vault you want to update its access policy
- api-version: uses 2016-10-01
Purging a specified deleted vault requires POST method without any Http content. You can set null in the request parameter. Here is the sample code
public static async Task PurgeDeletedVault(HttpClient client) { string url = $"/subscriptions/{Subscription}/providers/Microsoft.KeyVault/locations/{Location}/deletedVaults/{vaultName}/purge?api-version=2016-10-01"; using (var httpResponse = await client.PostAsync(url, null)) { httpResponse.EnsureSuccessStatusCode(); Console.WriteLine(JObject.Parse(await httpResponse.Content.ReadAsStringAsync()));); } }
The response body only returns status code 202 Accepted. It means the specified deleted vault is being purged. Once it is completely purged, you can create a new vault using the same name. Once again, if the soft-delete deleted vault has not been purged, you cannot create a new vault using that deleted vault’s name.
Conclusion
This article shows you different operations against vault in Azure Key Vault service by HttpClient and REST API. During demonstration, you have gained some basic knowledge of Azure Key Vault, as well as some important notes.
Although, Microsoft has documented poorly for Azure Key Vault REST API for vault, it’s worth referring:
Operation | Description | Method | api-version | Note |
---|---|---|---|---|
Check Name Availability | Checks that the vault name is valid and is not already in use | POST | 2016-10-01 | Make sure request body is in form of Http content. |
Create | Create a key vault in a specified subscription | PUT | 2016-10-01 | Request body format must be valid |
Update | Update specifications of an existing key vault in a specified subscription | PUT | 2016-10-01 | Similar to Create operation |
Update | Update specifications of an existing key vault in a specified subscription | PATCH | 2016-10-01 | Not yet tested |
Delete | Delete a key vault | DELETE | 2016-10-01 | It is no longer retrievable if not setting soft-delete feature. |
Get | Get a specified key vault | GET | 2016-10-01 | N/A |
Get Deleted | Gets a deleted key vault. | GET | 2016-10-01 | Can only get deleted vault that enables soft-delete feature. |
List | Get all vaults associated to a specified subscription | GET | 2018-01-01 | api-version is not 2016-10-01 |
List By Resource Group | Get all vaults in a specified subscription within a resource group | GET | 2018-01-01 | Similar to List operation |
List By Subscription | Get all vaults associated to a specific subscription | GET | 2018-01-01 | Similar to List operation, without resource group specified in URI parameter |
List Deleted | Get all deleted vaults in a specified subscription | GET | 2016-10-01 | Can only get deleted vaults that enables soft-delete feature. |
Purge Deleted | Permanently purge a deleted vault | POST | 2016-10-01 | Http content can be null. Only purge deleted vaults that enable soft-delete feature |
Update Access Policy | Update access policy of a vault | PUT | 2016-10-01 | Only prepare access policy in request body. Use Add to append policy safely. |
Pingback: Some fun with Azure Key Vault REST API and HttpClient – Part 2 | All about security on Microsoft Azure
Pingback: Some fun with Azure Key Vault REST API and HttpClient – Part 1 | All about security on Microsoft Azure
Pingback: Some fun with Azure Key Vault REST API and HttpClient – Part 4 | All about security on Microsoft Azure
Pingback: Some fun with Azure Key Vault REST API and HttpClient – Part 5 | All about security on Microsoft Azure