在获取 Azure Key Vault 的令牌时,尝试从令牌凭据的所有变体中弄明白

问题描述

我正在使用 .Net 5 构建 Web API。Web API 受 Azure AD 保护并且可由单个租户访问。 Web API 将连接到其他 Azure 资源(存储、Cosmos DB 等),这些资源的连接字符串作为机密存储在 Azure Key Vault 中。

我的目标是在 API 启动时从 Azure Key Vault 获取这些连接字符串(机密),并使用它们连接到这些资源。当 Web API 部署到生产环境时,它将使用 managed identity 连接到 Key Vault 并获取机密。在开发过程中,我想使用其他一些机制来连接和获取秘密。我不想为此创建 Service Principal 并使用客户端 ID/客户端机密。

我想知道如何在开发过程中完成连接,然后我发现了获取令牌的不同机制。然而,当我使用它们时,我遇到了许多问题,现在我对使用它们感到困惑。

1. ChainedTokenCredential

在研究过程中,我遇到了 Secretless Development from Local to Cloud with the New Azure SDKs,Project Tye,and Kubernetes 视频和随后的 memealyzer 项目,在那里我了解了 ChainedTokenCredential。根据我的理解,您可以链接多个令牌凭据,并且 SDK 将尝试连接到每个令牌凭据,直到成功为止。这对我来说听起来很完美,我最终实现了类似于以下的代码

ChainedTokenCredential chainedTokenCredential = new ChainedTokenCredential(
    new ManagedIdentityCredential(),new VisualStudioCredential()
    );
SecretClient client = new SecretClient(new Uri("https://mykv.vault.azure.net"),chainedTokenCredential);
keyvaultSecret secret = await secretClient.GetSecretAsync("mysecretkeyname");

根据我的理解,如果我在 Visual Studio 中运行上面的代码代码应该首先尝试使用 ManagedIdentityCredential()(它会失败),然后是 VisualStudioCredential()(它应该会成功,因为我是使用有权访问 Key Vault 机密的帐户登录 Visual Studio

然而令我惊讶的是,代码抛出了以下异常:

    Azure.Identity.CredentialUnavailableException: The ChainedTokenCredential Failed to retrieve a token from the included credentials. 
    - ManagedIdentityCredential authentication unavailable. No Managed Identity endpoint found. 

异常是有道理的,因为我在本地运行代码。但是,我的理解是,如果出现异常,SDK 将自动尝试链中的下一个凭据提供程序。就我而言,如果通过 VisualStudioCredential 获取令牌失败,我希望代码自动尝试 ManagedIdentityCredential。然而,这并没有发生。

2. VisualStudioCredential

接下来,我注释掉了 ManagedIdentityCredential() 并只使用了 VisualStudioCredential,我认为考虑到我使用正确的凭据登录到 Visual Studio,它会起作用。

enter image description here

ChainedTokenCredential chainedTokenCredential = new ChainedTokenCredential(
    //new ManagedIdentityCredential(),chainedTokenCredential);
keyvaultSecret secret = await secretClient.GetSecretAsync("mysecretkeyname");

然而,这也失败了,并出现以下错误

Azure.Identity.CredentialUnavailableException: Operating system Darwin 20.3.0 Darwin Kernel Version 20.3.0: Thu Jan 21 00:06:51 PST 2021; root:xnu-7195.81.3~1/RELEASE_ARM64_T8101 isn't supported.

3. AzureCliCredential

感到困惑,我将 VisualStudioCredential 替换为 AzureCliCredential 并再次尝试。我已安装最新版本的 Azure CLI (2.21.0),并在外部终端和 Visual Studio 内的终端中使用 az login 命令登录到 Azure CLI。

enter image description here

ChainedTokenCredential chainedTokenCredential = new ChainedTokenCredential(
    //new ManagedIdentityCredential(),new AzureCliCredential()
    );
SecretClient client = new SecretClient(new Uri("https://mykv.vault.azure.net"),chainedTokenCredential);
keyvaultSecret secret = await secretClient.GetSecretAsync("mysecretkeyname");

然而,这也失败了,并出现以下错误

Azure.Identity.CredentialUnavailableException: Azure CLI not installed 

考虑到已安装 Azure CLI 并且我已登录,这没有任何意义。

4. DefaultAzureCredential

极度困惑和沮丧,我最终决定使用DefaultAzureCredential,认为这是我的最后手段。但是我没有在 Azure AD 等中创建任何应用注册,只是执行了以下代码

SecretClient client = new SecretClient(new Uri(keyvaultConfiguration.VaultUri),new DefaultAzureCredential());
keyvaultSecret secret = await secretClient.GetSecretAsync("mysecretkeyname");

现在我原以为代码会失败,但出乎我意料的是代码有效(我猜是 Azure 身份的奥秘:))并且我能够获得秘密。我想知道为什么上述代码有效以及它选择了哪个令牌凭据(考虑到我都使用相同的凭据登录到 Visual Studio 和 Azure CLI)。

开发环境

  • IDE:Visual Studio version 8.9.4 (build 25)
  • 操作系统:macOS Big Sur (11.2.3) [Apple Silicon]
  • SDK:Azure.Identity (version 1.3.0)

问题

感谢您阅读到目前为止(结果是一篇很长的文章)。总而言之,以下是我的问题:

  1. 在前三个案例中我做错了什么?
  2. 为什么 ChainedTokenCredential 的实现在 ManagedIdentityCredential 上失败并且没有继续到下一个?我是否误解了 ChainedTokenCredential 的实现?
  3. 为什么 VisualStudioCredential 实现失败并出现 not supported platform 错误
  4. 为什么 AzureCliCredential 实现失败并出现 Azure CLI not installed 错误,但它确实已安装并且我已登录
  5. 最后,没有做任何特别的事情,为什么 DefaultAzureCredential 实现有效?此外,它选择了哪些凭据?

对此的任何见解将不胜感激。

解决方法

有关这些问题的讨论,请参阅 GitHub 问题 https://github.com/Azure/azure-sdk-for-net/issues/20210

,

部分答案

我将开始回答一些问题。我在 Github (https://github.com/Azure/azure-sdk-for-net/issues/20210) 上提出了一个关于相同的问题,我的回答将基于我从那里得到的信息。

为什么 VisualStudioCredential 实现失败了 支持的平台错误?

Mac 上的 Visual Studio 目前基本上不支持 VisualStudioCredential,因为它目前不支持登录 Azure AD(除了许可)。跟踪此内容时出现问题:https://github.com/Azure/azure-sdk-for-net/issues/20283