This blog is part of a
series of tutorials explaining how to write serverless functions using the Functions-as-a-Service offering in
SAP Cloud Platform Serverless Runtime
Quicklinks:
Quick Guide
Sample Code
Introduction
In the
previous tutorial we‘ve learned how to call a service which is protected with OAuth and requires a scope.
The challenge was:
-> how can the function possess the scope?
The solution was:
-> configuration of both xs-security.json files
BUT:
There was a precondition:
-> both app and function have to live in the same subaccount
This is necessary because the central XSUAA of the subaccount creates one oauth-client for each instance and assigns the granted scope to the other client.
Thus, it has to resolve the names of the scope and involved clients
This is possible because the name of the scope is made unique and identifiable by adding the variable
$XSAPPNAME to the scope name.
As we all know, the value of the variable is not just the same as the name of the property
xsappname
The value of
$XSAPPNAME is generated at runtime and contains some mystic suffix
!t1234
OK.
Today we want to call from the function to a service which lives in a different subaccount.
So now, the XSUAA has to find not only the correct scope and oauth-client.
It has to find it in a different subaccount (identityzone)
How to do it?
-> communicate with the other central XSUAA
How to find that one?
-> By the unique identifier of the subaccount (identityzone)
As such, we have to add the subaccountID to the
GRANT statement

And that’s already all for today
Nevertheless, let’s make it real
Overview
In this tutorial, we’re going to learn how to assign a scope to an application in a different subaccount
The scenario is almost the same as in the
previous tutorial.
We can either re-use it and do the required little changes
Or create the project as described below, everything based on the previous blog
In the first part of this tutorial, we’re creating a very basic app which exposes an endpoint which is protected with OAuth and which requires a certain scope
In the second part, we’re creating a Function which tries to call that endpoint
Part 1: The Protected App
Create xsuaa, define scope
Create app, check scope
Part 2: The Calling Function
Create xsuaa, define authority
Create Function, do OAuth flow
Prerequisites
- If you’re new to the topic, the previous tutorial is a prerequisite, along with all its prerequisites and blablabla
- In addition:
To follow this tutorial, we need 2 different subaccounts.
In my example, I’m using my trial account, in addition to my FaaS-account (containing the instance of SAP Cloud Platform serverless runtime)
Limitation:
Both accounts have to live in the same data center (in my example, eu10)
Preparation: Create Project Structure
Same
preparation like in previous blog: create files and folders
In addition:
We need to find the ID of the FaaS-subaccount.
It is easy to find: just open the subaccount in the cloud cockpit
Which subaccount?
We need the ID of the subaccount where the FaaS is located

Part 1: The Protected App
Almost same as
part 1 of previous tutorial
Really only the
xs-security.json file is little bit different
1.1. Security Configuration
This is the essential section of this tutorial:
Here we’re using the subaccount ID:
-> grant the scope to an oauth-client living in the specified subaccount
{
"xsappname" : "xsappforsafeapp",
"scopes": [{
"name": "$XSAPPNAME.scopeformysafety",
"grant-as-authority-to-apps" : [ "$XSAPPNAME(application, 12ab12ab-34cd-56ef-34cd-12ab12ab12ab, xsappforfaas)"]
}]
}
Syntax:
"grant-as-authority-to-apps" : [
"$XSAPPNAME(<service_plan>, <subaccount_id>, < xsappname_of_caller >)"
]
After clarifying the new security descriptor, we create an instance of XSUAA in our Trial account (or whatever account you’ve chosen)
We have to make sure that we're targeting the different account, e.g. trial
To change location:
cf t -o p123456trial
see:

OK, for your convenience, here's again the command to create a service instance:
In my example, we jump into
C:\tmp_faas_callsafe\safeapp and run the following command
cf cs xsuaa application xsuaaforsafetyapp -c xs-security-safe.json
1.2. Create Application
No change needed to the app.
Just take the sample code (Part 1) from
previous tutorial
1.3. Deploy and Run the App
Yapp, just deploy it to the different account.
No need to run it, we did it in the previous torture
1.4. Small Recap
We deploy a protected app to trial account.
We specify that the Function of FAC account is allowed to call us
So we add a statement to grant access to the calling xsapp
And here is the place to enter the ID of the FAC account
Part 2: The Calling Function
Again, all the same as in
one of the other boring tutorials
2.1. Security Configuration
In part 1 we learned how to grant a scope to an xsuaa instance in a different subaccount
Now we’re on the receiving side: we receive the granted scope and we need to accept it
In the previous tutorial, we used the following statement:
"authorities":["$XSAPPNAME(application,xsappforsafeapp).scopeformysafety"]
Now we would need to make clear where to find that foreign xsapp
However, I haven’t found a way to add the subaccountID in this statement
OK, no prob.
-> we have to fall back to the generic statement:
"authorities":["$ACCEPT_GRANTED_AUTHORITIES"]
Using this statement, we accept all scopes granted by anybody to our app (xsapp, to be more precise)
So now we open the file
xs-security-faas.json, in folder
unsafefunction and enter the following content
{
"xsappname" : "xsappforfaas",
"tenant-mode" : "dedicated",
"authorities":["$ACCEPT_GRANTED_AUTHORITIES"]
}
Note:
This statement doesn't apply only for different subaccounts, it can be used in any scenario

As usual. this JSON config can be used to create or update an instance of XSUAA.
Before executing a command, don't forget that this time, we have to make sure that we target the subaccount where FaaS is living
To create the XSUAA-instance for FaaS, we jump into the function folder
unsafefunction then:
cf cs xsuaa application xsuaaforfaas -c xs-security-faas.json
And create a service key:
cf csk xsuaaforfaas servicekeyforfaas
BUT:
If you have the scenario in place, It is enough to update the existing service:
cf update-service xsuaaforfaas -c xs-security-faas.json
2.2. Create Function
All the same as in
previous hands-on. It shouldn’t be necessary to do any change, register or deploy.
But it might be necessary to repeat steps, if the xsuaa instance was deleted, etc
Or to adapt the code, if the name of the protected app was changed in trial
Otherwise, we can just use the deployed function, if remaining from the previous blog
Or we create everything from scratch, based on the
sample code Part 2
And then, finally, we invoke the function and are happy to see the same result which we had before
No shame to be happy:
We’ve learned the little trick which enables us to cross the borders of subaccounts
Summary
In this blog we’ve learned almost nothing
Just adding a cryptic guid in the middle of a cryptic statement
Luckily, the blog post hasn’t been too long…
Quick Guide
The protected app which is called by the Function has to grant the scope to the Function
If both are not located in the same subaccount, then the subaccountID of the Function has to be added (ID can be found in the cockpit)
xs-security.json of protected app:
"scopes": [{
"name": "$XSAPPNAME.scopeformysafety",
"grant-as-authority-to-apps" : [
"$XSAPPNAME(application, 12345678-abcd-..., xsappforfaas)"
The calling Function has to accept the grant. In case of different subaccounts, the generic statement has to be used to accept all granted scopes
xs-security.json: of Function
"authorities":["$ACCEPT_GRANTED_AUTHORITIES"]
Links
Same as in
previous tuutorial
Appendix: All Project Files
The whole project can be found in
previous tutorial
However, we have to adjust the following files in both projects
Part 1: The Protected App
These files are located in the folder "safeapp"
xs-security-safe.json
{
"xsappname" : "xsappforsafeapp",
"tenant-mode" : "dedicated",
"scopes": [{
"name": "$XSAPPNAME.scopeformysafety",
"grant-as-authority-to-apps" : [
"$XSAPPNAME(application, 1a2b3c4d-0000-1111-aaaa-..., xsappforfaas)"
]
}]
}
Part 2: The Calling Function
They are located in the folder "unsafefunction"
xs-security-faas.json
{
"xsappname" : "xsappforfaas",
"tenant-mode" : "dedicated",
"authorities":["$ACCEPT_GRANTED_AUTHORITIES"]
}