MYCSS

2021-01-17

Використання Google Cloud IoT MQTT з консольного BASH сценарію та Mosquitto

Google Cloud Platform надає можливість використати IoT Core для підключення IoT пристроїв за протоколом MQTT та HTTP.
Приклади налаштування, і основи роботи є на багатьох ресурсах і у відео:

Моя задача створити безпечне підключення до Google IoT Core з консолі свого пристрою і використати мінімум програм:

Зв'язок mqtt topic (ts2) з google topic event (b01)

Публікація до google topic event (b01) з mosquitto_pub

Перегляд отриманих повідомлень в google sub підписки на mqtt topic (ts2)
 
Підписка до topic - error

Скрипти для автоматизації підключення.

Головна особливість для зв'язку з Google Cloud Platform, те що потрібно автентифікувати пристрій котрий надсилає #MQTT повідомлення за допомогою JWT.
Автентифікація пристрою за JWT
 В мережі було знайдено скрипт який генерує JWT, який я трохи модифікував, і використовую. Для генерації JWT необхідно попередньо згенерувати публічний та особистий ключ та прив'язати його за інструкцією до Вашого пристрю (RS256_X509): Device security | Cloud IoT Core Documentation | Google Cloud

Вся інша методика описана в - Publishing over the MQTT bridge | Cloud IoT Core Documentation.
Алгоритм створення JWT

Для безпечного підключення до MQTT брокеру від Google треба мати файл центру сертифікації.

mqtt_pub.sh:
#!/bin/bash

ProjectID="mqtt-lexxai"
LOCATIONS="europe-west1"
RegistryID="mqtt-lexxai"
DEVICE="wrt"
CLIENTID="projects/$ProjectID/locations/$LOCATIONS/registries/$RegistryID/devices/$DEVICE"
TOPICEVENT="/devices/${DEVICE}/events"
TOPICSTATUS="/devices/${DEVICE}/status"

function init_jwt() {
 ./jwt/generateJWTtoken.sh ${ProjectID}
}

function public() {
 echo "${CLIENTID}"
 mosquitto_pub -h mqtt.googleapis.com -p 8883 -d  \
 --cafile ./ca/roots.pem \
 --id "${CLIENTID}" \
 --username "unused" \
 --pw "$( cat ./jwt.txt )" \
  -q 1 -t "${1}" -m "${2}"
}

#MAIN

init_jwt

TOPIC="${TOPICEVENT}/b01"
MESSAGE="$( date )"

public ${TOPIC} ${MESSAGE}

generateJWTtoken.sh:
#! /usr/bin/env bash

RegistryID=$1
if [ -z "$RegistryID" ];then
 echo "Missed parameter about RegistryID"
 exit
fi

KEYFILE=./key/rsa_private.pem
OUTPUTFILE=jwt.txt

echo "Check OLD File JWT is ?"
if test `find "${OUTPUTFILE}" -mmin +20`
then
    echo "old enough, need generate a new"
else
    echo "not old enough, skip generate"
    exit
fi

# Static header fields.
HEADER='{
    "type": "JWT",
    "alg": "RS256"
}'

payload="{
    \"aud\": \"${RegistryID}\"
}"

# Use jq to set the dynamic `iat` and `exp`
# fields on the payload using the current time.
# `iat` is set to now, and `exp` is now + 1 second.
PAYLOAD=$(
    echo "${payload}" | jq --arg time_str "$(date +%s)" \
    '
    ($time_str | tonumber) as $time_num
    | .iat=$time_num
    | .exp=($time_num + 60 * 60)
    '
)

function b64enc() { openssl enc -base64 -A | tr '+/' '-_' | tr -d '='; }

function rs_sign() { openssl dgst -binary -sha256 -sign ${KEYFILE} ; }

JWT_HDR_B64="$(echo -n "$HEADER" | b64enc)"
JWT_PAY_B64="$(echo -n "$PAYLOAD" | b64enc)"
UNSIGNED_JWT="$JWT_HDR_B64.$JWT_PAY_B64"
SIGNATURE=$(echo -n "$UNSIGNED_JWT" | rs_sign | b64enc)

echo "$UNSIGNED_JWT.$SIGNATURE" > ${OUTPUTFILE}


Немає коментарів:

Коли забув ти рідну мову, біднієш духом ти щодня...
When you forgot your native language you would become a poor at spirit every day ...

Д.Білоус / D.Bilous
Рабів до раю не пускають. Будь вільним!

ipv6 ready