Working with Encrypted Key Value Maps using SAP Cloud Platform API Management UI
As an exciting update to SAP API Management three major updates have been made for the Key Value Map concept.
#1 – You can now securely encrypt the actual data stored within a Key Value Map, allowing for storage of sensitive data.
#2 – You can now access and update Key Value Map information through the SAP API Management Design Time UI in addition to API calls.
#3 – You can now add Key Value Maps at an API proxy level rather than the environment level. Read more here.
In this Blog I will assume that you would have already read the excellent previous blog on using Key Value Maps (KVMs) located here to understand what a KVM is, what it is used for, and when to use it. I will be focusing on using the Design Time UI to generate an encrypted KVM in a codeless manner and accessing that Encrypted KVMs data at runtime.
Note: I will also be working from the assumption that you have created the ES5_Gateway account and API Provider.
Oftentimes customers would like to access data from the SAP ERP Backend and expose this for consumption into an application either within their organization or to partners / 3rd party providers. Since ERP data is extremely valuable and important there is a very tight security process in place for adding users, which makes it impractical to administer for an unknown and potentially high number of incoming users.
This is where the common use case of Bi-Modal IT, with API Management as the “Umbrella” governance layer providing Agility and secure exposure on top of existing Legacy systems comes into the picture. SAP API Management will be the public facing access point, and will invisibly transform consumer requests into a service user provisioned on the Backend. One analogy is the funnel.
Exposing this sensitive ERP data will require some gating mechanism, so in this blog will explore utilizing the API Key as the new authentication mechanism, however API Management supports many other more advanced patterns, like OAuth, SAP IDP, callout to 3rd party IDP, IP whitelisting, etc. which I will not explore here.
Let’s get started!
As before we start by entering the API Portal from SAP Cloud Platform
Creating the Key Value Map
From the API Portal Home page expand the Menu and select Configure
In the Configure menu that comes up, select the Sub-tab Key Value Maps to pull up a list of Key Value Maps configured on your SAP API Management tenant. Click Create to generate a new KVM in the UI.
This will bring up the Create Key Value Map wizard. In this screen provide a distinct name for the KVM, this will be used in the API Proxy so make it something memorable but not too complex. Check the Encrypt Key Value Map box. You will notice when this box is checked, even in the Create Key Value Map screen the Value Data is hidden.
Then under Entries enter a distinct Key name, and a value for this Key, then click Add to enter additional entries. For this Blog, since we will be defining a Service user I will enter Username and Password keys:
<Your ES5 User ID>
<Your ES5 Password>
Once you have filled in all the KVM information, and are satisfied, click Save. Once you receive the message that it was saved successfully, we can create an API Proxy that leverages these credentials.
Creating an API Proxy
Open the Menu and select Develop to start creating an API Proxy. Then click Create to bring up the Create API Proxy window.
Now in the Create API Proxy Wizard, select the API Provider Radio Button and select your ES5 API Provider from the drop down list.
Click the Discover button to bring up the list of APIs defined in the ERP system.
In the Search field search for GWSAMPLE and select the GWSAMPLE_BASIC service and click OK.
Enter distinct information for the API Proxy describing what the API is and what it does. For the Blog I will be naming this as an Open API integration for ERP, using the following information:
|Title||Open authentication API for ERP|
|Description||<Leave as Default>|
|Host Alias||<Leave as Default>|
|API Base Path||/api/odata/v1/openerp|
Click Create to get into the final page of API creation, and then Click Deploy to bring the API live. Once the API has been successfully deployed, if you like, you can try the API at this point, and if you do not provide credentials, it will provide a 401 Unauthorized error as expected.
Adding KVM & Auth Policy to API Proxy
Within the API Proxy window you just created, click the Policies button on the top right of the API Proxy to enter the Policy Editor.
For passing Authentication credentials to the backend, it makes sense to place this policy at the end of the API Flow, so I will be placing these Policies in the Target Endpoint PostFlow, although this could be done elsewhere in the flow as well. If you need a refresher on API Policy Flows I recommend reviewing this intro blog or this advanced blog on flows
In the Flows section first click the Edit button on the top right. Then in the Flows window in the top left, either collapse the ProxyEndpoint flows, or scroll down until you see TargetEndpoint, and select PostFlow to add Policies there.
Adding KVM Policy
On the right hand side, scroll down the Policies list to Mediation Policies, and click the + symbol next to Key Value Map Operations to add the KVM Policy. This policy will be pulling the encrypted User Credentials before passing the request to the backend.
In the Add Policy Wizard enter the following information and then click Add:
Now select the newly created KVM Policy and replace the code with the following:
<!-- Key/value pairs can be stored, retrieved, and deleted from named existing maps by configuring this policy by specifying PUT, GET, or DELETE operations --> <!-- mapIdentifier refers to the name of the key value map --> <KeyValueMapOperations mapIdentifier="ES5Credentials" async="true" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt"> <!-- PUT stores the key value pair mentioned inside the element --> <Get assignTo="private.username"> <Key> <Parameter>ES5User</Parameter> </Key> </Get> <Get assignTo="private.password"> <Key> <Parameter>ES5Pass</Parameter> </Key> </Get> <!-- the scope of the key value map. Valid values are environment, organization, apiproxy and policy --> <Scope>environment</Scope> </KeyValueMapOperations>
This policy is creating an internal variable called “username” and “password” with the private flag to denote that this is coming from the encrypted data store, from the entries defined in the myES5Credential KVM step.
Adding Basic Authentication Policy
On the right hand side, scroll to the Policies list to Security Policies, and click the + symbol next to Basic Authentication to add the Auth Policy. This policy will be generating an encoded Header containing the User Credentials to be passed with the request to the backend.
In the Add Policy Wizard enter the following information and then click Add:
Select the newly created Basic Authentication policy and replace the code with the following:
<BasicAuthentication async='true' continueOnError='false' enabled='true' xmlns='http://www.sap.com/apimgmt'> <!-- Operation can be Encode or Decode --> <Operation>Encode</Operation> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables> <!-- for Encode, User element can be used to dynamically populate the user value --> <User ref='private.username' /> <!-- for Encode, Password element can be used to dynamically populate the password value --> <Password ref='private.password' /> <!-- Source is used to retrieve the encoded value of username and password. This should not be used if the operation is Encode--> <Source>request.header.Authorization</Source> <!-- Assign to is used to assign the encoded value of username and password to a variable. This should not be used if the operation is Decode --> <AssignTo createNew="false">request.header.Authorization</AssignTo> </BasicAuthentication>
Here SAP API Management Basic Auth is encoding a header containing User / Password called from the previously defined KVM variables calling against the encrypted KVM variables.
It is important that the policies happen in the correct order, KVM policy first, then Basic Authentication following after.
Once done, click Update in the Policy Editor to be taken back to the API Proxy page. Then click Save to save the changes to the runtime.
After you receive the success message – click the API Proxy URL to access the API, you should see a successful request without any request for credential information, generating the Service User call that we were looking to create at the start.
Securing the API Proxy
The calling user has now been successfully mapped to a service user in API Management, removing the need to onboard any consumers into the Backend ERP system, however this is not a secure exposure. So the last step would be to add an authentication mechanism in API Management, such as API Key. See an example of utilizing API Keys within Fiori Applications against APIs from API management here
- API Security Best Practices Blog Series
- For more blogs on SAP Cloud Platform, API Management visit us at SCN
This was exactly what I was searching for. With this strategy, we do have the opportunity to share our API's with other consumers, without sharing password's of systems behind the APIM.
Perfect, that was one of our intentions - very glad that it lines up with your expectations!
My question is, how to register and recover multiple users and passwords in Basic Authentication policy?
Can you share a little more information about what is meant by register and recover? In general the KVM is a persistent store of Key/Value pairs. This can be modified by the Key Value Map Operations policy, which can be used to READ or WRITE as needed. You can find more information on how to use this policy here https://help.sap.com/viewer/66d066d903c2473f81ec33acfe2ccdb4/Cloud/en-US/b72dc3f262c1441587e76d0e808a12fe.html
We have a similar problem.
Normally third party solutions are using an api key plus sap user and password. This makes a 1:1 binding which is good for audit purposes but also depending how the roles were set in the backend, also protects it.
We have other scenarios where we don't want to force to provide a user and password, this will be managed by my team with KVM. The thing is that depending on who is calling, we would like to maintain different sets of users and passwords. As well as for the scenario before, just for audit purposes but also to restrict access depending on who is calling. Imagine i want to give an update role in the backend for system A (product A) but just only read for system B (product B).
Apart from this, we tried also to restrict operation permission to each product but it seems is not possible in API Management. This will definitely help!. I don't want to give PUT permission to system A (product A), just GET. However i want to give full access (PUT, PATCH, POST, GET ...) to system B (product B). Is there any way to do this??
Thanks in advance.
For such a detailed question - can you raise this as a standalone question in the community https://answer.sap.com and tag it with SAP API Management ? This will make your question/answer searchable for others.
As a quick pass to your Q - in general you have two ways to restrict Authorizations; 1) API Proxy resource level restrictions (different products require different API Proxy) 2) OAuth scopes
Since you are looking to make access easier for users I would recommend copying your API Proxy and setting one for GET only (named as such) and one for FULL access (named as such) and adding them to the respective product.