6
votes

I am trying to use the CloudBlobClient c# class in my v2 function app to read data from a file stored on Azure Blob Storage. When running locally my code is able to pull back the data, however when the code is deployed with the same connection string and my code call GetBlobReferenceFromServerAsync, I get the following error:

Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

I took the connection string from Storage Account > Access Keys > Connection String for Key1, which has the following format:

DefaultEndpointsProtocol=https;AccountName=<AccountName>;AccountKey=<AccountKey>;EndpointSuffix=core.windows.net

I have tried giving the App Service Account Owner access to the storage account and tried using shared access signatures, but nothing has worked so far. Are there certain permissions that need to be applied on either the Function App or Storage Account end in order to get this functionality working?

Below is a snippet of the code:

var storageConnectionString = blobConfig.ConnectionString;
if (CloudStorageAccount.TryParse(storageConnectionString, out var storageAccount))
{
    try
    {
        // Create the CloudBlobClient that represents the Blob storage endpoint for the storage account.
        var cloudBlobClient = storageAccount.CreateCloudBlobClient();

        var container = cloudBlobClient.GetContainerReference(containerName);
        var uri = new Uri(cloudBlobClient.BaseUri, $"/{containerName}{path}");

        // get the blob object and download to file
        // ---- THROWS ON NEXT LINE ----
        var blobRef = await cloudBlobClient.GetBlobReferenceFromServerAsync(uri); 

        var tempFilePath = System.IO.Path.GetTempFileName();
        await blobRef.DownloadToFileAsync(tempFilePath, System.IO.FileMode.Truncate);

        return tempFilePath;
    }
    catch (StorageException ex)
    {
        log.LogError(ex, "Error returned from the service: {0}", ex.Message);
        throw;
    }
}

Edit I should mention that the deployed version of this function is running on an Azure Dev/Test subscription. Not sure if that is at play here. I am going to try to deploy to a non-Dev subscription and see if it resolves anything.

1
Are you sure the connection string is being properly loaded? Where is the blobConfig loaded from/is blobConfig.ConnectionString set properly?ikkentim
Please check that your connection string is properly configured (App Settings?) and loaded in your function in Azure.Sebastian Achatz
@ikkentim - It is being loaded from the function's app settings. I was able to check that it was correct by base64 encoding it and logging it to application insights.gwoody1984
Is there a slash missing in your string $"/{containerName}{path} between containername and path? Which may end up in a different container name (with different access permissions?)Sebastian Achatz
@SebastianAchatz - the path has a preceding "/". The output of the uri is well formed and does point to an existing blobgwoody1984

1 Answers

3
votes

So after some testing, it looks like this is an issue isolated to Dev/Test subscriptions. A bit frustrating that I had to bang my head against the wall for a day to figure this out, but I guess that is the name of the game.

Hopefully this can help someone else running up against this issue.