user8620003
user8620003

Reputation:

Azure Blob returning 403 on upload

I have an azure function that generates a sas key that I later use to upload files to my blob. Here is how I generate the sas key :

CloudBlobContainer container = blobClient.GetContainerReference("sasimagecontainer");
container.CreateIfNotExists();

static string GetContainerSasUri(CloudBlobContainer container)
{
    //Set the expiry time and permissions for the container.
    //In this case no start time is specified, so the shared access signature becomes valid immediately.
    SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy();
    sasConstraints.SharedAccessStartTime = DateTimeOffset.UtcNow.AddMinutes(-5);
    sasConstraints.SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddMinutes(25);
    sasConstraints.Permissions = SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Add | SharedAccessBlobPermissions.Create;

    //Generate the shared access signature on the container, setting the constraints directly on the signature.
    string sasContainerToken = container.GetSharedAccessSignature(sasConstraints);

    //Return the URI string for the container, including the SAS token.
    return container.Uri + sasContainerToken + "&comp=list&restype=container";
}

And then I can call

GetContainerSasUri(container));

to get the sas key. But when I use the following code to call it :

CloudBlockBlob blob = new CloudBlockBlob(thesaskey);
using (var fileStream = File.OpenRead(file))
{
    await blob.UploadFromStreamAsync(fileStream);
}

I keep getting 403 errors. That's all I'm getting from debugging in VS 2017, I'm not sure how can I acquire more information about this problem.

I already looked into most similar threads on SO regarding similar issues and applied possible fixes, like for example the "&comp=list&restype=container" parameter at the end.

// I tried adding SharedAccessBlobPermissions.List to permissions, that didn't work.

// I added literally all the permissions (except None, of course) to check if that might change something - it doesn't. The goal is still to only have permissions to upload.

Upvotes: 1

Views: 864

Answers (1)

Martin Brandl
Martin Brandl

Reputation: 59001

I was able to reproduce the error and this is how I fixed it:

You need to pass the SAS to a CloudBlobContainer instead of a CloudBlockBlob. Then use the container to retrieve a blob reference (you may want to use the filename property of your file):

var container = new CloudBlobContainer(thesaskey);
var blob = container.GetBlockBlobReference("<yourFileName>");
await blob.UploadFromFileAsync(@"YOURPATH")

Notice that there is a convenience method UploadFromFileAsync that you can use


Here is the console application that I used to test it:

class Program
{
    static void Main(string[] args)
    {

        var connectionString = String.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
            "<AccountName>",
            "<AccountKey>");
        var storageAccount = CloudStorageAccount.Parse(connectionString);
        var blobClient = storageAccount.CreateCloudBlobClient();


        var container = blobClient.GetContainerReference("sasimagecontainer");
        container.CreateIfNotExistsAsync().GetAwaiter().GetResult();

        var sasUri = GetContainerSasUri(container);


        var container2 = new CloudBlobContainer(new Uri(sasUri));
        var blob2 = container2.GetBlockBlobReference("blobCreatedViaSAS.txt");
        blob2.UploadFromFileAsync(@"D:\test.txt").GetAwaiter().GetResult();

    }

    private static string GetContainerSasUri(CloudBlobContainer container)
    {

        //Set the expiry time and permissions for the container.
        //In this case no start time is specified, so the shared access signature becomes valid immediately.
        SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy();
        sasConstraints.SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddHours(24);
        sasConstraints.Permissions = SharedAccessBlobPermissions.List | SharedAccessBlobPermissions.Write |
                                     SharedAccessBlobPermissions.Create |
                                     SharedAccessBlobPermissions.Add | SharedAccessBlobPermissions.Read;

        //Generate the shared access signature on the container, setting the constraints directly on the signature.
        var sasContainerToken = container.GetSharedAccessSignature(sasConstraints);

        //Return the URI string for the container, including the SAS token.
        return container.Uri + sasContainerToken;
    }
}

Upvotes: 1

Related Questions