SDK part 1 of the documentation introduced us to the "How to use APIs for Context Manager (Orion) and Time Series (QuantumLeap)".
In those documents we have seen how anybody could query any type of resources in the platform. That is, as you may imagine, not great in terms of security.
For demo'ing purposes, we left port 1026 open, so you could query services directly, now, for the production platform that won't be the case, all your requests will need to be authorized, for understanding how to do this we have wrote SDK part 2.
SDK part 2, introduces us to using those same APIs (and others) "securely".
By securely here we mean: the user making the request is authenticated -platform validates who you are-, but also getting authorization for our query -platform validates (or not) the action you want to do-.
The latter is what is called access control, which in simple words means checking whether you are authorized or not to retrieve, delete or modify a resource (*) of the platform.
Access controlled is enforced by PEP Proxy (Wilma), this service runs on port 1027, this is where all your requests are going to be sent to.
Note, here we use different HOST IPs cause each service could run in different machines.
This is also so the reader understands with which service is being used at each time when launching a script.
For simpler configuration we will have later on a single entry point, "the naiades server", which will run every service in the same machine, no need to set up several all this variables.
Each platform client uses credentials (email and password) for authenticating against the identity manager and PEP Proxy(IdM and Wilma)
We provide testing credentials, but be aware that those are not going to work in production :)
email@example.com : test firstname.lastname@example.org : test
So at some point you should ask the IdM maintainer (UDGA or SIMAVI) to create credentials for you.
email@example.com -> can READ and can WRITE into FlowerBed entity firstname.lastname@example.org -> can READ and cannot WRITE into FlowerBed entity
Oauth2 flow and http Authorization header
For this demo, we use grant type password for the Oauth2 app, this means that the app secret is not private, it is shared in clear text publicly in this repo scripts (Authorization http header).
This is not very safe, but for demo purposes it should be fine, we may request you to generate this on your own later on.
If you plan to implement your own app which issues tokens then you should use the standard OAuth2 flows described in the link MUST READ section,
The Authorization header is Authorization: Basic NDU3ODhiM2YtMzRjNy00YThlLTkwZGMtZGZiODdlOGFkMGNjOjVmMmI0YTQ5LTJkMDUtNDQ2Ny04NDQ4LTI1ZDA0OWQwMzQ5OQ==
GET /token using credentials
Please look at the first script created for getting a token with curl:
>>cat security_01_get_token_with_password.shcurl -iX POST \"http://$KEYROCK_HOST:3005/oauth2/token"\-H'Accept: application/json'\-H'Authorization: Basic NDU3ODhiM2YtMzRjNy00YThlLTkwZGMtZGZiODdlOGFkMGNjOjVmMmI0YTQ5LTJkMDUtNDQ2Ny04NDQ4LTI1ZDA0OWQwMzQ5OQ=='\-H'Content-Type: application/x-www-form-urlencoded'\--email@example.com&password=test&scope=permanent'
Now, lets try it out using the development deployment of keyrock:
Great! soil moisture value is 8, let's try to write into that value
PUT /entity attribute value, with a token
Lets update moisture value to a random number:
curl --location--request PUT \"http://$PROXY_HOST:1027/v2/entities/urn:ngsi-ld:FlowerBed:FlowerBed-1/attrs/soilMoistureVwc/value"\--header"Fiware-Service: carouge"\--header"Fiware-ServicePath: /Watering"\--header"X-Auth-Token: $KEYROCK_TOKEN"\--header"Content-Type: text/plain"\-d$(( RANDOM %10))
>> ./security_04_update_entity_with_token.shQuerying Fiware entry point (PEP_PROXY) at: 220.127.116.11If you didn't get any error message, then you can re-run script <security_04...>.sh you will get a different value for the entity
PUT request was accepted, now lets see what inside of that value again:
>>./security_03_request_with_token.shQuerying Fiware entry point (PEP_PROXY) at: 18.104.22.1682%
Woo-hoo! we managed to update an entity attribute with our token! We have been granted to do this cause our token was generate with a user with privileges to do so (access control).
How is this handled in the back-end? What's under the hood??
Here there is a snapshot of the keyrock dashboard for this (for those of you who are curious about how this is managed) :
Advanced: users without writing rights to write certain entities (wms)
Lets do the same tests we did before, but now using a token with less privileges that before:
change in script security_01... user to firstname.lastname@example.org, same password.
repeat security_01..., update env var for the token
run security_03... returns requested value, great ..
lets try to write that value with ./security_04_update_entity_with_token.sh
it returns: User access-token not authorized
Voilà! our wms-1 user doesn't have the right to write to this specific entity, this demonstrates how access control works in the NAIADES context.
Advanced: using the JWT scope
Instead of using a bearer token, we can use JWT, which has some added advantages, this demonstrates one of them:
Request token using jwt
Note we can use &scope=jwt as query param:
curl -iX POST \"http://$KEYROCK_HOST:3005/oauth2/token"\-H'Accept: application/json'\-H'Authorization: Basic NDU3ODhiM2YtMzRjNy00YThlLTkwZGMtZGZiODdlOGFkMGNjOjVmMmI0YTQ5LTJkMDUtNDQ2Ny04NDQ4LTI1ZDA0OWQwMzQ5OQ=='\-H'Content-Type: application/x-www-form-urlencoded'\--email@example.com&password=test&scope=jwt'
Returns a bigger token containing our roles in the platform!