Получение ошибки при создании токена SAS для большого двоичного объекта службы хранилища Azure с помощью MSI

Я пытаюсь создать маркер SAS для большого двоичного объекта хранилища. Я использую StorageCredentials, который был создан с помощью MSI (Managed Service Identity) для создания CloudBlobClient. При создании SAS я получаю сообщение Невозможно создать подпись общего доступа, если не используются учетные данные ключа учетной записи. Есть ли поддержка SAS с MSI?

var container = blobClient.GetContainerReference(containerName);
var blockBlob = container.GetBlockBlobReference(snapname);
var sas = string.Concat(blockBlob.Uri.ToString(), blockBlob.GetSharedAccessSignature(sasConstraints));

Вот как я создаю StorageCredentials:

tokenCallback = CreateMsiCallback();
var initToken = await tokenCallback(audience);
return new StorageCredentials(
  new TokenCredential(initToken, async (state, token) =>
  {
    var accessToken = await _tokenCallback(audience);

    return new NewTokenAndFrequency(accessToken, TimeSpan.FromMinutes(1));
  }, null, TimeSpan.FromMinutes(1))
);

Чтобы создать обратный вызов токена, я использую HttpClient

public Func<string, Task<string>> CreateMsiCallback()
{
  var handler = new HttpClientHandler
  {
     ServerCertificateCustomValidationCallback =
         (httpRequestMessage, cert, certChain, policyErrors) =>
         {
             if (policyErrors == SslPolicyErrors.None)
             {
                 return true;
             }

             return 0 == string.Compare(cert.GetCertHashString(), FabricThumbprint, StringComparison.OrdinalIgnoreCase);
        }
  };

     var client = new HttpClient(handler)
     {
         DefaultRequestHeaders =
         {
            {"secret", FabricAuthenticationCode }
         }
     };

     return async (resource) =>
     {
            var requestUri = $"{FabricMsiEndpoint}?api-version={FabricApiVersion}&resource={HttpUtility.UrlEncode(resource)}";
            var requestMessage = new HttpRequestMessage(HttpMethod.Get, requestUri);
            var response = await client.SendAsync(requestMessage);
            response.EnsureSuccessStatusCode();
            var tokenResponseString = await response.Content.ReadAsStringAsync();
            var tokenResponseObject =
                JsonConvert.DeserializeObject<ManagedIdentityTokenResponse>(tokenResponseString);
            
            return tokenResponseObject.AccessToken;
        };
    }
}

person Shimon Shrem    schedule 05.05.2021    source источник
comment
Поскольку вы используете MSI, почему вы не используете Azure ad auth для доступа к Azure Blob?   -  person Jim Xu    schedule 05.05.2021
comment
У нас есть платформа, которая подключается к различным средам, некоторые из них основаны на Service Fabric, некоторые нет, а некоторые предназначены для тестирования и разработки на локальных машинах. Итак, нам нужен общий API.   -  person Shimon Shrem    schedule 07.05.2021


Ответы (1)


Исходя из этого Github issue, вам нужно будет назначить данные хранилища ролей в ваш MSI, чтобы сгенерировать токен SAS. Из этой ветки:

Ошибка связана с тем, что у вашей учетной записи oauth нет разрешения на созданиеUserDelegationKey. Чтобы получить SAS с контекстом хранения Oauth (New-AzStorageContext -UseConnectedAuth), нам нужно сначала сгенерировать UserDelegationKey с сервера, а затем использовать ключ для генерации токена SAS.

Убедитесь, что вы назначили правильные роли пользователю, входящему в систему Oauth (с помощью Connect-AzAccount). например, по крайней мере, одна из следующих 4 ролей в конкретной учетной записи хранения:

  • Владелец данных BLOB-объектов хранилища
  • Участник данных BLOB-объектов хранилища
  • Читатель данных BLOB-объектов хранилища
  • Делегатор BLOB-объектов хранилища
person Gaurav Mantri    schedule 05.05.2021