2023 Aug 23 7:45 AM - edited 2023 Aug 23 11:03 AM
(Check out the SAP Developer Challenge - APIs blog post for everything you need to know about the challenge to which this task relates!)
This task follows on from the previous task and moves you one step closer in your steady journey of enlightenment, moving towards calling an API endpoint on SAP BTP.
In the previous task, you created an instance of the SAP Cloud Management Service. Why? Because this service provides facilities to manage resources on SAP BTP, and those facilities include the APIs you've been learning about in previous tasks in this group. But merely having an instance of the service isn't going to get you far.
To consume a service's facilities, more is needed. In an application context, an app is bound to a service instance, and, once bound, can consume those facilities. The same goes for API calls. What's needed are a couple of things - endpoint information and credential information.
So. You've done step 1 of the steps introduced in the previous task. Now you're tackling step 2.
First, you need some information on the API endpoints. This is because information you found on the SAP Business Accelerator Hub for the endpoint you're going to call:
GET /accounts/v1/directories/{directoryGUID}
only presents a relative path (/accounts/v1/directories/{directoryGUID}). For it to be a callable endpoint it needs of course to be prefixed with the rest of the URL - the scheme and fully qualified domain name, at least.
To be precise, the http (or https) part of a URL is known as the "scheme". See the List of URI schemes Wikipedia page for more information. And while we're in precision mode, are you wondering about the difference between URL and URI? They're not the same. URLs are a subset of URIs. A URI (Uniform Resource Identifier) is just a string that identifies a resource. A URL (Uniform Resource Locator) identifies a resource, but also allows you to locate that resource. Yes, the clue really is in the name(s) 🙂
As well as endpoint information, you also need access, in the form of authentication. What form that takes, and how it's used, is sometime service-specific. But generally there will be a requirement to provide credentials in the API call itself.
You've done this already in a previous task, in that you provided an API key in an "APIKey" header, when you made the call to the country date format API endpoint in Task 5 - Call the country date format API endpoint
More commonly, the standard Authorization HTTP header is used to convey the credentials. The value for this header is usually made up of two parts, and formed like this:
Authorization: <auth scheme> <auth details>
In the bad (good?) old days, you may well have used Basic Authentication, i.e. provided a username and password, joined with a colon, and encoded in Base64. Here's an example of that:
Authorization: Basic d2VsbC1kb25lOnlvdXItY3VyaW9zaXR5LWlzLWdyZWF0IQ==
Note that encoding != encrypting, which means that this approach was somewhat insecure, in that anyone who could see the HTTP request headers could obtain those credentials. Moreover, obtaining credentials as fundamental as username and password means a world of pain if they are ever compromised.
This is why OAuth, which focuses on obtaining and using tokens as credentials, is a far better approach for managing the request and use of credentials. Generally, tokens are obtained up front (sometimes requiring username and password style information) and then also eventually expire (they can be refreshed using a similar but simpler approach to the original way they were obtained). Expired tokens are no use to anyone, and if a token is compromised, it can be expired a lot easier, and with far fewer side effects (on other consumers using the same credential approach) than expiring or invalidating a compromised username and password.
Anyway, getting back to this Authorization header, there are other more secure auth schemes that are standard and used with this header, and you'll be working towards using such a scheme in the next task.
This endpoint and credential information, essential to consume a service's facilities, is provisioned in so-called "service keys", that relate to an instance of a service.
Creating a service key effectively brings about the creation of credentials that are then valid for use by the consumer. Once a service key has been created, it can be retrieved, and will contain the credentials, plus information on the endpoints.
When an app is bound to a service instance, similar information is created (this is why one can equate the term "service key" with "binding" and why different cloud platform runtimes use these terms almost interchangeably).
Your task, then, is to create a service key for the instance of the SAP Cloud Management Service you created in the previous task. You should use the cf CLI to do this. You'll have to give the service key a name; it doesn't really matter too much what you call it; the name "sk" will do fine for the purpose of this task, but in the end, you can choose.
Once you have created a service key, you should retrieve it, and take a look at the information, which will be in JSON. You'll need to compose a value (to send to the hash service) based on some of the property names in this JSON data.
That value should be a sorted list of the endpoint property names (not their values), separated by commas. To be clear, these endpoint property names are the keys of the key/value pairs inside the credentials.endpoints node, and they all end in _url.
Once you have composed that value, you should hash it and share as a new reply to this discussion thread, as always, and as described in Task 0.
Oh, and while it's not part of this task's requirements, you might as well save the JSON in in a file, too, because you're going to need it again in the next task!
You're strongly encouraged to use the cf CLI for this task. This is for the usual obvious reasons, which are:
If, however, you do wish to use the GUI, in the form of the SAP BTP Cockpit, then go ahead. The cockpit, or any GUI for that matter, is great for one-off and occasional tasks, but it's no match for the power of the command line. You may wish to read the blog post Managing resources on SAP BTP – what tool do I choose? which touches on this topic.
If you're using the cf CLI, you'll want to avail yourself of the commands within the "Services integration" section.
Services integration: marketplace,m create-user-provided-service,cups services,s update-user-provided-service,uups create-service,cs create-service-key,csk update-service delete-service-key,dsk delete-service,ds service-keys,sk service service-key bind-service,bs bind-route-service,brs unbind-service,us unbind-route-service,urs
Note that once you've created your service key, and are looking at its output with:
cf service-key <service-instance> <service-key>
you'll notice that the output is JSON. Great! You can parse it and programatically generate the value you need to send to the hash service for your task reply.
However, note that the command is not entirely well-behaved, emitting "helpful" information just before the JSON itself. This is ultimately against the spirit of the UNIX command line philosophy. Here's an example of the output of such a command (some of the properties in the JSON have been removed for brevity):
Getting key cis-central-sk for service instance cis-central as dj.adams@sap.com... { "credentials": { "endpoints": "..." "grant_type": "user_token", "sap.cloud.service": "com.sap.core.commercial.service.central", "uaa": { "uaadomain": "authentication.eu10.hana.ondemand.com", "xsappname": "ut-f86082c9-7fbf-4e1e-8310-f5d018dab542-clone!b254751|cis-central!b42", "xsmasterappname": "cis-central!b42", "zoneid": "7da58aab-6c60-4492-a95b-b1ed3139e242" } } }
The first two lines ("Getting key ...", and the empty line) are not JSON. This means you will have to clean up the output of the command before processing it as JSON (and saving it to a file).
Note that the value of the endpoints property in the above output example is given as "..." - this is just for brevity in illustration; the value is in fact an object, containing properties, the names of which should be of interest to you for this task!
Note also that this example output also reminds us of one of the breaking changes between version 7 and version 8 of the cf CLI that were mentioned in the previous task. It's the advent of version 8 that brought along the outermost wrapping of the data within a new credentials property. Before version 8, that node does not exist in the JSON.
2023 Aug 23 7:52 AM
2023 Aug 23 8:17 AM
2023 Aug 24 11:31 AM
2023 Aug 23 8:27 AM
2023 Aug 23 8:37 AM
2023 Aug 23 8:51 AM
2023 Aug 23 10:32 AM - edited 2023 Aug 24 5:43 PM
2023 Aug 24 6:28 PM - edited 2023 Aug 24 6:28 PM
Posted the wrong reply earlier, as I had each key inside the double quotes.
I tried using jq this time and found it very easy than writing JS code to fetch the keys
2023 Aug 23 10:43 AM
2023 Aug 23 10:58 AM
2023 Aug 23 11:01 AM
Kudos for asking questions! This is great. The actual API URL, or at least the "base" for it, is in the `.credentials.endpoints` object in the service key data, and the URL of the authorization server, where you will (in the next task!) be making a request for an access token, is in the `.credentials.uaa` object, specifically the `.credentials.uaa.url` property 👍
2023 Aug 24 11:44 AM
2023 Aug 23 12:21 PM
2023 Aug 23 1:54 PM
2023 Aug 23 2:17 PM
2023 Aug 23 2:34 PM - edited 2023 Aug 23 2:42 PM
Sorry, my bad. The statement 'URLs are a subset of URIs' seems correct. I previously misinterpreted resource path of URL as URI.
2023 Aug 23 2:35 PM
2023 Aug 23 2:45 PM
you always learn new thing from DJ's article, this is fact. 😉
I just know that http(s) is URI schemes and after read the provided link there are also 2 schemas that has the same name (chrome). 🤔
2023 Aug 23 3:14 PM
2023 Aug 23 3:23 PM
2023 Aug 23 3:24 PM
2023 Aug 23 3:34 PM
2023 Aug 23 8:22 PM
2023 Aug 24 12:35 AM
2023 Aug 24 3:12 AM
2023 Aug 24 11:41 AM
2023 Aug 24 2:03 PM
2023 Aug 24 2:12 PM
2023 Aug 24 2:44 PM
2023 Aug 24 3:08 PM
2023 Aug 24 5:13 PM
2023 Aug 24 10:11 PM
2023 Aug 25 9:12 AM
2023 Aug 25 2:26 PM
2023 Aug 25 3:33 PM
2023 Aug 27 1:52 AM
2023 Aug 27 11:40 AM - edited 2023 Sep 02 8:46 AM
2023 Aug 27 3:34 PM
2023 Aug 28 8:34 AM