Introduction
MAC (Hash message authentication code) is a specific type of message authentication code involving a cryptographic hash function and a secret cryptographic key. Which can be used to simultaneously verify both the data integrity and the authenticity of a message. This blog post provides a mechanism on how to integrate such type of interfaces or webhooks into SAP Cloud system using SAP Cloud API Management.
Limitation: CPI inbound http adapter does not allow for a “no authorisation” policy nor does it have capability for other authorisation methods beside certificates/user-based authorisation but this can be resolved through API Management, which offers a great number of possibilities around policies.
Background
This blog post will illustrate the use case of API Management functioning as an intermediary between a source system, that triggers webhook notification secured with HMAC, and CPI, and getting in charge of the security between the systems. We use API management to authenticate the message and forward it to CPI then CPI does complex orchestration that is required to integrate into SAP Gigya and Marketing Cloud systems.
The objective of this blog post is to show how to verify HMAC-SHA1 Hash signature of sender system and generate and outbound call to CPI with user authentication.
API Policy Flow
The following diagram depicts the policy flow template that you need to create in SAP API Management to authenticate the message using HMAC-SHA1 and forward the message to SAP CPI Layer for complex orchestration.
Step 01 - vmBasic Policy
Retrieve Target system user/passwords from secure value mapping and save it into a parameter that can then be used on Policy Flow.
< KeyValueMapOperations async = "true" continueOnError = "false" enabled = "true" mapIdentifier = "CPI" xmlns = "http://www.sap.com/apimgmt" >
< Get assignTo = "private.basicAuth.username" >
< Key >
< Parameter >username</ Parameter >
</ Key >
</ Get >
< Get assignTo = "private.basicAuth.password" >
< Key >
< Parameter >password</ Parameter >
</ Key >
</ Get >
< Scope >environment</ Scope >
</ KeyValueMapOperations >
|
Webhook security
Step 02 - extJson
Allows to extract Json payload or a particular node and save it into a variable.
< JSONPayload >
< Variable name = "jsonPayl" >
< JSONPath >$</ JSONPath >
</ Variable >
</ JSONPayload >
< Source clearPayload = "false" >request</ Source >
< VariablePrefix >myprefix</ VariablePrefix >
</ ExtractVariables >
|
Step 03 - vmPartner
Retrieve partner key from secure value mapping and save it into a parameter
< KeyValueMapOperations async = "true" continueOnError = "false" enabled = "true" mapIdentifier = "SourceSystem" xmlns = "http://www.sap.com/apimgmt" >
< Get assignTo = "private.partner" >
< Key >
< Parameter >partner</ Parameter >
</ Key >
</ Get >
< Scope >environment</ Scope >
</ KeyValueMapOperations >
|
Step 04 - checkHash
Indicate the script name that will do the hash verification. In this case we used a Phyton script.
< ResourceURL >py://helper2.py</ ResourceURL >
</ Script >
|
Check the received hash string with our partner key. If they do not match it will raise an error, finalising the flow process.
import hashlib
import hmac
import base64
def make_digest(message, key):
digester = hmac.new(base64.b64decode(key), message, hashlib.sha1)
signature1 = digester.digest()
signature2 = base64.b64encode(signature1)
return signature2;
message = "";
message = flow.getVariable( "myprefix.jsonPayl" );
webhookHash = flow.getVariable( "request.header.<hashName>" );
result = make_digest( str (message), flow.getVariable( "private.partner" ));
flow.setVariable( "hash" ,result);
if (result ! = webhookHash):
raise NameError( "invalid origin" )
|
CPI Security.
Step 05 - basicAuthentication
Set the basic authentication for the target system call, with the secured parameters defined on first step:
< Operation >Encode</ Operation >
< IgnoreUnresolvedVariables >true</ IgnoreUnresolvedVariables >
< User ref = 'private.basicAuth.username' ></ User >
< Password ref = 'private.basicAuth.password' ></ Password >
< Source >request.header.Authorization</ Source >
< AssignTo createNew = "false" >request.header.Authorization</ AssignTo >
</ BasicAuthentication >
|
Test example on API Management
We can try the application directly on API Management by specifying the Webhook JSON payload and the security header hash.
API returns a successful response with the message set on CPI flow.
We can see on response headers SAP_MessageProcessingLogID of the message processed on SAP CPI.
In second test case we had altered the message data modifying the event id on the payload which invalidates HMAC signature.
API Management returns an error 500 to source system with the exception programmed on script validation step.
Conclusion:
API Managements offers a broad number of possibilities around security policies for API creation, which can also be used to set a bridge to more complex orchestration between systems and SAP Cloud Platform Integration, thus allowing to overcome CPI limitations regarding authorisation methods.
In this blog post we had explored one of such cases, using API Management to verify HMAC-SHA1 hash and act as a security handler between a source system and CPI.