Product Information
SAP Cloud Integration – Automated Notification of Keystore Entries Reaching Expiry
Introduction
Cloud Integration Keystore Monitor allows a tenant administrator to manage the tenant keystore and its entries. A keystore contains entries uniquely identified by an alias where each entry has its own lifecycle. Renewal of an entry is important task to be done before expiry, else it will lead to message failure for productive scenarios using specific certificates/key-pairs entries. The tenant administrator can be notified for those entries which are about to expire, so that he can take in-time actions for renewal of the same.
Within keystore monitor, expired keys and certificates are highlighted showing expiration date. In addition, an Integration Flow can be modeled to get notifications via mail for entries reaching their expiry. This document provides steps to model a scenario triggered via scheduler which looks across all entries of the tenant keystore and sends a mail with information about those entries reaching their expiry.
Scenario Description
Cloud Integration provides various REST APIs with technical protocol as Open Data Protocol (OData) with which you can access data. These APIs can be consumed via https://<tmnUrl>/api/v1 where <tmn> is the address of the tenant management node. Here we will use API for accessing keystore entries via https://<tmnUrl>/api/v1/KeystoreEntries .Overall scenario looks as below:
Create an integration flow with Start Timer Event. Using Request-Reply step call OData APIs to fetch details of the tenant keystore entries via OData receiver channel. Fetch Alias Name and ValidNotAfter for entity KeystoreEntries. Below find the configuration of OData Receiver channel:
Make sure the Page Size field value is null since entries in a keystore are not so many in numbers.
The response of the OData call will be a file containing all keystore entries with their Alias & Validity date. Now add a General Splitter step to split using XPath /KeystoreEntries/KeystoreEntry and pass split entries to a Local Integration Process.
In Local Integration Process, define a Content Modifier and store the values of keystore entry Alias and Validity Time in a header.
Additionally, add a message containing Alias & Validity Time information about keystore entry in body of Content Modifier. This message will be send via mail notification. You can choose to customize this information as per your need.
Now add a script to fetch Validity Time from header and compare with current date. Output of script shall be number of days left for Keystore entry to expire. You can find a sample code below:
def map = message.getHeaders();
String getCertExpirydate = map.get(“CertExpiryDate”);
Date CertExpirydate = new SimpleDateFormat(“yyyy-MM-dd“).parse(getCertExpirydate);
Date dateNow = new Date(System.currentTimeMillis());
long dateDiff = CertExpirydate.getTime() – dateNow.getTime();
def daysToExpire = TimeUnit.DAYS.convert(dateDiff, TimeUnit.MILLISECONDS);
message.setHeader(“daysToExpire”, daysToExpire);
Add a router step to route those entries whose expiry is in less than defined number of days (e.g. daysToExpire < 4) and send an email to specific participants informing them about the expiry.
For the example explained above, here is router configuration screenshot:
Note: This might differ depending on the condition defined for your use-case or the variable defined either as Header/Property.
Hello
Thanks a lot for your blog. it's perfect.
I have created the package, deploy.. and everything is green.. But I don't receive any email with the alert...
How can I verify in which part is not working properly?
Hello Toni
Good to know that you were able to build and deploy the iflow. I hope you have understood that Alert mail will be generated only if there is any keystore entry reaching expiry (As per condition set) or already expired.
Can you activate tracing referring to https://blogs.sap.com/2018/03/13/troubleshooting-message-processing-in-the-cpi-web-application/ and check if there are entries for the expiry condition.
Thanks
Amar
Hello Amar
Thanks for you helping.
I have obtained the error in Content Modifier
Error Details
org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[ID-vsa5107462-40927-1541369381630-22-5], cause: org.apache.camel.language.simple.types.SimpleParserException: expected symbol functionEnd but was eol
What does it mean?. any idea?
Thanks
Hello Toni
Seems some issue with conversion. Can you recheck Header configuration in Content Modifier step and you are using right Type for Header defined as well as body is correct.
Thanks
Amar
Hello Amar,
Now, I have problems with script:
Hello Toni
Kindly confirm if you copied the script code from above blog and pasted it. If this is the case, copy/paste sometime changes format for special characters and they are no more recognized during runtime when corresponding jars are created.
Kindly write that specific line of code and recheck.
Thanks
Amar
Hello Amar,
No I have obtained an other error, in my script:
javax.script.ScriptException: groovy.lang.MissingPropertyException: No such property: message for class: new__Script, cause: groovy.lang.MissingPropertyException: No such property: message for class: new__Script
What does it means?
Thanks
Best regards
Hi Amar,
any idea how to identify the certificates actually being used? Is there property/header available which tells you this?
Thanks,
Hilmar
Hello Hilmar
Do you mean any Where-Used list for certificates/Keystore entires from the entire set. In case yes, this is not possible as of now.
Feel free to file your request to Mandy Krimmel regarding the same.
Warm Regards
Amar
Hi Amar,
I am unable to open below document link you have provided,
https://help.sap.com/viewer/368c481cd6954bdfa5d0435479fd4eaf/DEV/en-US/a617d6f37ddc43db8eeb1279662ed5c2.html
Please review & help.
Regards,
Deepak
Hi Amar,
The error is 403:You don't have rights to view this page.
Regards,
Deepak
Hello Deepak
Sorry for wrong link. Here is the correct one: https://help.sap.com/viewer/368c481cd6954bdfa5d0435479fd4eaf/Cloud/en-US/a617d6f37ddc43db8eeb1279662ed5c2.html. Can you recheck.
Thanks
Amar
similar thing for the CertificateUserMappings
Hi Amar,
Can you please add more information on last content modifier which you used in local integration process.
Regards,
Swati
Hello Swati
The Content Modifier used in Local integration process is to read each Certificate/Keypair and store the same in header/property. In addition use this to create body of the mail being sent to Administrator so that Administrator easily know which entry is reaching expiry and accordingly take appropriate actions for renewal of the same.
Amar
Hello Amar,
While calling this Entity, I am receiving 403 Forbidden error. Do I need any additional roles to access this entity?
Regards,
Anil
Hello Anil
You would need AuthGroup.Administrator role on the tenant to call the APIs or deploy a credential with a user having this role and then use this credential in your flow.
Thanks
Amar
Hi Amar,
Thank you for your helpful blog, everything working fine for me. Right now with the above approach i am getting four mails if there are four items expires in same date. I am looking to send only one mail for all four expire items. Can i achieve this with help of Gather with splitter ? or can you suggest what would better approach.
Thanks,
Swati
Hello Swati
Straight forward using Gather & Join would not be enough since Gather is meant for collecting data coming from multiple routes.
Easiest would be store/append certificate in SFTP and then have another flow which pulls data from SFTP and send it collectively to mail receiver.
Thanks
Amar
Works like a charm!
Hi Kumar Amar ,
While running the script , i got the below error.
My Groovy script is as below
Details from Content Modifier is as below:
Could you please have a look and help me in this.
Thanks & Regards
Shubham
Hi Shubham
Actually in my blog description, I write as:
In Local Integration Process, define a Content Modifier and store the values of keystore entry Alias and Validity Time in a header.
However you have defined Property in Content Modifier and hence you need to change your script code instead of def map = message.getHeaders();
to
Hi Kumar Amar ,
Thanks for your response.
I am again receiving the below error :
Shubham
Hello Shubam
Kindly check someone at your end for Groovy script code. I used the below code and it works for me.
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import groovy.json.JsonSlurper;
import java.util.HashMap;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Callable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import groovy.json.JsonOutput
def Message processData(Message message) {
//Headers
def map = message.getHeaders();
String getCertExpirydate = map.get("CertExpiryDate");
Date CertExpirydate = new SimpleDateFormat("yyyy-MM-dd").parse(getCertExpirydate);
Date dateNow = new Date(System.currentTimeMillis());
long dateDiff = CertExpirydate.getTime() - dateNow.getTime();
def daysToExpire = TimeUnit.DAYS.convert(dateDiff, TimeUnit.MILLISECONDS);
message.setHeader("daysToExpire", daysToExpire);
return message;
}
Thanks
Amar
i am getting issues with handling of long in the groovy script.
is there any way to resolve this??
Thanks
Shubham
Hi Shubham Srivastava,
Sometimes, It might occurs due to copy paste of the code, try to delete the minus(-) sign from this line and type again.
long dateDiff = CertExpirydate.getTime() – dateNow.getTime();
It will solve your issue.
Thanks,
Poushali Bhandari
Hi ,
Could you please provide me with the Router conditions to be put in the router steps.
Thanks
Shubham
Hi,
I would be also intrested in the Router Conditions!
Maybe you could also add them to the blog via screenshot
Thanks
Patrick
Hi Patrick
I added it today.
Thanks
Amar
Thanks Kumar Amar I have already found an example in Mandys Blog 😉
Hi Kumar Amar,
It's a great blog.
Similarly, Is it possible to trigger the public key expiry notification from the pubring deployed as security Material in the CPI Tenant? Pubring contains around 20 public keys, We have a requirement to notify if any of the key is going to expire.
Thanks in advance,
Poushali Bhandari
Hi Poushali
Thanks for your inputs. Unfortunately this is not possible. I will inform about your requirement to my development team.
Thanks
Amar
Is this solution valid for cloud foundry as well. As there is no certifiacte to user mapping for cloud foundry, is there any way we can use this solution in cloud foundry tenants.
Hello Harish
Yes this is valid for getting notification for Certificates reaching expiry within the Keystore.
As anyways there is no concept of Certificate to User Mapping in Cloud Foundry, this is not a valid query as such.
Hello Kumar Amar,
does this solution work for certificates, directly deployed in iFlow? I tried CertificateUserMappings and KeystoreEntries APIs, none of them seems return certificate details, which directly deployed in iflow.
Thanks in advance.
Regards,
Deb
Hello Debtirtha Das
I didn't get what you meant by certificates directly deployed in Integration Flows.
Certificates from CertificateUserMappings and KeystoreEntries are used in IFlow but actually deployed on the tenant and not in IFlow.
In case you are looking for solution to get notification of expired CertificateUserMappings, you can refer https://blogs.sap.com/2019/03/01/sap-cloud-platform-integration-automated-notification-for-client-certificates-reaching-expiry/ and for Keystore Entries, this blog suffice.
Thanks
Amar
Hi Amar,
For example, if we add a client certificate in an inbound SOAP channel, I do not see that certificate added to keystore. Though I read that this is not SAP recommened process for client certificates.
Hello Debtirtha Das
When you do inbound authentication via Client Certificates, you add certificate in the Sender Channel and this doesn't need to be part of the CPI Keystore as such.
Only when you do outbound authentication using Client Certificates, you need to add respective Key-pair in Keystore and refer it via the alias name in the receiver channel.
Also I am not sure how does your query relates to this blog but anyways hope its clarified.
For inbound and outbound authentication, refer below blogs:
https://blogs.sap.com/2017/06/05/cloud-integration-how-to-setup-secure-http-inbound-connection-with-client-certificates/
https://blogs.sap.com/2017/06/19/cloud-integration-how-to-setup-secure-outbound-http-connection-using-keystore-monitor/
Thanks
Amar
Hi people!
Nice entry Kumar. The governance from outside SAP BTP Integration Suite is a little weird. By the way, I have the doubt if this connection to the oData service consumes one of the pool of the licensed connections.
I supose that no, but I've havent any information about it. Do you know it? Have you ever had any trouble?
Thank you so much
Hi Xavier
Sorry I missed to see your query and only saw today. All connection here mentioned are within Cloud Integration and nothing outside BTP.
Or may be I didn't get your question. Can you give more details ?
Warm Regards
Amar
Hello Kumar,
I am trying to enable the notifications of expiring certificates in the Cloud Platform Integration (CPI).
I read through your blog. When you go to create an iFLOW with "Start Timer Event", is there a particular Package or a Base Package I need to select?
Your first screen shot with the "Adapter Specific" configuration looks like it's a General OData package. Where do I find this to get started?
Thanks for your help.
Hiko Watanabe
Hello Hiko
As this is custom flows you can create the integration flow in any of your package created in your Cloud Integration tenant. And yes it uses Standard OData adapter which is part of Cloud integration feature.
To get started create an Integration Package in your design workspace of cloud integration tenant and then create an integration flow to get started.
Warm Regards
Amar
Hi Kumar Amar
first of all thanks for this helpfull blog post. Is it also possible to call this API for keystore credentials with OAuth authentification which can be provided by process integration? Then I do not have the dependencies to any user / assigned roles in this tenant.
Thanks
Best regards
DL
Hello Dominik
Yes of course instead of using Basic Auth, you can use OAuth Credential and call the APIs. Refer https://help.sap.com/docs/CLOUD_INTEGRATION/368c481cd6954bdfa5d0435479fd4eaf/20e26a837a8449c4b8b934b07f71cb76.html for more information.
Thanks
Amar
Hi Kumar Amar
thanks for the hint. Access via OAuth to CPI is working fine. For me better option because we have no dependencies now between user and CPI access / roles.
Thanks
best regards
Dominik
Perfect, glad that it works for you and I could help you.
Hi Kumar Amar
I have consumed the OData service via "https://<tmnUrl>/api/v1/KeystoreEntries". It was working fine a week before. But now getting the below error. Please assist me to resolve this.