How to provision a Dockerized secure IoT Agent with Keyrock? - iot

I'm failing to find this information within the existing documentation - either permanent or non-permanent tokens.
Using Keyrock 7.8, Ultralight 1.11.0 (though any current agent will do)
The following Docker parameters are set:
- IOTA_AUTH_ENABLED=true
- IOTA_AUTH_TYPE=oauth2
- IOTA_AUTH_HEADER=Authorization
- IOTA_AUTH_HOST=keyrock
- IOTA_AUTH_PORT=3000
- IOTA_AUTH_URL=http://keyrock:3000
- IOTA_AUTH_CLIENT_ID=tutorial-dckr-site-0000-xpresswebapp
# - IOTA_AUTH_PERMANENT_TOKEN=true
The default Docker configuration is used in the image, so no provisioning group types are created.
I am able to provision a trusted group as shown:
curl -X POST \
http://iot-agent:4041/iot/services \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"services": [
{
"apikey": "4jggokgpepnvsb2uv4s40d59ov",
"cbroker": "http://orion:1026",
"entity_type": "Motion",
"resource": "/iot/d",
"trust": "<motn-auth-token>"
}
]
}'
Question 1 - how do I generate the trust token within Keyrock.
When I provision the device
curl -X POST \
http://iot-agent:4041/iot/devices \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"devices": [
{
"device_id": "motion001",
"entity_name": "urn:ngsi-ld:Motion:001",
"entity_type": "Motion",
"timezone": "Europe/Berlin",
"attributes": [
{ "object_id": "c", "name":"count", "type":"Integer"}
],
"static_attributes": [
{"name":"refStore", "type": "Relationship","value": "urn:ngsi-ld:Store:001"}
]
}
]
}
'
I receive the following error in the IoT Agent:
{
"name": "SECURITY_INFORMATION_MISSING",
"message": "Some security information was missing for device type:Motion"
}
And the following in the Keyrock logs:
Fri, 06 Dec 2019 14:13:52 GMT idm:oauth2-model_oauth_server -------getClient-------
Executing (default): SELECT `id`, `redirect_uri`, `token_types`, `jwt_secret`, `scope`, `grant_type` FROM `oauth_client` AS `OauthClient` WHERE `OauthClient`.`id` = 'tutorial-dckr-site-0000-xpresswebapp' AND `OauthClient`.`secret` = 'tutorial-lcal-host-0000-clientsecret';
Fri, 06 Dec 2019 14:13:52 GMT idm:oauth_controller Error { invalid_client: Invalid client: client is invalid
Question 2: What additional information needs to be supplied?

How do I generate the trust token within Keyrock.
Trust tokens are described as access tokens within in the Keyrock documentation, Firstly set up the client application to generate permanent tokens:
This can also be done programmatically by using the /v1/applications endpoint.
Request
curl -iX POST \
'http://keyrock:3005/v1/applications' \
-H 'Content-Type: application/json' \
-H 'X-Auth-token: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' \
-d '{
"application": {
"name": "Tutorial Application",
"description": "FIWARE Application protected by OAuth2 and Keyrock",
"redirect_uri": "http://tutorial/login",
"url": "http://tutorial",
"grant_type": [
"authorization_code",
"implicit",
"password"
],
"token_types": ["permanent"]
}
}'
To generate a permanent trust token, ensure the Keyrock application has been configured to offer permanent tokens and log in as an authorised user using the standard Authorization: Basic header holding a base 64 concatenation of the client id and secret. The parameter
scope=permanent is added to retrieve permanent tokens when available. The response contains an access_token (a.k.a. Trust Token) which
can be used for device provisioning.
Request
curl -X POST \
http://keyrock:3005/oauth2/token \
-H 'Accept: application/json' \
-H 'Authorization: Basic dHV0b3JpYWwtZGNrci1zaXRlLTAwMDAteHByZXNzd2ViYXBwOnR1dG9yaWFsLWRja3Itc2l0ZS0wMDAwLWNsaWVudHNlY3JldA==' \
-d 'username=alice-the-admin#test.com&password=test&grant_type=password&scope=permanent'
Response
{
"access_token": "e37aeef5d48c9c1a3d4adf72626a8745918d4355",
"token_type": "Bearer",
"scope": ["permanent"]
}
Setting up the IoT Agent to use Keyrock and a PEP proxy
The following additional Docker parameters are required
- IOTA_CB_HOST=orion-proxy
- IOTA_CB_PORT=${ORION_PROXY_PORT}
- IOTA_AUTH_ENABLED=true
- IOTA_AUTH_TYPE=oauth2
- IOTA_AUTH_HEADER=Authorization
- IOTA_AUTH_HOST=keyrock
- IOTA_AUTH_PORT=${KEYROCK_PORT}
- IOTA_AUTH_URL=http://keyrock:${KEYROCK_PORT}
- IOTA_AUTH_CLIENT_ID=tutorial-dckr-site-0000-xpresswebapp
- IOTA_AUTH_CLIENT_SECRET=tutorial-dckr-host-0000-clientsecret
- IOTA_AUTH_PERMANENT_TOKEN=true
- IOTA_AUTH_TOKEN_PATH=/oauth2/token
IoT Agent - provisioning a trusted service group
The Access token (also known as a Trust Token) must be added to the service group.
This is held in the trust attribute and repeats the token retrieved in the step above
Request
curl -iX POST \
'http://iot-agent:4041/iot/services' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"services": [
{
"apikey": "4jggokgpepnvsb2uv4s40d59ov",
"cbroker": "http://orion:1026",
"entity_type": "Motion",
"resource": "/iot/d",
"trust": "e37aeef5d48c9c1a3d4adf72626a8745918d4355"
}
]
}'
Once a trusted service group has been created, a device can be provisioned in the usual manner
Request
curl -iX POST \
'http://iot-agent:4041/iot/devices' \
-H 'Content-Type: application/json' \
-H 'fiware-service: openiot' \
-H 'fiware-servicepath: /' \
-d '{
"devices": [
{
"device_id": "motion001",
"entity_name": "urn:ngsi-ld:Motion:001",
"entity_type": "Motion",
"timezone": "Europe/Berlin",
}
]
}
'

Related

WhatsApp API Call Rails

I'd like to execute the following call in rails:
curl -i -X POST \
https://graph.facebook.com/v12.0/FROM_PHONE_NUMBER_ID/messages \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{ "messaging_product": "whatsapp", "to": "TO_PHONE_NUMBER", "type": "template", "template": { "name": "hello_world", "language": { "code": "en_US" } } }'
How can I do this using an http-client? I can do it in postman but formatting it for an http client usually has some syntax issue.
You can look at the HTTParty gem, which helps make API-call easier.

Mendeley - can not search catalog anymore "client is not allowed"

Since last week, the catalog search on Mendeley API is giving me the following result:
{
"message": "Client ID <client_id> is not allowed",
"status": 403
}
I am using standard code in Python that worked before:
mendel = Mendeley(client_id=client_id, client_secret=client_secret)
auth = mendel.start_client_credentials_flow()
session = auth.authenticate()
print(session.catalog.search('Nitrogen dynamics', view='all').list(50).items)
And I have the same result using curl:
curl -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-u client_id:client_secret \
-d "grant_type=client_credentials&scope=all" \
https://api.mendeley.com/oauth/token
curl -X GET "https://api.mendeley.com/search/catalog?access_token={access_token}"

How to use etag with the Youtube API

I am trying to understand how etag works with the Youtube API. Here is the request I am making:
curl -X GET \
'https://www.googleapis.com/youtube/v3/channels?part=statistics&fields=items&id=UCmRtPmgnQ04CMUpSUqPfhxQ' \
-H 'Authorization: Bearer dezferfnr....' \
-H 'Cache-Control: no-cache' \
-H 'If-None-Match: \"g7k5f8kvn67Bsl8L-Bum53neIr4/4ygpLCFz2IoIJNkG3XO1Pys1hck\"'
And here is the response I am getting:
{
"items": [
{
"kind": "youtube#channel",
"etag": "\"g7k5f8kvn67Bsl8L-Bum53neIr4/4ygpLCFz2IoIJNkG3XO1Pys1hck\"",
"id": "UCmRtPmgnQ04CMUpSUqPfhxQ",
"statistics": {
"viewCount": "4757859",
"commentCount": "63",
"subscriberCount": "68151",
"hiddenSubscriberCount": false,
"videoCount": "898"
}
}
]
}
As you can see, the etag found in the response is the same as the one I sent in the request's header, and I can't understand why I am not getting an HTTP 304 response (Not Modified) instead.
Try removing escaped double quotes from the beginning and the end of etag (leave the unescaped ones because they are part of etag):
curl -X GET \
'https://www.googleapis.com/youtube/v3/channels?part=statistics&fields=items&id=UCmRtPmgnQ04CMUpSUqPfhxQ' \
-H 'Authorization: Bearer dezferfnr....' \
-H 'Cache-Control: no-cache' \
-H 'If-None-Match: "g7k5f8kvn67Bsl8L-Bum53neIr4/4ygpLCFz2IoIJNkG3XO1Pys1hck"'
(use curl -i -X GET... to see the headers of response in CLI, you'll see 304 Status, otherwise it would just be empty string).

Cloud Speech API error: RecognitionAudio not set

While trying to follow the [quick start] (https://cloud.google.com/speech/docs/getting-started) for cloud speed API, after execute the "curl" command in command prompt, error occurred depicted as below:
{
"error": {
"code": 400,
"message": "RecognitionAudio not set.",
"status": "INVALID_ARGUMENT"
}
}
Why the RecognitionAudio is not set in the API itself? The sync-request.json used is same as the one in the quick start:
{
"config": {
"encoding":"FLAC",
"sampleRateHertz": 16000,
"languageCode": "en-US",
"enableWordTimeOffsets": false
},
"audio": {
"uri":"gs://cloud-samples-tests/speech/brooklyn.flac"
}
}
I'm not sure exactly what you're doing wrong but I was able to use the request as-is from the documentation without issue.
Did you get an access token for a Google Cloud project that had the speech API enabled? The following command generates the access token that can be used as a Bearer:
gcloud auth application-default print-access-token
It was helpful for me to use put the following into a script file (req.sh)
curl -s -H "Content-Type: application/json" \
-H "Authorization: Bearer <output>" \
https://speech.googleapis.com/v1/speech:recognize \
-d #sync-request.json
I then just used the output from print-access-token with the script.
I had exactly the same problem and I solved it adding quotes in the -d value, like this:
curl -s -H "Content-Type: application/json" \
-H "Authorization: Bearer <your-access-token>" \
https://speech.googleapis.com/v1/speech:recognize \
-d "#sync-request.json"
I was getting this error because I was not running the command in the cli in the same directory as my sync-request.json file.
Once I changed directories, I used the command from the documentation with my access token, and it worked fine.
I had the same problem and it worked for me when I omitted the #sync- from the curl command. This command worked for me:
curl -s -H "Content-Type: application/json" \
-H "Authorization: Bearer " \
https://speech.googleapis.com/v1/speech:recognize \
-d #request.json
Not sure what the exact function is of #sync ?

Updating Parse installation object removes it

I create an installation object using a REST API call like this :
curl -X POST \
-H "X-Parse-Application-Id: ${APPLICATION_ID}" \
-H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"deviceType": "ios",
"deviceToken": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"channels": [
""
]
}' \
https://<your.parseprovider.here>/1/installations
The installation object is created and is indicated by the response :
{
"objectId": "EmqGmZXGEm",
"createdAt": "2017-02-15T10:13:18.647Z"
}
Now let's say I want to update the channels field to include the "foo" channel in the installation object, I could simply issue a call like :
curl -X PUT \
-H "X-Parse-Application-Id: ${APPLICATION_ID}" \
-H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"channels": [
"",
"foo"
]
}' \
https://<your.parseprovider.here>/1/installations/EmqGmZXGEm
Success is then indicated by the response :
{
"updatedAt": "2017-02-15T10:18:31.055Z"
}
However, when I execute the PUT call like this (as in the REST API docs, note the inclusion of the deviceType and deviceToken fields) :
curl -X PUT \
-H "X-Parse-Application-Id: ${APPLICATION_ID}" \
-H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"deviceType":"ios",
"deviceToken":"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"channels": [
"",
"foo"
]
}' \
https://<your.parseprovider.here>/1/installations/EmqGmZXGEm
I now get the following response :
{
"code": 101,
"error": "Object not found."
}
The installation object has now suddenly been deleted from the Parse server database.
This seems to happen as soon as the deviceToken field is included in the PUT request.
Is this supposed to happen, or am I missing something? I am using a Parse API for Delphi which is breaking because of this "phenomenon". I would rather not hack the API if the error is due to a Parse bug that should be fixed on the server side.
Try PATCH instead of PUT. See table. Both PUT and PATCH can be used for update.

Resources