cancel
Showing results for 
Search instead for 
Did you mean: 

Subdomain does not map to a valid identity zone in a Multi-Tenant Environment (SAP CAP, MTXS)

dontobi
Explorer
0 Kudos

The application I'm currently developing uses SAP CAP with the MTXS Sidecar for Tenant Subscription Handling.
The subscription works. A unique URL is created that I can map to the application router. Also a new HDI Container is created by the service manager.

But on attempt to access the application, I get rerouted to the XSUUA Service with an error message.

The URL for the authentification is:

https://$TENANT-$ORGNAME.authentication.eu10.hana.ondemand.com/oauth/authorize

with $TENANT and $ORGNAME being placeholders for the tenant and organization name respectively.

My mta.yaml looks like so:


_schema-version: "3.1"
ID: example
version: 1.0.0
description: ""
parameters:
  enable-parallel-deployments: true
  appname: example
  deploy_mode: html5-repo
build-parameters:
  before-all:
    - builder: custom
      commands:
        - npm install --production
        - npm run build:cf

modules:
  - name: example-srv
    type: nodejs
    path: gen/srv
    parameters:
      buildpack: nodejs_buildpack
      disk-quota: 512M
      memory: 256M
    build-parameters:
      builder: npm-ci
    provides:
      - name: srv-api # required by consumers of CAP services (e.g. approuter)
        properties:
          srv-url: ${default-url}
    requires:
      - name: example-auth
      - name: example-db
      - name: example-registry

  - name: example-approuter
    type: approuter.nodejs
    path: router # from cds.env.folders. Consider also cds.env.build.target -> gen/app
    properties:
      TENANT_HOST_PATTERN: "^(.*)-${space}-${app-name}.${default-domain}"
    parameters:
      disk-quota: 256M
      memory: 256M
      routes:
        - route: https://${default-host}.${default-domain}
    requires:
      - name: example-html5-repo-runtime
      - name: example-auth
      - name: srv-api
        group: destinations
        properties:
          name: srv-api # must be used in xs-app.json as well
          url: ~{srv-url}
          forwardAuthToken: true
    provides:
      - name: app-api
        properties:
          app-protocol: ${protocol}
          app-uri: ${default-uri}
    build-parameters:
      builder: custom
      commands:
        - npm install
        - npm run build:ts

  - name: example-app-content
    type: com.sap.application.content
    path: .
    requires:
      - name: example-html5-repo-host
        parameters:
          content-target: true
    build-parameters:
      build-result: app_resources
      requires:
        - artifacts:
            - example.zip
          name: example
          target-path: app_resources/

  - name: example
    type: html5
    path: app/example
    build-parameters:
      build-result: dist
      builder: custom
      commands:
        - npm install
        - npm run build:cf
      supported-platforms: []

  - name: example-mtx
    type: nodejs
    path: gen/mtx/sidecar
    build-parameters:
      builder: npm-ci
    parameters:
      memory: 256M
      disk-quota: 512M
    provides:
      - name: mtx-api
        properties:
          mtx-url: ${default-url}
    requires:
      - name: app-api
        properties:
          SUBSCRIPTION_URL: ~{app-protocol}://\${tenant_subdomain}-~{app-uri}
      - name: example-db
      - name: example-auth
      - name: example-registry

resources:
  - name: example-auth
    type: org.cloudfoundry.managed-service
    parameters:
      service: xsuaa
      service-plan: application
      path: ./xs-security.json
      config:
        xsappname: example
        tenant-mode: shared
    requires:
      - name: app-api

  - name: example-html5-repo-host
    type: org.cloudfoundry.managed-service
    parameters:
      service: html5-apps-repo
      service-plan: app-host
      service-key: example-html5-repo-host-key
  - name: example-html5-repo-runtime
    type: org.cloudfoundry.managed-service
    parameters:
      service: html5-apps-repo
      service-plan: app-runtime
      service-name: html5-apps-repo-rt
  - name: example-registry
    type: org.cloudfoundry.managed-service
    requires:
      - name: mtx-api
    parameters:
      service: saas-registry
      service-plan: application
      config:
        xsappname: example
        appName: example
        displayName: example
        description: Example Substription Service
        category: "Example Services"
        appUrls:
          getDependencies: ~{mtx-api/mtx-url}/-/cds/saas-provisioning/dependencies
          onSubscription: ~{mtx-api/mtx-url}/-/cds/saas-provisioning/tenant/{tenantId}
          onSubscriptionAsync: true
          onUnSubscriptionAsync: true
          onUpdateDependenciesAsync: true
          callbackTimeoutMillis: 300000 # Increase if your deployments are taking longer than that
  - name: example-db
    type: org.cloudfoundry.managed-service
    parameters:
      service: service-manager
      service-plan: container
My application router:

{
	"welcomeFile": "index.html",
	"authenticationMethod": "route",
	"logout": {
		"logoutEndpoint": "/logout",
		"logoutPage": "LOGOUT_PAGE_URL"
	},
	"routes": [
		{
			"source": "^/logout.html$",
			"target": "example/logout.html",
			"service": "html5-apps-repo-rt",
			"authenticationType": "none"
		},
		{
			"source": "^/index.html",
			"target": "/userexample/index.html",
			"service": "html5-apps-repo-rt",
			"cacheControl": "no-cache, no-store, must-revalidate"
		},
		{
			"source": "/v2/exampleservice/(.*)$",
			"target": "/v2/exampleservice/$1",
			"authenticationType": "xsuaa",
			"destination": "srv-api",
			"csrfProtection": true
		},
		{
			"source": "^(/.*)",
			"target": "/userexample/$1",
			"authenticationType": "xsuaa",
			"service": "html5-apps-repo-rt"
		}
	]
}
I greatly appreciate any assistance in pinpointing possible sources of error.
View Entire Topic
martinfrick
Product and Topic Expert
Product and Topic Expert

Hi dontobi,

can you please double-check whether the URL you're returning during tenant provisioning is corresponding your TENANT_HOST_PATTERN? Feel free to check our sample implementation (bit different approach but at least to know the place where to search for). The URL you return to during the provisioning process must have the tenant subdomain in the very beginning as defined in your TENANT_HOST_PATTERN.

^(.*)-${space}-${app-name}.${default-domain}"

Sample (tenant subdomain = customerabc)

customerabc-dev-saasapp.cfapps.eu10.hana.ondemand.com

Maybe there's something wrong here. I hope that helps 🙂

Martin

dontobi
Explorer
0 Kudos

Hello martinfrick,

I am using the @sap/cds-mtxs package for providing multitenancy under the assumption that I am not required to manually configure such handlers for example during tenant provisioning.

If that assumption is incorrect, can I implement the handlers analogically to the example you've shared?

Thank you for your assistance

Tobias

martinfrick
Product and Topic Expert
Product and Topic Expert

Hi dontobi,

thanks for the additional context. I haven't used that "automated" approach yet, but looking at your mta.yaml file and into the code line, please consider the following details when it comes to variable usage in the mta.yaml.

  • default-host: ${default-host} # usually generated <Org>-<Space>-<Module>
  • default-domain: ${default-domain} # the default shared domain of the landscape
  • default-uri: ${default-uri} # composed by ${(default-)host}.${(default-)domain}
  • protocol: ${protocol} # usually defaults to "http"
  • default-url: ${default-url} # composed of ${protocol}://${default-uri}
  • app-uri: ${default-uri} # app-uri contains default-uri => mtx specific stuff

Based on this details, your subscription will return a subdomain like the following.

https://tenantsubdomain-org-space-appname.cfapps.eu10.hana.ondemand.com

SUBSCRIPTION_URL: ~{app-protocol}://\${tenant_subdomain}-~{app-uri}

Therefore, please check whether your TENANT_HOST_PATTERN is correct. From my understanding, the catch-group must contain the Org, but the Org needs to be placed in front of your Space as part of the TENANT_HOST_PATTERN ("^(.*)-${org}-${space}-${app-name}.${default-domain}").

Please let me know if that helps! In case you used an existing step-by-step guide or sample to setup your scenario please also feel free to share it with me!

Martin

dontobi
Explorer

Hi martinfrick,

thank you very much. I adjusted the TENANT_HOST_PATTERN to ^(.*)-${default-host}.${default-domain}, which solved the issue!

Thank you for providing insight into the structure of the variable usage and your suggestion for the pattern in the end, that really helped.

Thank you once more!

Tobias