Managing access control for containers and blobs
The Windows Azure Storage Service authenticates all requests against the Table service and Queue service. However, the storage service allows the possibility of unauthenticated access against the Blob service. The reason is that blobs provide an ideal location for storing large static content for a website. For example, the images in a photo-sharing site could be stored as blobs and downloaded directly from the Blob service without being transferred through a web role.
Public access control for the Blob service is managed at the container level. The Blob service supports the following three types of access control:
No public read access in which all access must be authenticated
Public read access which allows blobs in a container to be readable without authentication
Full public read access in which authentication is not required to read the container data and the blobs contained in it
No public read access is the same access control as for the Queue service and Table service. The other two access control types both allow anonymous access to a blob, so that, for example, the blob can be downloaded into a browser by providing its full URL.
In the Windows Azure Storage Client library, the BlobContainerPublicAccessType
enumeration specifies the three types of public access control for a container. The BlobContainerPermissions
class exposes two properties: PublicAccess
specifying a member of the BlobContainerPublicAccessType
enumeration and SharedAccessPolicies
specifying a set of shared access policies. The SetPermissions()
method of the CloudBlobContainer
class is used to associate a BlobContainerPermissions
instance with the container. The GetPermissions()
method retrieves the access permissions for a container.
In this recipe, we will learn how to specify the level of public access control for containers and blobs managed by the Blob service.
Getting ready
This recipe assumes the following is in the application configuration file:
<appSettings> <add key="DataConnectionString"value="DefaultEndpointsProtocol=https;AccountName={ACCOUNT_NAME};AccountKey={ACCOUNT_KEY}"/> </appSettings>
We must replace {ACCOUNT_NAME}
and {ACCOUNT_KEY}
with appropriate values for the account name and access key.
How to do it...
We are going to specify various levels of public access control for a container. We do this as follows:
Add a new class named
BlobContainerPublicAccessExample
to the project.Add the following
using
statements to the top of the class file:using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.StorageClient; using System.Configuration; using System.Net;
Add the following method, setting public access control for a container, to the class:
public static void CreateContainerAndSetPermission(String containerName, String blobName,BlobContainerPublicAccessType publicAccessType ) { CloudStorageAccount cloudStorageAccount =CloudStorageAccount.Parse(ConfigurationManager.AppSettings[ "DataConnectionString"]); CloudBlobClient cloudBlobClient =cloudStorageAccount.CreateCloudBlobClient(); CloudBlobContainer blobContainer =new CloudBlobContainer(containerName, cloudBlobClient); blobContainer.Create(); BlobContainerPermissions blobContainerPermissions =new BlobContainerPermissions() { PublicAccess = publicAccessType }; blobContainer.SetPermissions(blobContainerPermissions); CloudBlockBlob blockBlob =blobContainer.GetBlockBlobReference(blobName); blockBlob.UploadText("Has been changed glorious summer"); }
Add the following method, retrieving a blob, to the class:
public static void GetBlob(String containerName, String blobName) { CloudStorageAccount cloudStorageAccount =CloudStorageAccount.Parse(ConfigurationManager.AppSettings["DataConnectionString"]); Uri blobUri = new Uri(cloudStorageAccount.BlobEndpoint +containerName + "/" + blobName); HttpWebRequest httpWebRequest =(HttpWebRequest)HttpWebRequest.Create(blobUri); httpWebRequest.Method = "GET"; using (HttpWebResponse response =(HttpWebResponse)httpWebRequest.GetResponse()) { String status = response.StatusDescription; }}
Add the following method, using the method we just added, to the class:
public static void UseBlobContainerPublicAccessExample() { CreateContainerAndSetPermission("container1", "blob1",BlobContainerPublicAccessType.Blob); CreateContainerAndSetPermission("container2", "blob2",BlobContainerPublicAccessType.Container); CreateContainerAndSetPermission("container3", "blob3",BlobContainerPublicAccessType.Off); }
How it works...
In steps 1 and 2, we set up the class.
In step 3, we add a method that creates a container and blob, and applies a public access policy to the container. We create a CloudBlobClient
instance from the data connection string in the configuration file. We then create a new container using the name passed in to the method. Then, we create a BlobContainerPermissions
instance with the BlobContainerPublicAccessType
passed into the method and set the permissions on the container. Note that we must create the container before we set the permissions because SetPermissions()
sets the permissions directly on the container. Finally, we create a blob in the container.
In step 4, we use an HttpWebRequest
instance to retrieve the blob without providing any authentication. This request causes a 404 (Not Found) error when the request attempts to retrieve a blob that has not been configured for public access. Note that when constructing blobUri
for the storage emulator, we must add a /
into the path after cloudStorageAccount.BlobEndpoint
because of a difference in the way the Storage Client library constructs the endpoint for the storage emulator and the storage service. For example, we need to use the following for the storage emulator:
Uri blobUri = new Uri(cloudStorageAccount.BlobEndpoint + "/" +containerName + "/" + blobName);
In step 5, we add a method that invokes the CreateContainerAndSetPermission()
method once for each value of the BlobContainerPublicAccessType
enumeration. We then invoke the method twice, to retrieve blobs from different container. The second invocation leads to a 404 error since container3
has not been configured for unauthenticated public access.
See also
The recipe named Creating a Shared Access Signature for a container or blob in this chapter