简体   繁体   English

UWP/WinUI 桌面应用程序访问 Azure Key Vault 机密

[英]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. Microsoft 提供了多种方法来安全访问 Azure Key Vault 机密,特别是使用托管身份或服务主体作为身份提供者。 However, these methods are explicitly designed to work with Azure-based resources such as web apps and microservices.但是,这些方法明确设计用于基于 Azure 的资源,例如 web 应用程序和微服务。 They do NOT work with UWP/WinUI desktop applications.它们不适用于 UWP/WinUI 桌面应用程序。

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).到目前为止,我发现允许 UWP/WinUI 桌面应用程序访问 Key Vault 的唯一方法是将应用程序的 Azure 注册信息(TenentId、ClientId 和 ClientSecret -- 秘密,它们自己)加载到环境变量中,这些信息由创建新的 SecretClient object (Azure.Security.KeyVault.Secrets) 时的 DefaultAzureCredential() 方法。

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?在 2020 年,UWP/WinUI 桌面应用程序安全访问 Key Vault 机密的最佳做法是什么——而不会在此过程中暴露其他机密?

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.归根结底,您的应用程序必须存储某种秘密——因为它需要将该秘密提供给您的 Key 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.在我们的例子中,我们有一个 WinForms 应用程序,它由我们的支持团队明确安装到我们客户的机器上,这意味着我们一直在使用客户证书的旧黄金标准 - 显然有一个自定义验证步骤.

Thankfully, Key Vault explicitly supports client certificates (below steps reproduced from linked MSDN):值得庆幸的是, Key Vault 明确支持客户端证书(以下步骤从链接的 MSDN 复制):

  1. Create a PKCS#12 archive (.pfx) certificate.创建 PKCS#12 存档 (.pfx) 证书。 Options for creating certificates include MakeCert on Windows and OpenSSL.创建证书的选项包括 Windows 和 OpenSSL 上的 MakeCert。
  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).将 PKCS#12 存档 (.pfx) 证书导出为 DER 编码证书 (.cer)。
  4. Register the app with Azure AD (App registrations).使用 Azure AD(应用程序注册)注册应用程序。
  5. Upload the DER-encoded certificate (.cer) to Azure AD:将 DER 编码证书 (.cer) 上传到 Azure AD:
    a.一种。 Select the app in Azure AD. Select 公元 Azure 中的应用程序。
    b. b. Navigate to Certificates & secrets.导航到证书和机密。
    c. Select Upload certificate to upload the certificate, which contains the public key. c. Select Upload certificate 上传证书,其中包含公钥。 A.cer, .pem, or.crt certificate is acceptable.可接受 A.cer、.pem 或 .crt 证书。
  6. Store the key vault name, Application ID, and certificate thumbprint in the app's appsettings.json file.将密钥保管库名称、应用程序 ID 和证书指纹存储在应用程序的 appsettings.json 文件中。
  7. Navigate to Key vaults in the Azure portal.导航到 Azure 门户中的密钥保管库。
  8. Select the key vault that you created in the Secret storage in the Production environment with Azure Key Vault section. Select 您在生产环境的秘密存储中使用 Azure 密钥保管库部分创建的密钥保管库。
  9. Select Access policies. Select 访问策略。
  10. Select Add Access Policy. Select 添加访问策略。
  11. Open Secret permissions and provide the app with Get and List permissions.打开 Secret permissions 并为应用程序提供 Get 和 List 权限。
  12. Select Select principal and select the registered app by name. Select Select 主体和 select 按名称注册的应用程序。 Select the Select button. Select Select 按钮。
  13. Select OK. Select 好的。
  14. Select Save. Select 保存。
  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.我们目前正在用 Key Vault 替换我们的自定义客户端证书验证器,因为它只会让一切变得更容易 - 从 Azure 门户而不是我们的自定义管理应用程序管理证书和吊销。

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.您可以将 Azure 注册信息(TenentId、ClientId 和 ClientSecret)设置到 Secret manager 中并读取值而不是暴露秘密。

Please refer to the following steps:请参考以下步骤:

1.Enable Security Manager. 1.启用安全管理器。 You need to use init keyword by running on project directory .您需要通过在项目目录上运行来使用 init 关键字。

dotnet user-secrets init

This will create Guid for UserSecretId in the project .csproj file.这将在项目.csproj文件中为UserSecretId创建 Guid。

在此处输入图像描述

2.Set Secrets. 2.设置秘密。 You can set a secrets by using set keywords您可以使用 set 关键字设置秘密

dotnet user-secrets set tenantId "xxxxxxxxxxxx"

在此处输入图像描述

3.Read from secret manager in code. 3.在代码中读取secret manager。

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:工作 output 如下:

在此处输入图像描述

For more details about secret manager, you could refer to this article .有关 Secret Manager 的更多详细信息,您可以参考这篇文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM