January 7, 2012

Shared Access Signature

A “Shared Access Signature” (SAS) is a set of URL query parameters that represents all information necessary to grant controlled access to a Windows Azure blob or container resource.  The below diagram shows how a URL for accessing a secured blob resource looks like:



Given below a sample URL with shared access signature components:





The components   of “Shared Access Signature” or the URL query parameters representing “Shared Access Signature” are:

No:

Query Parameters
1
The interval over which the signature is valid:

Start time
st
End time
se
2
The resource
sr
3
The permissions associated with the signature
sp
4
The signature
sig
5
Identifier for the policy associated with the container
si

Table 1

Note: You might have noticed that the sample URL does not include query option si  (item 5 in the above Table1), this is an optional field and it’s associated with the “container-level access policy” which allows additional measure of control over Shared Access Signatures. I will explain how to use it in the section "Container Level Access Policy".

1.     The Signature (sig):

 This section shows how to construct a signature string for a Shared Access Signature, which is represented by the sig query option (item 4 in Table1).





Here’s the code where we construct signature using C#:

              string azureStorageSharedKey = "" // Your Storage Account key Here
        string permissions = "r";
        DateTime startTime = DateTime.Now;
        DateTime expiryTime = startTime.AddMinutes(60);
        string canonicalPathToResource = "/anuchandy/ebooks";
        string policyIdentifer = String.Empty;
        byte[] keyForSigning = Convert.FromBase64String(azureStorageSharedKey);
        string signature = null;

        string stringtosign = permissions + "\n" +
               startTime.ToUniversalTime().ToString("yyyy-MM-ddThh:mm:ssZ") + "\n" +
               expiryTime.ToUniversalTime().ToString("yyyy-MM-ddThh:mm:ssZ") + "\n" +
               canonicalPathToResource + "\n" +
               policyIdentifer;
               
        using (var hmac = new HMACSHA256(keyForSigning))
        {
            signature = Convert.ToBase64String(
               hmac.ComputeHash(Encoding.UTF8.GetBytes(stringtosign))
            );
        }

The following section describes the components which made up the “String to Sign”

1.1 Permission(s) [Permissions]

The permissions component of the “string to sign” indicates which operations are permitted on the secured resource (resource can be either a blob in the container or a container itself) which is going to be accessed using the Shared Access Signature. The resource is identified by the “CanonicalPathToResourcecomponent of “string to sign”.
        In the above C# code the canonical path to resource is "/anuchandy/ebooks" which represents the container. “/anuchandy/ebooks/pgmingAzure.pdf" represents canonical path to a blob resource. If the “CanonicalPathToResourceidentify the container, then the shared access signature can be used to perform the operations identified by “permissions” component on all the blobs under the container.
Supported permissions include read (r), write (w), delete (d), and list (l).
Permissions may be grouped so as to allow multiple operations, for example to grant read-write permissions we can use rw.
Note: The permissions should be in the following order: rwdl. Any combination of these permissions is acceptable, so long as they are in the specified order. For example rw is valid but wr is invalid.

1.2  Start-Time [UTC_StartTime_In_ yyyy-MM-ddThh:mm:ssZ_Format]

The time at which the Shared Access Signature becomes valid. The time must be UTC times and adhere to YYYY-MM-DDThh:mm:ssZ ISO 8061 format.

1.3  Expiry-Time [UTC_ExpiryTime_In_ yyyy-MM-ddThh:mm:ssZ_Format]

The time at which the Shared Access Signature becomes invalid. The time must be UTC times and adhere to YYYY-MM-DDThh:mm:ssZ ISO 8061 format.

1.4  CanonicalPathToResource [canonical path_to_resource]

The Shared Access Signature can be used to access two types of resources:
  • ·         A container
  • ·         A blob in the container
This component represents canonical path to the above types of reources. The formats of this component are:
  • ·         /<account name>/<container name> è container resource
             e.g. “/anuchandy/ebooks" represents canonical path to container resource.
  • ·         /<account name>/<container name>/<blob name> è blob resource.     
       e.g. /anuchandy/ebooks/pgmingAzure.pdf" represents canonical path to a blob resource.


1.5  Policy Identifier [Policy_identifier]

This is an optional component and it’s associated with the “container-level access policy” which allows additional measure of control over Shared Access Signatures. I will explain about this component later, for the timing we will keep the value of this component as empty string.

2.     The Resource (sr):


This (item 2 of Table 1) query parameter represents the type of resource needs to be accessible via the Shared Access Signature.  (b for blob and c for container).

3.     The Start-Time (st):


This (item 1.a of Table 1) query parameter represents the time at which the Shared Access Signature becomes valid. The time m ust be UTC times and adhere to YYYY-MM-DDThh:mm:ssZ ISO 8061 format.

4.     The Expiry-Time (se):


This (item 1.b of Table 1) query parameter represents the time at which the Shared Access Signature becomes invalid. The time must be UTC times and adhere to YYYY-MM-DDThh:mm:ssZ ISO 8061 format.


Putting all together: Creating Shared Access Signature (SAS)

Now we are aware of the query parameters that make up the SAS, we can form the SAS as follows:

string sharedAccessSignature = string.Format("st={0}&se={1}&sr=c&sp=r&sig={2}",
     Uri.EscapeDataString(startTime.ToUniversalTime().ToString("yyyy-MM-ddThh:mm:ssZ")),
     Uri.EscapeDataString(expiryTime.ToUniversalTime().ToString("yyyy-MM-ddThh:mm:ssZ")),
     Uri.EscapeDataString(signature));

signature” is the signature from code we used to construct signature.
The generated “sharedAccessSignature” looks like:

st=2012-01-07T10%3A15%3A08Z&se=2012-01-07T11%3A15%3A08Z&sr=b&sp=r&sig=sv%2BSQIofAcDd8KFrIsK5xtRkfxsBkK8vTUUkuwR6ymc%3D


Now we can use this SAS to access the blob resource as follows:

http://anuchandy.blob.core.windows.net/ebooks/pgmingAzure.pdf? st=2012-01-07T10%3A15%3A08Z&se=2012-01-07T11%3A15%3A08Z&sr=b&sp=r&sig=sv%2BSQIofAcDd8KFrIsK5xtRkfxsBkK8vTUUkuwR6ymc%3D


Life Time of Shared Access Signature
We used the starTime and expiryTime components of “signature (sig)” to define lifetime of SAS. Another component that affect SAS lifetime is “Policy Identifier”, for generating the “signature (sig)” component of SAS we used empty value for “Policy Identifier”
string policyIdentifer = String.Empty;

“Policy Identifier” links the SAS with “container level access policy” defined for your container.  If the SAS is not linked with “container level access policy” (i.e. with empty “Policy Identifier” in signature) then the maximum life time we can define for SAS is 1 Hour.
If a start time is specified, the expiration time must be 60 or fewer minutes from the start time, or the signature is invalid and cannot be used. If no start time is specified, the signature is valid only during the 60 minute period before the expiration time.
So if we define the following time interval:
        DateTime startTime = DateTime.Now;
        DateTime expiryTime = startTime.AddMinutes(65);

Then you will not be able to access the resource using the generated SAS.


Container Level Access Policy

yet to come....

January 2, 2012

OData PHP Producer


The OData PHP Producer library is a server side implementation of OData Protocol using PHP.

I was involved in the design and implementation of this library, thought of sharing some high level details of this project.

The "OData PHP Producer" is designed in a generic way such that you can expose data from any data source ( relational database, file system etc..)

The above diagram shows the high-level design of "OData PHP Producer" library and a set of sample services (NorthWind, WordPress). These sample services can be used as a reference to write your own service. Each sample service has the following components:

·         IServiceProvider and IDataService implementation, the main service entry point.
·         IDataServiceMetadataProvider implementation.
·         IDataServiceQueryProvider implementation.
·         IDataServiceStreamProivder implementation [optional].

The flexibility of exposing data from any data source requires the end developer, the one want to expose the data as OData service, to implement the above set of interfaces defined by the "OData PHP Producer" library.

1.     IDataServiceMetadataProvider:

Purpose of implementation of this interface is to let the "OData PHP Producer" library know the metadata of your data source, then the library will exposes a $metadata endpoint which can be used by the clients to fetch the service metadata document that describes how the service exposes the data and what structures and data types they should expect

2.     IDataServiceQueryProvider:

The library don't know anything about the underlying data source such as how to connect, how to query etc.. It’s the responsibility of the end developer to connect to the data source, fetch the data and give it to library based on the delegates invoked by the library.

The OData protocol defines URI conventions to address the resources in your data source and to control the amount and order of the data that an OData service returns for the resource identified by the URI. The library has the code to parse the incoming OData queries, these queries are translated into call to IDataServiceQueryPorivder methods

Note that there are two versions of Query Provider interface, IDataServiceQueryProvider and IDataServiceQueryProvider2. The IDataServiceQueryProvider2 is same as IDataServiceQueryProvider except  one difference that with IDataServiceQueryProvider library does the filtering using built-in expression provider and if result-set is huge then  performance of the library will not up to the marks.
The IDataServiceQueryProvider2,library generates the filter criteria with the help of custom expression provider and the IDataServiceQueryProvider2 can use this filter criteria to run query on the data source. So in this case library don’t need to scrub out the unnecessary records to get the final subset of data.

3.     IDataStreamProvider:

This is an optional interface that can be used to enable streaming of content such as Images or other binary formats

4.     IServiceProvider and IDataService:

IDataService is the interface that deals with the service endpoint and allows defining features such as Page size for the OData Server paging feature, access rules to the service, OData protocol version(s) accepted and so on. IServiceProvider is the interface that deals with access to the above interface implementations from the library.
                                                              ================

Before going into the details of implementing the above interfaces for your data source let us configure the "OData PHP Producer" library and associated sample service based on MySQL WordPress database.


Configuring the library and running MySQL based OData service on Windows

Prerequistes


1.      PHP version > 5.3.x
          Download and install PHP.
          Refer this link to configure PHP on IIS.
2.   IIS UrlRewrite Module
          Download and install IIS URL Rewrite module from here
3.   MySQL
4.   The sample service showcasing how to expose a MySQL database as OData Service uses WordPress database. Download and install WordPress from here

Installation


1.      Download the latest "OData PHP Producer" from official github site https://github.com/MSOpenTech/odataphpprod

2.      Extract the zip file to your local drive, for example E:\



3.      Add the path to the ‘library’ folder to the 'include_path' directive in php.ini. e.g.

   include_path = ".;E:\OData Producer for PHP\library"

4.      Create a website in IIS using the content of “OData Producer for PHP” directory.


5. Open the file

[root]\OData Producer for PHP\services\IDataServiceQueryProvider2 Implementation\WordPress\ wordpressQueryProvider.php

Update the value of connection parameters DB_NAME, DB_USER, DB_PASSWORD and DB_HOST so that it points to your WordPress MySQL database


 6. Restart IIS by running iisreset command from command prompt

7. Your service is ready :), open your browser and go to the website we created in step4, append the service name 'WordPress2.svc' to the root URL.

e.g: http://localhost:8083/WordPress2.svc

This will cause the "OData PHP Producer library"to return the Service Document of WordPress data service.



You can refer official OData site for more about URI options supported by  an OData service.
Here few service URI that you can try:
* http://localhost:8083/WordPress2.svc/$metadata
       Fetches the metadata of WordPress database.
* http://localhost:8083/WordPress2.svc/Posts
       Fetches post entity instances from the database
* http://localhost:8083/WordPress2.svc/Posts?$expand=Category
       Fetches the post entity instances and category instance associated with each post.