Using the Windows Azure Graph Store
The Windows Azure Graph Store or WAGS is a storage service, provided by Microsoft and included as part of an Azure Active Directory (AAD) tenant which is part of Office 365 as well as Azure itself. It features a simple REST interface for retrieving and updating members of a graph (graph tuples), a simple serialization format, a simple provisioning model (like none!) and a simple security model (sure, we had to secure the data…).
The scenarios for using WAGS are numerous, including extending entities in AAD, storing configuration and general application storage in a managed service. We will make more blog posts in the near future that focus on these scenarios.
This post will describe how to use the operations of the WAGS service. Please note that at this time WAGS is offered as a preview service – we work to ensure that the service is highly available, but we make no undertaking on availability or features and no SLA will be enforced.
While we definitely believe in the simplicity of REST and JSON for creating great services interfaces, we know that .NET developers love a framework library to support their interaction with services. The OData client libraries from the .NET Framework are compatible with WAGS and so can be integrated into a client application in the same way as any other OData compliant data service. One difference, however, is that because WAGS does not impose a strong schema for the data (technically, the WAGS entity sets are defined as Open Entity Types - http://www.odata.org/documentation/odata-v3-documentation/common-schema-definition-language-csdl/#614_The_edmOpenType_Attribute) the Visual Studio tooling for generating service references will only generate proxy classes that include the mandatory key attributes. Consequently, proxy classes should be manually written to support a flexible schema – there are multiple approaches to designing proxy classes for open types which I’ll discuss in a future post.
Provisioning a New Graph
WAGS is a multi-tenanted, multi-graph store. Stores like this typically involve some provisioning steps to allocate space and setup authentication and authorization rules. In the case of WAGS, this has already been provided and so a new graph is created simply by writing your first tuple.
The security model for a new graph may subsequently be modified, but the default model that is inherited at creation time will enable the creation, reading, updating and deletion of tuples in a graph without any configuration.
Adding Tuples to a Graph
Use the HTTP POST method to add a new tuple to either an existing or an entirely new graph via the following URL:
http://graphstore.windows.net/{tenant}/{graph}
The body of the request should be a JSON object as follows:
{
"_Item1" : "first item",
"_Item2" : "second item",
"AnyAttributeIWant" : AnyPrimativeValue,
"AnotherComplexAttribute" : {
"AttributeName" : "value",
"AnotherAttribute" : "another value"
},
"ACollectionOfAttributes" : [
{
"Attribute1" : 100,
"Attribute2" : true
},
{
"Attribute1" : 200,
"Attribute2" : false
}
]
}
Other than the _Item1 and _Item2 attributes, all other payload is completely arbitrary at the discretion of the application writer. This can include primitive values (AnyAttributeIWant), complex values (AnotherComplexAttribute) or collections (ACollectionOfAttributes).
The response for a successful operation is 201 – Created. The body of the response is the fully formed entity, JSON encoded.
Updating a Graph Tuple
An existing tuple in a graph can be updated using the HTTP MERGE or PUT methods at the following URL:
http://graphstore.windows.net/{tenant}/{graph}/{item1}/{item2}
The body of the request should be a JSON-encoded object, the same as the POST operation. The _Item1 and _Item2 attributes must match the values in the URL. The difference between a MERGE and a PUT operation is that MERGE will combine the attributes in the payload with those already in the store, PUT completely replaces the tuple in the store with that passed in the request.
The response for a successful operation is 204 - No Content. There is no body included in the response. If a tuple does not already exist as specified by the URL, then 404 – Not Found will be returned.
Deleting a Graph Tuple
To delete a tuple from a graph, use the HTTP DELETE method at the following URL:
http://graphstore.windows.net/{tenant}/{graph}/{item1}/{item2}
No body is required for a DELETE request.
The response for a successful operation is 204 - No Content. There is no body included in the response. If a tuple does not already exist as specified by the URL, then 404 – Not Found will be returned.
Querying for Graph Tuples
Tuples in a graph can be queried in three different ways, all using the HTTP GET method:
1. All the tuples in a graph
http://graphstore.windows.net/{tenant}/{graph}
2. All the tuples that have one part of the item key
http://graphstore.windows.net/{tenant}/{graph}/{item}
3. A single tuple identified by both item keys
http://graphstore.windows.net/{tenant}/{graph}/{item1}/{item2}
The first two methods return a JSON array of tuples, which may contain zero entries if the query does not match any tuples in the store:
{
"value" : [
{
"_Item1" : "http://graph.windows.net/contoso.com/Users/joe@contoso.com",
"_Item2" : "http://www.bing.com",
"Like" : true,
"Comment" : "I really like Bing’s search results and FB integration"
},
{
"_Item1" : "http://graph.windows.net/contoso.com/Users/mary@contoso.com",
"_Item2" : "http://www.nytimes.com",
"Like" : true,
"Comment" : "I like news from the Big Apple"
}
]
}
The third method returns a single tuple that matches the item key parts in the URL. The tuple is not wrapped in an array. This method returns 404 – Resource Not Found is the specified tuple does not exist.
Note that tuples in WAGS are stored with an implied ‘direction’ ie. From _Item1 To _Item2. However, when querying for tuples the service performs an undirected query such that tuples are returned if they match the query value regardless of which direction the key value is stored. While this feature is generally handy and relieves the application writer from worrying about the direction of their tuples, sometimes it is important to perform a directed query. WAGS supports directed queries by using wildcard placeholders in the query URL to specify which direction is to be queried.
To perform a directed query for all tuples where only _Item1 == value, send a URL of this form:
http://graphstore.windows.net/{tenant}/{graph}/keyvalue/*
Conversely, to query tuples where only _Item2 == value, use this URL format:
http://graphstore.windows.net/{tenant}/{graph}/*/keyvalue
Note that at this time there is no way to issue a query for a directed single exact tuple.
Securing Your Graphs
Nobody’s going to store anything of value in a multi-tenanted public cloud store if you can’t secure it. WAGS supports a security model that may be applied to an individual graph or to all graphs under a given tenant.
The URL for the permissions document for a graph is:
http://graphstore.windows.net/{tenant}/{graph}/$permissions
The URL for the tenant permissions document is:
http://graphstore.windows.net/{tenant}/$permissions
The permissions document in the response is the same for both requests:
{
"GraphName" : "graph",
"AnonymousRead" : true,
"AnonymousWrite" : false,
"AllowNonTlsChannel" : true,
"ReadClaim" : null,
"WriteClaim" : null
}
The permissions document specifies the name of claims that must be present in a bearer token obtained from Windows Azure Access Control Service (ACS). For information about obtaining access tokens from ACS, see the following link; http://go.microsoft.com/fwlink/p/?LinkID=228494.
The REST calls to WAGS may be authenticated by sending the ACS token in the ‘Authorization’ request header or as the ‘Authorization’ query parameter. The audience/realm of the access token must match the URL of the graph being queried. If the audience of the token matches the queried graph, then the claim name configured in the permissions document for the graph for the requested operation (ReadClaim or WriteClaim) is checked to be present in the supplied token. A HTTP response code of 403 – Forbidden is returned if the supplied access token does not contain the required claim.
If anonymous access is permitted to a graph via the permissions document for a given operation (AnonymousRead or AnonymousWrite are true), the REST request need not include an access token.
Also note that http or https access to a graph is controlled via the ‘AllowNonTlsChannel’ attribute. If this attribute is true (the default for all graphs), all REST requests must be made via https. This ensures that potentially sensitive data is encrypted in transit as well as providing a mechanism for the caller to verify the server to mitigate against Man In The Middle security attacks (see here for more information on MITM: http://en.wikipedia.org/wiki/Man-in-the-middle_attack).
The permissions document for a graph or a tenant may only be modified by a user that is an administrator in the AAD tenant of the same name. Administrators must use the web site at https://graphstore.windows.net/default.aspx and sign in with their AAD credentials to update the document (only the MERGE method is supported – you cannot delete a permissions document for a graph).
What’s Next?
Now that I have shown you the basic operation of WAGS, I encourage you to just try it out. Give us your feedback on how simple you find it to use and how well it fits your needs.
By way of a sample app that leverages WAGS, checkout http://www.orgshare.net/premier-lumber.com (sign in as joe@premier-lumber.com, gustavo@premier-lumber.com or ivo@premier-lumber.com all passwords: P@ssword). I’ll go through this sample in more detail in a future post, but for now have a look at what storing relationships between things can do!
Additionally, the Windows Azure Graph Store has a simple web interface for browsing and managing graphs. Go to https://graphstore.windows.net/default.aspx and start entering queries and issuing updates as described above directly into the app. Sign in using your AAD credentials to start managing the permissions of your graphs (if you’re a company administrator).
In my next post, I will discuss how we use WAGS to extend entities within the Windows Azure Graph.