【问题标题】:java.lang.IllegalArgumentException: Cannot create Shared Access Signature unless the Account Key credentials are used by the ServiceClientjava.lang.IllegalArgumentException:除非 ServiceClient 使用帐户密钥凭据,否则无法创建共享访问签名
【发布时间】:2019-08-04 17:58:11
【问题描述】:

我正在尝试使用 MSI 访问 Azure Blob 存储容器以生成共享访问签名。但是每次我尝试访问时,都会出现以下错误:

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

我不想使用凭据或 AAD 访问 blob 存储容器。只想使用 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 年的。

【问题讨论】:

    标签: azure azure-devops azure-blob-storage azure-managed-identity


    【解决方案1】:

    通过查看Azure Storage Java SDK,我发现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);
        }
    

    总之,如果您当前使用 MSI 作为身份验证,则无法生成 SharedAccessSignature。您可以将您的请求发布到Azure Storage User Voice。如果您的请求获得高票,开发人员团队可能会添加此功能。

    【讨论】:

      猜你喜欢
      • 2017-02-17
      • 2018-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      • 2023-01-03
      • 2023-04-09
      • 1970-01-01
      相关资源
      最近更新 更多