Secure access to an application's data in the cloud

This tutorial is part three of a series. You learn how to secure access to the storage account.

In part three of the series, you learn how to:

  • Use SAS tokens to access thumbnail images
  • Turn on server-side encryption
  • Enable HTTPS-only transport

Azure blob storage provides a robust service to store files for applications. This tutorial extends the previous topic to show how to secure access to your storage account from a web application. When you're finished the images are encrypted and the web app uses secure SAS tokens to access the thumbnail images.


To complete this tutorial you must have completed the previous Storage tutorial: Automate resizing uploaded images using Event Grid.

Set container public access

In this part of the tutorial series, SAS tokens are used for accessing the thumbnails. In this step, you set the public access of the thumbs container to off.


blobStorageAccountKey=$(az storage account keys list -g myResourceGroup \
-n $blobStorageAccount --query [0].value --output tsv) 

az storage container set-permission \ --account-name $blobStorageAccount \ --account-key $blobStorageAccountKey \ --name thumbs  \
--public-access off

Configure SAS tokens for thumbnails

In part one of this tutorial series, the web application was showing images from a public container. In this part of the series, you use Secure Access Signature (SAS) tokens to retrieve the thumbnail images. SAS tokens allow you to provide restricted access to a container or blob based on IP, protocol, time interval, or rights allowed.

In this example, the source code repository uses the sasTokens branch, which has an updated code sample. Delete the existing GitHub deployment with the az webapp deployment source delete. Next, configure GitHub deployment to the web app with the az webapp deployment source config command.

In the following command, <web-app> is the name of your web app.

az webapp deployment source delete --name <web-app> --resource-group myResourceGroup

az webapp deployment source config --name <web_app> \
--resource-group myResourceGroup --branch sasTokens --manual-integration \

The sasTokens branch of the repository updates the StorageHelper.cs file. It replaces the GetThumbNailUrls task with the code example below. The updated task retrieves the thumbnail URLs by setting a SharedAccessBlobPolicy to specify the start time, expiry time, and permissions for the SAS token. Once deployed the web app now retrieves the thumbnails with a URL using a SAS token. The updated task is shown in the following example:

public static async Task<List<string>> GetThumbNailUrls(AzureStorageConfig _storageConfig)
    List<string> thumbnailUrls = new List<string>();

    // Create storagecredentials object by reading the values from the configuration (appsettings.json)
    StorageCredentials storageCredentials = new StorageCredentials(_storageConfig.AccountName, _storageConfig.AccountKey);

    // Create cloudstorage account by passing the storagecredentials
    CloudStorageAccount storageAccount = new CloudStorageAccount(storageCredentials, true);

    // Create blob client
    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

    // Get reference to the container
    CloudBlobContainer container = blobClient.GetContainerReference(_storageConfig.ThumbnailContainer);

    // Set the permission of the container to public
    await container.SetPermissionsAsync(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob });

    BlobContinuationToken continuationToken = null;

    BlobResultSegment resultSegment = null;

    //Call ListBlobsSegmentedAsync and enumerate the result segment returned, while the continuation token is non-null.
    //When the continuation token is null, the last page has been returned and execution can exit the loop.
        //This overload allows control of the page size. You can return all remaining results by passing null for the maxResults parameter,
        //or by calling a different overload.
        resultSegment = await container.ListBlobsSegmentedAsync("", true, BlobListingDetails.All, 10, continuationToken, null, null);

        foreach (var blobItem in resultSegment.Results)
            CloudBlockBlob blob = blobItem as CloudBlockBlob;
            //Set the expiry time and permissions for the blob.
            //In this case, the start time is specified as a few minutes in the past, to mitigate clock skew.
            //The shared access signature will be valid immediately.
            SharedAccessBlobPolicy sasConstraints = new SharedAccessBlobPolicy();

            sasConstraints.SharedAccessStartTime = DateTimeOffset.UtcNow.AddMinutes(-5);

            sasConstraints.SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddHours(24);

            sasConstraints.Permissions = SharedAccessBlobPermissions.Read;

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

            //Return the URI string for the container, including the SAS token.
            thumbnailUrls.Add(blob.Uri + sasBlobToken);


        //Get the continuation token.
        continuationToken = resultSegment.ContinuationToken;

    while (continuationToken != null);

    return await Task.FromResult(thumbnailUrls);

The following classes, properties, and methods are used in the preceding task:

Class Properties Methods
CloudStorageAccount CreateCloudBlobClient
CloudBlobClient GetContainerReference
CloudBlobContainer SetPermissionsAsync
BlobResultSegment Results
CloudBlockBlob GetSharedAccessSignature
SharedAccessBlobPolicy SharedAccessStartTime

Server-side encryption

Azure Storage Service Encryption (SSE) helps you protect and safeguard your data. SSE encrypts data at rest, handling encryption, decryption, and key management. All data is encrypted using 256-bit AES encryption, one of the strongest block ciphers available.

In the following sample you enable encryption for blobs. Existing blobs created prior to enabling encryption are not encrypted. The x-ms-server-encrypted header on a request for a blob shows the encryption status of the blob.

az storage account update --encryption-services blob --name <storage-account-name> --resource-group myResourceGroup

Upload a new image to the web application now that encryption is enabled.

Using curl with the switch -I to retrieve only the headers, substitute your own values for <storage-account-name>, <container>, and <blob-name>.

sasToken=$(az storage blob generate-sas \
    --account-name <storage-account-name> \
    --account-key <storage-account-key> \
    --container-name <container> \
    --name <blob-name> \
    --permissions r \
    --expiry `date --date="next day" +%Y-%m-%d` \
    --output tsv)

curl https://<storage-account-name><container>/<blob-name>?$sasToken -I

In the response, note the x-ms-server-encrypted header shows true. This header identifies that the data is now encrypted with SSE.

HTTP/1.1 200 OK
Content-Length: 209489
Content-Type: image/png
Last-Modified: Mon, 11 Sep 2017 19:27:42 GMT
Accept-Ranges: bytes
ETag: "0x8D4F94B2BE76D45"
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 57047db3-001e-0050-3e34-2ba769000000
x-ms-version: 2017-04-17
x-ms-lease-status: unlocked
x-ms-lease-state: available
x-ms-blob-type: BlockBlob
x-ms-server-encrypted: true
Date: Mon, 11 Sep 2017 19:27:46 GMT

Enable HTTPS only

In order to ensure that requests for data to and from a storage account are secure, you can limit requests to HTTPS only. Update the storage account required protocol by using the az storage account update command.

az storage account update --resource-group myresourcegroup --name <storage-account-name> --https-only true

Test the connection using curl using the HTTP protocol.

curl http://<storage-account-name><container>/<blob-name> -I

Now that secure transfer is required, you receive the following message:

HTTP/1.1 400 The account being accessed does not support http.

Next steps

In part three of the series, you learned how to secure access to the storage account, such as how to:

  • Use SAS tokens to access thumbnail images
  • Turn on server-side encryption
  • Enable HTTPS-only transport

Advance to part four of the series to learn how to monitor and troubleshoot a cloud storage application.