Multitenancy

Overview

Multitenancy allows a Software as a Service (SaaS) vendor, or other software provider, to economically deliver service to many tenants (customers of the SaaS vendor). Using WaveMaker's multitenancy capabilities, many tenants are processed through a single infrastructure, including Java containers (Tomcat or J2EE servers), WaveMaker Runtime Framework, and databases.  Additional tenants can be added without adding servers, which provides the most cost effective approach to SaaS hosting.

WaveMaker provides automated support for multitenancy by isolating the data of each tenant and prohibiting unauthorized access to data.  Multitenancy can be enabled in WaveMaker Studio by configuring a few simple fields.  Multitenancy requires that database security is enabled. When multitenancy is enabled the WaveMaker Runtime Framework will inspect each client request to restrict any data access (create, read, update, delete) to only those records associated with the particular tenant.

Steps to Enable Multitenancy

1. Each Database Tenant-Specific Table Must Include Tenant Information

To enable multitenancy, each database table that contains client-specific data must include a tenant identifier (ID) column.  The tenant ID column must be named consistently throughout the schema and must be an integer type. The tenant ID field will be used by WaveMaker Runtime Framework to isolate the data of each tenant.  You may create your database using WaveMaker Studio's data model editor or you may create the database using the database designer of your choice (for example, sqlyog or command line tool). 

Some tables in your database schema may not require a tenant ID column. For example, you may have a table of reference data that is common and shared between all tenants in your system.

2. Configure WaveMaker Studio Multitenancy

In the Security Editor select database security and provide the configuration necessary to configure WaveMaker for database security. Enable multitenancy by providing the name of the database tenant ID field that was used when creating the database.  In the screenshot below, the Tenant ID field name is tenantid, which means each table in the schema has a column named tenantid with a type of integer.

multitenantdefinition.png

Multitenant configuration also includes the Default Tenant ID Value which is used within Studio so data can be presented through the LiveLayout system.

Runtime Behavior

A user must login to access the application. The database's user table will include username, password, and tenant ID. Through the login, the WaveMaker Runtime Framework will extract the user's tenant ID value as part of the login request and store the value within the server's session. The WaveMaker Runtime Framework will automatically insert the tenant ID into all database accesses (create, read, update and delete), prohibiting access to data not owned by the particular tenant. The client browser will present the results to the user.

The tenant ID is inserted on the server (by the WaveMaker Runtime Framework), making it impossible for clients to maliciously request the data of other clients through client requests (using a tool like FireBug, for example).

The diagram below outlines a basic interaction.  At login, the client is authenticated using information stored in the database (username and password).  The tenant ID for the user is read from the user authentication table and retained in the session managed by the server for the client.  Each request from the client is processed on the server.  The server processing will insert the tenant ID, retrieved from the session, into each database request, restricting all database accesses to the tenant ID assigned to the user.

Multitenancyv2.jpg

Design Patterns

There are many ways to use multitenancy.

Start with a single tenant application

One of the easiest ways to build a multi-tenanted application is to setup your database for multitenancy but to only consider the needs of a single tenant when building your application. For example, if we are building an application for tracking expenses, your first pass should only worry about logic needed for a single set of users/single tenant. This allows you to focus on designing the user experience and interactions that a typical user would see.

When you are ready to make your application multitenanted, you only need to enable multitenancy and all of your LiveVariables and HQL Queries will automatically be restricted to the tenant id of the user that is logged in (as indicated by the tenantid field of the user's account). Note that any java services you write will NOT be automatically filtered by multitenancy. You will need to write your own code if your java services need multi-tenancy support.

Role Based Access

A common scenario for a multitenanted application is that for each tenant, there will be one or more users with administrative privileges who can access all accounts and all data within the tenant, and users with standard "user" permissions who can edit their own data and perhaps view data created by other users within the tenant.

While this is a standard setup for many types of applications, setting up role based access within your multitenanted application means that each tenant can have its own admins and its own users.

The superadmin role

Your multitenanted application will need some kind of superadministrator who can see all tenants and their data and fix things when something goes wrong. At a minimum, the superadmin role would be needed to create a new tenant and to create the first admin account. But things do go wrong in the real world; the user with administrative access could leave their company and leave noone in the tenant with admin access. The superadmin user is the one able to set a different user or users to have the admin role.

There are two strategies for creating this superadmin role.

Adding a superadmin role

One approach is to use your existing application, but add support for a superadmin role that can view and access more data. The advantage of this approach: you don't have to reimplement your entire application; code reuse becomes a great deal easier. However, in order to follow this approach, you must do the following:

  1. Deploy two versions of the application; one with multitenancy enabled and one with it disabled
  2. You must disable login for all users who don't have the superadmin role
  3. Assuming you want your superadmin to be able to filter data by tenant, you will need to explicitly set/bind the tenant id for all of your LiveVariables and HQL Queries, which is exactly what WaveMaker's multitenancy solution was intended to help you avoid. But, being able to see only the users or data from a given tenant is important to the superadmin's job; and since the superadmin is running with multitenancy off, the filtering has to be done by you.
  4. You'll want to set some widgets and LiveVariables to only be visible to the superadmin role.

A separate superadmin application

The second approach is to build a separate superadmin application. Rather than building and maintaining two entirely separate applications, you could build a very simple superadmin application that just addresses the two key tasks of the superadmin:

  1. Create, delete, edit tenants
2. Add, delete, edit users and set admin priveledges

To keep your superadmin application especially simple, you could use this role to add an admin user to any tenant you need to log into, and then log into the regular application using that new user.

You can of course implement a full application with access to all the data of all of the users. Avoiding this is the goal behind the previous section "Adding a superadmin role".

Forum Topics

  • Issues with NOT NULL vs NULL tenant_id field:
http://dev.wavemaker.com/forums/?q=node/6170

      Share/Bookmark
© 2012 VMware, Inc. All Rights Reserved.