Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 10 Next »

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.

URAC Installation


SOAJS User Registration & Access Control (URAC) is a service that manages the Users records and their Access Controls.

The service is multitenant and provides the ability to have members accounts for different tenants.

Similar to any other SOAJS service, URAC can be installed via NPM:

URAC Installation
# go to soajs directory
cd /opt/soajs/node_modules

# install urac
npm install soajs.urac

# go to urac directory
cd /opt/soajs/node_modules/soajs.urac
# export necessary environment variables
export SOAJS_PROFILE=/opt/soajs/node_modules/soajs.utilities/data/getStarted/profile.js
export SOAJS_ENV=test
export SOAJS_SRVIP=127.0.0.1

# run urac
node .

URAC is now running on http://127.0.0.1:4001 and will be used to login with different users. Therefore, its maintenance port is 5001.

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

URAC heartbeat
curl -X GET "http://127.0.0.1:5001/heartbeat"

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

Heartbeat Reponse
{"result": true,"ts": 1425372634090,"service": {"service": "urac","type": "rest","route": "/heartbeat"}}

Service Exploration


Run the Service

# go to correct directory
cd /opt/soajs/node_modules/soajs.examples/example03/

# export necessary environment variables
export SOAJS_PROFILE=/opt/soajs/node_modules/soajs.utilities/data/getStarted/profile.js
export SOAJS_ENV=test
export SOAJS_SRVIP=127.0.0.1

# start service
node .

The service is now running and listens on port 4012. Therefore, its maintenance port is 5012.

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

curl -X GET "http://127.0.0.1:5012/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
Package 1NON/A
Package 2YESFULL
Package 3YES"buildName"

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

Package1 does not have access to the service.

Package2 has full access to the service.

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

For instance, a tenant with Package1 may not access any API of the service, whereas a tenant with package3 may only use the buildName API.

Tenant NamePackage NameOverrides PackageAccess to ServiceAccess Type
Tenant1Package1NONONA
Tenant1Package1YESYESFULL
Tenant2Package2NOYESFULL
Tenant3Package3NOYESbuildName

The example considers three tenants. Each of which using a package, as can be seen in the table above.

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

Therefore, the table above presents four applications.

Application1 is composed of tenant1 and package1.

Similarly, application2 is composed of tenant2 and package1. However, package1 is overriden in this application.

Thus, this application is able to have full access to the service APIs.

Now that the tenants, packages, and applications are clearly listed, it is time to explore the service APIs using the different tenants.

At the end of this tutorial, the user will have a clear idea on how multitenancy operates, and how SOAJS implements this concept,

in order to efficiently share the resources between tenants and clients, while protecting their data.

buildName using application1: Tenant1, package1

As stated above, tenant1 possesses two applications. This example shows a request to use the buildName API, sent using the external key of tenant1 using package1, which
does not have access to any of the service's APIs. The response should be an error stating that the user is not allowed to access the service API.

Make sure the controller is running.

Make sure oAuth is running.

Make sure you have a valid access token by logging in to oAuth.

Use your valid access token in the curl request below.


Request
curl -X GET -H "key:4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2" "http://127.0.0.1:4000/example03/buildName?lastName=Smith&access_token=valid_access_token"

The key sent with the request is that generated for tenant1 using application1.

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 application2: Tenant1, package1, overriden package

Next, the same API is requested. However, this time, the external key generated for the second application is used.

The tables above clearly show that the second application (Tenant1, package1, overridden package), has access

to all of the APIs of the service. Therefore, a correct request, using the key of this application should allow access to the API,

and generate the corresponding answer.

Request
curl -X GET -H "key:4232477ed993d167ec13ccf8836c29c4550e88551c880d36fd42223ef81e0a6e1f668d42edc70d3d98fa8d28757e951bd7a04cf43829b5c2f38ed8c9ee87f03b79e564dd6aeaf8c37e90c92e6a69dccbd52b5a7812cad139bfbeaab69b023322" "http://127.0.0.1:4000/example03/buildName?lastName=Smith"
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.

buildName using application3: Tenant2, package2

The same API is going to be called again. However, the external key of the third application (tenant2, package2) is used.

This application has access to all of the APIs of the service.

Request
curl -X GET "http://127.0.0.1:4000/example03/buildName?lastName=Thomas" -H "key:2423205b6ccd825aaa3dbf7f248f807996c1f39f4e128801107a10ea55eac9686f23b883b778b1763876fe47f7cc651fea232f7aa9dae3dfd1978d4948a3f26b948ebc1b71a9d6cacf08852312866d757b22392d8d3c0e28ee47edb0e7478157"

As expected, the response below indicates a positive response, with a correct answer for the user's query.

Response
{"result": true,"data": {"tenantName": "Client Two","fullName": "John Thomas"}}

testGet using application3: Tenant2, package2

Using the third application (tenant2, package2), a request for the second API (testGet) of the service is going to be generated. Since this application has access

to all of the APIs, the application should be able to receive a legitimate response with the correct data for the query:

Request
curl -X GET "http://127.0.0.1:4000/example03/testGet?lastName=Smith&firstName=John" -H "key:2423205b6ccd825aaa3dbf7f248f807996c1f39f4e128801107a10ea55eac9686f23b883b778b1763876fe47f7cc651fea232f7aa9dae3dfd1978d4948a3f26b948ebc1b71a9d6cacf08852312866d757b22392d8d3c0e28ee47edb0e7478157"

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

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

buildName using application4: Tenant3, package3

Application4 gives tenant3 access to buildName API only. In order to test the validity of this statement, the next request uses API buildName with the external key of application4.

Request
curl -X GET -H "key:7bc1e66d003a3b2acfce1557cbda7320ec45057be0505fd7e9dec19e9fe74c194b109a48568f53449c1cc607a3cb23d70de86831a2ac4b87f1c0c5d57d19702a74ac22a64531185af11f75967f9ba54cb930149ed8a1384f924be9baa4ed5b0b" "http://127.0.0.1:4000/example03/buildName?lastName=Smith"

The response below indicates a valid answer.

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

testGet using application4: Tenant3, package3

Application4 however, does not have access to testGet. Therefore, requesting this API with the corresponding tenant key of the application 4 should result

in an error:

Request
curl -X GET -H "key:7bc1e66d003a3b2acfce1557cbda7320ec45057be0505fd7e9dec19e9fe74c194b109a48568f53449c1cc607a3cb23d70de86831a2ac4b87f1c0c5d57d19702a74ac22a64531185af11f75967f9ba54cb930149ed8a1384f924be9baa4ed5b0b" "http://127.0.0.1:4000/example03/testGet?lastName=Smith&firstName=Jack"

The response below validates that this application does not have access to the testGet API

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

If we look at the terminal that is running the service "controller", we will see a more in-depth error message:

(/opt/soajs/node_modules/soajs/servers/controller.js:415 in logErrors): 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. What follows is a set of examples that highlight the user level access control.

UsertenantOverrides PackageOverrides TenantbuildNametestGetCustom Tenant Information
User1Tenant1NONONONONA
User2Tenant1YESNOYESYESChanges the tenant name
User3Tenant1NOYESYESNOChanges the tenant name

The above table shows three users. Each user has the ability to override the permissions their tenant, and its attributed package.
The examples that follow aim to present how a user can override the ACL permissions of the tenant it belongs to AND/OR the package that the tenant is using.

In addition to that, the examples will show that the user also has the ability to change these configurations, which, in this case, is "tenant name".

User1 Tests

OAUTH Login

Before using the service APIs, a user must be authenticated to the service. Each of the three users has a password. The first step would be to login to OAUTH with a user, and receiving an access token. This access token must be attached to each request.

Get the authorization key
curl -X GET -H "key:4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2" "http://127.0.0.1:4000/oauth/authorization"

The key in the request above is the tenant key.

Response
{"result":true,"data":"Basic MTBkMmNiNWZjMDRjZTUxZTA2MDAwMDAxOnNoaGggdGhpcyBpcyBhIHNlY3JldA=="}


Get the access token using the authorization key
curl -X POST -H "Authorization:Basic MTBkMmNiNWZjMDRjZTUxZTA2MDAwMDAxOnNoaGggdGhpcyBpcyBhIHNlY3JldA==" -H "key:4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2" "http://127.0.0.1:4000/oauth/token" -d "username=user1&password=123456&grant_type=password"
Response
{"token_type":"bearer","access_token":"a188a7fcb411a05159aaf4c97e7321eb77fb0f66","expires_in":7200,"refresh_token":"9e67bd8055e953240eaf91daabe7ecdc206f941b"}


Request
curl -X GET -H "key: 4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2" "http://127.0.0.1:4000/urac/account/getUser?username=user1"
Response
{"result":true,"data":{"_id":"54ee1a511856706c23639308","username":"user1","firstName":"user","lastName":"one","email":"user1@domain.com","ts":1480679707835,"status":"active","profile":{},"groups":["gold"],"tenant":{"id":"54ee2150b7a669fc22b7f6b9","code":"TNT1"},"config":{},"groupsConfig":[]},"soajsauth":"Basic c29hanM6QzAzd1ZqdVMtT1ZVTjNCcFZzd2xoQXNKMDdnOG9KNzRqak8="}

The response above contains the information of user1, followed by the soajs authentication key of that user.

This authentication must be attached to every request generated by user1.

buildName API with user1

The next request tries to use the "buildName" API with the tenant key, and the authentication key of user1. The table above clearly states that this user does not have access to this API. Therefore, the corresponding response must generate an error, stating that the user is forbidden from using the "buidName" API.

Request
curl -X GET "http://127.0.0.1:4000/example03/buildName?lastName=Smith&access_token=a188a7fcb411a05159aaf4c97e7321eb77fb0f66" -H "key:4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2"

The response generated states that user1 is forbidden from using the "buildName" application

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

If we look at the terminal that is running the service "controller", we will see a more in-depth error message:

(/opt/soajs/node_modules/soajs/servers/controller.js:415 in logErrors): Access denied: The service is not available in your current package.

User2 Tests

OAUTH Login

Similar to user1, the example below accesses the OAUTH service with the user2 account, in order to receive an access token.

Before using the service APIs, a user must be authenticated to the service. Each of the three users has a password. The first step would be to login to OAUTH with a user, and receiving an access token. This access token must be attached to each request.

Get the authorization key
curl -X GET -H "key:4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2" "http://127.0.0.1:4000/oauth/authorization"

The key in the request above is the tenant key.

Response
{"result":true,"data":"Basic MTBkMmNiNWZjMDRjZTUxZTA2MDAwMDAxOnNoaGggdGhpcyBpcyBhIHNlY3JldA=="}


Get the access token using the authorization key
curl -X POST -H "Authorization:Basic MTBkMmNiNWZjMDRjZTUxZTA2MDAwMDAxOnNoaGggdGhpcyBpcyBhIHNlY3JldA==" -H "key:4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2" "http://127.0.0.1:4000/oauth/token" -d "username=user2&password=123456&grant_type=password"
Response
{"token_type":"bearer","access_token":"a188a7fcb411a05159aaf4c97e7321eb77fb0f66","expires_in":7200,"refresh_token":"9e67bd8055e953240eaf91daabe7ecdc206f941b"}


Request
curl -X GET -H "key: 4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2" "http://127.0.0.1:4000/urac/account/getUser?username=user2"

The service replies with the corresponding authentication key

Response
{"result":true,"data":{"_id":"54ee46e7a8643c4d10a61ba3","username":"user2","firstName":"user","lastName":"two","email":"user2@domain.com","ts":1500998208596,"status":"active","profile":{},"groups":["silver"],"tenant":{"id":"54ee2150b7a669fc22b7f6b9","code":"TNT1"},"config":{"packages":{"PROD1_PCK1":{"acl":{"urac":{},"example03":{},"example04":{}}}},"keys":{"41eb3256ce660a891205d0a0eca19421":{"config":{"example03":{"tenantName":"Tenant name specific to user two"},"example04":{"tenantName":"Tenant name specific to user two"}}},"19c03e42c750467c3f8481fbe26f2fef":{}}}},"soajsauth":"Basic c29hanM6QzAyMmd5TTU0enplWW1oTHdXMjV5ZGdGb3B1VUthSWZ3b0s="}

buildName API with user2

The next request tries to use the "buildName" API with the tenant key, and the authentication key of user2. The table above clearly states that this user does have access to this API. Therefore, the corresponding response must generate a response containing the appropriate answer for the user's query.

Request
curl -X GET "http://127.0.0.1:4000/example03/buildName?lastName=Smith&access_token=a188a7fcb411a05159aaf4c97e7321eb77fb0f66" -H "key:4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2"

The response below shows that user2 was able to access the "buildName" API since the user overrides the ACL of package1. Moreover, we notice that the tenant name was changed.

Response
{"result":true,"data":{"tenantName":"Client One","fullName":"John Smith"},"soajsauth":"Basic c29hanM6QzAxWWNjUzJaSEpYenhBd0J5MDAzZG5RZ1BOdXFFd0d4UmM="}

testGet API with user2

Next, the request aims to use the "testGet" API with user2, that has access to the API, as shown in the table above.

Request
curl -X GET "http://127.0.0.1:4000/example03/testGet?firstName=John&lastName=Smith&access_token=a188a7fcb411a05159aaf4c97e7321eb77fb0f66" -H "key:4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2"

The corresponding response prove the above statement. User2 overrode the package ACL and obtained full access to the service's APIs

Response
{"result":true,"data":{"firstName":"John","lastName":"Smith"},"soajsauth":"Basic c29hanM6QzAyWWNjQXdaSDBYSnhTMkJ5ejAzZG5RZ1BOdXFFd0d4UmM="}

User3 Tests

OAUTH Login

The following request logs in to OAUTH using user3.

Get the authorization key
curl -X GET -H "key:4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2" "http://127.0.0.1:4000/oauth/authorization"

The key in the request above is the tenant key.

Response
{"result":true,"data":"Basic MTBkMmNiNWZjMDRjZTUxZTA2MDAwMDAxOnNoaGggdGhpcyBpcyBhIHNlY3JldA=="}


Get the access token using the authorization key
curl -X POST -H "Authorization:Basic MTBkMmNiNWZjMDRjZTUxZTA2MDAwMDAxOnNoaGggdGhpcyBpcyBhIHNlY3JldA==" -H "key:4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2" "http://127.0.0.1:4000/oauth/token" -d "username=user3&password=654321&grant_type=password"
Response
{"token_type":"bearer","access_token":"06ff4ec503f9ecd91af42cf8d324e65b5c780645","expires_in":7200,"refresh_token":"5479fa9d6fd049111c490229e7713e77e794ee41"}


Request
curl -X GET -H "key:4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2" "http://127.0.0.1:4000/urac/account/getUser?username=user3"

The response below contains the authentication key of user3.

Response
{"result":true,"data":{"_id":"54ee1bf91856706c2363930a","username":"user3","firstName":"user","lastName":"three","email":"user3@domain.com","ts":1500998208597,"status":"active","profile":{},"groups":["gold","silver","customer"],"tenant":{"id":"54ee2150b7a669fc22b7f6b9","code":"TNT1"},"config":{"packages":{"PROD1_PCK1":{"acl":{"urac":{},"example03":{},"example04":{}}}},"keys":{"19c03e42c750467c3f8481fbe26f2fef":{"config":{"example03":{"tenantName":"Tenant name specific to user three"},"example04":{"tenantName":"Tenant name specific to user three"}},"acl":{"urac":{},"example04":{},"example03":{"apisPermission":"restricted","apis":{"/buildName":{}}}}}}}},"soajsauth":"Basic c29hanM6QzAxNl9pUFltUUtkdnFsck5ZSmFoMG1mMmVEZzZ0SXkxaTU="}

buildName API with user3

User3 overrides the tenant, and has access to the "buildName" API. as can be seen in the response below.

Request
curl -X GET "http://127.0.0.1:4000/example03/buildName?lastName=Smith&access_token=06ff4ec503f9ecd91af42cf8d324e65b5c780645" -H "key:4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2"

User3 was also able to change the name of the tenant.

Response
{"result":true,"data":{"tenantName":"Tenant name specific to user three","fullName":"John Smith"},"soajsauth":"Basic c29hanM6QzAxaV9KRk5ZYU5VbHZCcC1QOEVoWHFKVjIxdzNyNFlVWF8="}

testGet API with user3

However, the ACL corresponding to this user prohibits it from using the "testGet" API.

Request
curl -X GET "http://127.0.0.1:4000/example03/testGet?lastName=Smith&access_token=06ff4ec503f9ecd91af42cf8d324e65b5c780645" -H "key:4232477ed993d167ec13ccf8836c29c400fef7eb3d175b1f2192b82ebef6fb2d129cdd25fe23c04f856157184e11f7f57b65759191908cb5c664df136c7ad16a56a5917fdeabfc97c92a1f199e457e31f2450a810769ff1b29269bcb3f01e3d2"

The response proves that user3 does not have access to the "testGet" API.

If we look at the terminal that is running the service "controller", we will see a more in-depth error message:

(/opt/soajs/node_modules/soajs/servers/service.js:415 in logErrors): System api access is restricted. api is not in provision.


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 v2 section.
  • No labels