We are in the midst of the age of cloud computing and the change in IT system landscapes and software development projects is both noticeable and irreversible. Large, heavyweight monoliths are no longer in vogue, IT systems are becoming smaller and more distributed, technology stacks more heterogeneous, a development that also no longer stops at the SAP world. In future, the core systems are to be kept clean; instead of Z-tables, the migration-plagued IT professional now prefers to use side-by-side extensions. If the standard functionality of a system does not sufficiently reflect the process reality of a company, additional functionality is provided as independent, small and lean Fiori apps. So far, so good. But of course these extensions do not exist on their own in a vacuum, but should be loosely coupled with other extensions and of course also with the underlying back-end systems in order to achieve a noticeable business benefit across the entire process chain. This sounds simple at first, but is quickly accompanied by hard nuts to crack:
- As a rule, and ideally, the interfaces of individual systems are not located on the internet with the gates wide open, but only grant entry if the corresponding authentication protocols are meticulously followed and adhered to.
- Not all systems are operated in the cloud; the older generation of business standard software still prefers to cavort on the company’s internal on-premise infrastructure, into which one first has to laboriously dig connection tunnels before even being allowed through to the entry control.
- In the simpler case, a technical user is sufficient to gain access to an interface, but this is not always sufficient. Sometimes it is necessary for system A to pass the identity of the user initiating an operation to system B so that the operation can continue there for that user. In complex and evolved IT landscapes, the identities of users are often distributed among different identity providers for different systems, which does not necessarily facilitate the transfer of identity information.
- Communication with another system via an interface usually runs via HTTP, which nevertheless leaves enough leeway for the design of the data transfer, depending on whether it is based on classic REST, OData, GraphQL or gRPC. If you are very lucky (as I was a few months ago in one of my projects), you will still occasionally come across rare examples of the SOAP interface, a protocol from long ago, when XML was still considered the solution to all present and future problems.
To master at least part of this challenge, SAP Business Technology Platform offers so-called destinations. Destinations are used to configure connection information and to simplify the handling of individual communication steps and outsource them to a destination service. The main focus here is on the respective mechanisms for authentication. There is already a lot of official documentation on Destinations on the Internet, as well as many great blog articles and other community contributions that help to familiarise oneself with the cosmos of SAP BTP Destinations. Nevertheless, in my day-to-day work with developers and architects, I notice that there is often a lack of clarity about how destinations are to be used and which destination type is suitable for the respective integration scenarios. What I personally have often lacked in my research over the past years were tangible and touchable examples. This motivated me to create a GitHub repository in which I gradually provide examples for the different destination types, supplementing them with text contributions in which I describe the use cases for which the respective destination type is suitable. I also provide some background information on what goes on behind the scenes of such a destination.
Prerequisites
In order to try out the examples in the repository, you should have some basic experience in working with the SAP BTP Cloud Foundry environment. Knowledge of node / npm / JavaScript is also definitely an advantage. All examples are built with SAP CAP with Node.js and use Multi Target Applications (MTA) for deployment. To build and deploy the examples you will need in any case:
- Access to an SAP Business Technology Platform subscription with an activated Cloud Foundry environment and a corresponding Cloud Foundry space, e.g. with a SAP BTP Trial account
- node and npm
- Cloud Foundry CLI
- MTA Build Tool (MBT) CLI
For each destination type there is a separate branch with a README file describing how to deploy client and server on Cloud Foundry and how to test the connection between client and server.
Cloud 2 Cloud – NoAuthentication
https://github.com/jfranken/sap-btp-destinations/tree/cloud-2-cloud-no-authentication
To make the introduction pleasant, I start at a very low level with the simplest conceivable integration scenario: System A (client) communicates with System B (server) via HTTP over the internet, the interface of System B is openly available and does not require any authentication. A classic use case for this is the consumption of a public API.
The repo contains two SAP CAP applications, client and server. The magic here takes place in the client-service.js file. Two service endpoints are defined in the client-service.cds file, both of which call a Hello Word endpoint of the server app, one using the Cloud SDK, one using step-by-step direct communication with the destination service, to better illustrate what happens behind the scenes in the Cloud SDK.
Cloud SDK
srv.on('helloWorldClientCloudSDK', async () =>
return executeHttpRequest({ destinationName: 'Server' })
.then((response) => response.data)
})
Plain
const { executeHttpRequest } = require('@sap-cloud-sdk/http-client'
const axios = require('axios')
module.exports = async (srv) => {
srv.on('helloWorldClientPlain', async () => {
// get all the necessary destination service parameters
// from the service binding in the VCAP_SERVICES env variable
const vcapServices = JSON.parse(process.env.VCAP_SERVICES)
const destinationServiceUrl =
vcapServices.destination[0].credentials.uri +
'/destination-configuration/v1/destinations/'
const destinationServiceClientId =
vcapServices.destination[0].credentials.clientid
const destinationServiceClientSecret =
vcapServices.destination[0].credentials.clientsecret
const destinationServiceTokenUrl =
vcapServices.destination[0].credentials.url +
'/oauth/token?grant_type=client_credentials'
// before we can fetch the destination from the
// destination service, we need to retrieve an auth token
const token = await axios.post(destinationServiceTokenUrl, null, {
headers: {
authorization:
'Basic ' +
Buffer.from(
`${destinationServiceClientId}:${destinationServiceClientSecret}`
).toString('base64'),
},
})
const destinationServiceToken = token.data.access_token
// with this token, we can now request the
// "Server" destination from the destination service
const headers = {
authorization: 'Bearer ' + destinationServiceToken,
}
const destinationResult = await axios.get(
destinationServiceUrl + 'Server',
{
headers,
}
)
const destination = destinationResult.data
// now, we use the retrieved the destination
// information to send a HTTP request to the server endpoint
const destinationResponse = await axios.get(
destination.destinationConfiguration.URL
)
return destinationResponse.data
})
srv.on('helloWorldClientCloudSDK', async () => {
return executeHttpRequest({ destinationName: 'Server' })
.then((response) => response.data)
})
})
The result is expected to be the same for both endpoints:
This example is far from passing for rocket science. But don’t worry – in terms of complexity, it is guaranteed to increase in the coming parts of this series!
What are your experiences with destinations in SAP BTP so far? Which integration scenarios have you already had to deal with? What were the biggest challenges? If you have any suggestions or improvement requests, or if something doesn’t work as you hoped, please let me know. It is my wish and goal to continuously expand and improve this repository, and for that I depend on your feedback from the SAP BTP community! 🙂
Disclaimer
The code examples provided are not suitable to be transferred 1:1 into productive implementations, but they only serve to illustrate the functioning of destinations and Destination Service. In some cases, the interaction with the Destination Service is deliberately implemented in a “cumbersome” manner in order to illustrate the communication processes as explicitly and in detail as possible. SAP CAP and the SAP Cloud SDK provide various functionality to simplify and abstract the use of destinations. However, this would be more of a hindrance than a benefit to the purpose of the illustration.