【问题标题】:Not able to connect to Azure Key Vault when using Service Identity使用服务标识时无法连接到 Azure Key Vault
【发布时间】:2019-01-26 05:10:34
【问题描述】:

我正在尝试使用 ASPNet 4.6.2 Web 应用程序中的服务标识从 Azure Key Vault 检索机密。我正在使用article 中概述的代码。在本地,一切正常,尽管这是因为它使用了我的身份。当我将应用程序部署到 Azure 时,调用 keyVaultClient.GetSecretAsync(keyUrl) 时出现异常。

据我所知,一切都已正确配置。我创建了一个用户分配的身份,以便可以重复使用它,并确保该身份可以获取访问 KeyVault 策略中的机密和密钥。

例外是AzureServiceTokenProviderException。它很冗长,并概述了它如何尝试四种方法进行身份验证。我担心的信息是它何时尝试使用托管服务身份:

尝试使用托管服务标识获取令牌。访问令牌可以 不会被收购。 MSI 响应代码:BadRequest,响应:

我检查了应用程序洞察力,发现它试图建立以下连接并出现 400 结果错误:

http://127.0.0.1:41340/MSI/token/?resource=https://vault.azure.net&api-version=2017-09-01

这有两点很有趣:

  1. 为什么要尝试连接到本地主机地址?这似乎是错误的。
  2. 这是否会因为资源参数未转义而返回 400?
  3. 在 MsiAccessTokenProvider source 中,它仅在设置环境变量 MSI_ENDPOINT 和 MSI_SECRET 时使用该形式的地址。它们没有在应用程序设置中设置,但是当我输出环境变量时,我可以在调试控制台中看到它们。

此时我不知道该怎么办。网上的例子都让它看起来很神奇,但如果我对问题的根源是正确的,那么有一些模糊的自动化设置需要修复。

为了完整起见,这里是我所有的相关代码:

public class ServiceIdentityKeyVaultUtil : IDisposable
{
    private readonly AzureServiceTokenProvider azureServiceTokenProvider;
    private readonly Uri baseSecretsUri;
    private readonly KeyVaultClient keyVaultClient;


    public ServiceIdentityKeyVaultUtil(string baseKeyVaultUrl)
    {
        baseSecretsUri = new Uri(new Uri(baseKeyVaultUrl, UriKind.Absolute), "secrets/");
        azureServiceTokenProvider = new AzureServiceTokenProvider();
        keyVaultClient = new KeyVaultClient(
            new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
    }

    public async Task<string> GetSecretAsync(string key, CancellationToken cancellationToken = new CancellationToken())
    {
        var keyUrl = new Uri(baseSecretsUri, key).ToString();
        try
        {
            var secret = await keyVaultClient.GetSecretAsync(keyUrl, cancellationToken);
            return secret.Value;
        }
        catch (Exception ex)
        {
            /** rethrows error with extra details */
        }
    }

    /** IDisposable support */
}

更新 #2 (我删除了更新 #1)

我创建了一个全新的应用程序或一个新的服务实例,并且能够重新创建错误。 然而,在所有情况下我都使用用户分配的身份。如果我删除它并使用 System Assigned Identity 那么它就可以正常工作。

我不知道为什么这些会有所不同。任何人都有见解,因为我希望用户分配一个。

【问题讨论】:

  • 请粘贴您的代码以获取秘密(当然要减去任何敏感信息)。 Microsoft.Azure.Services.AppAuthentication 库功能强大且经过验证,您无需深入研究问题。
  • @MurrayFoxcroft - 我更新了我的代码。
  • 4 的第一个例外是什么?
  • 这都是一个例外,但例外文本中的第一条消息是我在帖子中发布的。

标签: asp.net azure azure-keyvault


【解决方案1】:

用户分配身份的主要区别之一是您可以将其分配给多个服务。它在 azure 中作为单独的资产存在,而系统身份绑定到与之配对的服务的生命周期。

From the docs

系统分配的托管标识直接在 Azure 服务实例上启用。启用标识后,Azure 会在实例订阅信任的 Azure AD 租户中为实例创建一个标识。创建身份后,会将凭据配置到实例上。系统分配标识的生命周期直接与启用它的 Azure 服务实例相关联。如果实例被删除,Azure 会自动清理 Azure AD 中的凭据和标识。

用户分配的托管标识被创建为独立的 Azure 资源。通过创建过程,Azure 在 Azure AD 租户中创建一个受正在使用的订阅信任的身份。创建标识后,可以将标识分配给一个或多个 Azure 服务实例。用户分配标识的生命周期与其分配到的 Azure 服务实例的生命周期分开管理。

用户分配的身份仍处于应用服务的预览阶段。请参阅文档here。它可能仍处于私人预览版中(即 Microsoft 必须在您的订阅中明确启用它),它可能在您选择的区域不可用,或者它可能是一个缺陷。

【讨论】:

    【解决方案2】:

    要使用用户分配的身份,获取令牌的 HTTP 调用必须包含身份的 ID。 否则它将尝试使用系统分配的身份。

    为什么要尝试连接到本地主机地址?这似乎是错误的。

    因为 MSI 端点对于应用服务来说是本地的,只能从实例内部访问。

    这是否会因为资源参数未转义而返回 400?

    是的,但我认为这不是原因。

    在 MsiAccessTokenProvider 源中,它仅在设置环境变量 MSI_ENDPOINT 和 MSI_SECRET 时使用该地址形式。它们不是在应用程序设置中设置的,但是当我输出环境变量时,我可以在调试控制台中看到它们。

    这些是由应用服务隐形添加的,而不是添加到应用设置中。

    至于如何使用用户分配的身份, 我看不到使用 AppAuthentication 库的方法。 您可以在 Azure 中手动进行 HTTP 调用:https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http。 然后你必须照顾自己的缓存! 托管身份端点无法一次处理大量查询 :)

    【讨论】:

      猜你喜欢
      • 2020-02-09
      • 1970-01-01
      • 2021-10-22
      • 2021-10-11
      • 2020-05-04
      • 2020-06-02
      • 1970-01-01
      • 2021-12-22
      • 2021-05-17
      相关资源
      最近更新 更多