FactoryOptimizr
FactoryOptimizr

Reputation: 326

UWP/WinUI desktop app access to Azure Key Vault secrets

Microsoft provides several ways to gain secure access to Azure Key Vault secrets, particularly using Managed Identity or Service Principals as identity providers. However, these methods are explicitly designed to work with Azure-based resources such as web apps and microservices. They do NOT work with UWP/WinUI desktop applications.

The only method I've discovered so far to allow a UWP/WinUI desktop application access to Key Vault is to load the app's Azure registration info (TenentId, ClientId and ClientSecret -- secrets, themselves!) into environment variables that get picked up by the DefaultAzureCredential() method when creating a new SecretClient object (Azure.Security.KeyVault.Secrets).

But that means I'd need to store THESE secrets either in code or in a configuration file to be read in at run-time. Definitely NOT a best practice! I must be missing something.

What are the best practices in 2020 for UWP/WinUI desktop applications to SECURELY access Key Vault secrets -- without exposing other secrets in the process?

Upvotes: 6

Views: 3139

Answers (2)

At the end of the day, your app has to store a secret of SOME sort - as it needs to provide that secret to your Key Vault instance to prove that that app is, indeed, allowed to access the secrets stored in that Vault. It's similar to retrieving a value from a database - you have to store and provide a connection string before you can get values out.

Without knowing the particular use case of how you intend to deploy your application, it's impossible to advise what you should or should not be doing. In our case, we have a WinForms app that's explicitly installed by our support team onto our clients' machines, which means that the old, gold standard of client certificates is what we've been using until now - with a custom verification step, obviously.

Thankfully, Key Vault explicitly supports client certificates (below steps reproduced from linked MSDN):

  1. Create a PKCS#12 archive (.pfx) certificate. Options for creating certificates include MakeCert on Windows and OpenSSL.
  2. Install the certificate into the current user's personal certificate store. Marking the key as exportable is optional. Note the certificate's thumbprint, which is used later in this process.
  3. Export the PKCS#12 archive (.pfx) certificate as a DER-encoded certificate (.cer).
  4. Register the app with Azure AD (App registrations).
  5. Upload the DER-encoded certificate (.cer) to Azure AD:
    a. Select the app in Azure AD.
    b. Navigate to Certificates & secrets.
    c. Select Upload certificate to upload the certificate, which contains the public key. A .cer, .pem, or .crt certificate is acceptable.
  6. Store the key vault name, Application ID, and certificate thumbprint in the app's appsettings.json file.
  7. Navigate to Key vaults in the Azure portal.
  8. Select the key vault that you created in the Secret storage in the Production environment with Azure Key Vault section.
  9. Select Access policies.
  10. Select Add Access Policy.
  11. Open Secret permissions and provide the app with Get and List permissions.
  12. Select Select principal and select the registered app by name. Select the Select button.
  13. Select OK.
  14. Select Save.
  15. Deploy the app.

We're currently replacing our custom client certificate validator with Key Vault, as it's just going to make everything so much easier - managing certificates and revocations from within Azure Portal instead of our custom admin app.

Upvotes: 1

Joey Cai
Joey Cai

Reputation: 20127

I'd need to store THESE secrets either in code or in a configuration file to be read in at run-time

You could set Azure registration info (TenentId, ClientId and ClientSecret) into Secret manager and read the value instead of exposing the secrets.

Please refer to the following steps:

1.Enable Security Manager. You need to use init keyword by running on project directory.

dotnet user-secrets init

This will create Guid for UserSecretId in the project .csproj file.

enter image description here

2.Set Secrets. You can set a secrets by using set keywords

dotnet user-secrets set tenantId "xxxxxxxxxxxx"

enter image description here

3.Read from secret manager in code.

private readonly IConfiguration _configuration;

public WeatherForecastController( IConfiguration configuration)
{
    _configuration = configuration;
}
string keyVaultUrl = "https://xxxx.vault.azure.net";
TokenCredential credential = new DefaultAzureCredential();
credential = new ClientSecretCredential(_configuration["tenantId"], _configuration["clientId"], _configuration["clientSecret"]);

var secretClient = new SecretClient(new Uri(keyVaultUrl), credential);
KeyVaultSecret secret = secretClient.GetSecret("xxxx");
var secretvalue = secret.Value;

The working output is as below:

enter image description here

For more details about secret manager, you could refer to this article.

Upvotes: -1

Related Questions