Azure存储帐户拒绝托管服务标识的颁发者



我正在使用.NET的Microsoft.Azure.Services.AppAuthentication库(v1.0.3(,使用托管服务标识从Azure Function应用程序连接到blob存储。授权码:

var tokenProvider = new AzureServiceTokenProvider();
string accessToken = await tokenProvider.GetAccessTokenAsync("https://storage.azure.com/");
var tokenCredential = new TokenCredential(accessToken);
var credentials = new StorageCredentials(tokenCredential);
var storageUri = new Uri($"https://{accountName}.blob.core.windows.net");
var client = new CloudBlobClient(storageUri, credentials);

一个现有存储帐户拒绝接受MSI,而不管给定的RBAC角色是什么:

Microsoft.WindowsAzure.Storage.StorageException: Server failed to authenticate the request.
Make sure the value of Authorization header is formed correctly including the signature.
at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteAsyncInternal[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext, CancellationToken token)
at Microsoft.WindowsAzure.Storage.Blob.CloudBlobContainer.CreateIfNotExistsAsync(BlobContainerPublicAccessType accessType, BlobRequestOptions options, OperationContext operationContext, CancellationToken cancellationToken)

storageException.RequestInformation.ExtendedErrorInformation.AdditionalDetails的其他异常详细信息抱怨AuthenticationErrorDetail: Issuer validation failed. Issuer did not match.

当解码失败的jwt令牌时,颁发者似乎可以:

{
"aud": "https://storage.azure.com/",
"iss": "https://sts.windows.net/<my directory guid>/",
...
}

当我创建新的相同设置的存储帐户时,相同的功能应用程序MSI和身份验证代码起作用,甚至令牌中的颁发者也完全相同。因此,客户端功能应用程序及其MSI身份并不是罪魁祸首。

为什么这个存储帐户无法授权,以及如何让它接受MSI

更新:Cross发布到MS论坛,以引起MS的注意,验证这是否是一个azure错误。

我刚刚度过了一个有这个错误的美好一天。这可能不是由于与OP相同的根本原因,但它可能会帮助其他人,所以我想我会把它发布在这里。

我使用DefaultAzureCredential类为我的用户检索令牌,该令牌在Visual Studio中配置为Azure服务帐户。然后,这将自动切换到在非本地主机环境中使用应用服务器的托管标识。

对于我的特定案例,我发现JWT中发布者的租户id与JWT的oid属性中提到的用户对象的租户id不匹配。这意味着检索到了用户租户的令牌,而不是资源所在的租户。我通过在凭据选项中提供正确的租户id解决了这个问题。以下是一些步骤:

  1. 使用此选项可以检索和检查blob客户端使用的令牌
// This will try to use the VisualStudioCredential to get a token as all other options will fail
var token = await new DefaultAzureCredential().GetTokenAsync(new Azure.Core.TokenRequestContext(new[] { "https://mystorageaccount.blob.core.windows.net/.default" }));

通过jwt.ms解码此令牌将显示iss属性,其值类似于"https://sts.windows.net/{issuerTenantId}/"

  1. 如何手动设置凭据的正确租户
var cred = new DefaultAzureCredential(new DefaultAzureCredentialOptions()
{
VisualStudioTenantId = tenantId
});
var storageclient = new BlobServiceClient(new Uri(url), cred);
BlobContainerClient container = _storageclient.GetBlobContainerClient(containerId);
await container.CreateIfNotExistsAsync();
BlobClient blob = container.GetBlobClient(blobId);
byte[] byteArray = JsonSerializer.SerializeToUtf8Bytes(entity);
using (var stream = new MemoryStream(byteArray))
{
await blob.UploadAsync(stream, overwrite: true);
}

希望这能有所帮助!

我使用您的Auth代码进行测试,并且现有和新建的存储帐户都接受MSI。所以我同意juunas所说的,这可能是Azure存储上的一个错误。

你可以去这里给出你的反馈,让开发人员修复它。

即使在与MS核实后,也不清楚原因是什么,但将受影响的订阅移动到另一个Azure AD目录似乎已经解决了这个问题。

最新更新