Valet Key pattern

Another way of adding an extra layer of security to your cloud-based solution is using security tokens to access specific cloud resources.

As an example, let's consider a client application that sends a request to a cloud application. In this request, the cloud application needs to retrieve a Blob file from a cloud data store and returns them to the client:

We can handle this scenario with the Gatekeeper pattern, but in particular types of scenario, in order to increase the overall performances of the architecture, we could directly permit the data store to handle the streaming of data, bypassing the extra processing of the cloud service:

The Valet Key pattern diagram can be represented as shown in the following figure:

With the Valet Key pattern, the client application request for a resource to a cloud service. The cloud service checks for the validity of the request, generates a key token (valet key) and returns this token to the client application.

This token has the main feature: providing a time-limited and feature-limited access to a specific cloud resource. The client application can now access the target cloud resource by using the valet key token. On the target resource, the client application can perform only the operations that are permitted by the security token (for example, only download a certain Blob from a data store).

The client can access the cloud target resource only for a specific period of time. After that period, the valet key token becomes invalid and the access to the target resource will be denied.

As you can see, by implementing this pattern, you can guarantee a simplified managing access to cloud resources (no need to direct user configuration and authentication) and time-limit permission.

You can use this pattern in Azure when implementing solution architectures that use Azure Storage by using Shared Access Signatures. With this feature, you can grant access to an Azure Storage entity without the need to explicitly create a grant for the client application or share your account key. The client application receives a shared key with grants (permissions and time limit). It can perform the authorized operation on the storage entity and then the permissions will be released.

The Shared Access Signature is a special signed URI composed by a storage resource URI and by a SAS token (generated at the client side) that contains a signature and resources that the client application can access:

There are two types of shared access signatures in Azure:

  • Service Shared Access Signature: This permits access to a resource in only one storage service (Queue, Table, Blob, or File service).
For more information see Constructing a Service SAS at this link: https://msdn.microsoft.com/library/dn140255.aspx
  • Account Shared Access Signature: This permits access to a resource in one or more storage services and you can delegate access to operations.
For more information see Constructing an Account SAS at this link: https://msdn.microsoft.com/library/mt584140.aspx

Now we can see an example on how to generate a shared access signature for a Blob storage and generate a previously described access policy for implementing the pattern in a real scenario.

On my Azure subscription, I've created a Blob storage account with a container:

Let's open Visual Studio and create a new C# console application. After that, we need to add a reference to the Azure Storage Client library package (right-click on Reference and select Manage NuGet packages):

Also, provide a reference to the Microsoft.WindowsAzure.ConfigurationManager package:

In this application, we perform the following steps:

  1. Connect to the storage account
  2. Retrieve a reference to the container
  3. Generate a Shared Access Signature for the container, with only an expiry time and list and write permissions

The code for the application is as follows:

class Program
{
static void Main(string[] args)
{
//Read the Storage Account connection string from
App.config
CloudStorageAccount storageAccount =
CloudStorageAccount.Parse(CloudConfigurationManager.
GetSetting("AzureStorageConnectionString"));

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

//Reference to storage account container
CloudBlobContainer blobContainer = blobClient.GetContainerReference("demo");
blobContainer.CreateIfNotExists();

//Generate a Shared Access Signature URI for the storage account Blob container
Console.WriteLine("Generated Container SAS URI: " +
GenerateBlobContainerSASUri(blobContainer));

Console.ReadLine();
}

//Shared Access Signature generation
static string GenerateBlobContainerSASUri(CloudBlobContainer blobContainer)
{
//SAS policy with constraints and time-limit setup
SharedAccessBlobPolicy sasPolicy = new SharedAccessBlobPolicy();
sasPolicy.SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddHours(12);
sasPolicy.Permissions = SharedAccessBlobPermissions.List |
SharedAccessBlobPermissions.Write;

//SAS token creation
string sasToken = blobContainer.GetSharedAccessSignature(sasPolicy);

//Final SAS URI
return blobContainer.Uri + sasToken;
}
}

The Shared Access Signature for the container is created by the GenerateBlobContainerSASUri function and it's available immediately (no start time setup).

When you run the application, this is the final result:

You obtain a SAS URI that the client application can use to access the cloud resource (storage account container).

As described earlier, we can generate a Shared Access Signature also for a single Blob in a storage account container.

To do so, we can create a method similar to the following:

static string GenerateBlobSASUri(CloudBlobContainer blobContainer)
{
//Sets a reference to a blob inside the container in input
CloudBlockBlob blob =
blobContainer.GetBlockBlobReference("demo.txt");

//Creates a blob file (or updates it if existing)
string blobContent = "Demo Blob file created for Packt
Publishing.";
blob.UploadText(blobContent);

//SAS policy setup for the blob file (permissions and time-
limits)
SharedAccessBlobPolicy sasPolicy = new
SharedAccessBlobPolicy();
sasPolicy.SharedAccessStartTime =
DateTimeOffset.UtcNow.AddMinutes(-3);
sasPolicy.SharedAccessExpiryTime =
DateTimeOffset.UtcNow.AddHours(12);
sasPolicy.Permissions = SharedAccessBlobPermissions.Read |
SharedAccessBlobPermissions.Write;
//SAS Token generation
string sasToken = blob.GetSharedAccessSignature(sasPolicy);

//Final SAS URI
return blob.Uri + sasToken;
}

In the Main function of our Console application, we can call the function to generate the SAS key:

//Shared Access Signature generation for a specific blob inside a Blob Storage container
Console.WriteLine("Blob specific SAS URI: " + GenerateBlobSASUri(blobContainer));

As described in the pattern, an application that wants to use the storage has to first request the shared access key. When a shared access key is obtained, the application can perform operations on the storage container.

As an example, this is a function that a client application can use to perform operations on a Blob file in the previous container after having the Shared Access Key:

//Function for testing the usage of a SAS key for a blob
static void TestBlobSAS(string SASuri)
{
//Gets a blob reference from the SAS uri
CloudBlockBlob blob = new CloudBlockBlob(new Uri(SASuri));

//WRITE operation test
try
{
string blobContent = "Write test with SAS token for
Packt.";
MemoryStream msWrite = new
MemoryStream(Encoding.UTF8.GetBytes(blobContent));
msWrite.Position = 0;
using (msWrite)
{
blob.UploadFromStream(msWrite);
}
Console.WriteLine("Write operation completed
successfully");
}
catch (StorageException e)
{
Console.WriteLine("Write operation failed: " +
e.Message);
}

//READ operation test
try
{
MemoryStream msRead = new MemoryStream();
using (msRead)
{
blob.DownloadToStream(msRead);
msRead.Position = 0;
using (StreamReader reader = new
StreamReader(msRead, true))
{
string line;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
Console.WriteLine("Read operation completed
successfully.");
}
catch (StorageException e)
{
Console.WriteLine("Read operation failed: " +
e.Message);
}

//DELETE operation test
try
{
blob.Delete();
Console.WriteLine("Delete operation completed
successfully");
}
catch (StorageException e)
{
Console.WriteLine("Delete operation failed: " +
e.Message);
}
}

In this function, we perform different operations (write, read, and delete) on the blob file using the SAS URI previously retrieved.

If the URI (provided by the client application) grants the operation on the blob in the container, the task is performed successfully; otherwise, the client application receives an exception (StorageException).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.134.151