使用Azure Key Vault管理敏感信息

在开发应用程序时,经常需要处理各种敏感信息,如API密钥、数据库连接字符串等。这些信息如果直接硬编码在代码中,不仅不安全,而且难以管理。本文将介绍如何使用Azure Key Vault来安全地存储和管理这些敏感信息。

硬编码敏感信息的问题

在代码中直接硬编码敏感信息,虽然看似简单快捷,但存在以下问题:

  • 如果密钥需要更改,必须修改代码并重新部署。
  • 密钥在代码中清晰可见,容易被泄露。
  • 密钥会永久存在于源代码系统中,甚至可能被上传到公共代码仓库。
  • 在不同环境(开发、测试、生产)中,密钥可能会发生变化,硬编码的密钥无法适应这种变化。

Azure Key Vault简介

Azure Key Vault是一个安全的云服务,用于存储和管理敏感信息。它可以存储以下类型的数据:

  • 机密(Secrets):可以存储令牌、密码、密钥等。
  • 密钥(Keys):可以存储加密密钥,并在需要时引用它们进行数据的加密和解密。
  • 证书(Certificates):可以存储和管理SSL/TLS证书。

这些数据被安全地存储在Key Vault中,只有具有相应访问权限的用户或进程才能检索它们。访问情况会被监控,因此可以知道谁访问了什么,以及Key Vault的性能如何。

创建Azure Key Vault

要在Azure门户中创建Key Vault,请按照以下步骤操作:

  1. 登录到Azure门户。
  2. 点击左上角的“创建资源”按钮。
  3. 在搜索框中输入“Key Vault”,然后从列表中选择“Key Vault”。
  4. 点击“创建”并填写必要的参数:
    • 名称:为Key Vault指定一个唯一的名称。
    • 订阅:选择包含Key Vault的订阅。
    • 资源组:可以选择一个现有的资源组,或者创建一个新的资源组。
    • 位置:选择一个地理位置。
    • 定价层:通常选择标准层,除非需要HSM支持的密钥。
    • 访问策略:默认情况下,当前用户将成为Key Vault的所有者。可以在这里添加或删除权限。
  5. 点击“创建”,Azure将为创建Key Vault。这个过程可能需要一些时间。

向Key Vault中插入值

在Azure门户中找到新Key Vault并点击它。如果订阅包含很多对象,可能需要先选择包含Key Vault的资源组。

现在可以看到概览页面,其中包含一些有用的信息。这里最重要的信息是DNS名称(右上角)。将需要这个名称来从代码中连接到Key Vault。

在左侧菜单中点击“机密”。将看到所有当前存储的机密。如果刚刚创建了Key Vault,这里可能是空的。

点击“生成/导入”来创建一个新的机密:

  • 上传选项:手动
  • 名称:例如“Password”
  • 值:例如“My Secret”
  • 内容类型:留空

如果愿意,还可以为这个机密设置激活日期和过期日期。在示例中,将留空。

确保“启用”设置为“是”,然后点击“创建”。

当再次点击左侧的“机密”按钮时,将看到这个密钥的条目。

使用Azure Cloud Shell设置Key Vault

使用脚本创建Azure对象可以使其可重复。如果有多个租户,可以编写一个脚本,为每个租户创建必要的对象。这将节省时间,因为:

  • 执行脚本比手动创建每个对象更快。
  • 一致性。如果一切都是脚本化的,可以确保所有对象都为每个租户以相同的方式创建。这可以节省数小时的配置错误排查时间。
  • 可以将脚本保存在源代码控制系统中,这样也可以对它们进行版本控制。

打开Cloud Shell:

  1. 点击顶部的“Cloud Shell”图标。如果这是第一次打开Cloud Shell,将显示一个向导来设置Shell。可以选择要使用的脚本语言(PowerShell或Linux Bash),然后Azure将为创建一些存储。还有一个公平的警告,存储会花费一些钱。
  2. 对于这个示例,将使用Linux Bash。
RESOURCE_GROUP='CodeProject' LOCATION='WestEurope' KEY_VAULT='CPKeyVault666' az group create --name $RESOURCE_GROUP --location $LOCATION az keyvault create --resource-group $RESOURCE_GROUP --name $KEY_VAULT az keyvault list az keyvault secret set --vault-name $KEY_VAULT --name Password --value 'My Secret' az keyvault secret list --vault-name $KEY_VAULT az keyvault secret show --vault-name $KEY_VAULT --name Password --query value --output tsv

在.NET项目中使用Azure Key Vault

要在.NET项目中使用Azure Key Vault,请按照以下步骤操作:

  1. 使用Visual Studio 2019创建一个新的.NET Core控制台应用程序,将其命名为“KeyVault”。
  2. 要使用Azure Key Vault,首先需要向项目添加2个NuGet包:
    • Microsoft.Azure.KeyVault
    • Microsoft.Azure.Services.AppAuthentication
  3. 打开“包管理器控制台”(工具 > NuGet包管理器 > 包管理器控制台…),然后输入以下命令:
install-package Microsoft.Azure.KeyVault install-package Microsoft.Azure.Services.AppAuthentication

在源文件中,需要以下using语句:

using Microsoft.Azure.KeyVault; using Microsoft.Azure.Services.AppAuthentication;

为了从Key Vault中读取字符串,最好创建一个单独的类,例如:

using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Azure.KeyVault; using Microsoft.Azure.KeyVault.Models; using Microsoft.Azure.Services.AppAuthentication; namespace KeyVault { public class KeyvaultUtilities : IKeyvaultUtilities { private readonly IKeyVaultClient _keyVaultClient; private readonly string _vaultBaseUrl; public KeyvaultUtilities(string keyvaultName) { _vaultBaseUrl = $"https://{keyvaultName}.vault.azure.net"; AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(); _keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback)); } public async Task GetSecretAsync(string keyname) { try { var secret = await _keyVaultClient.GetSecretAsync(_vaultBaseUrl, keyname).ConfigureAwait(false); return secret.Value; } catch (KeyVaultErrorException kvex) { throw new KeyNotFoundException($"Keyname '{keyname}' does not seem to exist in this key vault", kvex); } } } }

这个类的目的是从Key Vault中读取机密,因此只实现了这一个方法。可以根据需要在类中添加其他与Key Vault相关的方法。

使用这个类很简单。可以通过设置文件获取Key Vault名称,而不是作为字符串传递。这也将允许在开发环境中轻松切换。

请注意,从未创建过名为“xyz”的机密。尝试检索这个值将抛出KeyNotFoundException。

using System; using System.Threading.Tasks; namespace KeyVault { class Program { static async Task Main(string[] args) { Console.WriteLine("Hello World!"); IKeyvaultUtilities util = new KeyvaultUtilities("cpkeyvault666"); string pwd = await util.GetSecretAsync("Password"); Console.WriteLine("Password: " + pwd); string xyz = await util.GetSecretAsync("xyz"); Console.WriteLine("xyz: " + pwd); } } }

在Azure中的清理

在Azure门户中,返回到Cloud Shell。删除“CodeProject”资源组:

RESOURCE_GROUP='CodeProject' az group delete --name $RESOURCE_GROUP --yes

这将删除“CodeProject”资源组及其所有内容。如果不执行这一步,不用担心,Key Vault的费用非常低,每10000次操作只需3美分。可以在这里计算费用:

也可以通过Azure门户删除资源组。

首次检索机密可能非常慢

检索第一个密钥可能需要几秒钟。如果不确定是否总是需要从Key Vault中检索机密,可以考虑使用Lazy<T>类。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485