SAP Business Technology Platform (BTP) offers a hundred of business services and a number of runtime environments, namely:
that customers and partners developing cloud native applications can choose from. |
A. Developing Multi-tenant SaaS applications with SAP BTP, Kyma runtime, SaaS Provisioning and Destination services | B. Easy routing with Kyma API rules and OAuth2SAMLBearer destinations |
|
|
Q. What if you had an existing multi-tenant application with SAP BTP Cloud Foundry or ABAP environments ? It is already multi-tenant solution so why would you have to migrate it to for instance Kyma ? At the same time the next generation of product functionalities could greatly benefit from Kyma qualities?
A. The good news is the above architecture caters for a such a use case as well. Nothing really prevents you from expanding your CF/ABAP-based solution into Kyma/Kubernetes.
Nowadays, [for all BTP services that are cross-consumable and support instance sharing], SAP BTP service broker allows for service instances to be shared from one runtime environment to another…
Thus, all the roles, roles collections, other security settings, destination definitions become shareable between CF/Other and Kyma/Kubernetes environments.
Last but not least, there ain't no good SaaS solution without a solid principal user propagation mechanism. Please continue reading...
SAP BTP subaccount 2/region 2 has a custom IDP for user authentication and has an xsuaa-based OAuth2 client to request a bearer access token by calling the token issuance endpoint, The token issuance endpoint is the AssertionConsumerService URL of the subaccount 2 (recognisable by its suffix alias/quovadis.aws-live-eu10 )As depicted above, SAP BTP subaccount 2 is in a BTP region 2 (region == data center) different from Provider/Consumers BTP region 1. This offers an elegant way to overcome the hard data center tie-in between Provider and Consumer sub-accounts. And eventually achieves a region-free SaaS multi-tenancy. |
weather-anywhere API destination definition (Provider/Consumer) | weather-anywhere API rule definition (kyma cluster) |
https://*.microsoft
domain name to the trust settings in every provider/consumer BTP sub-account...Kyma runtime offers intrinsic auto-healing, auto-scaling and high availability (multi-zone worker nodes) cloud qualities. | Kyma runtime main ingredients |
|
apiVersion: gateway.kyma-project.io/v1beta1
kind: APIRule
metadata:
name: "{{ .Values.services.srv.name }}-{{ .Release.Namespace }}"
spec:
gateway: {{ .Values.gateway }}
host: "{{ .Values.services.srv.name }}-{{ .Release.Namespace }}.{{ .Values.clusterDomain }}"
rules:
- accessStrategies:
- config:
jwks_urls:
- https://<tenant>.authentication.<region>.hana.ondemand.com/token_keys
trusted_issuers:
- https://<tenant>.authentication.<region>.hana.ondemand.com/oauth/token
required_scope:
- quovadis-xsuaa-master!t119894.Read
handler: jwt
methods:
- GET
- HEAD
- POST
path: /arcgis
- accessStrategies:
- config:
jwks_urls:
- >-
https://<tenant>.authentication.<region>.hana.ondemand.com/token_keys
required_scope:
- openid
trusted_issuers:
- >-
https://<tenant>.authentication.<region>.hana.ondemand.com/oauth/token
handler: jwt
methods:
- GET
path: /forecast
- accessStrategies:
- config:
jwks_urls:
- https://<tenant>.authentication.<region>.hana.ondemand.com/token_keys
trusted_issuers:
- https://<tenant>.authentication.<region>.hana.ondemand.com/oauth/token
required_scope:
- quovadis-xsuaa-master!t119894.Admin
handler: jwt
methods:
- GET
- HEAD
- POST
path: /
service:
name: {{ .Values.services.srv.name }}
port: {{ .Values.services.srv.port }}
JWT claim | API rule config name | Description |
---|---|---|
iss | trusted_issuers | Token issuance endpoint. A fully qualified URL with scheme, host, and sometimes with a port number and path components but with no query or fragment components. The URL definition must match one of the trusted_issuers provided in the API rule.
|
scope | required_scope (optional) | list of scopes.
|
aud | target_audience (optional) | list of audiences
|
kid
and the alg
header parameter.JWT header parameter | API rule config name | Description |
---|---|---|
kid | The "kid" (key ID) parameter is a case-sensitive id used to match a specific public key. | |
alg | allowed_algorithms (optional) | The "alg" (algorithm) parameter identifies the algorithm intended for use with the key. Defaults to "RS256". |
{
"xsappname": "quovadis-xsuaa-master",
"tenant-mode": "dedicated",
"authorities": ["$ACCEPT_GRANTED_AUTHORITIES"],
"scopes": [
{
"name": "$XSAPPNAME.Read",
"description": "Read Permissions."
},
{
"name": "$XSAPPNAME.Admin",
"description": "Admin permissions."
}
],
"role-templates": [
{
"name": "Viewer",
"description": "View Data",
"scope-references": [
"$XSAPPNAME.Read",
"uaa.user"
]
},
{
"name": "Administrator",
"description": "View Sensitive Data",
"scope-references": [
"$XSAPPNAME.Read",
"$XSAPPNAME.Admin"
]
}
],
"role-collections": [
{
"name": "Viewer",
"description": "Viewer (read)",
"role-template-references": [
"$XSAPPNAME.Viewer"
]
},
{
"name": "Administrator",
"description": "Administrator (read all)",
"role-template-references": [
"$XSAPPNAME.Administrator"
]
}
]
}
quovadis-xsuaa-master
is the sending application and the property authorities: ["$ACCEPT_GRANTED_AUTHORITIES"]
qualifies all the scopes as grantable to a receiving application<?xml version="1.0" encoding="utf-8"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://auth.pingone.eu/<tenant>" ID="<ID>">
<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>
MIIFGzCCAwMCBGBb1dwwDQYJKoZIhvcNAQELBQAwUjELMAkGA1UEBhMCVVMxDDAK
XT6c0QNVYg37DBU/qhSN
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:SingleLogoutService Location="https://auth.pingone.eu/<tenant>/saml20/idp/slo" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"/>
<md:SingleLogoutService Location="https://auth.pingone.eu/<tenant>/saml20/idp/slo" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"/>
<md:SingleSignOnService Location="https://auth.pingone.eu/<tenant>/saml20/idp/sso" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"/>
<md:SingleSignOnService Location="https://auth.pingone.eu/<tenant>/saml20/idp/sso" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"/>
<saml:Attribute xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="user.preferredLanguage"/>
<saml:Attribute xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="user.address.region"/>
<saml:Attribute xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="user.id"/>
<saml:Attribute xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="user.email"/>
</md:IDPSSODescriptor>
</md:EntityDescriptor>
{
"Name": "weather-anywhere",
"Type": "HTTP",
"URL": "https://weather-anywhere.<custom domain name>.com",
"Authentication": "OAuth2SAMLBearerAssertion",
"ProxyType": "Internet",
"KeyStorePassword": "<KeyStorePassword>",
"tokenServiceURLType": "Dedicated",
"audience": "https://<tenant>.authentication.<region>.hana.ondemand.com",
"Description": "weather-anywhere",
"authnContextClassRef": "urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession",
"assertionIssuer": "https://auth.pingone.eu/<pingone tenant>",
"tokenServiceUser": "sb-quovadis-xsuaa-master!t119894",
"tokenServiceURL": "https://<tenant>.authentication.<region>.hana.ondemand.com/oauth/token/alias/quovadis.aws-live-eu10",
"tokenServicePassword": "<tokenServicePassword>",
"HTML5.DynamicDestination": "true",
"clientKey": "sb-quovadis-xsuaa-master!t119894",
"KeyStoreLocation": "quovadis_ateam-isveng.p12",
"nameIdFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
"scope": "openid quovadis-xsuaa-master!t119894.Read quovadis-xsuaa-master!t119894.Admin",
"userIdSource": "email"
}
{
"alg": "RS256",
"jku": "https://<consumer tenant>.authentication.<consumer region>.hana.ondemand.com/token_keys",
"kid": "default-jwt-key--1249532834",
"typ": "JWT",
"jid": "<jid>"
}.{
"sub": "<sub>",
"user_name": "foo.bar@acme.com",
"iss": "https://<consumer tenant>.authentication.<consumer region>.hana.ondemand.com/oauth/token",
"aud": [
"uaa",
"openid"
],
"ext_attr": {
"enhancer": "XS_APPLICATIONUSER",
"zdn": "<consumer tenant>"
},
"zid": "<zid>",
"user_id": "<user_id>",
"azp": "<azp>",
"scope": [
"openid",
"uaa.user"
],
"exp": <exp>,
"iat": <iat>,
"jti": "<jti>",
"email": "foo.bar@acme.com",
"cid": "<cid>"
}.[Signature]
{
"alg": "RS256",
"jku": "https://<tenant>.authentication.<region>.hana.ondemand.com/token_keys",
"kid": "default-jwt-key--623944614",
"typ": "JWT",
"jid": "<jid>"
}.{
"jti": "<jti>",
"ext_attr": {
"enhancer": "XSUAA",
"subaccountid": "<subaccountid>",
"zdn": "quovadis"
},
"xs.system.attributes": {
"xs.rolecollections": [
"Administrator",
"Viewer"
]
},
"given_name": "foo.bar",
"xs.user.attributes": {},
"family_name": "acme.com",
"sub": "<sub>",
"scope": [
"quovadis-xsuaa-master!t119894.Read",
"openid",
"quovadis-xsuaa-master!t119894.Admin"
],
"client_id": "sb-quovadis-xsuaa-master!t119894",
"cid": "sb-quovadis-xsuaa-master!t119894",
"azp": "sb-quovadis-xsuaa-master!t119894",
"grant_type": "urn:ietf:params:oauth:grant-type:saml2-bearer",
"user_id": "<ser_id>",
"origin": "httpsauth.pingone.eu5f3341ef-3cf9-4c",
"user_name": "foo.bar@acme.com",
"email": "foo.bar@acme.com",
"rev_sig": "b4df0449",
"iat": <iat>,
"exp": <exo>,
"iss": "https://<tenant>.authentication.<region>.hana.ondemand.com/oauth/token",
"zid": "<zid>",
"aud": [
"sb-quovadis-xsuaa-master!t119894",
"quovadis-xsuaa-master!t119894",
"openid"
]
}.[Signature]
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
14 | |
12 | |
9 | |
9 | |
8 | |
6 | |
6 | |
6 | |
5 | |
5 |