Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
vanessadayanc
Explorer
Hello SAP Community,

in the context of a migration project from SAP CPI Neo to SAP IS Cloud Foundry (CF) Environment, I was searching for a solution to generate a notification for administrators about expiring Service Keys (Certificates) in SAP BTP CF via E-Mail. I did find some solutions for certificates in keystore, but no solution for the Service Keys - so I created one in form of an iFlow.

Background


When proceeding a migration from SAP CPI in Neo Environment to SAP Integration Suite in Cloud Foundry, you will find several differences between the two systems. There are already a lot of Blogs and Guides with detailed information about the differences and best practices for Migrating from the Neo Environment to the Multi-Cloud Foundation (Cloud Foundry and Kyma), but I would like to focus on mainly one point:

For SettingUp Inbound HTTP Connections for Integration Flow Processing in SAP Cloud Foundry Environment it is necessary to create a Service Instance and Service Key for Inbound Authentication (SAP Help). Depending on your use case you can create three different types of Service Keys:

  1. ClientId/Secret

  2. Certificate

  3. External Certificate


For further information please check out help.sap

If your use case requires External Certificate e.g. for Inbound Authentication from SAP ERP-Systems to SAP Integration Suite, you can add a sender client certificate (provided by sender administrator) to service key and maintain the validity date (validuntil).


In order to guarantee a constant communication, it is important to renew the certificates before the expire.

 

Getting Started:


First of all I searched for a possibility to retrieve the Service Key information by calling CF-API endpoint. Depending on your landscape you can find the Endpoint of your Cloud Foundry API in one of your SubAccounts.

 


To get the Service Key information it is necessary to use the cloud_controller API, the documentation for V3 can be found here (V2 ist already deprecated).

Authentication:


The Cloud Foundry V3 API is secured using OAuth 2. Clients are expected to present a valid bearer token via HTTP header, that can be obtained from the Cloud Foundry UUA server or via CF CLI.

The only solution that worked in my testings were based on the following post:


 

I tried different versions to get a valid Authorization token for the CF-API but the solution below was the only one that worked for me using Postman.

SAP Integration Suite provides three Options vor OAuth2 Security Materials: OAuth2 Client Credentials, OAuth2 SAML Bearer Assertion, OAuth2 Authoriation Code. None of them will work with the grant_type password. One way to get a token is to create the necessary Authorization data for a GET-Request via groovyscript in CPI:

  1. Create two different Client Credentials as Security Material:

    1. CF_API_Username : Contains Username and Password of a SAP BTP User (Only use technical Users here!)

    2. CF_API_ClientID: User = cf and leave the password empty



  2. Create a iFlow with a Start Timer and a Content Modifier

    1. Message Header: Content-Type = application/x-www-form-urlencoded

    2. Exchange Property: ApiUserCredentials = {{CF_API_Username}} for external configuration



  3. Create Script Step:


import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import com.sap.it.api.ITApiFactory;
import com.sap.it.api.securestore.SecureStoreService;
import com.sap.it.api.securestore.UserCredential;

def Message processData(Message message) {

//get User from Configuration
def map = message.getProperties();
String user = map.get("ApiUserCredentials");

//service to get the credentials
def service = ITApiFactory.getApi(SecureStoreService.class, null);

//get user credential
def userCred = service.getUserCredential(user);
if (userCred == null){
throw new IllegalStateException("No User credential found for alias" + user);}

//HTTP Parameters value
String grant_type = "password";
String username = userCred.getUsername();
String password = new String(userCred.getPassword());

//Query
def query = "grant_type=" + grant_type + "&username=" + username + "&password=" + password;

message.setBody(query);

return message;

}

(Based on post)

4. User HTTP-Adapter to get a Token


You will get back a response in the following format:



{
"access_token": "<Token>",
"token_type": "bearer",
"id_token": "<id_toke>",
"refresh_token": "<refresh_token<",
"expires_in": 1199,
"scope": "openid uaa.user cloud_controller.read password.write cloud_controller.write",
"jti": "<jti>"
}

5. Use a further script to extract the token from the response body and set it as Authorization header



import com.sap.gateway.ip.core.customdev.util.Message;
import groovy.json.*

def Message processData(Message message) {

def json = new JsonSlurper().parseText(message.getBody(String));
message.setHeader("Authorization", json.token_type + " " + json.access_token)
message.setBody()

return message;
}

 

Get Service-Key-Details form API


The necessary objects can be found in the entity "service_credential_bindings". To List all service_credential_bindings you have to use the following definition and Parameters:

GET  /v3/service_credential_bindings

Query parameters






















Name Type Description
service_instance_guids list of strings Comma-delimited list of service instance guids to filter by
type list of strings Type of credential binding to filter by. Valid values are: app or key

You will find the service_instance_guids in the details of your service_instances.

  1. Use HTTP-Adapter to get a list of service_credential_bindings



You will receive a list of resources from the type "key". As they do not contain the field "validuntil" it is necessary to check the details of each Service Key. The URL to check the details is already provided for each resource in the body
[..]
"links": {
"self": {
"href": "https://host/v3/service_credential_bindings/<guid>"
},
"details": {
"href": "https://host/v3/service_credential_bindings/<guid>/details"
},

7. Convert and Split the messages on XPath "//resources"


8. For each generated message Call a local Integration Process that extracts the URL of the Endpoint for the Service Key-Details and send a HTTP-Request


As the Authorization Token has a very long validity it is not necessary to generate a new Token and add them to the headers, so you can reuse the token, that was already set as Authorization header. If you run into issues here you may have to retrieve new Authorization Token.



You will receive all necessary informations for each Service Key



"certificatedetails": {
"issuerdn": "CN=DigiCert TLS RSA SHA256 2020 CA1,O=DigiCert Inc,C=US",
"subjectdn": "<subjectdn>",
"validuntil": "2023-05-03T23:59:59.000Z",
"serialnumber": "<serialnumber>"
}

9. Extract the "validuntil"-Value in a Content Modifier


10. Use a script the check the days-to-Expiry and set them as property


11. Create a Router with a configurable days-to-Expiry



12. Use a Content Modifier to create a Mail-Body and user Mail-Adapter to send information Mail to Administrators


 

So the result could look like this:

 


 

Resume


In this post I tried to provide a short explanation to create an iFlow to generate e-mail notifications for expiring Service Keys in different Service Instances. This is just one way that worked for me but if anyone has a better solution - especially how to get a Token for CF-API I'm openminded for improvements. Many thanks!

 

 

 

 

 
12 Comments
Ryan-Crosby
Active Contributor
0 Kudos
The GET for the service details doesn't provide the option to use OAuth credentials?  I recently activated the Alert Notification Service and it calls to an API endpoint using OAuth authentication for granting access to the resource.  In that setup I had two sets of credentials, but I could maintain them directly in the Security Material tile.  The rest of the content in the blog is very cool.  We don't use certificates that are not also in the keystore, but I'll tuck away your blog for future reference in case it's ever a thing for us.

 

Regards,

Ryan Crosby
inesa
Advisor
Advisor
Alternatively you can check out the embedded Alerting functionality of Health Monitoring in SAP Cloud ALM, which also provides Certificate validity information. See Blog Post: Centralized health monitoring of SAP Cloud Integration using SAP Cloud ALM.

Best regards, Ines
Martin-Pankraz
Active Contributor

Happy to see the efforts for key and certificate rotations here vanessa.dayanc, but the most important piece is missing: the automated renewal. Have you considered re-creating the service key, retrieving the credentials and updating the credential store? Have a look here for further inspiration. Either CF CLI, BTP REST interfaces or BTP CLI will give you the tools to complete the lifecycle.

Customers with hundreds of subaccounts and services cannot scale through email notifications.

Hoping for part two of this post 🙂

KR

Martin

KrishnaJain
Discoverer
0 Kudos

Hi,

When trying to retrieve the service key list, we are getting empty list.

{"pagination":{"total_results":0,"total_pages":1,"first":{"href":"https://api.cf.eu20.hana.ondemand.com/v3/service_credential_bindings?page=1\u0026per_page=50\u0026service_instance_guids=%3Cguid%3E\u0026type=key"},"last":{"href":"https://api.cf.eu20.hana.ondemand.com/v3/service_credential_bindings?page=1\u0026per_page=50\u0026service_instance_guids=%3Cguid%3E\u0026type=key"},"next":null,"previous":null},"resources":[]}

Do we need to specify a guid value? Where can we get the guid from for a particular service key?

Thanks,

Krishna

vanessadayanc
Explorer
0 Kudos
Hi Krishna,

 

you can find the service-instance-guid in the service Instance on Cloud Foundry.

SAP BTP -> Services: Instances and Subscriptions and than press on any Service Instance, where Service Keys have been created. If you press on the instance you can see the necessary informations. You can copy the Instance ID with the copy button.


 

Kind regards

 

Vanessa
danfqa
Explorer
0 Kudos
Hello Vanessa, thank you very much for the post!

I have a question, and I hope you could help me out. In an attempt to execute the process as you did, I've opened a Trial account in BTP and assigned all the role collections to my user, both at the organization and space levels, even through CF CLI. However, when I try to consume: https://login.xxxx-xxx.hana.ondemand.com/oauth/token, I'm getting a 401 error, unauthorized. Honestly, I don't know who the administrator user of the Cloud Foundry environment is. Do you know where I can find it? On another note, I tried to create a user with CF CLI, but I don't have the permissions to do so. Thank you very much for your assistance!
sreeniyn
Discoverer
0 Kudos
Hi vanessa.dayanc

I have tried this scenario to fetch certificate validity date from SAP BTP.

in the final call i have used same below API with my host i am getting credentials but not validity period. Could you please suggest is i am something missing.
"https://host/v3/service_credential_bindings/<guid>/details"

 

Thanks and Regards

Sreeni

 
vanessadayanc
Explorer
0 Kudos

Hello Daniel,

I tried it out with the trial account and it works. I did not change any permission. You get 401 when you try to get a Token with the following parameters:

 

Grant_type: Password

Client ID: cf

User: The e-mail adress from your S-User

PW: PW of your S-User

 

Is that correct? You could also try to get the token from:

https://uaa.cf.xxxx.hana.ondemand.com/oauth/token

 

Kind regards

Vanessa

vanessadayanc
Explorer
0 Kudos
Hi sreeniyn

 

you just receive validitys for service_keys that were created as certificates. Have the service_keys you like to check validity dates?

 

Kind regards

 

Vanessa Dayanc
sreeniyn
Discoverer
0 Kudos
Hi vanessa.dayanc,

 

Yes, I am looking to get certificate validity date to trigger email, but in v3 version i have not find API to fetch service keys.

Can you suggest in your scenario which api you are using to fetch valid date of certificate ?

 

Thanks and Regards

Sreeni
vanessadayanc
Explorer
0 Kudos

Hi sreeniyn

 

if you follow the exact steps from the blog it will work:

https://api.host.hana.ondemand.com/v3/service_credential_bindings?service_instance_guids=<guid>&type...

As <guid> use the id of the service instance, where your service key was created. If you are doing a GET-Request you will receive all of the service keys and the link to get the details via api.

Just follow the exact steps of the blog and it should work.

 

Kind regards

Vanessa

shishira123
Discoverer
0 Kudos

Hi,

I am getting https://login.eu20.hana.ondemand.com/oauth/token   please help me here.

Before its working now its not working.

 

Thanks

Labels in this area