DefaultAzureCredential的ManagedIdentity认证疑似存在Bug
DefaultAzureCredential因ManagedIdentity请求被网关拦截导致认证失败
问题现象
使用Azure.Storage.Blobs结合DefaultAzureCredential操作Azure存储账户时,程序因ManagedIdentityCredential认证失败崩溃;但在DefaultAzureCredentialOptions中设置ExcludeManagedIdentityCredential = true后,代码可正常运行,说明其他认证方式(如本地开发环境的Azure CLI/Visual Studio凭据)是有效的。
本地运行时抛出核心异常为403(GlobalBlock),提示公司网关拦截了对http://169.254.169.254/metadata/identity/oauth2/token的请求。
原因分析
DefaultAzureCredential会按预设顺序尝试多种认证方式,但并非所有失败都会被视为"凭据不可用"而跳过:
- 当请求IMDS(实例元数据服务)地址被网关拦截返回403时,该错误被判定为认证失败而非"凭据不可用",因此
DefaultAzureCredential会直接抛出异常,不会继续尝试后续的认证方式。 - 这并非SDK Bug,而是错误类型的判定逻辑导致:只有明确的"凭据不存在"类错误(如IMDS地址无法访问的连接超时)才会触发后续方式的尝试。
解决方案
方案1:排除ManagedIdentityCredential(最直接)
在初始化DefaultAzureCredential时显式排除ManagedIdentityCredential,让SDK跳过该认证方式,直接尝试其他可用方式:
var credential = new DefaultAzureCredential( new DefaultAzureCredentialOptions { ExcludeManagedIdentityCredential = true } );
方案2:调整网关策略(若公司允许)
联系IT团队,将http://169.254.169.254加入网关允许列表,解决IMDS请求被拦截的问题。
最小复现示例(MCVE)
项目文件
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Azure.Identity" Version="1.12.0" /> <PackageReference Include="Azure.Storage.Blobs" Version="12.20.0" /> </ItemGroup> </Project>
Program.cs
namespace ManagedIdentityCredentialProblem; using Azure.Identity; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; internal class Program { static async Task Main(string[] args) { var storageAccountName = "youraccountnamegoeshere"; var serviceUri = new Uri($"https://{storageAccountName}.blob.core.windows.net"); var credential = new DefaultAzureCredential( new DefaultAzureCredentialOptions { //// ExcludeManagedIdentityCredential = true } ); var blobServiceClient = new BlobServiceClient(serviceUri, credential); string containerName = "managedidentitycredentialproblem"; var blobContainerClient = blobServiceClient.GetBlobContainerClient(containerName); var cancellationToken = CancellationToken.None; await blobContainerClient.CreateIfNotExistsAsync(PublicAccessType.None, null, cancellationToken) .ConfigureAwait(false); } }
异常详情
Unhandled exception. Azure.Identity.AuthenticationFailedException: ManagedIdentityCredential authentication failed: Service request failed. Status: 403 (GlobalBlock) Content: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <script src="/mwg-internal/de5fs23hu73ds/files/javascript/sw.js" type="text/javascript" ></script> <title>Blocked Request: http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fstorage.azure.com%2F</title> <style type="text/css"> body { padding: 5px } p { margin: 1em 0; font-family: Tahoma,Sans; font-size: 12px; color: #333 } li { margin: 1em 0; font-family: Tahoma,Sans; font-size: 12px; color: #333 } </style> </head> <body> <h1 style="margin: 0 0 45px 0; font-family: Tahoma,Sans; font-size: 24px; font-weight: bold; color: #6569FE;">Redacted Security</h1> <!--Contents--> <p>The Web request to http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fstorage.azure.com%2F has been blocked. <p><b>Reason: Category (Global Blocklist)</b></p> <p>If you feel that the Web site you requested has been blocked inappropriately, please contact your system administrator.</p> <!--/Contents--> </body> </html> Headers: Cache-Control: no-cache X-Frame-Options: REDACTED Proxy-Connection: REDACTED Content-Type: text/html Content-Length: 1192 ---> Azure.RequestFailedException: Service request failed. Status: 403 (GlobalBlock) ...(省略后续堆栈跟踪)
内容的提问来源于stack exchange,提问作者Richardissimo
相关产品推荐
相关产品推荐

