Using WAWS for Tenant Isolation
21 February 2013 - Azure
In my second talk at Microsoft MVP Summit 2013 in Redmond/Bellevue I was speaking about a characteristic of Windows Azure Mobile Services (WAMS): The way that WAMS uses the infrastructure of Windows Azure Websites (WAWS) for tenant isolation. As people asked me to share the content of my talk, I summarize the most important take-aways in this article. Please note that all the code in this blog post is POC code. It should demonstrate the ideas and is by far not production ready (e.g. no error handling, no async programming, no good names, etc.).
Here are the slides that I have used during the talk. Only a few slides - I spent most of the time in Visual Studio showing/writing code:
If you are a developer writing a mobile application (e.g. a Windows Store app) you might need to store some data in the cloud (e.g. settings, high scores, devices for push notifications, etc.). Windows Azure gives you multiple types of data stores you could use. The problem is that you might run into problems trying to access these data stores directly from your mobile app. Here are just some examples:
- You cannot directly access a SQL database in Azure from your Windows Store app simply because ADO.NET is not available.
- Table Storage, the NoSQL option for Azure, offers you a REST-based API. However, where should you store the credentials?
In each of these cases you will need to create, deploy, and maintain a service in the cloud. Your mobile app will use the service and the service accesses the underlying data store. The problem is that you might not want to be responsible for such a service. The solution that Microsoft offers for this problem is a ready-made service provided by Microsoft that all mobile app vendors can use. Such services with a shared infrastructure are called multi-tenant services.
Multi-tenant services like WAMS have a special problem when it comes to user-provided code (e.g. scripts): Running the code in the shared infrastructure is not possible because the risk of a script from tenant A doing bad things to tenant B is too high. There has to be some kind of sandbox in which non- or semi-trusted code can run. It turns out that the WAMS developers did not invent their own sandbox. They decided to use an existing one: The sandbox that comes with Windows Azure Websites (WAWS).
Windows Azure Websites as an Isolation Mechanism
Although the name Windows Azure Websites indicates that this service has been built only for websites. In fact WAWS is much more versatile. You can run nearly everything that you can run in IIS including Web APIs. This leads to the core question of my session: Can't we use WAWS in customizable, multi-tenant line-of-business (LOB) SaaS solutions for tenant isolation similar to WAMS does? We can.
For my session at MS MVP Summit I have created a small POC scenario. Here is the setup that I have shown:
- Demo web application representing the website on which new customers can subscribe to the fictitious SaaS solution (of course this website also ran in WAWS).
- A worker responsible for provisioning new tenants. In my demo it was a persisted VM role in Azure; in practice I would recommend an Azure Cloud Service.
- A simple .NET-based API that can be used by power users for scripting. In my example I used the existing scripting technology in .NET (Dynamic Language Runtime, DLR) with a Python implementation built on top of it (IronPython). We have been using IronPython in our own SaaS offering time cockpit for quite a long time and are very happy with it.
- A sample full-client (WPF) representing e.g. a powerful ERP client for the SaaS offering.
- A template implementation for a Web API that is capable of running user-provided scripts. My example uses ASP.NET's Web API.
The following diagram shows an overview how the different components play together. I will go into more details about what goes on in the sample.
When a user subscribes to our service, the website queues a tenant creation request using Azure's Service Bus. This service makes communicating between servers in the cloud a piece of cake. Just as an example, here is the code I used in the sample to enqueue a tenant creation request.
Here is the code for the worker waiting for tenant creation request. I share this code because it demonstrates how you can use e.g. WAWS's command line tools to automate the creation of websites in Azure.
Adding script capabilities to a .NET program is quite simple. The .NET Framework contains the Dynamic Language Runtime (DLR). Multiple dynamic languages have been implemented on top of the DLR. Here are some examples:
In my opinion IronPython is the most mature implementation of a dynamic language on the DLR. If you want to play with it, I encourage you to install the following components:
- Python Tools for Visual Studio (you will even get debugging capabilities for your scripts; Simon Opelt, a colleague of mine has written a blog article about it)
- Add the IronPython Nuget package to the .NET projects in which you want to use it
The following code snippet demonstrates how the isolated WAWS website loads a Python script from the tenant's database and executes it. Be aware that in practice you would have to invest some time in making this code more robust (e.g. collect console output from script, special handling of syntax errors, etc.). However, you do not have to care about sandboxing. WAWS will take care of that.
Summary and Critical Evaluation
Technically it is possible to use WAWS as a tenant isolation mechanism for multi-tenant SaaS solutions. However, the solution does not scale for solutions with thousands and thousands of tenants because the number of websites per Azure subscription is limited today. In my experience this approach is feasible for SaaS offerings with a small to medium number of tenants.