Meeting 15.04.2021
Um die Daten der CO2-Ampel ins Web zu übertragen haben wir mit CouchDB herumexperimentiert.
jq
- Command-line JSON processor
man jq
is your friend- jq cookbook
get an cloudant.com access token
#!/bin/bash
# source this file once to get CLOUDANT_TOKEN environment variable for cloudant.sh
RESP=$(curl -s \
--header "Content-Type: application/x-www-form-urlencoded" \
--header "Accept: application/json" \
--data-urlencode "grant_type=urn:ibm:params:oauth:grant-type:apikey" \
--data-urlencode "apikey=_H7VZ92r1LrHpq4XJLblY11-S17J05RcD69XUWzY82pw" \
"https://iam.cloud.ibm.com/identity/token")
if [ $# -eq 0 ]
then
export CLOUDANT_TOKEN=$(echo $RESP|jq -r .access_token )
else
echo $RESP
fi
do couchdb stuff with token
#!/bin/bash -xe
# http method GET and POST get inferred
#METHOD="GET"
HOST="0f752390-1de3-4f38-8e20-d74fbc4c4199-bluemix.cloudant.com"
DB="test"
# query view index by_created_at
#QUERY="_design/app/_view/by_created_at?limit=5&include_docs=true&descending=true"
# get continuous updates
SINCE="now"
# to not wait upto 12s for a new doc (or no new are created), enter a 'seq' here
#SINCE="1186-g1AAAAdreJy11D9OwzAUBvAIkBjpDWCCKcV2bNeRkOiAYGCgbGzg9-yoqvoHoXaGG8AN4AZwA7gB3ABuADcosR3RZmoYvDhSZH0_vXzKGyZJ0uqvm2TXAE5ubNdApw2jFDG1s9TYlPI2Diczo8fT9thOh-X9NZ3A1nw-H_TX9cmofLEpGSgg0DilDoqVILTKE7Yr89ibKjccJWscVDfZanPHmfuVeerNAhVVBW8c5My9v6u0AUocelj7uJmATBaqedJ_64SuQ88q9MijQhK0MovXaM-Zl5XZ86Y2hEtU8Rq9cuakNiczCBRUxEavHXpbGxRMRpCJeI2ON8ozuSsfpXvv4HMPIzKFeSdaq8F9CO7jYmAJlHKjozUb3KfgPi-5hKocIV67AX4J8OtiUYCU1pAidsNvAX5fLAuTSSE4i9zwR3A_nXvgXa45kdRGbvgruN_OvfAutVpojPj_BvgnwEuLg9uOtTlvnjb4Bf-dUUU"
QUERY="_changes?feed=continuous&include_docs=true&since=$SINCE"
#JQ='.seq'
JQ='{error: .error, id: .doc._id, created_at: .doc.created_at, warmed_up: .doc.warmed_up, co2: .doc.co2, temp: .doc.temp}'
# useful curl options:
# -v ... verbose (shows HTTP Headers)
# -s ... silent
# -S ... shows error (like token expired)
# -N ... unbuffered output (doesn't wait for request to finish, useful for continuous feeds)
#useful jq options:
# -c ... compact output (less whitespace)
# --unbuffered ... unbuffered output (doesn't wait for end of input)
# -r ... raw output of strings ('lol' instead of '"lol"')
curl -SsN \
-H "Authorization: Bearer $CLOUDANT_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
"https://$HOST/$DB/$QUERY" |
jq -c --unbuffered "$JQ"
advanced use
1) create a file full of tokens
while(true); do ./cloudant_token.sh -c >> tokens; utimer -qc 10s; done
2) wait 3480 seconds 3) get a token with expiration only 2min in future instead of 3600s
#!/bin/bash -xe
SEC=$(($(date +%s) + 120))
OBJ=$(jq -cr "select(.expiration >= $SEC)" <tokens |head -n 1)
TOK=$(echo $OBJ | jq ".access_token")
EXP=$(echo $OBJ | jq ".expiration")
printf "token = $TOK;\nexpiration = $EXP;\n" | xclip -i
playing with a token
there are 3 parts, seperated by a dot. the first 2 are base64 encoded json, the third is probably an RSA-signature (using the specifiey key id). see: JSON Web Token.
TOK1='eyJraWQiOiIyMDIxMDMyMTE4MzUiLCJhbGciOiJSUzI1NiJ9'
echo $TOK1 | base64 -d | jq
>>> {"kid":"202103211835","alg":"RS256"}
TOK2='eyJpYW1faWQiOiJpYW0tU2VydmljZUlkLTFiZWUzNWU3LTQxZmUtNDU1MC1hM2RhLTg2MTBhMGM4YmFjNCIsImlkIjoiaWFtLVNlcnZpY2VJZC0xYmVlMzVlNy00MWZlLTQ1NTAtYTNkYS04NjEwYTBjOGJhYzQiLCJyZWFsbWlkIjoiaWFtIiwianRpIjoiYzEzOWVjNmEtNzIzNy00OGRiLWI2MjYtOGQzMjc2OTJlYWMyIiwiaWRlbnRpZmllciI6IlNlcnZpY2VJZC0xYmVlMzVlNy00MWZlLTQ1NTAtYTNkYS04NjEwYTBjOGJhYzQiLCJuYW1lIjoid3JpdGFibGUiLCJzdWIiOiJTZXJ2aWNlSWQtMWJlZTM1ZTctNDFmZS00NTUwLWEzZGEtODYxMGEwYzhiYWM0Iiwic3ViX3R5cGUiOiJTZXJ2aWNlSWQiLCJhdXRobiI6eyJzdWIiOiJpYW0tU2VydmljZUlkLTFiZWUzNWU3LTQxZmUtNDU1MC1hM2RhLTg2MTBhMGM4YmFjNCIsImlhbV9pZCI6ImlhbS1pYW0tU2VydmljZUlkLTFiZWUzNWU3LTQxZmUtNDU1MC1hM2RhLTg2MTBhMGM4YmFjNCIsInN1Yl90eXBlIjoiMSIsIm5hbWUiOiJ3cml0YWJsZSJ9LCJhY2NvdW50Ijp7InZhbGlkIjp0cnVlLCJic3MiOiIyZjIyNzBhYmU1NTM0YzZjOWVmOTc2NjdiNDQ3YjM0MCIsImZyb3plbiI6dHJ1ZX0sImlhdCI6MTYxODQ4MjQzNCwiZXhwIjoxNjE4NDg2MDM0LCJpc3MiOiJodHRwczovL2lhbS5jbG91ZC5pYm0uY29tL2lkZW50aXR5IiwiZ3JhbnRfdHlwZSI6InVybjppYm06cGFyYW1zOm9hdXRoOmdyYW50LXR5cGU6YXBpa2V5Iiwic2NvcGUiOiJpYm0gb3BlbmlkIiwiY2xpZW50X2lkIjoiZGVmYXVsdCIsImFjciI6MSwiYW1yIjpbInB3ZCJdfQ'
echo $TOK2 | base64 -d
>> {"iam_id":"iam-ServiceId-1bee35e7-41fe-4550-a3da-8610a0c8bac4","id":"iam-ServiceId-1bee35e7-41fe-4550-a3da-8610a0c8bac4","realmid":"iam","jti":"c139ec6a-7237-48db-b626-8d327692eac2","identifier":"ServiceId-1bee35e7-41fe-4550-a3da-8610a0c8bac4","name":"writable","sub":"ServiceId-1bee35e7-41fe-4550-a3da-8610a0c8bac4","sub_type":"ServiceId","authn":{"sub":"iam-ServiceId-1bee35e7-41fe-4550-a3da-8610a0c8bac4","iam_id":"iam-iam-ServiceId-1bee35e7-41fe-4550-a3da-8610a0c8bac4","sub_type":"1","name":"writable"},"account":{"valid":true,"bss":"2f2270abe5534c6c9ef97667b447b340","frozen":true},"iat":1618482434,"exp":1618486034,"iss":"https://iam.cloud.ibm.com/identity","grant_type":"urn:ibm:params:oauth:grant-type:apikey","scope":"ibm openid","client_id":"default","acr":1,"amr":["pwd"]}
Die Signatur wird dadurch erzeugt, dass der Header und der Payload im Base64 kodierten und durch einen Punkt getrennten Format mit der spezifizierten Hashmethode gehashed wird:
var encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload);
var hash = HMACSHA256(encodedString, secret);
Aber das Secret ist nur dem Server bekannt. source
CouchDB and Cloudant.com resources
getting started
https://cloud.ibm.com/docs/Cloudant?topic=Cloudant-getting-started-with-cloudant
authentification
https://cloud.ibm.com/docs/Cloudant?topic=Cloudant-connecting https://cloud.ibm.com/docs/account?topic=account-iamapikeysforservices#token_auth
couchdb doku
https://docs.couchdb.org/en/2.3.1/index.html (cloudant uses couchdb 2.1.1)