Multitenancy

Introduction


In the Basic Service example, we learned to perform a heartbeat check on a service, in order to monitor its health.

Moreover,  sample tests to expose the basic functionalities of a SOAJS service, and those of the IMFV.

In the oAuth Security example, one of the APIs from the Basic Service example will be secured with oAuth.

The example allowed the user to explain the integration of the oAuth service with a SOAJS service.

This example explores SOAJS' ability of multitenancy.

Multitenancy allows a collection of tenants/users to share the same set of resources (i.e., a database, service, etc) by allowing each tenant to access only the allowed portion of that resource, and prohibiting them from accessing resources of other tenants.

SOAJS allows different tenants to use the same service, each using their own settings, ACL and configurations.

This example also introduces the User Registration & Access Control (URAC) service, which holds records of all the tenants and its corresponding users.

Moreover, the example teaches how to benefit from multitenancy, and how to configure ACLs, in addition to securing the APIs using tenant keys.

Code Walkthrough


This page shows you how to interact with the example03 & URAC services after you install them and run them. It also demonstrates how SOAJS implements multitenancy.

The code walkthrough is located in a sub page and explained in depth. Click here to read the explanation.

Service Exploration


To turn on URAC in a development environment you just need to start the environment as follow 

Controller Installation
sudo soajs services start --env=example

Verify URAC

To verify if oauth is running you need to login to soajs console and

  • go under deploy tab
  • select environment example  
  • click on SOAJS catalog from the left menu 
  • expand URAC item
  • click on maintenance operations
  • select heartbeat
# go to examples/example03 and start the service
cd soajs.examples/example03/
  
# start the soajs example environment
sudo soajs services start --env=example
  
# export necessary environment variables to create local awareness
export SOAJS_ENV=EXAMPLE
export SOAJS_SRVPORT=4023
export SOAJS_DEPLOY_MANUAL=1
export SOAJS_REGISTRY_API=127.0.0.1:21000
  
  
# start service
node .

The service is now running and listens on port 4023. Therefore, its maintenance port is 5023.

Next, a heartbeat request is sent to check the health of the service.

curl -X GET "http://127.0.0.1:5023/heartbeat"

A response similar to the one below indicates a healthy functioning of the service.

{"result":true,"ts":1425372737466,"service": {"service":"example03","type":"rest","route":"/heartbeat"}}

Tenant Level Access Control


Using the Service APIs

As mentioned previously, this example is multitenant. Therefore, this tutorial simulates several tenants, which will be used across the examples that follow.

Package NameAccess to ServiceAccess Type
ExampleNON/A
Example2YESFULL
Example3YES"buildName"

The table above lists three packages. each package represents a list of permissions.

Example does not have access to the service.

Example2 has full access to the service.

Example3 has access to only the buildName API of the service.


What we also did is we create an example tenant and we gave added 3 applications one per package under this tenant where each application has its own API key and 

Tenant NameApplication NameAccess to ServiceAccess Type
Tenant exampleEXAMP_BASICNONA
Tenant exampleEXAMP_3ZE08YESFULL
Tenant exampleEXAMP_4H6CQYES"buildName"

An application is defined as the combination of a tenant and a package assigned to that tenant.

buildName using EXAMP_BASIC

Request
curl -X GET -H "key:4ea5db4c70b6168aeede6a8a56cb4624efdb6cb2cf3c7b88cbc1f5d97080a44f18083fa195e20dcc0b42496ae268ea91c657dd9b252b72de14c862e64f8522a9dbdaa1ce0f48ba2d5ed5eff49b47d0f728bddb2080c8cbc7bde3771116192b51" "http://127.0.0.1:20000/example03/buildName?lastName=Smith&access_token=valid_access_token"

The key sent with the request is that generated for EXAMP_BASIC

The response to the request is shown below

Response
{"result": false,"errors": {"codes": [154],"details": [{"code": 154,"message": "Access denied: The service is not available in your current package."}]}}

buildName using EXAMP_3ZE08

Request
curl -X GET -H "key:4ea5db4c70b6168aeede6a8a56cb46246ca38b1b4f801f090d5821bd76b339e34b8ddb9ac2cb7ffee220cf3e463ac9cdf3902e91720c8f56684d7d88287affc0092eeb37648e7bde4f565f509b1b384127022bc2c1c1581f4ba50e28564d1c5c" "http://127.0.0.1:20000/example03/buildName?lastName=Smith&access_token=valid_access_token"

The key sent with the request is that generated for EXAMP_3ZE08

Response
{"result": true,"data": {"tenantName": "Client One","fullName": "John Smith"}}

Clearly, the response generated proves that the second application has access to the API, and the response came back with a positive result to the tenant's query.

More importantly, the response containts the name of the tenant that requested the query.

testGet using EXAMP_3ZE08

Request
curl -X GET -H "key:4ea5db4c70b6168aeede6a8a56cb46246ca38b1b4f801f090d5821bd76b339e34b8ddb9ac2cb7ffee220cf3e463ac9cdf3902e91720c8f56684d7d88287affc0092eeb37648e7bde4f565f509b1b384127022bc2c1c1581f4ba50e28564d1c5c" "http://127.0.0.1:20000/example03/testGet?lastName=Smith&firstName=John&access_token=valid_access_token"

The response below contains the answer to the user's query.

Response
{"result": true,"data": {"firstName": "John","lastName": "Smith"}}

testGetusing EXAMP_4H6CQ

Request
curl -X GET -H "key:4ea5db4c70b6168aeede6a8a56cb4624079ff72a87d5174f5d880d546f326077dd82b8131322c2a5dbc02edec9d5ad7bfbfcf3730c2205850ffe7644e259ad2ee20280d25a1cfecdb7a62992920d2155cb30edffb6e53d49c528cc2e1ae54a6e" "http://127.0.0.1:20000/example03/testGet?lastName=Smith&firstName=John&access_token=valid_access_token"

The response to the request is shown below

Response
{"result": false,"errors": {"codes":[159],"details":[{"code":159,"message":"System api access is restricted. api is not in provision."}]}}


In conclusion, multitenancy is a powerful approach that allows the sharing of the resources while ensuring the integrity and security of each tenants resources.

The examples above elaborate how SOAJS implements this concept, allowing numerous tenants to use the same service.

Our documentation provides a detailed explanation for the concepts of multitenancy and productization.

User Level Access Control


The examples above clearly exploit multitenancy using SOAJS, on the tenant level. Indeed, SOAJS permits several tenants to share the same resources (i.e., application, service, etc..).

The ACLs provide permissions for each tenant, thus restricting each tenant's access to what is included in the permissions list.

Interestingly, SOAJS does not enforce access control on the the tenant level only. The framework goes one step further and enforces is on the users of the same tenant.

Consider the following example of a company, composed of two departments: The IT department, and the financial department. The company represents the tenant, and each department

represents a user of that tenant. The IT department should only have access to the IT resources. It must not have access to the resources of the financial department.

The same thing applies for the financial department as well. In this regard, multitenancy on the user level is also supported by SOAJS.

Conclusion


In conclusion, multitenancy, productization and urac are efficient concepts that allow the tenants and users to share the available resources, in an optimized way, while respecting the privacy of each tenant/user's data,


using the Access Control Lists, which, as the name states, contain the permissions of each tenant/user.

  • The ACL is explained in depth in the Access Levels section.
  • Products and packages are explained in depth in the Productization section.
  • Tenants, and applications are explained in the Multitenancy section.
  • Finally users, groups and ACL overriding are explain in the URAC section.