Skip to Content
Product Information

Using SaaS Provisioning Service to develop Multitenant application on SAP Cloud Platform, Cloud Foundry Environment

In the context of Cloud Computing, Multitenancy allows an application provider to serve applications and services to multiple tenants – a set of users. End users of the application access it through a URL dedicated to that tenant.

A tenant-aware application has the capability to separate data securely per tenant, can share resources across the tenants, and can serve features from a single code repository.

This blog elaborates on the process to build a multitenant application on SAP Cloud Platform in the Cloud Foundry environment. For multitenancy on the Neo environment, please see this blog.

Understanding Software as a Service (SaaS) Provisioning service

In the SAP Cloud Platform Cloud Foundry environment service marketplace, we can see SaaS Provisioning service as shown in the image below.

To make our SaaS Application available to multiple tenants we must set up a registry for our application. The SaaS Provisioning service is where we, as a SaaS Application provider, register our app. The SaaS Provisioning service enables us to automate the subscription process. It also maintains a list of all dependencies and subscriptions of an application.

A SaaS Application provider creates a subaccount to deploy the application. Inside this subaccount, the provider creates a space and deploys the SaaS Application. The provider then registers the application with a SaaS registry. The SaaS registry service on SAP Cloud Platform creates a new entry. Through this service, any sub-account, within the same global account, will see an entry of the provider application in the subscriptions tiles. The consumer then can subscribe to the application by just a click of a button. Each subaccount has a unique subdomain and identity zone id.

 

Understanding the concept through an example

Let’s look at how one can use SaaS Provisioning service to build a simple ‘Hello World’ multitenant application.

There is a SaaS Application provider – Provider ZZZ. Provider ZZZ would like to build an application that displays a hello message. The hello message will display the logged in user’s name and the tenant from which the user has logged in – as shown in the image

 

As ZZZ, we will build a ‘Hello World’ application to display the ‘hello message’. Also, since each tenant will access the application from a unique URL, we will build an app router app to resolve the URL, authorize the request and forward the request to our application.

Overview of the Steps Involved

1.     Develop A SaaS Application

In our application’s default end-point (GET – ‘/’) we will return a hello statement displaying the username, tenant subdomain, and tenant identity zone.

We deploy this application on our (provider’s) sub-account and test the application. Once we are satisfied with the development, we add the configurations required to make our application available across tenants.

 

2.     Add Configurations For Multitenancy

To make our application available to SaaS Provisioning service and to automate the subscription process we must add the following configuration to our SaaS Application.

The SaaS Provisioning service requires us to define the following API end-points.

  • PUT – ‘callback/v1.0/tenants/*
    • To onboard a tenant, i.e. when a consumer subscribes to the application
  • DELETE – ‘callback/v1.0/tenants/*’
    • To off-board a tenant, i.e. when a consumer unsubscribes to the application

Each consumer accesses the SaaS Application through a unique URL. To ensure that these requests come to the target application, we define a tenant host pattern for our app router app in the MTA.yaml file. Click here for the detailed documentation.

We specify the SaaS Application name, description, app category while creating a SaaS Provisioning service instance. We mention these details in a config.json

{

  "appId": "<XS-App Name>",

  "displayName": "Hello World",

  "description": "A sample hello world app to explain the concepts of Multitenancy",

  "category": "Provider ZZZ",

  "appUrls": {

    "onSubscription": "<Your back-end app URL>/callback/v1.0/tenants/{tenantId}"

  }

}

 

3.     Register the SaaS Application to SaaS Provisioning

Upon completing our configuration, we create a SaaS Provisioning service and bind it to our SaaS Application. To complete this set of actions we require Cloud Foundry Command Line Interface.

We start this process by creating a new SaaS Provisioning service instance.

cf cs saas-registry application <Service name> -c <Path to config.js file>

Next, we bind our SaaS Application to the newly created SaaS Provisioning service instance.

cf bs <SaaS Provider Application Name> <SaaS Provisioning Service Name>

Once we bind our application to this service instance we will be prompted to restage our application. To do so, we execute the following command.

cf restage mt-hw-node-app

 

4.     Subscription of the SaaS Application by a Consumer

A consumer can subscribe to the application either through the SAP Cloud Platform Cockpit or through REST APIs.

Subscription through SAP Cloud Platform Cockpit

In your global account, create a new subaccount and go to the Subscriptions tab. The SaaS registry service shows the applications that have been registered with it. Here, you will find the provider’s application.

Click on the application tile and click on the subscribe button.

Subscription through REST APIs

You will require a client that can make REST API calls (such as Postman).

We first get the application authorization token. Using your Cloud Foundry Command Line Interface tool execute the following command

cf env <Name Of You SaaS App>

Create a new request in your client with the following setup. Copy the corresponding values from the environment variables.

HTTP Method – POST

URL – <"System-Provided"."VCAP_Services"."saas-registry"."credentials"."url">

Parameters

Key: grant_type

Value: client_credentials

Authentication Type – Basic Authentication

Username - <"System-Provided"."VCAP_Services"."saas-registry"."credentials"."clientId">

Password - <"System-Provided"."VCAP_Services"."saas-registry"."credentials"."clientSecret">

You will receive the following as a response.

{

  "access_token": "xxxxxx",

  "token_type": "bearer",

  "expires_in": 43199,

  "scope": "yyyyyy",

  "jti": "zzzzz"

}

We use the access_token returned to call the subscription API in the next step.

HTTP Method – PUT

URL - <"System-Provided"."VCAP_Services"."saas-registry"."credentials"."tenant_onboarding_url">/api/v2.0/subscription/tenants/{tenantId}

tenantId – Tenant Zone Identity

Parameters

Key: jobUuid

Value: A newly generated GUID

Authentication Type – OAuth 2.0

Access Token – Access token copied from the response of the earlier API

In upcoming blogs, we will take a look at the different APIs that can be used.

 

5.     Mapping Consumers’ Routes

In the last step, the provider needs to add a new route to ensure that a consumer’s request goes to the app router.

You can now launch the app for the consumer

In upcoming blogs, we will take a closer look at methods that we can adopt to automate the process of route mapping.

 

 

Please find the code for a ‘Hello World’ sample application here. This application has been developed using node.js. For further information and a step by step guide, please go through the Readme.MD file. If you prefer a video, please check out this playlist by SAP HANA Academy.

 

Now that you have an understanding of SaaS Provisioning and steps involved in building a multitenant application you can go through this blog to see how can we achieve multitenancy at persistence layer through SAP Cloud Platform, Cloud Foundry environment. The blog explains the concepts through a sample product inventory management application. To gain a deeper understanding of the architecture please read this blog.

52 Comments
You must be Logged on to comment or reply to a post.
  • Why is it necessary for tenant to be in the same global account as the provider when we use saas registry? Is there a config mode that needs to be changed to allow subscription of tenants from other global accounts?

  • Hi Sandeep,

    Are we supposed to add the route tenantId+appurl  to access the app? in my case, I have done this way but while trying to access the Tenant ID in the subscriber application, I’m getting tenant ID of the dev space where app deployed.

    I’m not sure if this is because of the app route that I have created after SaaS subscription or anything missing while provisioning/subscribing the app.

     

    Best regards,

    Gopal

    • Hi Gopal,

      Thank you for your question.

      You are expected to add construct your onSubscription URL in the following format:

      var tenantAppURL = https:\/\/ + <subdomain name of the consumer+ <name of your application+ <CF App Domain>;

      Please note that this is required only for those services which have to be multi-tenant. You need not do this for the app-router application.

      For code specific details please refer to the sample app included in the blog.

      I hope this answers your query.

  • Hi SANDEEP TDS

    Thanks for the post.

    How would you implement a similar approach for a Fiori Launchpad module with some HTML5 applications (for apps built using Fiori Elements template) consuming odata? 

    Best regards,
    André

     

      • Hi SANDEEP TDS / Jan Rumig

        When creating an MTA with SAP Fiori Launchpad Module, the WebIDE generates the Approuter module. Which module should be used as the App Router : the Fiori Launchpad module or the App Router created by the WebIDE?

        Thanks,

        Ashish

        • With Portal service 2.0 the Portal service is bound as a service to the approuter application running in CF. The Fiori Launchpad module is actually a deployer application that upload FLP content into the Portal service (e.g.: tiles configuration).

          Applications routing is supported by the approuter application. Running FLP is achieved by running a url with the following pattern:

          https://<approuter-url>/cp.portal/index.html

          Note that the approuter url host may be dynamic in case of multitenant approuter.

          Best Regards

          Sergio

          • Thanks for the information, Sergio Rozenszajn !

            I am trying to build a multitenant app. When creating the app in a dedicated tenant mode, the app works fine. Portal gets launched with https://<approuter-url>/cp.portal/

            But when the same app is deployed as a multitenant app, the portal url shows the message “Internal Server Error”

            The app subscription from a tenant is successful. I am even able to access backend_api routes via the Approuter.

            Here is a sample xs-app.json file for the Approuter:

            {
            	"welcomeFile": "/cp.portal",
            	"authenticationMethod": "route",
            	"logout": {
            		"logoutEndpoint": "/do/logout"
            	},
            	"routes": [{
            		"source": "^/callback/(.*)",
            		"target": "/callback/$1",
            		"destination": "backend_api"
            	}, {
            		"source": "^/be/(.*)",
            		"target": "$1",
            		"destination": "backend_api"
            	}]
            }

             

            Any thoughts on this?

            Thanks,

            Ashish

    • Hi @andrefernandescontax,

      Did you implement the Fiori Launchpad module approach? Was this approach similar to this guide or were there some changes involved?

       

      Thanks,

      Ashish

  • Hi Sandeep,

    Little question about this topic can we use any language for this or only using javascript?
    If I have an application develop for example in ruby, can I deploy it ? Can we use container that contain the application ?

    Thanks for your help

    • Hi Emmanuel,

      Thank you so much for the question.

      No, you are not limited to Javascript. You can use Java, Python or other languages supported by the Cloud Foundry Community Buildpack.

      Irrespective of your development technologies, you must ensure that your application defines the required callbacks (See Step 2 of this Blog).

      You must architect your application in a way which allows you to define the callbacks and bind SaaS Provisioning Service.I hope this answers your query.

  • Hi Sandeep

     

    I have a new cloud platform (enterprise version) and this is the first thing I have done in it. I have not installed a HANA database as yet. I have picked up the cloud foundry endpoint from the Cloud Foundry subaccount in the box on the right hand side detailing the organisation, spaces, members and API endpoint (Sydney data centre: api.cf.ap10.hana.ondemand.com).

    The app builds and deploys successfully, but when I try to launch it, I get redirected to a SAP HANA XS Advanced logon page. If I use my cloud platform credentials, it does not work.

    Is there something I need to do to my user or do I need to create a role for this to work?

    Regards

    Neil

     

    • Hi Neil,

      Thank you so much for your query.

      I am really glad that you are using SAP CP and were successfully able to deploy the application.

      Coming to your query, this happens because of the Tenant Host Pattern we define in our MTA.yaml file.

      Can you please try to create a new route that complies with the following pattern:

      https://<sub-account sub domain>-<app name>.<cf app url>

      For further details please refer to the guide here

      • Hi Sandeep

        Thanks for your response. Your response appear to apply to creating a route manually after the app has been subscribed too.

        Unfortunately, the XSA login screen appears for me after completion of step 4. Does this mean I have the tenant url in Step 3 incorrect?

        Regards

        Neil

        • Hi Neil,

          I apologize for the delay in my response.

          When we define a Tenant Host Pattern in our MTA.yaml file, as we have done in this application, our application routes and URL must conform to this pattern.

          Your current application URL, for the provider sub-account, should look something like this:

          https://<org-name>-<sub-accountName>-<space>-<appName&gt;.<cf-app url>

          This route doesn’t comply with the tenant-host pattern defined by us in the MTA.yaml file.

          Thus, to access the provider’s application, you must create a route which matches the host pattern defined by us.

          For further understanding, you can remove the Tenant-Host Pattern and make other required changes (change UAA service to dedicated in xs-security.json) and deploy the application. When you do this, you will be able to access the application using the default URL constructed by the platform.

  • Hi Sandeep,

    While I am trying to delete the SaaS-registry instance, it throws the following error:

    Service instance pci-registry: Service broker error: SaaS application has active subscriptions for tenants: 50681641-b011-4073-9004-3e0267387329

    I am even not able to deploy my MTA application. It throws the following error:

    Error creating services: Error updating service “pci-registry” from offering “saas-registry” and plan “application”: Service broker operation failed: 502 Bad Gateway: Service broker error: Service broker parameters are invalid: appName can’t be changed.

    I have attached the screenshot of the same.

    Kindly help provide a solution to the same.

    Thanks and Regards

    Debojit

    • Hi Debojit,

      Thank you so much for your query.

      To delete a SaaS Provisioning Service the provider must ensure that there are no active subscriptions on the service.

      The flow to delete a SaaS Provisioning is as follows:

      1. Ask all tenants to un-subscribe your application.
      2. Verify that no active subscriptions are present on your service.
      3. Delete the SaaS provisioning service.

      For the other issue that you have encountered, I need more information. Can you please reach out to me internally?

      Thank you so much for your cooperation.

      I hope this response helps you.

      Warm Regards

      Sandeep T D S

       

  • Hi SANDEEP TDS ,

    I am trying to subscribe a tenant to my multitenant application written in java. I am on canary.

    From the tenant account, when i click on subscribe, the status shows as processing for sometime and then comes back to unsubscribed.

    when trying to subscribe through the REST API, I am able to get the access token,

    but when i hit the tenant onboarding url, i am, getting access denied error.

    I think I am missing something here.

    can you please help me with this.

    Maybe we can connect internally.

    • Hi Nandan,

      Thank you so much for your query.

      From what you’ve described in your comment, I believe the error could be in your application – either where you are defining the callbacks or where you configure the authentication.

      Can you please refer to this sample application, written in JAVA, and try to identify if there’s any deviation in your implementation?

      If you do not find any parity, I will be happy to assist you further.

      Warm Regards
      Sandeep T D S

  • Hi SANDEEP TDS,

    I’m trying to create a multi-tenant application based on HANA.

    Is it possible that we can grant some HANA db roles to tenant user when they subscribe the application?

     

    Thanks in advance,

    Regards,

    Sandy

  • Hi SANDEEP TDS ,

    Thanks for your blog.

    I have a question about the destination on multi-tenant. We use the destination on CF to connect the S/4 HANA system.

    Now the multi-tenant application is deployed in CF canary as provider subaccount.

    How the application could get the destination in consumer subaccount during runtime?

    Then we can connect to according S/4 HANA system base on consumer destination configuration.

    Best Regards

    Clark Huang

  • Hi Sandeep,

    My provider sub account and consumer sub account belongs to different infrastructure provider and regions in the same global account. Can consumer sub account still be able to subscribe the application deployed in provider sub account? I have tried with the sample “Hello World” application: https://github.com/SAP/cloud-cf-multitenant-saas-provisioning-sample

    But i cant see the application in consumer sub account under Subscriptions page/option.

    Thanks

    Ravindra

     

    • Hi Ravindra,

      Thank you for your question.

      This feature was not available when we wrote the blog. I have since moved to a new project.

      Jan Rumig should be able to help us out. Jan, can you please comment? Thank You.

      Regards
      SandeepTDS

        • Hi Jan,

          Thanks for your reply.

          Yes, I have registered the application mt-hw-node-app with the SaaS Provisioning service as explained in the blog and SAP help portal. But still i cant see the SaaS application in consumer sub account under Subscriptions page/option.

          Also apart from this, I am facing below issue,

          On successful deployment of the app, when i open the app-router application which is mt-hw-ar-app in the provider sub-account i am getting error “The subdomain does not map to a valid identity zone.” instead of Hello message.

          Is this something to do with TENANT_HOST_PATTERN. I have mentioned value as “^(.*)-mt-hw-ar-app.cfapps.eu20.hana.ondemand.com” in mta.yaml under mt-hw-ar-app application.

          When i remove the Tenant-Host Pattern and make other required changes (change UAA service to dedicated in xs-security.json) and deploy the application, i can see the Hello message if i open the app-router application mt-hw-ar-app in the provider sub-account.

          Regards,

          Ravindra

          • Hi Ravindra,
            Please provide me the landscape of your account.
            Global account and subaccount id’s and
            appName you used to register your application
            in SaaS Manager.
            Regards,
            Nimrod Oron
          • Hi Nimrod,

            Thanks for your reply.

            I have mentioned the details in incident 404291 / 2019. You may please have a look and help.

            Appreciate your help.

            Regards,

            Ravindra

             

    • Hi Sindy,

       

      Thank you for reaching out to me. I’ve written an e-mail to you. Can we please discuss this over a quick call?

       

      Thank you
      Sandeep T D S

  •  

    Could you help me ? I am sap partner and I have plans to create an application saas multi-tenant .

    I saw that is possible using sub account in the same global account.

    But my approach will be different, I need that my customers subscribe in my application using their global account.

    Where I can find documentation about this ? e.g partner sale in SAP Store.

    • Hi Erico,

      thanks for the question.

      As documented: currently, customers of partner applications can only be subscribed from a subaccount within the same global account.

      We will update you, if there will be a change later.

      Thanks and best regards,

      Jan

        • Hi Erico,

          I would recommend to you, to go ahead with the current possible setup. Provide every customer of yours, a separate subaccount and subscribe this to your application in your provider subaccount.

          There is no naming convention for applications in cloud foundry.

          Best regards,

          Jan