java.lang.IllegalArgumentException: невозможно создать подпись общего доступа, если учетные данные ключа учетной записи не используются ServiceClient

Я пытаюсь использовать MSI для доступа к контейнерам хранилища BLOB-объектов Azure для создания подписи общего доступа. Но каждый раз, когда я пытаюсь получить доступ, я получаю следующую ошибку:

`java.lang.IllegalArgumentException: Cannot create Shared Access Signature unless the Account Key credentials are used by the ServiceClient.` 

Я не хочу получать доступ к контейнеру хранилища BLOB-объектов, используя учетные данные или AAD. Просто хочу использовать MSI, так как это уникальный режим, который мы хотим адаптировать в нашем приложении для доступа к ресурсам Azure. Чего мне не хватает. Я проверил в своих журналах Splunk, что токен MSI успешно генерируется. Ниже показано, как я создаю CloudBlobClient для доступа к контейнеру Blob:

public CloudBlobClient cloudBlobClient() throws URISyntaxException {
    String storageAccountName = propertyUtil.getStorageAccountName();
    // Implemented some logic in AzureStorageMSICredential class to fetch access 
    // token, and its working correctly
    String msiToken = azureStorageMSICredentials.getToken();
    LOG.info("Initiating CloudBlobClient.... msitoken = " + msiToken);
    StorageCredentials storageCredentials =
      new StorageCredentialsToken(storageAccountName, msiToken);

    URI storageAccountURI = URIUtils.getStorageAccountURI(storageAccountName);
    CloudBlobClient cloudBlobClient = new CloudBlobClient(storageAccountURI, 
      storageCredentials);
    return cloudBlobClient;
  }

Я просмотрел много потоков в stackoverflow, которые кажутся дубликатами этого, но на самом деле это не так. Некоторые из них 2017 года.


person KCS    schedule 04.08.2019    source источник


Ответы (1)


Изучив пакет SDK для Java службы хранилища Azure, я обнаружил, что метод generateSharedAccessSignature, наконец, вызовет следующее:

public String generateSharedAccessSignature(
        final SharedAccessBlobPolicy policy, final SharedAccessBlobHeaders headers,
        final String groupPolicyIdentifier, final IPRange ipRange, final SharedAccessProtocols protocols)
        throws InvalidKeyException, StorageException {

    if (!StorageCredentialsHelper.canCredentialsSignRequest(this.blobServiceClient.getCredentials())) {
        throw new IllegalArgumentException(SR.CANNOT_CREATE_SAS_WITHOUT_ACCOUNT_KEY);
    }

    final String resourceName = this.getCanonicalName(true);

    final String signature = SharedAccessSignatureHelper.generateSharedAccessSignatureHashForBlobAndFile(
            policy, headers, groupPolicyIdentifier, resourceName, ipRange, protocols, this.blobServiceClient,
            this.isSnapshot() ? Constants.QueryConstants.BLOB_SNAPSHOT_SERVICE : Constants.QueryConstants.BLOB_RESOURCE,
            this.getSnapshotID());

    final UriQueryBuilder builder = SharedAccessSignatureHelper.generateSharedAccessSignatureForBlobAndFile(
            policy, headers, groupPolicyIdentifier,
            this.isSnapshot() ? Constants.QueryConstants.BLOB_SNAPSHOT_SERVICE : Constants.QueryConstants.BLOB_RESOURCE,
            ipRange, protocols, signature);

    return builder.toString();
}

Строка подписи представляет собой строку Hmac256. В StorageCredentialsHelper есть метод для его вычисления.

public static synchronized String computeHmac256(final StorageCredentials creds, final String value) throws InvalidKeyException {
    if (creds.getClass().equals(StorageCredentialsAccountAndKey.class)) {
        byte[] utf8Bytes = null;
        try {
            utf8Bytes = value.getBytes(Constants.UTF8_CHARSET);
        }
        catch (final UnsupportedEncodingException e) {
            throw new IllegalArgumentException(e);
        }
        return Base64.encode(((StorageCredentialsAccountAndKey) creds).getHmac256().doFinal(utf8Bytes));
    }
    else {
        return null;
    }
}

В этом методе требуется StorageCredentialsAccountAndKey. Это ключ, который можно использовать для подписи данных. Однако, поскольку вы использовали MSI в качестве аутентификации, используемый вами токен на самом деле был токеном доступа AAD, который нельзя использовать для входа в этом месте. Вы можете проверить это с помощью следующего кода:

StorageCredentials credentials = blobClient.getCredentials();
System.out.println(credentials.toString(true));

Итак, в методе generateSharedAccessSignature будет выброшена ошибка:

    if (!StorageCredentialsHelper.canCredentialsSignRequest(this.blobServiceClient.getCredentials())) {
        throw new IllegalArgumentException(SR.CANNOT_CREATE_SAS_WITHOUT_ACCOUNT_KEY);
    }

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

person Jack Jia    schedule 05.08.2019