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

﹥>﹥吖頭↗ 提交于 2019-12-11 04:49:05

问题


I am trying to use MSI to access Azure Blob Storage containers to generate shared access signature. But every time i am trying to access , i am getting following error:

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

I dont want to access blob storage container using credentials or AAD. Just want to use MSI, as this is the unique mode that we want to adapt in our application to access Azure resources. What this thing i am missing. I checked in my Splunk logs that MSI token is generating successfully. Below is the way i am creating the CloudBlobClient to access Blob container:

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;
  }

I searched many threads on stackoverflow, which seems dupliate of this one, but not really. Some are of 2017.


回答1:


By reviewing the Azure Storage Java SDK, I find that the generateSharedAccessSignature method will finally call the following:

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();
}

The signature string is a Hmac256 string. There is a method in StorageCredentialsHelper to compute it.

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;
    }
}

In this method, a StorageCredentialsAccountAndKey is required. It is a key which can be used to sign data. However, as you were using MSI as authentication, the token you used was actually an AAD access token which cannot be used to sign in this place. You can check that with the following code:

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

So, in the generateSharedAccessSignature method, an error will be thrown:

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

In conclusion, you are not able to generate SharedAccessSignature if you use MSI as authentication currently. You may post your request to the Azure Storage User Voice. If your request is voted high, the developer team may add this feature.



来源:https://stackoverflow.com/questions/57349028/java-lang-illegalargumentexception-cannot-create-shared-access-signature-unless

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!