Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
ale_biagi
Product and Topic Expert
Product and Topic Expert
NOTE: this blog post is intended for developers who have previous experience in developing multi-tenant CAP applications using SAP Business Application Studio, SAP BTP destinations, and the destination and XSUAA services.

Introduction


After I published this blog post, many developers reached out to me with the classical question: "does this microservice work in a multi-tenant scenario?"

My first reaction was to provide them a quick and straightforward answer: "yes, as long as you properly handle the on-board and off-board processes for the subscription and the access to the appropriate subscriber XSUAA APIs to manage its users".

Looks quite simple, right? Well, but, of course, the queries kept coming (having the same quick and straightforward answer). Then, I finally made the decision to take on the challenge and develop the multi-tenant version of the microservice to serve as a definitive reference for those who want to embarc on that adventure.

So, before you continue reading this post, I strongly recommend that you read through the first post (as this one is just its spin-off) to fully understand what's going to be discussed in the following topics. That post explains in detail the single-tenant version of the microservice - this version just contains some specific modifications to make it multi-tenant.

Therefore, without further due, let's dive into the service details.

Application Architecture


The business problem is exactly the same of the first post. The scenario in this post is intended to deep dive into a fully working multi-tenant version of the CAP microservice leveraging an SAP Fiori UI for subscribers. The service manages users who are assigned to specific role collections (the ones belonging to the business application that is consuming the service) reading and writing user information from BTP in the subscriber subaccount using its XSUAA service APIs. The microservice is ready to deploy on BTP, Cloud Foundry Runtime.

Here’s a diagram representing the overall architecture of the microservice:


Figure 1 - Application Architecture


You may have noticed that the contents inside the provider subaccount are exactly the same as in the architecture described in the first post.

In the subscribers subaccounts, there's the microservice subscription and a specific destination pointing to the XSUAA APIs from the subaccount.

XSUAA manages the BTP user store (namely “Shadow Users”). In the subscriber subaccount the CAP microservice subscription is created and  will be responsible for managing the business application’s users in there. Once again, as in the original version, the microservice will “filter” users from BTP based on a set of role collections belonging to the business application.

It interacts with the XSUAA service in the subscriber through a destination to make REST API calls to the services’ user management APIs which are based on the System for Cross-Domain Identity Management (SCIM) standard.

That being said and looking to the architecture diagram, it's obvious that each subscriber will require its own instance of the XSUAA service with the apiaccess plan (which also requires enabling Cloud Foundry and creating a CF space - no memory quota assignment is needed in this case). This is well detailed in the Git repo branch instructions.

The Fiori Elements HTML5 application will serve as the UI for the microservice's subscribers.

Prerequisites


As in the first post, that application is already built using SAP Cloud Application Programming Model (CAP) and BTP’s XSUAA APIs. The full code can be found in this branch of the GitHub repo from SAP samples.

As previously mentioned, the intent of this blog post is just to walk through and understand the key-points of the development.

Therefore, as first prerequisite to follow-up with this post (besides reading through the first one), you must clone the repo branch strictly following the instructions from its README.md to setup the project locally.

NOTE: do not miss any single step of the instructions, otherwise you won't be able to run and deploy the application.

Security Descriptor (xs-security.json)


The only difference in the security descriptor from the first post is that "tenant-mode" is shared instead of dedicated:


Figure 2 - Application info


We also changed the "xsappname" in case you decide to deploy the microservice in the same subaccount of the single-tenant version, otherwise it's absolutely not mandatory.

The role collections for the generic application served by the microservice have been prefixed with GenericMtxApp instead of GenericApp also in case you want to deploy this version in the same subaccount as the single-tenant version, thus avoiding to share the same role collections between both versions. And that's all!

To learn more about the syntax of the XSUAA security descriptor you can read this official document.

Required Services


Same as in the first post. The only exception is that, upon deployment the MTA will create an additional service to manage the on-board and off-board processes of subscriptions to the microservice: the SaaS Provisioning Service (namely saas-registry). That service is bound to the CAP backend service in the mta.yaml:


Figure 3 - New service binding for the CAP backend service in mta.yaml


And is configured as shown below:


Figure 4 - SaaS Provisioning Service configuration


I strongly recommend you examine the mta.yaml in detail to look for the differences in relation to the single-tenant version from the first post. You'll notice that the managed approuter has been replaced by a standalone approuter:


Figure 5 - Standalone Approuter in mta.yaml


Thus, all references to the HTML5 repo and runtime services and respective configurations have been completely removed. This also leads to changes in the approuter configuration within the xs-app.json file:


Figure 6 - xs-app.json


Besides the replacement of all routes related to the HTML5 repo and runtime, another route has been added to point to the on-subscription and on-dependencies callbacks required by the SaaS Provisioning Service.

Destination Setup


Same as in the first post.

Package Setup


Few modifications have been made to the projects’ package.json file in relation to the first post.

First, some dependencies have been added to handle the on-board, off-board and get dependencies processes of subscription life-cycle:


Figure 7 - New project dependencies


The @sap/cds-mtx package is also responsible for managing the different schemas (HDI containers in the case of SAP HANA Cloud) where the data model is deployed for each tenant (subscriber) to provide full data isolation.

Second, some changes have been made to the cds.requires section:

1. Indication of a "mock tenant" for each "mock user";


Figure 8 - Mock tenant for mock user


2. Multitenancy setup:


Figure 9 - Multitenancy setup


3. There's also an additional API setup which is not part of the original microservice and has been added as a bonus that will be discussed later:


Figure 10 - Additional API reference



Microservice Configuration


The new GenericMtxApp prefix for the role collections has also been adjusted in the corresponding environment variable in the microservice configuration:


Figure 11 - New role collections prefix



Service Definition


In the service definition, a new action has been bound to the User entity. This has been done to execute the bonus snippet, which will be discussed later in this post:


Figure 12 - New action bound to the User entity



Annotations for the UI


Like it has been done with the previously defined action, we also annotate the criticality of the newly added action (which is also non-critical), but with no side effect in this case:


Figure 13 - UI annotations for the new action



Subscription Handling


The subscription handling process is fully implemented in the server.js file into the srv folder. That file has been entirely generated by the SAP HANA Academy CAP SaaS Multi-tenant Application Generator, selecting the options to automatically create routes and return required destination dependency in the respective callbacks, with no further modification (please, refer to the corresponding videos in the playlist from the link to better understand the generator).

Code Analysis


The application code is basically the same with the only exception that, as it's running in a multi-tenant context, the control flag that was a simple boolean variable in the single-tenant version has been changed to a JSON object like demonstrated in the screenshots below:


Figure 14 - New JSON object control flag



Figure 15 - Control flag handling upon data read



Figure 16 - Control flag reset upon data refresh



Bonus Snippet!


A while ago I also wrote and published a blog posts series focusing on how to get authenticated user information using three different approaches. One of them (which is the most complete) uses the XSUAA API from the application service binding - you can check it here.

And guess what? Same old classical recurring question: "does it work in a multi-tenant context?". Well, in this case the answer is: "yes, but with a slight modification in the code of the post to consider the authentication made in the subscriber".

So, once again, I decided to take advantage of the effort to produce the mult-tenant version of this microservice and add the multi-tenant version of the procedure to get authenticated user information.

NOTE: to understand what I'm talking about here, please also read through the blog post, before inspecting the bonus snippet.

OK, so here's the code executed by the previously mentioned userInfo action:


Figure 17 - userInfo action main code


In the single-tenant version described in the post, the url in the credentials is simply filled with the one gotten from the XSUAA service binding. As this binding is done in the provider subaccount (where the service is actually deployed), when the "/userinfo" endpoint is invoked XSUAA yields error, because the authentication (handled by the approuter) has been done in the subscriber subaccount and not the provider.

Well, the trick here is simple: as subscriptions can be done only in subaccounts located in the same region as the provider we can safely assume the authentication domain is always the same for both provider and subscribers. Therefore, for XSUAA to correctly interpret the authenticated user info, we just need to change the subdomain of the API URL to point to the subscriber subdomain instead of the provider. This is exactly what the highlighted code snippet does.

And this concludes the analysis and explanation of the multi-tenant user management microservice CAP project (with bonus snippet).

Additional Resources


Here's a list of resources to enhance your learning experience on this topic:

Conclusion


After setting up the project from this git repo branch and going through this blog post content, you'll have learnt and experimented how to build a multi-tenant CAP microservice which will allow your business application to manage its business users autonomously for each application subscriber. Hope you have enjoyed the journey!

Please, do not hesitate to submit your questions in Q&A in SAP Community: https://answers.sap.com/index.html
5 Comments