Introduction:
In this blog post, I will show how to use SAP credential store and access the credential storage API using Python.
What Is SAP Credential Store?
A repository for passwords, keys and keyrings for the applications that are running on SAP BTP.
How to setup credential Store in BTP trial account?
Go to BTP sub-account -> Instances and Subscription
Click on 'View Dashboard'.
The SAP Credential Store logically segregates data by namespaces.
Click on 'Create Namespace'.
Select credential type as password.
Now, lets bind this to application named 'WeatherApp'.
Now, navigate to the app -> environment variables.
Environment variable named 'VCAP_SERVICES' contains the rest api endpoint details of SAP credential store and associated credentials to access the api. Also, It contains 'client_private_key' details which is used to decrypt the response payload.
{
"VCAP_SERVICES": {
"credstore": [
{
"label": "credstore",
"provider": null,
"plan": "trial",
"name": "credential-store",
"tags": [
"credstore",
"securestore",
"keystore",
"credentials"
],
"instance_guid": "b5b73270-6336-419e-8c38-90161efa8132",
"instance_name": "credential-store",
"binding_guid": "30d62116-331f-4086-b228-7681a9dbdc85",
"binding_name": null,
"credentials": {
"password": "<password>",
"expires_at": "2024-05-10T09:00:44.0Z",
"encryption": {
"client_private_key": "<client private key>",
"server_public_key": "<server public key>"
},
"parameters": {
"authorization": {
"default_permissions": [
"create",
"decrypt",
"delete",
"encrypt",
"info",
"list",
"namespaces",
"read",
"update"
]
},
"encryption": {
"payload": "enabled",
"key": {
"size": 3072
}
},
"authentication": {
"type": "basic"
},
"access_policy": {
"creds_api": "public",
"token_api": "public",
"kms_api": "public",
"encryption_api": "public"
}
},
"url": "https://credstore.cfapps.us10.hana.ondemand.com/api/v1/credentials",
"username": "<username>"
},
"syslog_drain_url": null,
"volume_mounts": []
}
]
}
}
Python code to access credential storage API
SAP Credential Store exposes a RESTful API to create, read and delete credentials.
Demo Scenario:
For this demo, Sample Weather API is used.
from jwcrypto import jwk, jwe
from flask import Flask
import requests
import os
import json
# latitude of Bengaluru
LAT = 12.9716
#longitude of Bengaluru
LON = 77.5946
namespace = "APIKeyHub"
api_key_name = "Weather_API_Key"
cred_headers = {
"sapcp-credstore-namespace": namespace
}
cred_params = {
"name": api_key_name
}
vcap_services = os.getenv('VCAP_SERVICES')
if vcap_services:
binding = json.loads(vcap_services)['credstore'][0]['credentials']
response = requests.get(url=f"{binding['url']}/password", headers=cred_headers, params=cred_params,
auth=(binding['username'], binding['password']))
private_key_pem =f"-----BEGIN PRIVATE KEY-----\n{binding['encryption']['client_private_key']}\n-----END PRIVATE KEY-----"
private_key = jwk.JWK.from_pem(private_key_pem.encode('utf-8'))
jwetoken = jwe.JWE()
jwetoken.deserialize(response.text, key=private_key)
resp = jwetoken.payload.decode('utf-8')
json_payload = json.loads(resp)
api_key_val = json_payload['value']
FORECAST_URL = "https://api.openweathermap.org/data/2.5/forecast"
query_params = {
"lat": LAT,
"lon": LON,
"appid": api_key_val,
"cnt": 4
}
forecast_response = requests.get(url=FORECAST_URL,params=query_params)
data = forecast_response.json()
app = Flask(__name__)
@app.route('/')
def home():
if data:
return data
else:
return 'No data'
if __name__ == "__main__":
app.run()
Requirements:
flask~=3.0.2
gunicorn~=21.2.0
requests~=2.31.0
jwcrypto~=1.5.6
Reference Link:
Credential Management – Example (Node.js)
Regards,
Priyanka Chakraborti