Technical Articles
Enable mTLS with SAP Application Router, Custom Domain Service and XSUAA to Protect Your Application
In order to use mTLS to protect your application, you can directly leverage the capabilities of Cloud Foundry in combination with the SAP BTP Custom Domain service to implement mTLS.
In order to use mTLS to secure the connection between your application and the SAP Authorization and Trust Management service (XSUAA) to get the access token in the client credentials flow, XSUAA provides the related support.
Alternatively, you can use the SAP Application Router to do the mTLS handshake with your backend application and get an access token from XSUAA in the mTLS way. This post is mainly focused on this part.
Client Authentication Flow
In the Cloud Foundry architecture, Client Authentication (part of mTLS) is implemented as follows:
-
Certificate Validation:
When an external client or end user accesses an application deployed in Cloud Foundry, the request will be resolved to the IPs of the central load balancer of the landscape setup. Then, the load balancer sends the request to HAProxy, which is used to connect the landscape specific load balancer to the Cloud Foundry Gorouter, and handle SSL termination as well as blocking of embargoed countries. Your application runs in a container at a lower level, the Gorouter finally routes incoming traffic to the hosted application running on a Diego Cell. So, the basic traffic is:
End user
->Load Balancer
->HAProxy
->Gorouter
->Application
.During the phase of client authentication, a client certificate as well as the corresponding private key can be included in a request when accessing an application in a certain domain (configured by SAP BTP Custom Domain service and synchronized to HAProxy). The request is being routed through the HAProxy and where mTLS termination happens upfront. After client and server certificate have been mutually validated, the request is then being routed to your application via HTTPS.
If this client certificate has been signed by a CA which is known by HAProxy, it is forwarded to the application in the http-header
X-Forwarded-Client-Cert
, as well as a set of mTLS-specific headers with aX-SSL-Client-
prefix (see below). In case of the request not containing a client certificate, theX-Forwarded-Client-Cert
header won’t be set. If theX-Forwarded-Client-Cert
header is manually set by a client, HAProxy overwrites the header by a valid certificate received by HAProxy in the mTLS handshake, if theforwarded_client_cert
property is set tosanitize_set
. Otherwise, if the HAProxy doesn’t know the root CA that sign your client certificate, you can add the root CA in your trust list via the SAP BTP Custom Domain service. -
Certificate Identity Verification:
When the request reaches your application, at this point there is no longer a certificate on TLS level (mTLS to be precise). The SSL connection is terminated on the HAProxy.
The latter api is then handed specific headers about the certificate (such as the
x-ssl-client-verify
header) by the HAProxy that have to checked by the did management api to make sure validation was successfull. A filter about the request’s origin is applied on top to determine the sending party.So your application (e.g. Spring) just receives the information about the X.509 / mTLS certificate in the header added to the request. Therefore it does not make sense to add / configure x509 support to the Spring application, as no real mTLS will ever reach the endpoint. Rather you need to get your application to read out the header and do your logic based on it, for example: check if the CN is whitelisted and sends the appropriate response.
See for more details and .
SAP Application Router
The application router supports the use of certificates for the creation of tokens and an mTLS handshake in backend connections.
To enable the mTLS authentication for backend connections, the following prerequisites must be met:
-
The authentication service instance that is bound to the application router, Authorization and Trust Management service (XSUAA) or Identity Authentication (IAS), must provide a certificate chain and a private key in its credentials.
If the private key isn’t provided in the credentials, you can also configure the environment variables XSUAA_PRIVATE_KEY (Authorization and Trust Management) and IAS_PRIVATE_KEY (Identity Authentication) in the application router to provide the private key.
-
In Cloud Foundry, the client certificate is propagated using the x-forwarded-client-cert header. To enable this, the backend URL must contain a .cert segment in its domain, or you can set TLS configurations with the SAP BTP Custom Domain service.
The application router gets the XSUAA or IAS tokens that provide the certificates chain and private key. The application router uses the certificates chain and private key from the credentials of the authentication service instance for the following:
-
The application router creates the HTTP connection to backend using the private key and a chain of intermediate and client certificates to enable the mTLS handshake. If the FULL_CERTIFICATE_CHAIN environment variable is enabled, the application router sends the entire chain of certificates provided in the binding of the authentication service (XSUAA or IAS) to the backend applications. If this environment variable is not enabled, the application router sends only the root and intermediate certificates from the chain.
-
When forwarding a request to business services, the application router uses these certificates also to create a client_credentials token or to exchange the login token.
For more details, please read:
Headers for mTLS
Name | Meaning | Set On |
---|---|---|
FULL_CERTIFICATE_CHAIN | Application router sends the entire chain of certificates provided in the binding of the authentication service (XSUAA or IAS) to the backend applications. | Application router |
SKIP_DEFAULT_MTLS_AUTH_CA | Application router skips adding xsuaa/ias mTLS certificate. | Application router |
XSUAA_PRIVATE_KEY | Application router also supports providing XSUAA private key via this header. | Application router |
IAS_PRIVATE_KEY | Application router also supports providing IAS private key via this header. | Application router |
X-Forwarded-Client-Cert | Base64-encoded binary version of the client certificate | mTLS connections |
X-SSL-Client-Session-ID | The SSL session ID of the client connection. Useful for debugging purposes. | mTLS connections |
X-SSL-Client-Verify | 0 if the client certificate verification was successful. Otherwise it contains the appropriate OpenSSL return code | mTLS connections |
X-SSL-Client-Subject-DN | Subject distinguished name of the client certificate | mTLS connections |
X-SSL-Client-Subject-CN | Subject common name of the client certificate | mTLS connections |
X-SSL-Client-Issuer-DN | Issuer distinguished name of the client certificate | mTLS connections |
X-SSL-Client-NotBefore | Start date of the client certificate in YYMMDDhhmmss[Z] format | mTLS connections |
X-SSL-Client-NotAfter | Expiration date of the client certificate in YYMMDDhhmmss[Z] format | mTLS connections |
Prerequisites
-
You have an SAP BTP Account with the following entitlements:
-
Cloud Foundry Runtime
-
Custom Domain service
-
XSUAA (Free)
Fore more details about the services and their plans, please see: .
-
-
You have configured your custom domain with the Custom Domain service.
For more details on how to get your custom domain, please see:
Steps
Step 1: Prepare an Application
Prepare an application that you would like to secure with mTLS.
Besides, you can expose a simple /header endpoint that when called (GET request) will return all available headers. For example (Spring Boot):
@RestController public class GreetingController { @RequestMapping(value = "/headers") public String header(@RequestHeader HttpHeaders headers) { return "Headers: " + headers.toString(); } }
Step 2: Add Application Router Application
Create a new folder called approuter in the root directory.
Under the approuter folder, create a file called package.json with the following content:
{ "dependencies": { "@sap/approuter": "^14.2.1" }, "scripts": { "start": "node node_modules/@sap/approuter/approuter.js" } }
Please update the dependency @sap/approuter with latest version.
Under the approuter folder, create a file called xs-app.json, for example:
{ "routes": [ { "source": "^/(.*)$", "target": "$1", "destination": "myapp" } ] }
Destination will be defined later in the deployment descriptor file.
Install the dependencies locally:
npm i
For more details, please read and
Step 3: Add XSUAA to Generate Client Certificate and Secure Application as an Authorization Server
We can leverage XSUAA to generate XSUAA-managed client certificates. To do that, we need to create an XSUAA instance with x509 setup.
Before creating an XSUAA instance, let’s prepare a security descriptor file called xs-security.json.
In the xs-security.json file,
-
You can define scopes, attributes, role-templates and role-collections for your application. With them, you can restrict the permissions of end users to access your application. For more details on how to define them, please read: .
-
You can set some customized configurations for the OAuth 2.0 clients with oauth2-configuration property, such as:
-
redirect-uris: This key contains a list of the redirect URIs that SAP BTP checks for when redirecting. If your landscape domain or custom domain aren’t on this list, including wildcards, the XSUAA won’t redirect users there.
-
credential-types: Specifies the types of secrets available for binding applications to the service instance. The first type listed is the default type of secret. Otherwise, specify the type of secret when you create the binding or service key. For more information, see .
-
For example, in BTP@AliCloud:
{ "xsappname":"sample", "scopes":[ ..... ], "attributes":[ ..... ], "role-templates":[ ..... ], "role-collections":[ ..... ], "oauth2-configuration":{ "credential-types":[ "x509", "binding-secret" ], "redirect-uris":[ "https://*.enablement.canaryac.apps.vlab-sapcloudplatformdev.cn/**" ] } }
If you provide x509 as default credential type in your xs-security.json, your XSUAA is able to provide XSUAA-managed client certificates. Otherwise, you can set the credential type when binding applications or creating service keys:
cf bind-service <app-name> <XSUAA-instance-name> -c parameters.json cf create-service-key <XSUAA-instance-name> <service-key-name> -c parameters.jsonThe following form of parameters.json is expected for XSUAA managed certificates:
{ "credential-type": "x509", "x509": { "key-length": 2048, "validity": 7, "validity-type": "DAYS" } }
credential-type
(optional) is only required if X509 is not the default type in the xs-security.json and you want to use it.
key-length
(optional) specifies the bit length of the generated private key, defaults to 2048
validity-type
(optional) specifies the validity time unit, onlyDAYS
,MONTHS
andYEARS
are supported, defaults toDAYS
validity
(optional) specifies the number of time units invalidity-type
, defaults to7
, thus the complete validity defaults to 7 days
In the Cloud Foundry space in the provider’s subaccount where your application is going to be deployed, create an xsuaa service instance with the security configurations, which you defined in the security descriptor file in the previous step, by executing this command in the Cloud Foundry command line interface (cf CLI):
cf create-service xsuaa application <XSUAA-instance-name> -c xs-security.json
For more details, please read: .
Step 4: Configure in SAP BTP Custom Domain Service (Custom Domain Manager)
In Cloud Foundry, the client certificate is propagated using the x-forwarded-client-cert header. To enable this, the backend URL must contain a .cert segment in its domain, or you can set TLS configurations with the SAP BTP Custom Domain service. Here we show how to set it with Custom Domain Manager.
Create new TLS configurations that can be used for one or multiple server certificate activations:
-
Choose the TLS Configurations tile, and choose Create TLS Configurations to use the wizard to create each required configuration:
-
Enter a name and choose Next Step:
Note:
The Client Authentication (mTLS) mode is displayed as disabled by default. Once the new configuration has been created, Client Authentication (mTLS) can be turned on by adding one or multiple trusted CA certificates.
-
Choose Next Step:
-
The summary information displays the entered configuration name and the status of the mTLS mode again. Choose Finish to exit the wizard and manage the created configuration.
-
If you want to turn the Client Authentication (mTLS) mode on, from the corresponding drop-down list, select optional or required, as the case may be:
In the Configuration pane, under the General Information section, you can use the Edit button to change the name, if desired. You can also use the Duplicate button to copy the existing configuration, with a new name. Alternatively, you can delete it by using the Delete button and then create a new one again, if desired.
Note: Configurations that are already in use cannot be edited or deleted; they can only be duplicated.
-
Switch to the Trust List tab and choose Add Trust List to upload your list of trusted certificates and assign it to your custom domains.
On adding the trust list, client authentication is enabled. However, when the last CA certificate is removed from the trust list, client authentication is automatically turned off.
-
Copy your trusted certificates list into the Add to Trust List text box and choose Add:
-
Upload your server certificate by referring to
-
When activating your server certificate, the activation has to be done for one or more of the certificate’s SANs and the TLS configuration of your choice. The activation can be modified or removed at any time and will take a few minutes until it is effective in the landscape load balancer. Any corresponding SaaS routes are also automatically activated.
In the detail pane, choose Activate, and select the SANs you want to activate and choose Next Step.
-
Select the TLS Configuration you created before, and choose Next Step:
-
Confirm the TLS configuration and choose Finish:
For more details, please read
Step 5: Add or Update Deployment Descriptor
You can use manifest.yaml in Cloud Foundry or mta.yaml in the multitarget application (MTA) way as the deployment descriptor for your application.
For example, in the manifest.yaml way, add one more application for the application router:
- name: approuter host: approuter path: approuter memory: 128M routes: - route: approuter.enablement.canaryac.apps.vlab-sapcloudplatformdev.cn env: destinations: > [ { "name":"myapp", "url":"https://backend.enablement.canaryac.apps.vlab-sapcloudplatformdev.cn", "forwardAuthToken": true } ] services: - uaa
We define the application called approuter with route approuter.enablement.canaryac.apps.vlab-sapcloudplatformdev.cn.
The application exposes one environment variable called destinations for xs-app.json to discover the backend application.
The application is bound to an XSUAA instance called uaa.
Please bind the XSUAA instance to your backend application as well, for example:
--- applications: - name: backend memory: 1024M path: target/backend-1.0-SNAPSHOT.jar routes: - route: backend.enablement.canaryac.apps.vlab-sapcloudplatformdev.cn services: - uaa
Step 6: Build and Deploy to SAP BTP Cloud Foundry
Package your Java project to .jar file.
For the MTA way, you can build the MTA with the and deploy the .mtar file with MTA CLI plugin. For more details, please read: .
For the manifest way we show here, you can directly deploy the applications to Cloud Foundry with command:
cf push
For more details, please read .
Step 7: Test
Access the URL of the application router with the endpoint you defined, for example:
The endpoint prints the headers that backend application received from the application router. You can see the token and client certificate related information from the request.
More Reading