Some fun with Azure Key Vault REST API and HttpClient – Part 4

The Part 2 in Some fun with Azure Key Vault REST API and HttpClient series provides simple guidance on how to create a new fresh secret without creating a new version of existing secret under a specified vault in Azure Key Vault. So far, what we have been using is only HttpClient with Azure Key Vault REST API.

You might ask if you can store a certificate as secret in a key vault and how to retrieve it. If so, this article is for you.

Keep track of the series:

Prerequisites 

For REST API call, we need access token. The valid access token is supplied when your authorization header and resource are valid. The authorization header is format of bearer token in OAuth 2.0. The resource is Azure Key Vault we need. There would be a confusion in resource we are supposed to use. For instance, you would wrongly indicate Azure Resource Manager endpoint as a resource when retrieving an access token. With vault, it is correct because vault is considered a resource type in Azure. However, secret is part of a vault and it does not work over Azure Resource Manager REST API.

To get the list of registered resource types in your Azure subscription, use Get-AzureRmResourceProvider  or from Resource provider in subscription

The resource endpoint of Azure Key Vault is https://vault.azure.net (with no forward slash “/”).

If you follow my series, the only thing to be changed is the URL in vaultResourcevariable as highlighted above.

Getting a secret value

Getting information including value, attributes of a secret can be done by GET method. The following URI parameters are needed:

  • Vault base URL: it is constructed by http://<your_vault_name>.vault.azure.net.
  • Secret name: the secret you need to retrieve
  • Secret version: each secret can have multiple versions. Each version is an instance of secret and does not have to be similar to each other. If secret version is not specified, Azure will return the in-use version (latest version)
  • api-version: it is 2016-10-01

Here is the sample code:

…and if you need to retrieve only secret value, it can be done easily as follows:

If you want to pass the return value to another method, saying creating a new container of a Blob Storage, it can be done easily as follows with .NET client:

Setting and retrieving certificate as a secret

Sometimes you need to protect your certificate as a secret rather than kind of string or integer. There could be some reasons you want to do so. Perhaps you would need to have Azure Key Vault as a certificate store over Keys or Certificates. In the case of working with *.pfx or *.pem file, if being uploaded to Keys store you cannot retrieve its private part. Another case is when you don’t use Azure Key Vault for encryption and decryption process like this case.

Although this feature has been recently deprecated due to nonsense, you still can store a certificate as in Azure Key Vault secret. If you do the work in Azure Portal, you can see the warning message. I don’t know when this feature is no longer available but the existence over here would lead to the misuse.

Another thing is that you was able to upload a password-protected certificate to secret store. Now your certificate must not have password protected before being uploaded. A funny thing from my past experience was that when a certificate got uploaded to secret store, its password was removed. This means if you get it from a secret identifier, you can install it on your local certificate store without the need of password.

For demonstration purpose, let’s see if we can by pass to this feature over HttpClient and REST API. First, let’s create a sample self-signed *.pfx file by the following PowerShell:

Because the value parameter to pass to the request body is a string type so you need to convert your *.pfx file into Base64 string.  This can be done via PowerShell if you’d like to know

But I’m sure that you don’t want to declare a very long string in your code. So let’s do the whole work including Base64 conversion programatically.

Pay attention to the highlighted lines above. The first three lines does the Base64 conversion. In the request body, you must indicate the content type application application/x-pkcs12.

When reading value from a secret, you will get the Base64 encoded string. If you need to convert secret value and export to a *.pfx file, just simply use Convert.FromBase64String()

The bug of password protected seems to be fixed. However, with this demonstration there seems to be another problem with storing a password-protected certificate to a secret store.

Updating a secret

Updating a secret does not mean updating its value. In fact, secret value cannot be changed or overwritten. You can only change secret attributes such as secret status (enabled or disabled), expiration and activation date. If you want to update a secret value without changing secret identifier, you can create a new version for an existing secret.

The bad new is that you can only use PATCH to update secret attributes. Using PUT, it doesn’t allow you to update even you do the trick by sending the request to the existing secret with its version. I spend a couple of hours researching over the Internet to make the use of PATCH done.

Because PATCH is not a built-in method in HttpClient, we can look at SendAsync as an alternative. The request in SendAsync()  needs  HttpRequestMessage passed along. In HttpRequestMessage, we can declare HTTP method, request Uri and HttpContent. The sample code below shows you exactly what we need to do for a ‘custom’ HTTP method to disable a specified secret (its version is f5440084ed2e4ab5898795fcfe92a230) (enabled = false,).

Note that the request body can be anonymous type. Also, HttpContent parameter requires JSON string so I use JsonConvert.SerializeObject  to perform serialization.

The response returns the information about the secret, except its value.

Getting versions of a secret

This stuff is super straightforward and similar to getting a secret. The only difference is that getting versions of a specified secret does not return secret value. It only returns full secret identifiers and relatively attributes.

If you want to filter, just follow Part 2 to make a List<string>  of  all versions.

Conclusion

The article complements to Part 2 to show you on how to upload a certificate to secret store and retrieve its. Once again, there are two interesting things during the demonstration:

  • Via Azure Portal, you cannot upload a password-protected certificate. Programtically you can.
  • A password-protected certificate can be downloaded and converted to binary file (.pfx) and it requires a password before you can install it NOW. If you actually believe this is a normal behavior, stay tuned to read my upcoming article which shows you exactly this so-called normal stuff has been fixed.

Unlike Part 3 that covered all basic operations for vault, this article only shows you things around setting and getting secret and secret version. The next article of the series will cover some sort of secret backup and recovery.

Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

© 2018 The Soldier of Fortune.