You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用系统托管身份在C# Azure Function中无法获取Key Vault密钥

问题描述

我在Azure Function(服务总线主题触发器)中启用了系统分配托管身份,将该身份的对象(主体)ID添加到Key Vault访问策略,授予密钥、机密的Get,List权限。已在Azure Function应用设置中添加Key Vault引用,部署后运行时可正常获取密钥,引用格式为@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931)。

代码实现

private async Task<string> FetchSecretValueFromKeyvault(string secretName)
{
    _logger.LogInformation($"FetchSecretValueFromKeyvault: SecretName {secretName}");
    string actualSecret = string.Empty;
    try
    {
        string systemAssignedClientId = GetEnvironmentVariable("AzureADManagedIdentityClientId");
        string azureKeyVaultUrl = GetEnvironmentVariable("AzureKeyVaultUrl");
        var defaultAzureCredentialOptions = new DefaultAzureCredentialOptions();
        defaultAzureCredentialOptions.ExcludeAzureCliCredential = true;
        defaultAzureCredentialOptions.ExcludeEnvironmentCredential = true;
        defaultAzureCredentialOptions.ExcludeAzurePowerShellCredential = true;
        defaultAzureCredentialOptions.ExcludeInteractiveBrowserCredential = true;
        defaultAzureCredentialOptions.ExcludeManagedIdentityCredential = false;
        defaultAzureCredentialOptions.ExcludeSharedTokenCacheCredential = true;
        defaultAzureCredentialOptions.ExcludeVisualStudioCodeCredential = true;
        defaultAzureCredentialOptions.ExcludeVisualStudioCredential = true;
        defaultAzureCredentialOptions.ManagedIdentityClientId = systemAssignedClientId;

        var credential = new DefaultAzureCredential(defaultAzureCredentialOptions);

        var client = new SecretClient(new Uri(AzureKeyVaultUrl)), credential);
        var secret = await client.GetSecretAsync(secretName).ConfigureAwait(false);
        actualSecret = secret.Value.Value;
        _logger.LogInformation($"FetchSecretValueFromKeyvault:  Received secretValue for {secretName}");
    }
    catch (RequestFailedException ex)
    {
        actualSecret = string.Empty;
        _logger.LogError($"Message: {ex.Message}. \nInnerException:{ex.InnerException}. \nStackTrace: {ex.StackTrace}. \nInnerExceptionMessage:{ex.InnerException?.Message}.");
    }
    catch (Exception ex)
    {
        actualSecret = string.Empty;
        _logger.LogError($"Message: {ex.Message}. \nInnerException:{ex.InnerException}. \nStackTrace: {ex.StackTrace}. \nInnerExceptionMessage:{ex.InnerException?.Message}.");
    }
    return actualSecret;
}

环境配置

  • 本地与Azure Function应用设置:
    "AzureADManagedIdentityClientId": "xxx-123-abc-xyz-567890",
    "AzureKeyVaultUrl": "https://keyvaulturl.azurewebsites.net"
    
  • NuGet包版本:
    • Azure.Security.KeyVault.Secrets -- 4.3.0
    • Azure.Extensions.AspNetCore.Configuration.Secrets -- 1.2.2
    • Azure.Identity -- 1.6.1
  • Function运行时版本:.NET Core V3.1

报错信息

  • 本地调试:ManagedIdentityCredential authentication unavailable. Multiple attempts failed to obtain a token from the managed identity endpoint.
  • 部署后(Application Insights):No Managed Identity found for specified ClientId/ResourceId/PrincipalId. Status: 400 (Bad Request)

已反复核对PrincipalId,确认本地和应用设置中值正确,请问哪里操作有误?


问题排查与解决

1. 系统分配托管身份无需指定ClientId

系统分配托管身份与Azure Function资源绑定,不需要手动设置ManagedIdentityClientId。你给DefaultAzureCredentialOptions.ManagedIdentityClientId赋值后,SDK会按用户分配托管身份的逻辑去查找,而你的场景是系统分配,自然会找不到对应身份,触发400错误。

解决:删除defaultAzureCredentialOptions.ManagedIdentityClientId = systemAssignedClientId;这一行代码,SDK会自动使用系统分配的托管身份。

2. 本地调试的托管身份适配

本地环境没有Azure托管身份的运行时支撑,直接用ManagedIdentityCredential必然报错。可以修改DefaultAzureCredentialOptions,允许使用Azure CLI或Visual Studio的凭据进行本地调试:

defaultAzureCredentialOptions.ExcludeAzureCliCredential = false;
// 或保留Visual Studio凭据选项
defaultAzureCredentialOptions.ExcludeVisualStudioCredential = false;

调试前确保你登录Azure CLI/VS的账号已拥有Key Vault的Get,List权限。

3. Key Vault URL配置错误

你的AzureKeyVaultUrl设置为https://keyvaulturl.azurewebsites.net,这是Web App的URL格式,Key Vault的正确URL应为https://{vault-name}.vault.azure.net(例如https://myvault.vault.azure.net),错误的URL会导致SecretClient无法连接到正确服务。

4. 代码语法错误

创建SecretClient的语句存在括号配对错误,且变量名大小写不一致:

// 错误写法
var client = new SecretClient(new Uri(AzureKeyVaultUrl)), credential);
// 修正后
var client = new SecretClient(new Uri(azureKeyVaultUrl), credential);

内容的提问来源于stack exchange,提问作者PavanKumar GVVS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 16:24:14