たそらぼ

日頃思ったこととかメモとか。

node.jsでAWS IoTにクライアント証明書でHTTPS送信する

AWS IoTにHTTPでPOSTしたいが、極力今ある環境をいじりたくないので、
既にインストールしてあったjavascriptで頑張ってみた。

HTTPでPOSTする方法の調査

基本的にMQTTでpublishするものなので、HTTPで送信する方法は情報が少なかった。
でも、必ずしもMQTTのポートが開いてることばかりじゃない!制限もあるし!
ということで、HTTPでできる方法を調べた。
分かったのは以下の通り。
①"aws iot-data publish"コマンドで、aws cli のcredentialを使って認証する。
dev.classmethod.jp
これはほぼプロトコルを意識せずに使用できる。
でも、ローカルに認証情報を生でおくので、自分のマシン以外ではなんか気がひける。

curlでクライアント証明書を指定してPOSTする。
dev.classmethod.jp
Macだとなんか上手くいかないらしい。
しかもwindowsとかcurlがない環境だと面倒臭い。

今回は①も②もなんか採択するには微妙なので、第3の方法として、javascriptでなんとかPOSTできないかと思って足掻いてみた。

クライアント側の準備

①node.jsをインストール
②プロジェクトの作成
③npm install request

AWS IoT側の準備(モノやポリシーの設定は省略)

①POSTに必要な情報をAWS IoTから取得しておく。
・エンドポイント:IoT Core > 設定 > カスタムエンドポイント > エンドポイント
・認証情報
 モノにアタッチするポリシーを作成する際に、ダウンロードして有効化しておく。
 -プライベートキー
 -モノの証明書
 -ルートCA(表示されたURLをたどって、ダウンロードする。)

②テストからテスト用のトピックをサブスクライブしておく。

nodeの実装

requestでPOSTする際に、メッセージをBodyに持たせる形で送信する。
AWS IoT側ではstringで取得される。

埋め込む変数は以下の通り。
$ENDPOINT:エンドポイント
$TOPIC:テストでサブスクライブしているトピック
$PRIVATE_KEY:プライベートキー
$CERTIFICATE_OF_THINGS:モノの証明書
$ROOT_CA:ルートCA
$MESSAGE:送信するメッセージ

var request = require('request');
var fs = require('fs');

var options = {
    url: 'https://$ENDPOINT:8443/topics/$TOPIC',
    method: 'POST',
    key: fs.readFileSync($PRIVATE_KEY),
    cert: fs.readFileSync($CERTIFICATE_OF_THINGS),
    ca: fs.readFileSync($ROOT_CA),
    requestCert: true,
    body: $MESSAGE,
    rejectUnauthorized: true
}

request(options, function(error, response, body){
console.log(error);
console.log(response);
console.log(body);
});