Учетная запись хранения Azure отклоняет отправителя удостоверения управляемой службы

Я использую библиотеку Microsoft.Azure.Services.AppAuthentication (v1.0.3) для.NET для подключения из приложения-функции Azure к хранилищу больших двоичных объектов с использованием идентификатора управляемой службы. Код авторизации:

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?

ОБНОВЛЕНИЕ: Кросс отправил на форум MS, чтобы привлечь внимание MS при проверке, является ли это лазурной ошибкой.

3 ответа

Я только что провел хороший день с этой ошибкой. Возможно, это не связано с той же основной причиной, что и OP, но это может помочь другим, поэтому я решил опубликовать это здесь.

я использовалдля получения токена для моего пользователя, настроенного как учетная запись службы Azure в Visual Studio. Затем это автоматически переключится на использование управляемого удостоверения сервера приложений в средах, отличных от локального хоста.

В моем конкретном случае я увидел, что идентификатор клиента эмитента в JWT не соответствует идентификатору клиента объекта пользователя, упомянутому всобственность JWT. Это означало, что был получен токен для клиента моего пользователя, а не для клиента, в котором находился ресурс. Я решил эту проблему, указав правильный идентификатор клиента в параметрах учетных данных. Вот несколько шагов:

  1. Используйте это для получения и проверки токена, используемого клиентом больших двоичных объектов.
      // 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 показывает вамсвойство со значением типа"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);
}

Надеюсь это поможет!

Даже после проверки с помощью MS неясно, в чем была причина, но перемещение затронутых подписок в другой каталог Azure AD, похоже, устранило проблему.

Я проверяю ваш код авторизации, и как существующая, так и новая созданная учетная запись хранения принимают MSI. Поэтому я согласен с тем, что сказал juunas, это может быть ошибка в хранилище Azure.

Вы можете пойти сюда, чтобы оставить свой отзыв, чтобы позволить разработчикам исправить это.