Bill Noel
Bill Noel

Reputation: 1150

Azure Functions Blob Container Binding SaS Key

I'm trying to use the C# and Azure Storage bindings to get access to a blob container so that I can generate a SaS token in an authenticated HttpTrigger function. I want a user to be able to upload and download their stuff from a mobile device.

I know how to do this if I load the entire Storage SDK, but I was trying to do it somehow through the bindings, including using IBinder.

I already have the code working with the SDK, (partial below) but there are some incompatibilities between the SDK and various versions of the storage extensions for Azure Functions.

I thought it would be best to just use the extensions, but without being able to bind to the container, it's unclear to me how to do it.

I thought for sure this would be possible, but I can't seem to figure this out.

Anyone have any ideas?

TIA

var container =
    storageAccount.CreateCloudBlobClient().GetContainerReference($"{partitionId}");

var exists =
    await container.ExistsAsync();

if (!exists)
{
    await container.CreateAsync();
}

int sasBlobExpirationMinutes =
    Convert.ToInt32(
        Environment.GetEnvironmentVariable(BLOB_SAS_EXPIRATION_MINUTES)
    ); ;

var policy = new SharedAccessBlobPolicy
{
    SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5),
    SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(sasBlobExpirationMinutes),
    Permissions =
        SharedAccessBlobPermissions.Read |
        SharedAccessBlobPermissions.List
};

var token =
    container.GetSharedAccessSignature(policy);

Upvotes: 1

Views: 1164

Answers (1)

George Chen
George Chen

Reputation: 14334

If you just want to know how to bind the container you could just use [Blob("test")]CloudBlobContainer container to implement it, however you still use Microsoft.WindowsAzure.Storage.Blob package to use it.

The below is my test code, bind the container to get the sas uri then use the uri to create a blob.

[FunctionName("Function1")]
    public static HttpResponseMessage Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req,
        [Blob("test")]CloudBlobContainer container,
         TraceWriter log)
    {
        log.Info("C# HTTP trigger function processed a request.");
        var policyName = "testpolicy";
        var storedPolicy = new SharedAccessBlobPolicy()
        {
            SharedAccessExpiryTime = DateTime.UtcNow.AddHours(10),
            Permissions = SharedAccessBlobPermissions.Read |
              SharedAccessBlobPermissions.Write |
              SharedAccessBlobPermissions.List
        };

        // get the existing permissions (alternatively create new BlobContainerPermissions())
        var permissions = container.GetPermissions();

        // optionally clear out any existing policies on this container
        permissions.SharedAccessPolicies.Clear();
        // add in the new one
        permissions.SharedAccessPolicies.Add(policyName, storedPolicy);
        // save back to the container
        container.SetPermissions(permissions);

        // Now we are ready to create a shared access signature based on the stored access policy
        var containerSignature = container.GetSharedAccessSignature(null, policyName);
        // create the URI a client can use to get access to just this container
        Uri uri = new Uri(container.Uri + containerSignature);

        var cloudBlobContainer = new CloudBlobContainer(uri);

        foreach (var blob in cloudBlobContainer.ListBlobs())
        {
            Console.WriteLine(blob.Uri);
        }

        var blockBlob = cloudBlobContainer.GetBlockBlobReference("testBlob.txt");
        blockBlob.UploadText("Hello world");

        return req.CreateResponse(HttpStatusCode.OK,  uri);
    }

Here is the result picture.

enter image description here

enter image description here

Hope this is what you want, if you still have problem please let me know.

Upvotes: 1

Related Questions